summaryrefslogtreecommitdiffstats
path: root/tools/designer/editor
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
commitbd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch)
tree7a520322212d48ebcb9fbe1087e7fca28b76185c /tools/designer/editor
downloadqt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz
qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip
Add Qt3 development HEAD version
Diffstat (limited to 'tools/designer/editor')
-rw-r--r--tools/designer/editor/arghintwidget.cpp239
-rw-r--r--tools/designer/editor/arghintwidget.h69
-rw-r--r--tools/designer/editor/browser.cpp149
-rw-r--r--tools/designer/editor/browser.h66
-rw-r--r--tools/designer/editor/cindent.cpp163
-rw-r--r--tools/designer/editor/cindent.h63
-rw-r--r--tools/designer/editor/completion.cpp714
-rw-r--r--tools/designer/editor/completion.h110
-rw-r--r--tools/designer/editor/conf.cpp269
-rw-r--r--tools/designer/editor/conf.h75
-rw-r--r--tools/designer/editor/editor.cpp251
-rw-r--r--tools/designer/editor/editor.h111
-rw-r--r--tools/designer/editor/editor.pro40
-rw-r--r--tools/designer/editor/markerwidget.cpp491
-rw-r--r--tools/designer/editor/markerwidget.h75
-rw-r--r--tools/designer/editor/paragdata.h65
-rw-r--r--tools/designer/editor/parenmatcher.cpp215
-rw-r--r--tools/designer/editor/parenmatcher.h78
-rw-r--r--tools/designer/editor/preferences.ui510
-rw-r--r--tools/designer/editor/preferences.ui.h181
-rw-r--r--tools/designer/editor/viewmanager.cpp276
-rw-r--r--tools/designer/editor/viewmanager.h100
-rw-r--r--tools/designer/editor/yyindent.cpp1170
23 files changed, 5480 insertions, 0 deletions
diff --git a/tools/designer/editor/arghintwidget.cpp b/tools/designer/editor/arghintwidget.cpp
new file mode 100644
index 0000000..9d600f6
--- /dev/null
+++ b/tools/designer/editor/arghintwidget.cpp
@@ -0,0 +1,239 @@
+/**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "arghintwidget.h"
+#include <qbutton.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+
+static const char * left_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #FFFFFF",
+"+ c #000000",
+" ",
+" ",
+" + ",
+" ++ ",
+" +++ ",
+" ++++ ",
+" +++++ ",
+" ++++++ ",
+" ++++++ ",
+" +++++ ",
+" ++++ ",
+" +++ ",
+" ++ ",
+" + ",
+" ",
+" "};
+
+static const char * right_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #FFFFFF",
+"+ c #000000",
+" ",
+" ",
+" + ",
+" ++ ",
+" +++ ",
+" ++++ ",
+" +++++ ",
+" ++++++ ",
+" ++++++ ",
+" +++++ ",
+" ++++ ",
+" +++ ",
+" ++ ",
+" + ",
+" ",
+" "};
+
+static const char * left_disabled_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #FFFFFF",
+"+ c darkgray",
+" ",
+" ",
+" + ",
+" ++ ",
+" +++ ",
+" ++++ ",
+" +++++ ",
+" ++++++ ",
+" ++++++ ",
+" +++++ ",
+" ++++ ",
+" +++ ",
+" ++ ",
+" + ",
+" ",
+" "};
+
+static const char * right_disabled_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #FFFFFF",
+"+ c darkgray",
+" ",
+" ",
+" + ",
+" ++ ",
+" +++ ",
+" ++++ ",
+" +++++ ",
+" ++++++ ",
+" ++++++ ",
+" +++++ ",
+" ++++ ",
+" +++ ",
+" ++ ",
+" + ",
+" ",
+" "};
+
+class ArrowButton : public QButton
+{
+ Q_OBJECT
+
+public:
+ enum Dir { Left, Right };
+
+ ArrowButton( QWidget *parent, const char *name, Dir d );
+ void drawButton( QPainter *p );
+
+private:
+ QPixmap pix, pix_disabled;
+
+};
+
+ArrowButton::ArrowButton( QWidget *parent, const char *name, Dir d )
+ : QButton( parent, name )
+{
+ setFixedSize( 16, 16 );
+ if ( d == Left ) {
+ pix = QPixmap( left_xpm );
+ pix_disabled = QPixmap( left_disabled_xpm );
+ } else {
+ pix = QPixmap( right_xpm );
+ pix_disabled = QPixmap( right_disabled_xpm );
+ }
+}
+
+void ArrowButton::drawButton( QPainter *p )
+{
+ if ( isDown() )
+ p->fillRect( 0, 0, width(), height(), darkGray );
+ else
+ p->fillRect( 0, 0, width(), height(), lightGray );
+ if ( isEnabled() )
+ p->drawPixmap( 0, 0, pix );
+ else
+ p->drawPixmap( 0, 0, pix_disabled );
+}
+
+
+ArgHintWidget::ArgHintWidget( QWidget *parent, const char*name )
+ : QFrame( parent, name, WType_Popup ), curFunc( 0 ), numFuncs( 0 )
+{
+ setFrameStyle( QFrame::Box | QFrame::Plain );
+ setLineWidth( 1 );
+ setBackgroundColor( white );
+ QHBoxLayout *hbox = new QHBoxLayout( this );
+ hbox->setMargin( 1 );
+ hbox->addWidget( ( prev = new ArrowButton( this, "editor_left_btn", ArrowButton::Left ) ) );
+ hbox->addWidget( ( funcLabel = new QLabel( this, "editor_func_lbl" ) ) );
+ hbox->addWidget( ( next = new ArrowButton( this, "editor_right_btn", ArrowButton::Right ) ) );
+ funcLabel->setBackgroundColor( white );
+ funcLabel->setAlignment( AlignCenter );
+ connect( prev, SIGNAL( clicked() ), this, SLOT( gotoPrev() ) );
+ connect( next, SIGNAL( clicked() ), this, SLOT( gotoNext() ) );
+ updateState();
+ setFocusPolicy( NoFocus );
+ prev->setFocusPolicy( NoFocus );
+ next->setFocusPolicy( NoFocus );
+ funcLabel->setFocusPolicy( NoFocus );
+}
+
+void ArgHintWidget::setFunctionText( int func, const QString &text )
+{
+ funcs.replace( func, text );
+ if ( func == curFunc ) {
+ funcLabel->clear();
+ funcLabel->setText( text );
+ }
+}
+
+void ArgHintWidget::setNumFunctions( int num )
+{
+ funcs.clear();
+ numFuncs = num;
+ curFunc = 0;
+ updateState();
+}
+
+void ArgHintWidget::gotoPrev()
+{
+ if ( curFunc > 0 ) {
+ curFunc--;
+ funcLabel->setText( funcs[ curFunc ] );
+ updateState();
+ }
+}
+
+void ArgHintWidget::gotoNext()
+{
+ if ( curFunc < numFuncs - 1 ) {
+ curFunc++;
+ funcLabel->setText( funcs[ curFunc ] );
+ updateState();
+ }
+}
+
+void ArgHintWidget::updateState()
+{
+ prev->setEnabled( curFunc > 0 );
+ next->setEnabled( curFunc < numFuncs - 1 );
+}
+
+void ArgHintWidget::relayout()
+{
+ funcLabel->setText( "" );
+ funcLabel->setText( funcs[ curFunc ] );
+}
+
+#include "arghintwidget.moc"
diff --git a/tools/designer/editor/arghintwidget.h b/tools/designer/editor/arghintwidget.h
new file mode 100644
index 0000000..79a4ed6
--- /dev/null
+++ b/tools/designer/editor/arghintwidget.h
@@ -0,0 +1,69 @@
+/**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef ARGHINTWIDGET_H
+#define ARGHINTWIDGET_H
+
+#include <qframe.h>
+
+class QLabel;
+class ArrowButton;
+
+class ArgHintWidget : public QFrame
+{
+ Q_OBJECT
+
+public:
+ ArgHintWidget( QWidget *parent, const char*name );
+
+ void setFunctionText( int func, const QString &text );
+ void setNumFunctions( int num );
+
+public slots:
+ void relayout();
+ void gotoPrev();
+ void gotoNext();
+
+private:
+ void updateState();
+
+private:
+ int curFunc;
+ int numFuncs;
+ QMap<int, QString> funcs;
+ QLabel *funcLabel;
+ ArrowButton *prev, *next;
+
+};
+
+#endif
diff --git a/tools/designer/editor/browser.cpp b/tools/designer/editor/browser.cpp
new file mode 100644
index 0000000..9d8d818
--- /dev/null
+++ b/tools/designer/editor/browser.cpp
@@ -0,0 +1,149 @@
+/**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "browser.h"
+#include "editor.h"
+#include <private/qrichtext_p.h>
+
+
+EditorBrowser::EditorBrowser( Editor *e )
+ : curEditor( e ), oldHighlightedParag( 0 )
+{
+ curEditor = e;
+
+ // ### disabled for now
+// curEditor->viewport()->installEventFilter( this );
+// curEditor->installEventFilter( this );
+
+ QFont fn( curEditor->font() );
+ fn.setUnderline( TRUE );
+ highlightedFormat = new QTextFormat( fn, blue );
+}
+
+EditorBrowser::~EditorBrowser()
+{
+ delete highlightedFormat;
+}
+
+bool EditorBrowser::eventFilter( QObject *o, QEvent *e )
+{
+ if ( ::qt_cast<Editor*>(o->parent()) || ::qt_cast<Editor*>(o) ) {
+ QMouseEvent *me;
+ QKeyEvent *ke;
+ switch ( e->type() ) {
+ case QEvent::MouseMove:
+ me = (QMouseEvent*)e;
+ if ( ( me->state() & ControlButton ) == ControlButton ) {
+ curEditor->viewport()->setCursor( pointingHandCursor );
+ QTextCursor c( curEditor->document() );
+ curEditor->placeCursor( curEditor->viewportToContents( me->pos() ), &c );
+ QTextCursor from, to;
+ if ( oldHighlightedParag ) {
+ oldHighlightedParag->setEndState( -1 );
+ oldHighlightedParag->format();
+ oldHighlightedParag = 0;
+ }
+ if ( findCursor( c, from, to ) && from.paragraph() == to.paragraph() ) {
+ // avoid collision with other selections
+ for ( int i = 0; i < curEditor->document()->numSelections(); ++i )
+ curEditor->document()->removeSelection( i );
+ from.paragraph()->setFormat( from.index(), to.index() - from.index() + 1, highlightedFormat, FALSE );
+ lastWord = from.paragraph()->string()->toString().mid( from.index(), to.index() - from.index() + 1 );
+ oldHighlightedParag = from.paragraph();
+ } else {
+ lastWord = "";
+ }
+ curEditor->repaintChanged();
+ return TRUE;
+ }
+ break;
+ case QEvent::MouseButtonPress: {
+ bool killEvent = !lastWord.isEmpty();
+ if ( !lastWord.isEmpty() )
+ showHelp( lastWord );
+ lastWord = "";
+ curEditor->viewport()->setCursor( ibeamCursor );
+ if ( oldHighlightedParag ) {
+ oldHighlightedParag->setEndState( -1 );
+ oldHighlightedParag->format();
+ curEditor->repaintChanged();
+ oldHighlightedParag = 0;
+ }
+ if ( killEvent )
+ return TRUE;
+ } break;
+ case QEvent::KeyRelease:
+ lastWord = "";
+ ke = (QKeyEvent*)e;
+ if ( ke->key() == Key_Control ) {
+ curEditor->viewport()->setCursor( ibeamCursor );
+ if ( oldHighlightedParag ) {
+ oldHighlightedParag->setEndState( -1 );
+ oldHighlightedParag->format();
+ curEditor->repaintChanged();
+ oldHighlightedParag = 0;
+ }
+ }
+ default:
+ break;
+ }
+ }
+ return FALSE;
+}
+
+void EditorBrowser::setCurrentEdior( Editor *e )
+{
+ curEditor = e;
+ curEditor->installEventFilter( this );
+}
+
+void EditorBrowser::addEditor( Editor *e )
+{
+ e->installEventFilter( this );
+}
+
+bool EditorBrowser::findCursor( const QTextCursor &c, QTextCursor &from, QTextCursor &to )
+{
+ from = c;
+ while ( from.paragraph()->at( from.index() )->c != ' ' && from.paragraph()->at( from.index() )->c != '\t' && from.index() > 0 )
+ from.gotoLeft();
+ if ( from.paragraph()->at( from.index() )->c == ' ' || from.paragraph()->at( from.index() )->c == '\t' )
+ from.gotoRight();
+ to = c;
+ while ( to.paragraph()->at( to.index() )->c != ' ' && to.paragraph()->at( to.index() )->c != '\t' &&
+ to.index() < to.paragraph()->length() - 1 )
+ to.gotoRight();
+ if ( to.paragraph()->at( to.index() )->c == ' ' || to.paragraph()->at( to.index() )->c == '\t' )
+ to.gotoLeft();
+ return TRUE;
+}
diff --git a/tools/designer/editor/browser.h b/tools/designer/editor/browser.h
new file mode 100644
index 0000000..a90a9df
--- /dev/null
+++ b/tools/designer/editor/browser.h
@@ -0,0 +1,66 @@
+/**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef BROWSER_H
+#define BROWSER_H
+
+#include <qobject.h>
+
+class Editor;
+class QTextCursor;
+class QTextParagraph;
+class QTextFormat;
+
+class EditorBrowser : public QObject
+{
+ Q_OBJECT
+
+public:
+ EditorBrowser( Editor *e );
+ ~EditorBrowser();
+
+ bool eventFilter( QObject *o, QEvent *e );
+ virtual void setCurrentEdior( Editor *e );
+ virtual void addEditor( Editor *e );
+ virtual bool findCursor( const QTextCursor &c, QTextCursor &from, QTextCursor &to );
+ virtual void showHelp( const QString & ) {}
+
+protected:
+ Editor *curEditor;
+ QTextParagraph *oldHighlightedParag;
+ QString lastWord;
+ QTextFormat *highlightedFormat;
+
+};
+
+#endif
diff --git a/tools/designer/editor/cindent.cpp b/tools/designer/editor/cindent.cpp
new file mode 100644
index 0000000..545c374
--- /dev/null
+++ b/tools/designer/editor/cindent.cpp
@@ -0,0 +1,163 @@
+/**********************************************************************
+** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "cindent.h"
+#include "qregexp.h"
+
+extern int indentForBottomLine( const QStringList& program, QChar typedIn );
+extern void setTabSize( int s );
+extern void setIndentSize( int s );
+
+CIndent::CIndent()
+ : QTextIndent(), tabSize( 8 ), indentSize( 4 ),
+ autoIndent( TRUE ), keepTabs( TRUE ), lastDoc( 0 )
+{
+}
+
+static int indentation( const QString &s )
+{
+ if ( s.simplifyWhiteSpace().length() == 0 )
+ return 0;
+ int i = 0;
+ int ind = 0;
+ while ( i < (int)s.length() ) {
+ QChar c = s.at( i );
+ if ( c == ' ' )
+ ind++;
+ else if ( c == '\t' )
+ ind += 8;
+ else
+ break;
+ ++i;
+ }
+ return ind;
+}
+
+void CIndent::tabify( QString &s )
+{
+ if ( !keepTabs )
+ return;
+ int i = 0;
+ for ( ;; ) {
+ for ( int j = i; j < (int)s.length(); ++j ) {
+ if ( s[ j ] != ' ' && s[ j ] != '\t' ) {
+ if ( j > i ) {
+ QString t = s.mid( i, j - i );
+ int spaces = 0;
+ for ( int k = 0; k < (int)t.length(); ++k )
+ spaces += ( t[ k ] == ' ' ? 1 : tabSize );
+ s.remove( i, t.length() );
+ int tabs = spaces / tabSize;
+ spaces = spaces - ( tabSize * tabs );
+ QString tmp;
+ tmp.fill( ' ', spaces );
+ if ( spaces > 0 )
+ s.insert( i, tmp );
+ tmp.fill( '\t', tabs );
+ if ( tabs > 0 )
+ s.insert( i, tmp );
+ }
+ break;
+ }
+ }
+ i = s.find( '\n', i );
+ if ( i == -1 )
+ break;
+ ++i;
+ }
+}
+
+void CIndent::indentLine( QTextParagraph *p, int &oldIndent, int &newIndent )
+{
+ QString indentString;
+ indentString.fill( ' ', newIndent );
+ indentString.append( "a" );
+ tabify( indentString );
+ indentString.remove( indentString.length() - 1, 1 );
+ newIndent = indentString.length();
+ oldIndent = 0;
+ while ( p->length() > 0 && ( p->at( 0 )->c == ' ' || p->at( 0 )->c == '\t' ) ) {
+ ++oldIndent;
+ p->remove( 0, 1 );
+ }
+ if ( p->string()->length() == 0 )
+ p->append( " " );
+ if ( !indentString.isEmpty() )
+ p->insert( 0, indentString );
+}
+
+
+void CIndent::indent( QTextDocument *doc, QTextParagraph *p, int *oldIndent, int *newIndent )
+{
+ lastDoc = doc;
+ int oi = indentation( p->string()->toString() );
+ QStringList code;
+ QTextParagraph *parag = doc->firstParagraph();
+ while ( parag ) {
+ code << parag->string()->toString();
+ if ( parag == p )
+ break;
+ parag = parag->next();
+ }
+
+ int ind = indentForBottomLine( code, QChar::null );
+ indentLine( p, oi, ind );
+ if ( oldIndent )
+ *oldIndent = oi;
+ if ( newIndent )
+ *newIndent = ind;
+}
+
+void CIndent::reindent()
+{
+ if ( !lastDoc )
+ return;
+ // #### this is sloooooooow (O(n^2))
+ QTextParagraph *parag = lastDoc->firstParagraph();
+ while ( parag ) {
+ indent( lastDoc, parag, 0, 0 );
+ parag = parag->next();
+ }
+}
+
+void CIndent::setTabSize( int ts )
+{
+ tabSize = ts;
+ ::setTabSize( ts );
+}
+
+void CIndent::setIndentSize( int is )
+{
+ indentSize = is;
+ ::setIndentSize( is );
+}
diff --git a/tools/designer/editor/cindent.h b/tools/designer/editor/cindent.h
new file mode 100644
index 0000000..b184049
--- /dev/null
+++ b/tools/designer/editor/cindent.h
@@ -0,0 +1,63 @@
+/**********************************************************************
+** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef CINDENT_H
+#define CINDENT_H
+
+#include <private/qrichtext_p.h>
+
+class CIndent : public QTextIndent
+{
+public:
+ CIndent();
+ virtual ~CIndent() {}
+ void indent( QTextDocument *doc, QTextParagraph *parag, int *oldIndent, int *newIndent );
+
+ void setTabSize( int ts );
+ void setIndentSize( int is );
+ void setAutoIndent( bool ai ) { autoIndent = ai; reindent(); }
+ void setKeepTabs( bool kt ) { keepTabs = kt; }
+
+private:
+ void reindent();
+ void indentLine( QTextParagraph *p, int &oldIndent, int &newIndent );
+ void tabify( QString &s );
+
+public:
+ int tabSize, indentSize;
+ bool autoIndent, keepTabs;
+ QTextDocument *lastDoc;
+
+};
+
+#endif
diff --git a/tools/designer/editor/completion.cpp b/tools/designer/editor/completion.cpp
new file mode 100644
index 0000000..9ab09fa
--- /dev/null
+++ b/tools/designer/editor/completion.cpp
@@ -0,0 +1,714 @@
+/**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "completion.h"
+#include "paragdata.h"
+#include "editor.h"
+#include <qlistbox.h>
+#include <qvbox.h>
+#include <qmap.h>
+#include <private/qrichtext_p.h>
+#include <qapplication.h>
+#include <qregexp.h>
+#include "arghintwidget.h"
+#include <qsizegrip.h>
+#include <qtimer.h>
+
+static QColor getColor( const QString &type )
+{
+ if ( type == "function" || type == "slot" || type == "package" )
+ return Qt::blue;
+ else if ( type == "variable" || type == "widget" || type == "dir" )
+ return Qt::darkRed;
+ else if ( type == "object" || type == "class" )
+ return Qt::darkBlue;
+ else if ( type == "property" )
+ return Qt::darkGreen;
+ else if ( type == "enum" )
+ return Qt::darkYellow;
+ return Qt::black;
+}
+
+class CompletionItem : public QListBoxItem
+{
+public:
+ CompletionItem( QListBox *lb, const QString &txt, const QString &t, const QString &p,
+ const QString &pre, const QString &p2 )
+ : QListBoxItem( lb ), type( t ), postfix( p ), prefix( pre ), postfix2( p2 ),
+ parag( 0 ), lastState( FALSE ) { setText( txt ); }
+ ~CompletionItem() { delete parag; }
+ void paint( QPainter *painter ) {
+ if ( lastState != isSelected() ) {
+ delete parag;
+ parag = 0;
+ }
+ lastState = isSelected();
+ if ( !parag )
+ setupParagraph();
+ parag->paint( *painter, listBox()->colorGroup() );
+ }
+
+ int height( const QListBox * ) const {
+ if ( !parag )
+ ( (CompletionItem*)this )->setupParagraph();
+ return parag->rect().height();
+ }
+ int width( const QListBox * ) const {
+ if ( !parag )
+ ( (CompletionItem*)this )->setupParagraph();
+ return parag->rect().width() - 2;
+ }
+ QString text() const { return QListBoxItem::text() + postfix; }
+
+private:
+ void setupParagraph();
+ QString type, postfix, prefix, postfix2;
+ QTextParagraph *parag;
+ bool lastState;
+
+};
+
+void CompletionItem::setupParagraph() {
+ if ( !parag ) {
+ QTextFormatter *formatter;
+ formatter = new QTextFormatterBreakWords;
+ formatter->setWrapEnabled( FALSE );
+ parag = new QTextParagraph( 0 );
+ parag->setTabStops( listBox()->fontMetrics().width( "propertyXXXX" ) );
+ parag->pseudoDocument()->pFormatter = formatter;
+ parag->insert( 0, " " + type + ( type.isEmpty() ? " " : "\t" ) + prefix +
+ QListBoxItem::text() + postfix + postfix2 );
+ bool selCol = isSelected() && listBox()->colorGroup().highlightedText() != listBox()->colorGroup().text();
+ QColor sc = selCol ? listBox()->colorGroup().highlightedText() : getColor( type );
+ QTextFormat *f1 = parag->formatCollection()->format( listBox()->font(), sc );
+ QTextFormat *f3 = parag->formatCollection()->format( listBox()->font(), isSelected() ?
+ listBox()->colorGroup().highlightedText() :
+ listBox()->colorGroup().text() );
+ QFont f( listBox()->font() );
+ f.setBold( TRUE );
+ QTextFormat *f2 =
+ parag->formatCollection()->format( f, isSelected() ? listBox()->colorGroup().highlightedText() :
+ listBox()->colorGroup().text() );
+ parag->setFormat( 1, type.length() + 1, f1 );
+ parag->setFormat( type.length() + 2, prefix.length() + QListBoxItem::text().length(), f2 );
+ if ( !postfix.isEmpty() )
+ parag->setFormat( type.length() + 2 + prefix.length() + QListBoxItem::text().length(),
+ postfix.length(), f3 );
+ parag->setFormat( type.length() + 2 + prefix.length() + QListBoxItem::text().length() + postfix.length(),
+ postfix2.length(), f3 );
+ f1->removeRef();
+ f2->removeRef();
+ f3->removeRef();
+ parag->format();
+ }
+}
+
+
+EditorCompletion::EditorCompletion( Editor *e )
+{
+ enabled = TRUE;
+ lastDoc = 0;
+ completionPopup = new QVBox( e->topLevelWidget(), 0, WType_Popup );
+ completionPopup->setFrameStyle( QFrame::Box | QFrame::Plain );
+ completionPopup->setLineWidth( 1 );
+ functionLabel = new ArgHintWidget( e->topLevelWidget(), "editor_function_lbl" );
+ functionLabel->hide();
+ completionListBox = new QListBox( completionPopup, "editor_completion_lb" );
+ completionListBox->setFrameStyle( QFrame::NoFrame );
+ completionListBox->installEventFilter( this );
+ completionListBox->setHScrollBarMode( QScrollView::AlwaysOn );
+ completionListBox->setVScrollBarMode( QScrollView::AlwaysOn );
+ completionListBox->setCornerWidget( new QSizeGrip( completionListBox, "editor_cornerwidget" ) );
+ completionPopup->installEventFilter( this );
+ functionLabel->installEventFilter( this );
+ completionPopup->setFocusProxy( completionListBox );
+ completionOffset = 0;
+ curEditor = e;
+ curEditor->installEventFilter( this );
+}
+
+EditorCompletion::~EditorCompletion()
+{
+ delete completionPopup;
+ delete functionLabel;
+}
+
+void EditorCompletion::addCompletionEntry( const QString &s, QTextDocument *, bool strict )
+{
+ QChar key( s[ 0 ] );
+ QMap<QChar, QStringList>::Iterator it = completionMap.find( key );
+ if ( it == completionMap.end() ) {
+ completionMap.insert( key, QStringList( s ) );
+ } else {
+ if ( strict ) {
+ QStringList::Iterator sit;
+ for ( sit = (*it).begin(); sit != (*it).end(); ) {
+ QStringList::Iterator it2 = sit;
+ ++sit;
+ if ( (*it2).length() > s.length() && (*it2).left( s.length() ) == s ) {
+ if ( (*it2)[ (int)s.length() ].isLetter() && (*it2)[ (int)s.length() ].upper() != (*it2)[ (int)s.length() ] )
+ return;
+ } else if ( s.length() > (*it2).length() && s.left( (*it2).length() ) == *it2 ) {
+ if ( s[ (int)(*it2).length() ].isLetter() && s[ (int)(*it2).length() ].upper() != s[ (int)(*it2).length() ] )
+ (*it).remove( it2 );
+ }
+ }
+ }
+ (*it).append( s );
+ }
+}
+
+QValueList<CompletionEntry> EditorCompletion::completionList( const QString &s, QTextDocument *doc ) const
+{
+ if ( doc )
+ ( (EditorCompletion*)this )->updateCompletionMap( doc );
+
+ QChar key( s[ 0 ] );
+ QMap<QChar, QStringList>::ConstIterator it = completionMap.find( key );
+ if ( it == completionMap.end() )
+ return QValueList<CompletionEntry>();
+ QStringList::ConstIterator it2 = (*it).begin();
+ QValueList<CompletionEntry> lst;
+ int len = s.length();
+ for ( ; it2 != (*it).end(); ++it2 ) {
+ CompletionEntry c;
+ c.type = "";
+ c.text = *it2;
+ c.postfix = "";
+ c.prefix = "";
+ c.postfix2 = "";
+ if ( (int)(*it2).length() > len && (*it2).left( len ) == s && lst.find( c ) == lst.end() )
+ lst << c;
+ }
+
+ return lst;
+}
+
+void EditorCompletion::updateCompletionMap( QTextDocument *doc )
+{
+ bool strict = TRUE;
+ if ( doc != lastDoc )
+ strict = FALSE;
+ lastDoc = doc;
+ QTextParagraph *s = doc->firstParagraph();
+ if ( !s->extraData() )
+ s->setExtraData( new ParagData );
+ while ( s ) {
+ if ( s->length() == ( (ParagData*)s->extraData() )->lastLengthForCompletion ) {
+ s = s->next();
+ continue;
+ }
+
+ QChar c;
+ QString buffer;
+ for ( int i = 0; i < s->length(); ++i ) {
+ c = s->at( i )->c;
+ if ( c.isLetter() || c.isNumber() || c == '_' || c == '#' ) {
+ buffer += c;
+ } else {
+ addCompletionEntry( buffer, doc, strict );
+ buffer = QString::null;
+ }
+ }
+ if ( !buffer.isEmpty() )
+ addCompletionEntry( buffer, doc, strict );
+
+ ( (ParagData*)s->extraData() )->lastLengthForCompletion = s->length();
+ s = s->next();
+ }
+}
+
+bool EditorCompletion::doCompletion()
+{
+ searchString = "";
+ if ( !curEditor )
+ return FALSE;
+
+ QTextCursor *cursor = curEditor->textCursor();
+ QTextDocument *doc = curEditor->document();
+
+ if ( cursor->index() > 0 && cursor->paragraph()->at( cursor->index() - 1 )->c == '.' &&
+ ( cursor->index() == 1 || cursor->paragraph()->at( cursor->index() - 2 )->c != '.' ) )
+ return doObjectCompletion();
+
+ int idx = cursor->index();
+ if ( idx == 0 )
+ return FALSE;
+ QChar c = cursor->paragraph()->at( idx - 1 )->c;
+ if ( !c.isLetter() && !c.isNumber() && c != '_' && c != '#' )
+ return FALSE;
+
+ QString s;
+ idx--;
+ completionOffset = 1;
+ for (;;) {
+ s.prepend( QString( cursor->paragraph()->at( idx )->c ) );
+ idx--;
+ if ( idx < 0 )
+ break;
+ if ( !cursor->paragraph()->at( idx )->c.isLetter() &&
+ !cursor->paragraph()->at( idx )->c.isNumber() &&
+ cursor->paragraph()->at( idx )->c != '_' &&
+ cursor->paragraph()->at( idx )->c != '#' )
+ break;
+ completionOffset++;
+ }
+
+ searchString = s;
+
+ QValueList<CompletionEntry> lst( completionList( s, doc ) );
+ if ( lst.count() > 1 ) {
+ QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
+ int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
+ int x = cursor->paragraph()->rect().x() + chr->x;
+ int y, dummy;
+ cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
+ y += cursor->paragraph()->rect().y();
+ completionListBox->clear();
+ for ( QValueList<CompletionEntry>::ConstIterator it = lst.begin(); it != lst.end(); ++it )
+ (void)new CompletionItem( completionListBox, (*it).text, (*it).type, (*it).postfix,
+ (*it).prefix, (*it).postfix2 );
+ cList = lst;
+ completionPopup->resize( completionListBox->sizeHint() +
+ QSize( completionListBox->verticalScrollBar()->width() + 4,
+ completionListBox->horizontalScrollBar()->height() + 4 ) );
+ completionListBox->setCurrentItem( 0 );
+ completionListBox->setFocus();
+ if ( curEditor->mapToGlobal( QPoint( 0, y ) ).y() + h + completionPopup->height() < QApplication::desktop()->height() )
+ completionPopup->move( curEditor->mapToGlobal( curEditor->
+ contentsToViewport( QPoint( x, y + h ) ) ) );
+ else
+ completionPopup->move( curEditor->mapToGlobal( curEditor->
+ contentsToViewport( QPoint( x, y - completionPopup->height() ) ) ) );
+ completionPopup->show();
+ } else if ( lst.count() == 1 ) {
+ curEditor->insert( lst.first().text.mid( completionOffset, 0xFFFFFF ),
+ (uint) ( QTextEdit::RedoIndentation |
+ QTextEdit::CheckNewLines |
+ QTextEdit::RemoveSelected ) );
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+bool EditorCompletion::eventFilter( QObject *o, QEvent *e )
+{
+ if ( !enabled )
+ return FALSE;
+ if ( e->type() == QEvent::KeyPress && ::qt_cast<Editor*>(o)) {
+ curEditor = (Editor*)o;
+ QKeyEvent *ke = (QKeyEvent*)e;
+ if ( ke->key() == Key_Tab ) {
+ QString s = curEditor->textCursor()->paragraph()->string()->toString().
+ left( curEditor->textCursor()->index() );
+ if ( curEditor->document()->hasSelection( QTextDocument::Standard ) ||
+ s.simplifyWhiteSpace().isEmpty() ) {
+ if ( curEditor->document()->indent() ) {
+ curEditor->indent();
+ int i = 0;
+ for ( ; i < curEditor->textCursor()->paragraph()->length() - 1; ++i ) {
+ if ( curEditor->textCursor()->paragraph()->at( i )->c != ' ' &&
+ curEditor->textCursor()->paragraph()->at( i )->c != '\t' )
+ break;
+ }
+ curEditor->drawCursor( FALSE );
+ curEditor->textCursor()->setIndex( i );
+ curEditor->drawCursor( TRUE );
+ } else {
+ curEditor->insert( "\t" );
+ }
+ return TRUE;
+ }
+ }
+
+ if ( functionLabel->isVisible() ) {
+ if ( ke->key() == Key_Up && ( ke->state() & ControlButton ) == ControlButton ) {
+ functionLabel->gotoPrev();
+ return TRUE;
+ } else if ( ke->key() == Key_Down && ( ke->state() & ControlButton ) == ControlButton ) {
+ functionLabel->gotoNext();
+ return TRUE;
+ }
+ }
+
+ if ( ke->text().length() && !( ke->state() & AltButton ) &&
+ ( !ke->ascii() || ke->ascii() >= 32 ) ||
+ ( ke->text() == "\t" && !( ke->state() & ControlButton ) ) ) {
+ if ( ke->key() == Key_Tab ) {
+ if ( curEditor->textCursor()->index() == 0 &&
+ curEditor->textCursor()->paragraph()->isListItem() )
+ return FALSE;
+ if ( doCompletion() )
+ return TRUE;
+ } else if ( ke->key() == Key_Period &&
+ ( curEditor->textCursor()->index() == 0 ||
+ curEditor->textCursor()->paragraph()->at( curEditor->textCursor()->index() - 1 )->c != '.' )
+ ||
+ ke->key() == Key_Greater &&
+ curEditor->textCursor()->index() > 0 &&
+ curEditor->textCursor()->paragraph()->at( curEditor->textCursor()->index() - 1 )->c == '-' ) {
+ doObjectCompletion();
+ } else {
+ if ( !doArgumentHint( ke->text() == "(" ) )
+ functionLabel->hide();
+ }
+ }
+ } else if ( o == completionPopup || o == completionListBox ||
+ o == completionListBox->viewport() ) {
+ if ( e->type() == QEvent::KeyPress ) {
+ QKeyEvent *ke = (QKeyEvent*)e;
+ if ( ke->key() == Key_Enter || ke->key() == Key_Return || ke->key() == Key_Tab ) {
+ if ( ke->key() == Key_Tab && completionListBox->count() > 1 &&
+ completionListBox->currentItem() < (int)completionListBox->count() - 1 ) {
+ completionListBox->setCurrentItem( completionListBox->currentItem() + 1 );
+ return TRUE;
+ }
+ completeCompletion();
+ return TRUE;
+ } else if ( ke->key() == Key_Left || ke->key() == Key_Right ||
+ ke->key() == Key_Up || ke->key() == Key_Down ||
+ ke->key() == Key_Home || ke->key() == Key_End ||
+ ke->key() == Key_Prior || ke->key() == Key_Next ) {
+ return FALSE;
+ } else if ( ke->key() != Key_Shift && ke->key() != Key_Control &&
+ ke->key() != Key_Alt ) {
+ int l = searchString.length();
+ if ( ke->key() == Key_Backspace ) {
+ searchString.remove( searchString.length() - 1, 1 );
+ } else {
+ searchString += ke->text();
+ l = 1;
+ }
+ if ( !l || !continueComplete() ) {
+ completionPopup->close();
+ curEditor->setFocus();
+ }
+ QApplication::sendEvent( curEditor, e );
+ return TRUE;
+ }
+ } else if ( e->type() == QEvent::MouseButtonDblClick ) {
+ completeCompletion();
+ return TRUE;
+ }
+ }
+ if ( o == functionLabel || ::qt_cast<Editor*>(o) && functionLabel->isVisible() ) {
+ if ( e->type() == QEvent::KeyPress ) {
+ QKeyEvent *ke = (QKeyEvent*)e;
+ if ( ke->key() == Key_Escape ) {
+ functionLabel->hide();
+ } else {
+ if ( !doArgumentHint( ke->text() == "(" ) )
+ functionLabel->hide();
+ if ( o == functionLabel ) {
+ QApplication::sendEvent( curEditor, e );
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+void EditorCompletion::completeCompletion()
+{
+ int idx = curEditor->textCursor()->index();
+ QString s = completionListBox->currentText().mid( searchString.length() );
+ curEditor->insert( s, (uint) ( QTextEdit::RedoIndentation |
+ QTextEdit::CheckNewLines |
+ QTextEdit::RemoveSelected ) );
+ int i = s.find( '(' );
+ completionPopup->close();
+ curEditor->setFocus();
+ if ( i != -1 && i < (int)s.length() ) {
+ curEditor->setCursorPosition( curEditor->textCursor()->paragraph()->paragId(), idx + i + 1 );
+ doArgumentHint( FALSE );
+ }
+}
+
+void EditorCompletion::setCurrentEdior( Editor *e )
+{
+ curEditor = e;
+ curEditor->installEventFilter( this );
+}
+
+void EditorCompletion::addEditor( Editor *e )
+{
+ e->installEventFilter( this );
+}
+
+bool EditorCompletion::doObjectCompletion()
+{
+ searchString = "";
+ QString object;
+ int i = curEditor->textCursor()->index();
+ i--;
+ QTextParagraph *p = curEditor->textCursor()->paragraph();
+ for (;;) {
+ if ( i < 0 )
+ break;
+ if ( p->at( i )->c == ' ' || p->at( i )->c == '\t' )
+ break;
+ object.prepend( p->at( i )->c );
+ i--;
+ }
+
+ if ( object[ (int)object.length() - 1 ] == '-' )
+ object.remove( object.length() - 1, 1 );
+
+ if ( object.isEmpty() )
+ return FALSE;
+ return doObjectCompletion( object );
+}
+
+bool EditorCompletion::doObjectCompletion( const QString & )
+{
+ return FALSE;
+}
+
+static void strip( QString &txt )
+{
+ int i = txt.find( "(" );
+ if ( i == -1 )
+ return;
+ txt = txt.left( i );
+}
+
+bool EditorCompletion::continueComplete()
+{
+ if ( searchString.isEmpty() ) {
+ completionListBox->clear();
+ for ( QValueList<CompletionEntry>::ConstIterator it = cList.begin(); it != cList.end(); ++it )
+ (void)new CompletionItem( completionListBox, (*it).text, (*it).type,
+ (*it).postfix, (*it).prefix, (*it).postfix2 );
+ completionListBox->setCurrentItem( 0 );
+ completionListBox->setSelected( completionListBox->currentItem(), TRUE );
+ return TRUE;
+ }
+
+ QListBoxItem *i = completionListBox->findItem( searchString );
+ if ( !i )
+ return FALSE;
+
+ QString txt1 = i->text();
+ QString txt2 = searchString;
+ strip( txt1 );
+ strip( txt2 );
+ if ( txt1 == txt2 && !i->next() )
+ return FALSE;
+
+ QValueList<CompletionEntry> res;
+ for ( QValueList<CompletionEntry>::ConstIterator it = cList.begin(); it != cList.end(); ++it ) {
+ if ( (*it).text.left( searchString.length() ) == searchString )
+ res << *it;
+ }
+ if ( res.isEmpty() )
+ return FALSE;
+ completionListBox->clear();
+ for ( QValueList<CompletionEntry>::ConstIterator it2 = res.begin(); it2 != res.end(); ++it2 )
+ (void)new CompletionItem( completionListBox, (*it2).text, (*it2).type,
+ (*it2).postfix, (*it2).prefix, (*it2).postfix2 );
+ completionListBox->setCurrentItem( 0 );
+ completionListBox->setSelected( completionListBox->currentItem(), TRUE );
+ return TRUE;
+}
+
+bool EditorCompletion::doArgumentHint( bool useIndex )
+{
+ QTextCursor *cursor = curEditor->textCursor();
+ int i = cursor->index() ;
+ if ( !useIndex ) {
+ bool foundParen = FALSE;
+ int closeParens = 0;
+ while ( i >= 0 ) {
+ if ( cursor->paragraph()->at( i )->c == ')' && i != cursor->index() )
+ closeParens++;
+ if ( cursor->paragraph()->at( i )->c == '(' ) {
+ closeParens--;
+ if ( closeParens == -1 ) {
+ foundParen = TRUE;
+ break;
+ }
+ }
+ --i;
+ }
+
+ if ( !foundParen )
+ return FALSE;
+ }
+ int j = i - 1;
+ bool foundSpace = FALSE;
+ bool foundNonSpace = FALSE;
+ while ( j >= 0 ) {
+ if ( foundNonSpace && ( cursor->paragraph()->at( j )->c == ' ' || cursor->paragraph()->at( j )->c == ',' ) ) {
+ foundSpace = TRUE;
+ break;
+ }
+ if ( !foundNonSpace && ( cursor->paragraph()->at( j )->c != ' ' || cursor->paragraph()->at( j )->c != ',' ) )
+ foundNonSpace = TRUE;
+ --j;
+ }
+ if ( foundSpace )
+ ++j;
+ j = QMAX( j, 0 );
+ QString function( cursor->paragraph()->string()->toString().mid( j, i - j + 1 ) );
+ QString part = cursor->paragraph()->string()->toString().mid( j, cursor->index() - j + 1 );
+ function = function.simplifyWhiteSpace();
+ for (;;) {
+ if ( function[ (int)function.length() - 1 ] == '(' ) {
+ function.remove( function.length() - 1, 1 );
+ function = function.simplifyWhiteSpace();
+ } else if ( function[ (int)function.length() - 1 ] == ')' ) {
+ function.remove( function.length() - 1, 1 );
+ function = function.simplifyWhiteSpace();
+ } else {
+ break;
+ }
+ }
+
+ QChar sep;
+ QString pre, post;
+ QValueList<QStringList> argl = functionParameters( function, sep, pre, post );
+ if ( argl.isEmpty() )
+ return FALSE;
+
+ QString label;
+ int w = 0;
+ int num = 0;
+ if ( !functionLabel->isVisible() )
+ functionLabel->setNumFunctions( (int)argl.count() );
+ for ( QValueList<QStringList>::Iterator vit = argl.begin(); vit != argl.end(); ++vit, ++num ) {
+ QStringList args = *vit;
+ int argNum = 0;
+ int inParen = 0;
+ for ( int k = 0; k < (int)part.length(); ++k ) {
+ if ( part[ k ] == sep && inParen < 2 )
+ argNum++;
+ if ( part[ k ] == '(' )
+ inParen++;
+ if ( part[ k ] == ')' )
+ inParen--;
+ }
+
+ QString func = function;
+ int pnt = -1;
+ pnt = func.findRev( '.' );
+ if ( pnt == -1 )
+ func.findRev( '>' );
+ if ( pnt != -1 )
+ func = func.mid( pnt + 1 );
+
+ QString s = func + "( ";
+ if ( s[ 0 ] == '\"' )
+ s.remove( (uint)0, 1 );
+ i = 0;
+ for ( QStringList::Iterator it = args.begin(); it != args.end(); ++it, ++i ) {
+ if ( i == argNum )
+ s += "<b>" + *it + "</b>";
+ else
+ s += *it;
+ if ( i < (int)args.count() - 1 )
+ s += ", ";
+ else
+ s += " ";
+ }
+ s += ")";
+ s.prepend( pre );
+ s.append( post );
+ label += "<p>" + s + "</p>";
+ functionLabel->setFunctionText( num, s );
+ w = QMAX( w, functionLabel->fontMetrics().width( s ) + 10 );
+ }
+ w += 16;
+ if ( label.isEmpty() )
+ return FALSE;
+ if ( functionLabel->isVisible() ) {
+ functionLabel->resize( w + 50, QMAX( functionLabel->fontMetrics().height(), 16 ) );
+ } else {
+ QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
+ int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
+ int x = cursor->paragraph()->rect().x() + chr->x;
+ int y, dummy;
+ cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
+ y += cursor->paragraph()->rect().y();
+ functionLabel->resize( w + 50, QMAX( functionLabel->fontMetrics().height(), 16 ) );
+ functionLabel->move( curEditor->mapToGlobal( curEditor->contentsToViewport( QPoint( x, y + h ) ) ) );
+ if ( functionLabel->x() + functionLabel->width() > QApplication::desktop()->width() )
+ functionLabel->move( QMAX( 0, QApplication::desktop()->width() - functionLabel->width() ),
+ functionLabel->y() );
+ functionLabel->show();
+ curEditor->setFocus();
+ }
+ QTimer::singleShot( 0, functionLabel, SLOT( relayout() ) );
+
+ return TRUE;
+}
+
+QValueList<QStringList> EditorCompletion::functionParameters( const QString &, QChar &, QString &, QString & )
+{
+ return QValueList<QStringList>();
+}
+
+void EditorCompletion::setContext( QObject * )
+{
+}
+
+void EditorCompletion::showCompletion( const QValueList<CompletionEntry> &lst )
+{
+ QTextCursor *cursor = curEditor->textCursor();
+ QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
+ int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
+ int x = cursor->paragraph()->rect().x() + chr->x;
+ int y, dummy;
+ cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
+ y += cursor->paragraph()->rect().y();
+ completionListBox->clear();
+ for ( QValueList<CompletionEntry>::ConstIterator it = lst.begin(); it != lst.end(); ++it )
+ (void)new CompletionItem( completionListBox, (*it).text, (*it).type,
+ (*it).postfix, (*it).prefix, (*it).postfix2 );
+ cList = lst;
+ completionPopup->resize( completionListBox->sizeHint() +
+ QSize( completionListBox->verticalScrollBar()->width() + 4,
+ completionListBox->horizontalScrollBar()->height() + 4 ) );
+ completionListBox->setCurrentItem( 0 );
+ completionListBox->setFocus();
+ if ( curEditor->mapToGlobal( QPoint( 0, y ) ).y() + h + completionPopup->height() < QApplication::desktop()->height() )
+ completionPopup->move( curEditor->mapToGlobal( curEditor->
+ contentsToViewport( QPoint( x, y + h ) ) ) );
+ else
+ completionPopup->move( curEditor->mapToGlobal( curEditor->
+ contentsToViewport( QPoint( x, y - completionPopup->height() ) ) ) );
+
+ completionPopup->show();
+}
diff --git a/tools/designer/editor/completion.h b/tools/designer/editor/completion.h
new file mode 100644
index 0000000..94acf6b
--- /dev/null
+++ b/tools/designer/editor/completion.h
@@ -0,0 +1,110 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef COMPLETION_H
+#define COMPLETION_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qobject.h>
+#include <qmap.h>
+
+class QTextDocument;
+class Editor;
+class QVBox;
+class QListBox;
+class ArgHintWidget;
+
+struct CompletionEntry
+{
+ QString type;
+ QString text;
+ QString postfix;
+ QString prefix;
+ QString postfix2;
+
+ bool operator==( const CompletionEntry &c ) const {
+ return ( c.type == type &&
+ c.text == text &&
+ c.postfix == postfix &&
+ c.prefix == prefix &&
+ c.postfix2 == postfix2 );
+ }
+};
+
+class EditorCompletion : public QObject
+{
+ Q_OBJECT
+
+public:
+ EditorCompletion( Editor *e );
+ ~EditorCompletion();
+
+ virtual void addCompletionEntry( const QString &s, QTextDocument *doc, bool strict );
+ virtual QValueList<CompletionEntry> completionList( const QString &s, QTextDocument *doc ) const;
+ virtual void updateCompletionMap( QTextDocument *doc );
+
+ bool eventFilter( QObject *o, QEvent *e );
+ virtual void setCurrentEdior( Editor *e );
+ virtual bool doCompletion();
+ virtual bool doObjectCompletion();
+ virtual bool doObjectCompletion( const QString &object );
+ virtual bool doArgumentHint( bool useIndex );
+
+ virtual void addEditor( Editor *e );
+ virtual QValueList<QStringList> functionParameters( const QString &func, QChar &, QString &prefix, QString &postfix );
+
+ virtual void setContext( QObject *this_ );
+
+ void setEnabled( bool b ) { enabled = b; }
+
+protected:
+ virtual bool continueComplete();
+ virtual void showCompletion( const QValueList<CompletionEntry> &lst );
+ virtual void completeCompletion();
+
+protected:
+ QVBox *completionPopup;
+ QListBox *completionListBox;
+ ArgHintWidget *functionLabel;
+ int completionOffset;
+ Editor *curEditor;
+ QString searchString;
+ QValueList<CompletionEntry> cList;
+ QMap<QChar, QStringList> completionMap;
+ bool enabled;
+ QTextDocument *lastDoc;
+
+};
+
+#endif
diff --git a/tools/designer/editor/conf.cpp b/tools/designer/editor/conf.cpp
new file mode 100644
index 0000000..11e4f0a
--- /dev/null
+++ b/tools/designer/editor/conf.cpp
@@ -0,0 +1,269 @@
+/**********************************************************************
+** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "conf.h"
+#include <qapplication.h>
+#include <qfont.h>
+#include <qcolor.h>
+#include <qsettings.h>
+
+QMap<QString, ConfigStyle> Config::defaultStyles()
+{
+ ConfigStyle s;
+ QMap<QString, ConfigStyle> styles;
+ int normalSize = qApp->font().pointSize();
+ QString normalFamily = qApp->font().family();
+ QString commentFamily = "times";
+ int normalWeight = qApp->font().weight();
+
+ s.font = QFont( normalFamily, normalSize, normalWeight );
+ s.color = Qt::black;
+ styles.insert( "Standard", s );
+
+ s.font = QFont( commentFamily, normalSize, normalWeight, TRUE );
+ s.color = Qt::red;
+ styles.insert( "Comment", s );
+
+ s.font = QFont( normalFamily, normalSize, normalWeight );
+ s.color = Qt::blue;
+ styles.insert( "Number", s );
+
+ s.font = QFont( normalFamily, normalSize, normalWeight );
+ s.color = Qt::darkGreen;
+ styles.insert( "String", s );
+
+ s.font = QFont( normalFamily, normalSize, normalWeight );
+ s.color = Qt::darkMagenta;
+ styles.insert( "Type", s );
+
+ s.font = QFont( normalFamily, normalSize, normalWeight );
+ s.color = Qt::darkYellow;
+ styles.insert( "Keyword", s );
+
+ s.font = QFont( normalFamily, normalSize, normalWeight );
+ s.color = Qt::darkBlue;
+ styles.insert( "Preprocessor", s );
+
+ s.font = QFont( normalFamily, normalSize, normalWeight );
+ s.color = Qt::darkRed;
+ styles.insert( "Label", s );
+
+ return styles;
+}
+
+QMap<QString, ConfigStyle> Config::readStyles( const QString &path )
+{
+ QMap<QString, ConfigStyle> styles;
+ styles = defaultStyles();
+
+ QString family;
+ int size = 10;
+ bool bold = FALSE, italic = FALSE, underline = FALSE;
+ int red = 0, green = 0, blue = 0;
+
+ QString elements[] = {
+ "Comment",
+ "Number",
+ "String",
+ "Type",
+ "Keyword",
+ "Preprocessor",
+ "Label",
+ "Standard",
+ QString::null
+ };
+
+ for ( int i = 0; elements[ i ] != QString::null; ++i ) {
+ QSettings settings;
+ bool ok = TRUE;
+ for (;;) {
+ family = settings.readEntry( path + elements[ i ] + "/family", QString::null, &ok );
+ if ( !ok )
+ break;
+ size = settings.readNumEntry( path + elements[ i ] + "/size", 10, &ok );
+ if ( !ok )
+ break;
+ bold = settings.readBoolEntry( path + elements[ i ] + "/bold", FALSE, &ok );
+ if ( !ok )
+ break;
+ italic = settings.readBoolEntry( path + elements[ i ] + "/italic", FALSE, &ok );
+ if ( !ok )
+ break;
+ underline = settings.readBoolEntry( path + elements[ i ] + "/underline", FALSE, &ok );
+ if ( !ok )
+ break;
+ red = settings.readNumEntry( path + elements[ i ] + "/red", 0, &ok );
+ if ( !ok )
+ break;
+ green = settings.readNumEntry( path + elements[ i ] + "/green", 0, &ok );
+ if ( !ok )
+ break;
+ blue = settings.readNumEntry( path + elements[ i ] + "/blue", 0, &ok );
+ if ( !ok )
+ break;
+ break;
+ }
+ if ( !ok )
+ continue;
+ QFont f( family );
+ f.setPointSize( size );
+ f.setBold( bold );
+ f.setItalic( italic );
+ f.setUnderline( underline );
+ QColor c( red, green, blue );
+ ConfigStyle s;
+ s.font = f;
+ s.color = c;
+ styles.remove( elements[ i ] );
+ styles.insert( elements[ i ], s );
+ }
+ return styles;
+}
+
+void Config::saveStyles( const QMap<QString, ConfigStyle> &styles, const QString &path )
+{
+ QString elements[] = {
+ "Comment",
+ "Number",
+ "String",
+ "Type",
+ "Keyword",
+ "Preprocessor",
+ "Label",
+ "Standard",
+ QString::null
+ };
+
+ QSettings settings;
+ for ( int i = 0; elements[ i ] != QString::null; ++i ) {
+ settings.writeEntry( path + "/" + elements[ i ] + "/family", styles[ elements[ i ] ].font.family() );
+ settings.writeEntry( path + "/" + elements[ i ] + "/size", styles[ elements[ i ] ].font.pointSize() );
+ settings.writeEntry( path + "/" + elements[ i ] + "/bold", styles[ elements[ i ] ].font.bold() );
+ settings.writeEntry( path + "/" + elements[ i ] + "/italic", styles[ elements[ i ] ].font.italic() );
+ settings.writeEntry( path + "/" + elements[ i ] + "/underline", styles[ elements[ i ] ].font.underline() );
+ settings.writeEntry( path + "/" + elements[ i ] + "/red", styles[ elements[ i ] ].color.red() );
+ settings.writeEntry( path + "/" + elements[ i ] + "/green", styles[ elements[ i ] ].color.green() );
+ settings.writeEntry( path + "/" + elements[ i ] + "/blue", styles[ elements[ i ] ].color.blue() );
+ }
+}
+
+bool Config::completion( const QString &path )
+{
+ QSettings settings;
+ bool ret = settings.readBoolEntry( path + "/completion", TRUE );
+ return ret;
+}
+
+bool Config::wordWrap( const QString &path )
+{
+ QSettings settings;
+ bool ret = settings.readBoolEntry( path + "/wordWrap", TRUE );
+ return ret;
+}
+
+bool Config::parenMatching( const QString &path )
+{
+ QSettings settings;
+ bool ret = settings.readBoolEntry( path + "/parenMatching", TRUE );
+ return ret;
+}
+
+int Config::indentTabSize( const QString &path )
+{
+ QSettings settings;
+ int ret = settings.readNumEntry( path + "/indentTabSize", 8 );
+ return ret;
+}
+
+int Config::indentIndentSize( const QString &path )
+{
+ QSettings settings;
+ int ret = settings.readNumEntry( path + "/indentIndentSize", 4 );
+ return ret;
+}
+
+bool Config::indentKeepTabs( const QString &path )
+{
+ QSettings settings;
+ bool ret = settings.readBoolEntry( path + "/indentKeepTabs", TRUE );
+ return ret;
+}
+
+bool Config::indentAutoIndent( const QString &path )
+{
+ QSettings settings;
+ bool ret = settings.readBoolEntry( path + "/indentAutoIndent", TRUE );
+ return ret;
+}
+
+void Config::setCompletion( bool b, const QString &path )
+{
+ QSettings settings;
+ settings.writeEntry( path + "/completion", b );
+}
+
+void Config::setWordWrap( bool b, const QString &path )
+{
+ QSettings settings;
+ settings.writeEntry( path + "/wordWrap", b );
+}
+
+void Config::setParenMatching( bool b,const QString &path )
+{
+ QSettings settings;
+ settings.writeEntry( path + "/parenMatching", b );
+}
+
+void Config::setIndentTabSize( int s, const QString &path )
+{
+ QSettings settings;
+ settings.writeEntry( path + "/indentTabSize", s );
+}
+
+void Config::setIndentIndentSize( int s, const QString &path )
+{
+ QSettings settings;
+ settings.writeEntry( path + "/indentIndentSize", s );
+}
+
+void Config::setIndentKeepTabs( bool b, const QString &path )
+{
+ QSettings settings;
+ settings.writeEntry( path + "/indentKeepTabs", b );
+}
+
+void Config::setIndentAutoIndent( bool b, const QString &path )
+{
+ QSettings settings;
+ settings.writeEntry( path + "/indentAutoIndent", b );
+}
diff --git a/tools/designer/editor/conf.h b/tools/designer/editor/conf.h
new file mode 100644
index 0000000..fe5111f
--- /dev/null
+++ b/tools/designer/editor/conf.h
@@ -0,0 +1,75 @@
+/**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef CONF_H
+#define CONF_H
+
+#include <qfont.h>
+#include <qcolor.h>
+#include <qmap.h>
+
+struct ConfigStyle
+{
+ QFont font;
+ QColor color;
+
+ Q_DUMMY_COMPARISON_OPERATOR( ConfigStyle )
+};
+
+struct Config
+{
+ QMap<QString, ConfigStyle> styles;
+ bool hasCompletion, hasParenMatching, hasWordWrap;
+
+ static QMap<QString, ConfigStyle> defaultStyles();
+ static QMap<QString, ConfigStyle> readStyles( const QString &path );
+ static void saveStyles( const QMap<QString, ConfigStyle> &styles, const QString &path );
+ static bool completion( const QString &path );
+ static bool wordWrap( const QString &path );
+ static bool parenMatching( const QString &path );
+ static int indentTabSize( const QString &path );
+ static int indentIndentSize( const QString &path );
+ static bool indentKeepTabs( const QString &path );
+ static bool indentAutoIndent( const QString &path );
+
+ static void setCompletion( bool b, const QString &path );
+ static void setWordWrap( bool b, const QString &path );
+ static void setParenMatching( bool b,const QString &path );
+ static void setIndentTabSize( int s, const QString &path );
+ static void setIndentIndentSize( int s, const QString &path );
+ static void setIndentKeepTabs( bool b, const QString &path );
+ static void setIndentAutoIndent( bool b, const QString &path );
+
+};
+
+#endif
diff --git a/tools/designer/editor/editor.cpp b/tools/designer/editor/editor.cpp
new file mode 100644
index 0000000..e75f052
--- /dev/null
+++ b/tools/designer/editor/editor.cpp
@@ -0,0 +1,251 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "editor.h"
+#include "parenmatcher.h"
+#include <qfile.h>
+#include <private/qrichtext_p.h>
+#include "conf.h"
+#include <qapplication.h>
+#include <qpopupmenu.h>
+#include <qaccel.h>
+
+Editor::Editor( const QString &fn, QWidget *parent, const char *name )
+ : QTextEdit( parent, name ), hasError( FALSE )
+{
+ document()->setFormatter( new QTextFormatterBreakInWords );
+ if ( !fn.isEmpty() )
+ load( fn );
+ setHScrollBarMode( QScrollView::AlwaysOff );
+ setVScrollBarMode( QScrollView::AlwaysOn );
+ document()->setUseFormatCollection( FALSE );
+ parenMatcher = new ParenMatcher;
+ connect( this, SIGNAL( cursorPositionChanged( QTextCursor * ) ),
+ this, SLOT( cursorPosChanged( QTextCursor * ) ) );
+ cfg = new Config;
+ document()->addSelection( Error );
+ document()->addSelection( Step );
+ document()->setSelectionColor( Error, red );
+ document()->setSelectionColor( Step, yellow );
+ document()->setInvertSelectionText( Error, FALSE );
+ document()->setInvertSelectionText( Step, FALSE );
+ document()->addSelection( ParenMatcher::Match );
+ document()->addSelection( ParenMatcher::Mismatch );
+ document()->setSelectionColor( ParenMatcher::Match, QColor( 204, 232, 195 ) );
+ document()->setSelectionColor( ParenMatcher::Mismatch, Qt::magenta );
+ document()->setInvertSelectionText( ParenMatcher::Match, FALSE );
+ document()->setInvertSelectionText( ParenMatcher::Mismatch, FALSE );
+
+ accelComment = new QAccel( this );
+ accelComment->connectItem( accelComment->insertItem( ALT + Key_C ),
+ this, SLOT( commentSelection() ) );
+ accelUncomment = new QAccel( this );
+ accelUncomment->connectItem( accelUncomment->insertItem( ALT + Key_U ),
+ this, SLOT( uncommentSelection() ) );
+ editable = TRUE;
+}
+
+Editor::~Editor()
+{
+ delete cfg;
+ delete parenMatcher;
+}
+
+void Editor::cursorPosChanged( QTextCursor *c )
+{
+ if ( parenMatcher->match( c ) )
+ repaintChanged();
+ if ( hasError ) {
+ emit clearErrorMarker();
+ hasError = FALSE;
+ }
+}
+
+void Editor::load( const QString &fn )
+{
+ filename = fn;
+ QFile f( filename );
+ if ( !f.open( IO_ReadOnly ) )
+ return;
+ QCString txt;
+ txt.resize( f.size() );
+ f.readBlock( txt.data(), f.size() );
+ QString s( QString::fromLatin1( txt ) );
+ setText( s );
+}
+
+void Editor::save( const QString &fn )
+{
+ if ( !filename.isEmpty() )
+ filename = fn;
+}
+
+void Editor::configChanged()
+{
+ document()->invalidate();
+ viewport()->repaint( FALSE );
+}
+
+void Editor::setErrorSelection( int line )
+{
+ QTextParagraph *p = document()->paragAt( line );
+ if ( !p )
+ return;
+ QTextCursor c( document() );
+ c.setParagraph( p );
+ c.setIndex( 0 );
+ document()->removeSelection( Error );
+ document()->setSelectionStart( Error, c );
+ c.gotoLineEnd();
+ document()->setSelectionEnd( Error, c );
+ hasError = TRUE;
+ viewport()->repaint( FALSE );
+}
+
+void Editor::setStepSelection( int line )
+{
+ QTextParagraph *p = document()->paragAt( line );
+ if ( !p )
+ return;
+ QTextCursor c( document() );
+ c.setParagraph( p );
+ c.setIndex( 0 );
+ document()->removeSelection( Step );
+ document()->setSelectionStart( Step, c );
+ c.gotoLineEnd();
+ document()->setSelectionEnd( Step, c );
+ viewport()->repaint( FALSE );
+}
+
+void Editor::clearStepSelection()
+{
+ document()->removeSelection( Step );
+ viewport()->repaint( FALSE );
+}
+
+void Editor::doChangeInterval()
+{
+ emit intervalChanged();
+ QTextEdit::doChangeInterval();
+}
+
+void Editor::commentSelection()
+{
+ QTextParagraph *start = document()->selectionStartCursor( QTextDocument::Standard ).paragraph();
+ QTextParagraph *end = document()->selectionEndCursor( QTextDocument::Standard ).paragraph();
+ if ( !start || !end )
+ start = end = textCursor()->paragraph();
+ while ( start ) {
+ if ( start == end && textCursor()->index() == 0 )
+ break;
+ start->insert( 0, "//" );
+ if ( start == end )
+ break;
+ start = start->next();
+ }
+ document()->removeSelection( QTextDocument::Standard );
+ repaintChanged();
+ setModified( TRUE );
+}
+
+void Editor::uncommentSelection()
+{
+ QTextParagraph *start = document()->selectionStartCursor( QTextDocument::Standard ).paragraph();
+ QTextParagraph *end = document()->selectionEndCursor( QTextDocument::Standard ).paragraph();
+ if ( !start || !end )
+ start = end = textCursor()->paragraph();
+ while ( start ) {
+ if ( start == end && textCursor()->index() == 0 )
+ break;
+ while ( start->at( 0 )->c == '/' )
+ start->remove( 0, 1 );
+ if ( start == end )
+ break;
+ start = start->next();
+ }
+ document()->removeSelection( QTextDocument::Standard );
+ repaintChanged();
+ setModified( TRUE );
+}
+
+QPopupMenu *Editor::createPopupMenu( const QPoint &p )
+{
+ QPopupMenu *menu = QTextEdit::createPopupMenu( p );
+ menu->insertSeparator();
+ menu->insertItem( tr( "C&omment Code\tAlt+C" ), this, SLOT( commentSelection() ) );
+ menu->insertItem( tr( "Unco&mment Code\tAlt+U" ), this, SLOT( uncommentSelection() ) );
+ return menu;
+}
+
+bool Editor::eventFilter( QObject *o, QEvent *e )
+{
+ if ( ( e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut ) &&
+ ( o == this || o == viewport() ) ) {
+ accelUncomment->setEnabled( e->type() == QEvent::FocusIn );
+ accelComment->setEnabled( e->type() == QEvent::FocusIn );
+ }
+ return QTextEdit::eventFilter( o, e );
+}
+
+void Editor::doKeyboardAction( KeyboardAction action )
+{
+ if ( !editable )
+ return;
+ QTextEdit::doKeyboardAction( action );
+}
+
+void Editor::keyPressEvent( QKeyEvent *e )
+{
+ if ( editable ) {
+ QTextEdit::keyPressEvent( e );
+ return;
+ }
+
+ switch ( e->key() ) {
+ case Key_Left:
+ case Key_Right:
+ case Key_Up:
+ case Key_Down:
+ case Key_Home:
+ case Key_End:
+ case Key_Prior:
+ case Key_Next:
+ case Key_Direction_L:
+ case Key_Direction_R:
+ QTextEdit::keyPressEvent( e );
+ break;
+ default:
+ e->accept();
+ break;
+ }
+}
diff --git a/tools/designer/editor/editor.h b/tools/designer/editor/editor.h
new file mode 100644
index 0000000..1364bbb
--- /dev/null
+++ b/tools/designer/editor/editor.h
@@ -0,0 +1,111 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef EDITOR_H
+#define EDITOR_H
+
+#include <qtextedit.h>
+
+struct Config;
+class ParenMatcher;
+class EditorCompletion;
+class EditorBrowser;
+class QAccel;
+
+class Editor : public QTextEdit
+{
+ Q_OBJECT
+
+public:
+ enum Selection {
+ Error = 3,
+ Step = 4
+ };
+
+ Editor( const QString &fn, QWidget *parent, const char *name );
+ ~Editor();
+ virtual void load( const QString &fn );
+ virtual void save( const QString &fn );
+ QTextDocument *document() const { return QTextEdit::document(); }
+ void placeCursor( const QPoint &p, QTextCursor *c ) { QTextEdit::placeCursor( p, c ); }
+ void setDocument( QTextDocument *doc ) { QTextEdit::setDocument( doc ); }
+ QTextCursor *textCursor() const { return QTextEdit::textCursor(); }
+ void repaintChanged() { QTextEdit::repaintChanged(); }
+
+ virtual EditorCompletion *completionManager() { return 0; }
+ virtual EditorBrowser *browserManager() { return 0; }
+ virtual void configChanged();
+
+ Config *config() { return cfg; }
+
+ void setErrorSelection( int line );
+ void setStepSelection( int line );
+ void clearStepSelection();
+ void clearSelections();
+
+ virtual bool supportsErrors() const { return TRUE; }
+ virtual bool supportsBreakPoints() const { return TRUE; }
+ virtual void makeFunctionVisible( QTextParagraph * ) {}
+
+ void drawCursor( bool b ) { QTextEdit::drawCursor( b ); }
+
+ QPopupMenu *createPopupMenu( const QPoint &p );
+ bool eventFilter( QObject *o, QEvent *e );
+
+ void setEditable( bool b ) { editable = b; }
+
+protected:
+ void doKeyboardAction( KeyboardAction action );
+ void keyPressEvent( QKeyEvent *e );
+
+signals:
+ void clearErrorMarker();
+ void intervalChanged();
+
+private slots:
+ void cursorPosChanged( QTextCursor *c );
+ void doChangeInterval();
+ void commentSelection();
+ void uncommentSelection();
+
+protected:
+ ParenMatcher *parenMatcher;
+ QString filename;
+ Config *cfg;
+ bool hasError;
+ QAccel *accelComment, *accelUncomment;
+ bool editable;
+
+};
+
+#endif
diff --git a/tools/designer/editor/editor.pro b/tools/designer/editor/editor.pro
new file mode 100644
index 0000000..dc9235f
--- /dev/null
+++ b/tools/designer/editor/editor.pro
@@ -0,0 +1,40 @@
+TEMPLATE = lib
+CONFIG += qt warn_on staticlib
+CONFIG -= dll
+HEADERS = editor.h \
+ parenmatcher.h \
+ completion.h \
+ viewmanager.h \
+ markerwidget.h\
+ conf.h \
+ browser.h \
+ arghintwidget.h \
+ cindent.h
+
+SOURCES = editor.cpp \
+ parenmatcher.cpp \
+ completion.cpp \
+ viewmanager.cpp \
+ markerwidget.cpp \
+ conf.cpp \
+ browser.cpp \
+ arghintwidget.cpp \
+ cindent.cpp \
+ yyindent.cpp
+
+FORMS = preferences.ui
+
+TARGET = editor
+DESTDIR = ../../../lib
+VERSION = 1.0.0
+
+INCLUDEPATH += $$QT_SOURCE_TREE/tools/designer/interfaces
+
+target.path=$$libs.path
+
+INSTALLS += target
+
+unix {
+ QMAKE_CFLAGS += $$QMAKE_CFLAGS_SHLIB
+ QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_SHLIB
+}
diff --git a/tools/designer/editor/markerwidget.cpp b/tools/designer/editor/markerwidget.cpp
new file mode 100644
index 0000000..cabe39a
--- /dev/null
+++ b/tools/designer/editor/markerwidget.cpp
@@ -0,0 +1,491 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "markerwidget.h"
+#include "viewmanager.h"
+#include <private/qrichtext_p.h>
+#include "editor.h"
+#include <qpainter.h>
+#include <qpopupmenu.h>
+#include "paragdata.h"
+
+static const char * error_xpm[] = {
+"15 15 35 1",
+" c None",
+". c #FF0000",
+"+ c #F50F0F",
+"@ c #BF5F5F",
+"# c #FF1010",
+"$ c #FF7878",
+"% c #FF0A0A",
+"& c #FF0606",
+"* c #FF1414",
+"= c #FFFFFF",
+"- c #FFA3A3",
+"; c #FF0707",
+"> c #FF0202",
+", c #FF9898",
+"' c #FF8888",
+") c #D04747",
+"! c #FFA7A7",
+"~ c #FF9D9D",
+"{ c #FFB1B1",
+"] c #FF0C0C",
+"^ c #F90A0A",
+"/ c #FFB5B5",
+"( c #FF0909",
+"_ c #A08F8F",
+": c #FFACAC",
+"< c #FF0303",
+"[ c #9F8F8F",
+"} c #FB0606",
+"| c #9F9090",
+"1 c #CE4949",
+"2 c #999999",
+"3 c #FF1919",
+"4 c #F70C0C",
+"5 c #A38A8A",
+"6 c #B37272",
+" .... ",
+" ........ ",
+" .........+@ ",
+" ..#$%..&$*.+ ",
+" ..$=-;>,='..) ",
+"...%-=!~={]..^ ",
+"....;!==/(...._",
+"....>~==:<....[",
+"...&,=/:=!;..}|",
+" ..$={(<!='..12",
+" ..*']..;'3.45 ",
+" +........462 ",
+" @+......462 ",
+" )^..}152 ",
+" _[|2 "};
+
+static const char * breakpoint_xpm[] = {
+"15 15 3 1",
+" c None",
+". c #8B0000",
+"+ c #FFFFFF",
+" ....... ",
+" ......... ",
+" ........... ",
+" ............. ",
+"..+.+++.+..++..",
+".+.+.+.+.+.+.+.",
+".+...+.+.+.+.+.",
+"..+..+.+.+.++..",
+"...+.+.+.+.+...",
+".+.+.+.+.+.+...",
+"..+..+..+..+...",
+" ............. ",
+" ........... ",
+" ......... ",
+" ....... " };
+
+static const char * step_xpm[] = {
+"16 16 128 2",
+" c None",
+". c #B4B6BF",
+"+ c #7893D8",
+"@ c #8D95BF",
+"# c #B8BFC1",
+"$ c #B6D1E6",
+"% c #7193E6",
+"& c #8893C2",
+"* c #B3BDC4",
+"= c #AAD2EC",
+"- c #9AD0FF",
+"; c #6690EF",
+"> c #8894C8",
+", c #AFBAC4",
+"' c #95BFEC",
+") c #99CBFF",
+"! c #8EC3FF",
+"~ c #6D95F0",
+"{ c #8792CA",
+"] c #9DA7C3",
+"^ c #8BA2E3",
+"/ c #809AE0",
+"( c #8398D1",
+"_ c #93A0CC",
+": c #ACB3CB",
+"< c #B4B9C4",
+"[ c #B6BAC4",
+"} c #93A4CC",
+"| c #82B0F5",
+"1 c #8BBCFF",
+"2 c #8EC0FF",
+"3 c #8FC1FF",
+"4 c #6594F4",
+"5 c #7381CC",
+"6 c #81A7E9",
+"7 c #D0F5FF",
+"8 c #C1EBFF",
+"9 c #AEDAFF",
+"0 c #A2D1FC",
+"a c #A3C8F3",
+"b c #AACAE6",
+"c c #B4CFE9",
+"d c #ADCCF9",
+"e c #84B2FF",
+"f c #82B4FF",
+"g c #86B7FF",
+"h c #88B7FF",
+"i c #83B4FF",
+"j c #5F8AF3",
+"k c #7585C8",
+"l c #77A4F3",
+"m c #ABDFFF",
+"n c #9CCAFF",
+"o c #96C7FF",
+"p c #97C8FF",
+"q c #95C5FF",
+"r c #9DCCFF",
+"s c #A0CDFF",
+"t c #90C0FF",
+"u c #82AFFF",
+"v c #7FAFFF",
+"w c #7DAEFF",
+"x c #79AAFF",
+"y c #6C9EFF",
+"z c #4366EB",
+"A c #6894F2",
+"B c #93C6FF",
+"C c #82B3FF",
+"D c #7AABFF",
+"E c #73A5FF",
+"F c #71A3FF",
+"G c #6C9DFF",
+"H c #699BFF",
+"I c #76A8FF",
+"J c #7EB0FF",
+"K c #7BADFF",
+"L c #74A5FF",
+"M c #608BFF",
+"N c #3462FF",
+"O c #2444E5",
+"P c #577AE0",
+"Q c #5D90FF",
+"R c #4C7AFF",
+"S c #3B66FF",
+"T c #335CF9",
+"U c #365AF1",
+"V c #3858E5",
+"W c #3959E0",
+"X c #416CF9",
+"Y c #75A5FF",
+"Z c #78A9FF",
+"` c #74A4FF",
+" . c #6191FF",
+".. c #3059FF",
+"+. c #1B37F1",
+"@. c #6A75C7",
+"#. c #828BC1",
+"$. c #4358D8",
+"%. c #374BDA",
+"&. c #4759CA",
+"*. c #636CC4",
+"=. c #8489C0",
+"-. c #9DA1C1",
+";. c #A3A6BF",
+">. c #7486CB",
+",. c #6E98F5",
+"'. c #719EFF",
+"). c #608DFF",
+"!. c #315EFF",
+"~. c #1432F4",
+"{. c #5C63C8",
+"]. c #B1B4B9",
+"^. c #B3BABB",
+"/. c #ABB4C3",
+"(. c #7299E9",
+"_. c #5486FF",
+":. c #224EFF",
+"<. c #1733F2",
+"[. c #7079C5",
+"}. c #5C7DE9",
+"|. c #2450FF",
+"1. c #1B39EC",
+"2. c #7077C5",
+"3. c #3A54E1",
+"4. c #1E36EA",
+"5. c #858CBF",
+"6. c #525FCB",
+"7. c #727CBC",
+" ",
+" . + @ ",
+" # $ % & ",
+" * = - ; > ",
+" , ' ) ! ~ { ",
+"] ^ / ( _ : < [ } | 1 2 3 4 5 ",
+"6 7 8 9 0 a b c d e f g h i j k ",
+"l m n o p q r s t u v u w x y z ",
+"A B C D E F G H I J K D L M N O ",
+"P Q R S T U V W X Y Z ` ...+.@.",
+"#.$.%.&.*.=.-.;.>.,.'.).!.~.{. ",
+" ].^. /.(._.:.<.[. ",
+" }.|.1.2. ",
+" 3.4.5. ",
+" 6.7. ",
+" "};
+
+static const char *stack_frame_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #00c000",
+"................",
+".###............",
+".#####..........",
+".#######........",
+".#########......",
+".###########....",
+".#############..",
+".##############.",
+".##############.",
+".#############..",
+".###########....",
+".#########......",
+".#######........",
+".#####..........",
+".###............",
+"................"};
+
+static QPixmap *errorPixmap = 0;
+static QPixmap *breakpointPixmap = 0;
+static QPixmap *stepPixmap = 0;
+static QPixmap *stackFrame = 0;
+
+MarkerWidget::MarkerWidget( ViewManager *parent, const char*name )
+ : QWidget( parent, name, WRepaintNoErase | WStaticContents | WResizeNoErase ), viewManager( parent )
+{
+ if ( !errorPixmap ) {
+ errorPixmap = new QPixmap( error_xpm );
+ breakpointPixmap = new QPixmap( breakpoint_xpm );
+ stepPixmap = new QPixmap( step_xpm );
+ stackFrame = new QPixmap( stack_frame_xpm );
+ }
+}
+
+void MarkerWidget::paintEvent( QPaintEvent * )
+{
+ buffer.fill( backgroundColor() );
+
+ QTextParagraph *p = ( (Editor*)viewManager->currentView() )->document()->firstParagraph();
+ QPainter painter( &buffer );
+ int yOffset = ( (Editor*)viewManager->currentView() )->contentsY();
+ while ( p ) {
+ if ( !p->isVisible() ) {
+ p = p->next();
+ continue;
+ }
+ if ( p->rect().y() + p->rect().height() - yOffset < 0 ) {
+ p = p->next();
+ continue;
+ }
+ if ( p->rect().y() - yOffset > height() )
+ break;
+ if ( !((p->paragId() + 1) % 10) ) {
+ painter.save();
+ painter.setPen( colorGroup().dark() );
+ painter.drawText( 0, p->rect().y() - yOffset, width() - 20, p->rect().height(),
+ Qt::AlignRight | Qt::AlignTop, QString::number( p->paragId() + 1 ) );
+ painter.restore();
+ }
+ ParagData *paragData = (ParagData*)p->extraData();
+ if ( paragData ) {
+ switch ( paragData->marker ) {
+ case ParagData::Error:
+ painter.drawPixmap( 3, p->rect().y() +
+ ( p->rect().height() - errorPixmap->height() ) / 2 -
+ yOffset, *errorPixmap );
+ break;
+ case ParagData::Breakpoint:
+ painter.drawPixmap( 3, p->rect().y() +
+ ( p->rect().height() - breakpointPixmap->height() ) / 2 -
+ yOffset, *breakpointPixmap );
+ break;
+ default:
+ break;
+ }
+ switch ( paragData->lineState ) {
+ case ParagData::FunctionStart:
+ painter.setPen( colorGroup().foreground() );
+ painter.setBrush( colorGroup().base() );
+ painter.drawLine( width() - 11, p->rect().y() - yOffset,
+ width() - 11, p->rect().y() + p->rect().height() - yOffset );
+ painter.drawRect( width() - 15, p->rect().y() + ( p->rect().height() - 9 ) / 2 - yOffset, 9, 9 );
+ painter.drawLine( width() - 13, p->rect().y() + ( p->rect().height() - 9 ) / 2 - yOffset + 4,
+ width() - 9, p->rect().y() +
+ ( p->rect().height() - 9 ) / 2 - yOffset + 4 );
+ if ( !paragData->functionOpen )
+ painter.drawLine( width() - 11,
+ p->rect().y() + ( p->rect().height() - 9 ) / 2 - yOffset + 2,
+ width() - 11,
+ p->rect().y() +
+ ( p->rect().height() - 9 ) / 2 - yOffset + 6 );
+ break;
+ case ParagData::InFunction:
+ painter.setPen( colorGroup().foreground() );
+ painter.drawLine( width() - 11, p->rect().y() - yOffset,
+ width() - 11, p->rect().y() + p->rect().height() - yOffset );
+ break;
+ case ParagData::FunctionEnd:
+ painter.setPen( colorGroup().foreground() );
+ painter.drawLine( width() - 11, p->rect().y() - yOffset,
+ width() - 11, p->rect().y() + p->rect().height() - yOffset );
+ painter.drawLine( width() - 11, p->rect().y() + p->rect().height() - yOffset,
+ width() - 7, p->rect().y() + p->rect().height() - yOffset );
+ break;
+ default:
+ break;
+ }
+ if ( paragData->step )
+ painter.drawPixmap( 3, p->rect().y() +
+ ( p->rect().height() - stepPixmap->height() ) / 2 -
+ yOffset, *stepPixmap );
+ if ( paragData->stackFrame )
+ painter.drawPixmap( 3, p->rect().y() +
+ ( p->rect().height() - stackFrame->height() ) / 2 -
+ yOffset, *stackFrame );
+ }
+ p = p->next();
+ }
+ painter.end();
+
+ bitBlt( this, 0, 0, &buffer );
+}
+
+void MarkerWidget::resizeEvent( QResizeEvent *e )
+{
+ buffer.resize( e->size() );
+ QWidget::resizeEvent( e );
+}
+
+void MarkerWidget::mousePressEvent( QMouseEvent *e )
+{
+ if ( e->button() != LeftButton )
+ return;
+ bool supports = ( (Editor*)viewManager->currentView() )->supportsBreakPoints();
+ QTextParagraph *p = ( (Editor*)viewManager->currentView() )->document()->firstParagraph();
+ int yOffset = ( (Editor*)viewManager->currentView() )->contentsY();
+ while ( p ) {
+ if ( e->y() >= p->rect().y() - yOffset && e->y() <= p->rect().y() + p->rect().height() - yOffset ) {
+ QTextParagraphData *d = p->extraData();
+ if ( !d )
+ return;
+ ParagData *data = (ParagData*)d;
+ if ( supports && ( e->x() < width() - 15 ) ) {
+ if ( data->marker == ParagData::Breakpoint ) {
+ data->marker = ParagData::NoMarker;
+ } else {
+ bool ok = TRUE;
+ isBreakpointPossible( ok, ( (Editor*)viewManager->currentView() )->text(), p->paragId() );
+ if ( ok )
+ data->marker = ParagData::Breakpoint;
+ else
+ emit showMessage( tr( "<font color=red>Can't set breakpoint here!</font>" ) );
+ }
+ } else {
+ if ( data->lineState == ParagData::FunctionStart ) {
+ if ( data->functionOpen )
+ emit collapseFunction( p );
+ else
+ emit expandFunction( p );
+ }
+ }
+ break;
+ }
+ p = p->next();
+ }
+ doRepaint();
+ emit markersChanged();
+}
+
+void MarkerWidget::contextMenuEvent( QContextMenuEvent *e )
+{
+ QPopupMenu m( 0, "editor_breakpointsmenu" );
+
+ int toggleBreakPoint = 0;
+// int editBreakpoints = 0;
+
+ QTextParagraph *p = ( (Editor*)viewManager->currentView() )->document()->firstParagraph();
+ int yOffset = ( (Editor*)viewManager->currentView() )->contentsY();
+ bool supports = ( (Editor*)viewManager->currentView() )->supportsBreakPoints();
+ while ( p && supports ) {
+ if ( e->y() >= p->rect().y() - yOffset && e->y() <= p->rect().y() + p->rect().height() - yOffset ) {
+ if ( ( (ParagData*)p->extraData() )->marker == ParagData::Breakpoint )
+ toggleBreakPoint = m.insertItem( tr( "Clear Breakpoint\tF9" ) );
+ else
+ toggleBreakPoint = m.insertItem( tr( "Set Breakpoint\tF9" ) );
+// editBreakpoints = m.insertItem( tr( "Edit Breakpoints..." ) );
+ m.insertSeparator();
+ break;
+ }
+ p = p->next();
+ }
+
+ const int collapseAll = m.insertItem( tr( "Collapse All" ) );
+ const int expandAll = m.insertItem( tr( "Expand All" ) );
+ const int collapseFunctions = m.insertItem( tr( "Collapse all Functions" ) );
+ const int expandFunctions = m.insertItem( tr( "Expand all Functions" ) );
+
+ int res = m.exec( e->globalPos() );
+ if ( res == -1)
+ return;
+
+ if ( res == collapseAll ) {
+ emit collapse( TRUE );
+ } else if ( res == collapseFunctions ) {
+ emit collapse( FALSE );
+ } else if ( res == expandAll ) {
+ emit expand( TRUE );
+ } else if ( res == expandFunctions ) {
+ emit expand( FALSE );
+ } else if ( res == toggleBreakPoint ) {
+ if ( ( (ParagData*)p->extraData() )->marker == ParagData::Breakpoint ) {
+ ( (ParagData*)p->extraData() )->marker = ParagData::NoMarker;
+ } else {
+ bool ok;
+ isBreakpointPossible( ok, ( (Editor*)viewManager->currentView() )->text(), p->paragId() );
+ if ( ok )
+ ( (ParagData*)p->extraData() )->marker = ParagData::Breakpoint;
+ else
+ emit showMessage( tr( "<font color=red>Can't set breakpoint here!</font>" ) );
+ }
+// } else if ( res == editBreakpoints ) {
+// emit editBreakPoints();
+ }
+ doRepaint();
+ emit markersChanged();
+}
diff --git a/tools/designer/editor/markerwidget.h b/tools/designer/editor/markerwidget.h
new file mode 100644
index 0000000..f1d406e
--- /dev/null
+++ b/tools/designer/editor/markerwidget.h
@@ -0,0 +1,75 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef MARKERWIDGET_H
+#define MARKERWIDGET_H
+
+#include <qwidget.h>
+#include <qpixmap.h>
+
+class ViewManager;
+class QTextParagraph;
+
+class MarkerWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ MarkerWidget( ViewManager *parent, const char*name );
+
+signals:
+ void markersChanged();
+ void expandFunction( QTextParagraph *p );
+ void collapseFunction( QTextParagraph *p );
+ void collapse( bool all /*else only functions*/ );
+ void expand( bool all /*else only functions*/ );
+ void editBreakPoints();
+ void isBreakpointPossible( bool &possible, const QString &code, int line );
+ void showMessage( const QString &msg );
+
+public slots:
+ void doRepaint() { repaint( FALSE ); }
+
+protected:
+ void paintEvent( QPaintEvent *e );
+ void resizeEvent( QResizeEvent *e );
+ void mousePressEvent( QMouseEvent *e );
+ void contextMenuEvent( QContextMenuEvent *e );
+
+private:
+ QPixmap buffer;
+ ViewManager *viewManager;
+
+};
+
+#endif
diff --git a/tools/designer/editor/paragdata.h b/tools/designer/editor/paragdata.h
new file mode 100644
index 0000000..64bb050
--- /dev/null
+++ b/tools/designer/editor/paragdata.h
@@ -0,0 +1,65 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef PARAGDATA_H
+#define PARAGDATA_H
+
+#include "parenmatcher.h"
+#include <private/qrichtext_p.h>
+
+struct ParagData : public QTextParagraphData
+{
+public:
+ enum MarkerType { NoMarker, Error, Breakpoint };
+ enum LineState { FunctionStart, InFunction, FunctionEnd, Invalid };
+
+ ParagData() : lastLengthForCompletion( -1 ), marker( NoMarker ),
+ lineState( Invalid ), functionOpen( TRUE ), step( FALSE ), stackFrame( FALSE ) {}
+ ~ParagData() {}
+ void join( QTextParagraphData *data ) {
+ ParagData *d = (ParagData*)data;
+ if ( marker == NoMarker )
+ marker = d->marker;
+ lineState = d->lineState;
+ }
+ ParenList parenList;
+ int lastLengthForCompletion;
+ MarkerType marker;
+ LineState lineState;
+ bool functionOpen;
+ bool step;
+ bool stackFrame;
+
+};
+
+#endif
diff --git a/tools/designer/editor/parenmatcher.cpp b/tools/designer/editor/parenmatcher.cpp
new file mode 100644
index 0000000..ae7a3b5
--- /dev/null
+++ b/tools/designer/editor/parenmatcher.cpp
@@ -0,0 +1,215 @@
+/**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "parenmatcher.h"
+#include "paragdata.h"
+
+#include "qtextedit.h"
+#include <private/qrichtext_p.h>
+#include <qapplication.h>
+
+ParenMatcher::ParenMatcher()
+{
+ enabled = TRUE;
+}
+
+bool ParenMatcher::match( QTextCursor *cursor )
+{
+ if ( !enabled )
+ return FALSE;
+ bool ret = FALSE;
+
+ QChar c( cursor->paragraph()->at( cursor->index() )->c );
+ bool ok1 = FALSE;
+ bool ok2 = FALSE;
+ if ( c == '{' || c == '(' || c == '[' ) {
+ ok1 = checkOpenParen( cursor );
+ ret = ok1 || ret;
+ } else if ( cursor->index() > 0 ) {
+ c = cursor->paragraph()->at( cursor->index() - 1 )->c;
+ if ( c == '}' || c == ')' || c == ']' ) {
+ ok2 = checkClosedParen( cursor );
+ ret = ok2 || ret;
+ }
+ }
+
+ return ret;
+}
+
+bool ParenMatcher::checkOpenParen( QTextCursor *cursor )
+{
+ if ( !cursor->paragraph()->extraData() )
+ return FALSE;
+ ParenList parenList = ( (ParagData*)cursor->paragraph()->extraData() )->parenList;
+
+ Paren openParen, closedParen;
+ QTextParagraph *closedParenParag = cursor->paragraph();
+
+ int i = 0;
+ int ignore = 0;
+ bool foundOpen = FALSE;
+ QChar c = cursor->paragraph()->at( cursor->index() )->c;
+ for (;;) {
+ if ( !foundOpen ) {
+ if ( i >= (int)parenList.count() )
+ goto bye;
+ openParen = parenList[ i ];
+ if ( openParen.pos != cursor->index() ) {
+ ++i;
+ continue;
+ } else {
+ foundOpen = TRUE;
+ ++i;
+ }
+ }
+
+ if ( i >= (int)parenList.count() ) {
+ for (;;) {
+ closedParenParag = closedParenParag->next();
+ if ( !closedParenParag )
+ goto bye;
+ if ( closedParenParag->extraData() &&
+ ( (ParagData*)closedParenParag->extraData() )->parenList.count() > 0 ) {
+ parenList = ( (ParagData*)closedParenParag->extraData() )->parenList;
+ break;
+ }
+ }
+ i = 0;
+ }
+
+ closedParen = parenList[ i ];
+ if ( closedParen.type == Paren::Open ) {
+ ignore++;
+ ++i;
+ continue;
+ } else {
+ if ( ignore > 0 ) {
+ ignore--;
+ ++i;
+ continue;
+ }
+
+ int id = Match;
+ if ( c == '{' && closedParen.chr != '}' ||
+ c == '(' && closedParen.chr != ')' ||
+ c == '[' && closedParen.chr != ']' )
+ id = Mismatch;
+ cursor->document()->setSelectionStart( id, *cursor );
+ int tidx = cursor->index();
+ QTextParagraph *tstring = cursor->paragraph();
+ cursor->setParagraph( closedParenParag );
+ cursor->setIndex( closedParen.pos + 1 );
+ cursor->document()->setSelectionEnd( id, *cursor );
+ cursor->setParagraph( tstring );
+ cursor->setIndex( tidx );
+ return TRUE;
+ }
+ }
+
+ bye:
+ return FALSE;
+}
+
+bool ParenMatcher::checkClosedParen( QTextCursor *cursor )
+{
+ if ( !cursor->paragraph()->extraData() )
+ return FALSE;
+ ParenList parenList = ( (ParagData*)cursor->paragraph()->extraData() )->parenList;
+
+ Paren openParen, closedParen;
+ QTextParagraph *openParenParag = cursor->paragraph();
+
+ int i = (int)parenList.count() - 1;
+ int ignore = 0;
+ bool foundClosed = FALSE;
+ QChar c = cursor->paragraph()->at( cursor->index() - 1 )->c;
+ for (;;) {
+ if ( !foundClosed ) {
+ if ( i < 0 )
+ goto bye;
+ closedParen = parenList[ i ];
+ if ( closedParen.pos != cursor->index() - 1 ) {
+ --i;
+ continue;
+ } else {
+ foundClosed = TRUE;
+ --i;
+ }
+ }
+
+ if ( i < 0 ) {
+ for (;;) {
+ openParenParag = openParenParag->prev();
+ if ( !openParenParag )
+ goto bye;
+ if ( openParenParag->extraData() &&
+ ( (ParagData*)openParenParag->extraData() )->parenList.count() > 0 ) {
+ parenList = ( (ParagData*)openParenParag->extraData() )->parenList;
+ break;
+ }
+ }
+ i = (int)parenList.count() - 1;
+ }
+
+ openParen = parenList[ i ];
+ if ( openParen.type == Paren::Closed ) {
+ ignore++;
+ --i;
+ continue;
+ } else {
+ if ( ignore > 0 ) {
+ ignore--;
+ --i;
+ continue;
+ }
+
+ int id = Match;
+ if ( c == '}' && openParen.chr != '{' ||
+ c == ')' && openParen.chr != '(' ||
+ c == ']' && openParen.chr != '[' )
+ id = Mismatch;
+ cursor->document()->setSelectionStart( id, *cursor );
+ int tidx = cursor->index();
+ QTextParagraph *tstring = cursor->paragraph();
+ cursor->setParagraph( openParenParag );
+ cursor->setIndex( openParen.pos );
+ cursor->document()->setSelectionEnd( id, *cursor );
+ cursor->setParagraph( tstring );
+ cursor->setIndex( tidx );
+ return TRUE;
+ }
+ }
+
+ bye:
+ return FALSE;
+}
diff --git a/tools/designer/editor/parenmatcher.h b/tools/designer/editor/parenmatcher.h
new file mode 100644
index 0000000..9bb2568
--- /dev/null
+++ b/tools/designer/editor/parenmatcher.h
@@ -0,0 +1,78 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef PARENMATCHER_H
+#define PARENMATCHER_H
+
+#include <qstring.h>
+#include <qvaluelist.h>
+
+class QTextCursor;
+
+struct Paren
+{
+ Paren() : type( Open ), chr( ' ' ), pos( -1 ) {}
+ Paren( int t, const QChar &c, int p ) : type( (Type)t ), chr( c ), pos( p ) {}
+ enum Type { Open, Closed };
+ Type type;
+ QChar chr;
+ int pos;
+
+ Q_DUMMY_COMPARISON_OPERATOR( Paren )
+};
+
+typedef QValueList<Paren> ParenList;
+
+class ParenMatcher
+{
+public:
+ enum Selection {
+ Match = 1,
+ Mismatch
+ };
+
+ ParenMatcher();
+
+ virtual bool match( QTextCursor *c );
+
+ void setEnabled( bool b ) { enabled = b; }
+
+private:
+ bool checkOpenParen( QTextCursor *c );
+ bool checkClosedParen( QTextCursor *c );
+
+ bool enabled;
+
+};
+
+#endif
diff --git a/tools/designer/editor/preferences.ui b/tools/designer/editor/preferences.ui
new file mode 100644
index 0000000..5dc1d53
--- /dev/null
+++ b/tools/designer/editor/preferences.ui
@@ -0,0 +1,510 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>PreferencesBase</class>
+<comment>*********************************************************************
+** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+*********************************************************************</comment>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>PreferencesBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>362</width>
+ <height>396</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>6</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>GroupBox2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>S&amp;yntax Highlighting</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Element:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>listElements</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="1" rowspan="3" colspan="1">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>checkBold</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Bold</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" row="5" column="1">
+ <property name="name">
+ <cstring>buttonColor</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>comboFamily</cstring>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Family:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>comboFamily</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>checkUnderline</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Underline</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>spinSize</cstring>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>checkItalic</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Italic</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Change co&amp;lor:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>buttonColor</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Size:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>spinSize</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QListBox" row="1" column="0">
+ <item>
+ <property name="text">
+ <string>Comment</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Number</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>String</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Keyword</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Preprocessor</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Label</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Standard</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>listElements</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Preview:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>editPreview</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="3" column="0">
+ <property name="name">
+ <cstring>editPreview</cstring>
+ </property>
+ <property name="text">
+ <string>Some Text</string>
+ </property>
+ </widget>
+ <spacer row="4" column="1">
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>GroupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Optio&amp;ns</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkWordWrap</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Word Wrap</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkCompletion</cstring>
+ </property>
+ <property name="text">
+ <string>Comple&amp;tion</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkParenMatching</cstring>
+ </property>
+ <property name="text">
+ <string>Parentheses &amp;Matching</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox" row="1" column="1">
+ <property name="name">
+ <cstring>GroupBox3_2</cstring>
+ </property>
+ <property name="title">
+ <string>Indentation</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>spinTabSize</cstring>
+ </property>
+ <property name="value">
+ <number>8</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Tab Size:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>spinIndentSize</cstring>
+ </property>
+ <property name="value">
+ <number>4</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel2_3</cstring>
+ </property>
+ <property name="text">
+ <string>Indent Size:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkKeepTabs</cstring>
+ </property>
+ <property name="text">
+ <string>Keep Tabs</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkAutoIndent</cstring>
+ </property>
+ <property name="text">
+ <string>Auto Indent</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>spinSize</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>PreferencesBase</receiver>
+ <slot>sizeChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>checkBold</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PreferencesBase</receiver>
+ <slot>boldChanged(bool)</slot>
+ </connection>
+ <connection>
+ <sender>checkItalic</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PreferencesBase</receiver>
+ <slot>italicChanged(bool)</slot>
+ </connection>
+ <connection>
+ <sender>checkUnderline</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PreferencesBase</receiver>
+ <slot>underlineChanged(bool)</slot>
+ </connection>
+ <connection>
+ <sender>buttonColor</sender>
+ <signal>clicked()</signal>
+ <receiver>PreferencesBase</receiver>
+ <slot>colorClicked()</slot>
+ </connection>
+ <connection>
+ <sender>comboFamily</sender>
+ <signal>activated(const QString&amp;)</signal>
+ <receiver>PreferencesBase</receiver>
+ <slot>familyChanged(const QString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>listElements</sender>
+ <signal>highlighted(const QString&amp;)</signal>
+ <receiver>PreferencesBase</receiver>
+ <slot>elementChanged(const QString&amp;)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>listElements</tabstop>
+ <tabstop>editPreview</tabstop>
+ <tabstop>comboFamily</tabstop>
+ <tabstop>spinSize</tabstop>
+ <tabstop>checkBold</tabstop>
+ <tabstop>checkItalic</tabstop>
+ <tabstop>checkUnderline</tabstop>
+ <tabstop>checkWordWrap</tabstop>
+ <tabstop>checkCompletion</tabstop>
+ <tabstop>checkParenMatching</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">qmap.h</include>
+ <include location="local" impldecl="in declaration">conf.h</include>
+ <include location="global" impldecl="in implementation">qpalette.h</include>
+ <include location="global" impldecl="in implementation">qlineedit.h</include>
+ <include location="global" impldecl="in implementation">qpixmap.h</include>
+ <include location="global" impldecl="in implementation">qcombobox.h</include>
+ <include location="global" impldecl="in implementation">qfontdatabase.h</include>
+ <include location="local" impldecl="in implementation">editor.h</include>
+ <include location="global" impldecl="in implementation">qpushbutton.h</include>
+ <include location="global" impldecl="in implementation">qcheckbox.h</include>
+ <include location="global" impldecl="in implementation">qcolordialog.h</include>
+ <include location="global" impldecl="in implementation">qsettings.h</include>
+ <include location="local" impldecl="in implementation">preferences.ui.h</include>
+</includes>
+<variables>
+ <variable>QString path;</variable>
+ <variable>QMap&lt;QString, ConfigStyle&gt; styles;</variable>
+ <variable>ConfigStyle currentStyle;</variable>
+ <variable>QString currentElement;</variable>
+</variables>
+<slots>
+ <slot>init()</slot>
+ <slot>destroy()</slot>
+ <slot>colorClicked()</slot>
+ <slot>reInit()</slot>
+ <slot>save()</slot>
+ <slot>updatePreview()</slot>
+ <slot>boldChanged( bool b )</slot>
+ <slot>elementChanged( const QString &amp; element )</slot>
+ <slot>familyChanged( const QString &amp; f )</slot>
+ <slot>italicChanged( bool b )</slot>
+ <slot>setColorPixmap( const QColor &amp; c )</slot>
+ <slot>setPath( const QString &amp; p )</slot>
+ <slot>sizeChanged( int s )</slot>
+ <slot>underlineChanged( bool b )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/tools/designer/editor/preferences.ui.h b/tools/designer/editor/preferences.ui.h
new file mode 100644
index 0000000..b175ca8
--- /dev/null
+++ b/tools/designer/editor/preferences.ui.h
@@ -0,0 +1,181 @@
+/**********************************************************************
+** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+void PreferencesBase::init()
+{
+ QFontDatabase fdb;
+ comboFamily->insertStringList( fdb.families() );
+ listElements->setCurrentItem( listElements->firstItem() );
+ currentElement = "";
+}
+
+void PreferencesBase::destroy()
+{
+
+}
+
+void PreferencesBase::colorClicked()
+{
+ QColor c = QColorDialog::getColor( currentStyle.color, this, "editor_getcolor_dlg" );
+ if ( c.isValid() ) {
+ currentStyle.color = c;
+ setColorPixmap( c );
+ }
+}
+
+void PreferencesBase::reInit()
+{
+ styles = Config::readStyles( path );
+ currentElement = "";
+ elementChanged( "Comment" );
+ for ( int i = 0; i < comboFamily->count(); ++i ) {
+ if ( listElements->text( i ) == "Comment" ) {
+ listElements->setCurrentItem( i );
+ break;
+ }
+ }
+ checkWordWrap->setChecked( Config::wordWrap( path ) );
+ checkCompletion->setChecked( Config::completion( path ) );
+ checkParenMatching->setChecked( Config::parenMatching( path ) );
+ spinTabSize->setValue( Config::indentTabSize( path ) );
+ spinIndentSize->setValue( Config::indentIndentSize( path ) );
+ checkKeepTabs->setChecked( Config::indentKeepTabs( path ) );
+ checkAutoIndent->setChecked( Config::indentAutoIndent( path ) );
+}
+
+void PreferencesBase::save()
+{
+ if ( !currentElement.isEmpty() ) {
+ styles.remove( currentElement );
+ styles.insert( currentElement, currentStyle );
+ currentElement = "";
+ }
+
+ QSettings settings;
+ Config::saveStyles( styles, path );
+ Config::setWordWrap( checkWordWrap->isChecked(), path );
+ Config::setCompletion( checkCompletion->isChecked(), path );
+ Config::setParenMatching( checkParenMatching->isChecked(), path );
+ Config::setIndentTabSize( spinTabSize->value(), path );
+ Config::setIndentIndentSize( spinIndentSize->value(), path );
+ Config::setIndentKeepTabs( checkKeepTabs->isChecked(), path );
+ Config::setIndentAutoIndent( checkAutoIndent->isChecked(), path );
+}
+
+void PreferencesBase::updatePreview()
+{
+ editPreview->setFont( currentStyle.font );
+ QPalette pal = editPreview->palette();
+ pal.setColor( QPalette::Active, QColorGroup::Text, currentStyle.color );
+ pal.setColor( QPalette::Active, QColorGroup::Foreground, currentStyle.color );
+ editPreview->setPalette( pal );
+}
+
+void PreferencesBase::boldChanged( bool b )
+{
+ currentStyle.font.setBold( b );
+ updatePreview();
+}
+
+void PreferencesBase::elementChanged( const QString &element )
+{
+ if ( !currentElement.isEmpty() ) {
+ styles.remove( currentElement );
+ styles.insert( currentElement, currentStyle );
+ currentElement = "";
+ }
+ QMap<QString, ConfigStyle>::Iterator it = styles.find( element );
+ if ( it == styles.end() )
+ return;
+ ConfigStyle s = *it;
+ currentStyle = s;
+ comboFamily->lineEdit()->setText( s.font.family() );
+ spinSize->setValue( s.font.pointSize() );
+ checkBold->setChecked( s.font.bold() );
+ checkItalic->setChecked( s.font.italic() );
+ checkUnderline->setChecked( s.font.underline() );
+ setColorPixmap( s.color );
+ currentElement = element;
+ updatePreview();
+}
+
+void PreferencesBase::familyChanged( const QString &f )
+{
+ QString oldFamily = currentStyle.font.family();
+ currentStyle.font.setFamily( f );
+ if ( currentElement == "Standard" ) {
+ for ( QMap<QString, ConfigStyle>::Iterator it = styles.begin(); it != styles.end(); ++it ) {
+ if ( (*it).font.family() == oldFamily )
+ (*it).font.setFamily( f );
+ }
+ }
+ updatePreview();
+}
+
+void PreferencesBase::italicChanged( bool b )
+{
+ currentStyle.font.setItalic( b );
+ updatePreview();
+}
+
+void PreferencesBase::setColorPixmap( const QColor &c )
+{
+ QPixmap pm( 20, 20 );
+ pm.fill( c );
+ buttonColor->setPixmap( pm );
+ updatePreview();
+}
+
+void PreferencesBase::setPath( const QString &p )
+{
+ path = p;
+}
+
+void PreferencesBase::sizeChanged( int s )
+{
+ int oldSize = currentStyle.font.pointSize();
+ currentStyle.font.setPointSize( s );
+ if ( currentElement == "Standard" ) {
+ for ( QMap<QString, ConfigStyle>::Iterator it = styles.begin(); it != styles.end(); ++it ) {
+ if ( (*it).font.pointSize() == oldSize )
+ (*it).font.setPointSize( s );
+ }
+ }
+ updatePreview();
+}
+
+void PreferencesBase::underlineChanged( bool b )
+{
+ currentStyle.font.setUnderline( b );
+ updatePreview();
+}
diff --git a/tools/designer/editor/viewmanager.cpp b/tools/designer/editor/viewmanager.cpp
new file mode 100644
index 0000000..cc6f634
--- /dev/null
+++ b/tools/designer/editor/viewmanager.cpp
@@ -0,0 +1,276 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "viewmanager.h"
+#include "editor.h"
+#include "markerwidget.h"
+#include <qlayout.h>
+#include <private/qrichtext_p.h>
+#include "paragdata.h"
+#include <qobjectlist.h>
+#include <qlabel.h>
+#include <qtimer.h>
+
+ViewManager::ViewManager( QWidget *parent, const char *name )
+ : QWidget( parent, name ), curView( 0 )
+{
+ QHBoxLayout *l = new QHBoxLayout( this );
+ markerWidget = new MarkerWidget( this, "editor_markerwidget" );
+ connect( markerWidget, SIGNAL( markersChanged() ),
+ this, SIGNAL( markersChanged() ) );
+ connect( markerWidget, SIGNAL( collapseFunction( QTextParagraph * ) ),
+ this, SIGNAL( collapseFunction( QTextParagraph * ) ) );
+ connect( markerWidget, SIGNAL( expandFunction( QTextParagraph * ) ),
+ this, SIGNAL( expandFunction( QTextParagraph * ) ) );
+ connect( markerWidget, SIGNAL( collapse( bool ) ),
+ this, SIGNAL( collapse( bool ) ) );
+ connect( markerWidget, SIGNAL( expand( bool ) ),
+ this, SIGNAL( expand( bool ) ) );
+ connect( markerWidget, SIGNAL( editBreakPoints() ),
+ this, SIGNAL( editBreakPoints() ) );
+ connect( markerWidget, SIGNAL( isBreakpointPossible( bool&, const QString &, int ) ),
+ this, SIGNAL( isBreakpointPossible( bool&, const QString &, int ) ) );
+ connect( markerWidget, SIGNAL( showMessage( const QString & ) ),
+ this, SLOT( showMessage( const QString & ) ) );
+ messageTimer = new QTimer( this );
+ connect( messageTimer, SIGNAL( timeout() ), this, SLOT( clearStatusBar() ) );
+ markerWidget->setFixedWidth( fontMetrics().width( "0000" ) + 20 );
+ l->addWidget( markerWidget );
+ layout = new QVBoxLayout( l );
+}
+
+void ViewManager::addView( QWidget *view )
+{
+ layout->addWidget( view );
+ curView = view;
+ connect( ( (Editor*)curView )->verticalScrollBar(), SIGNAL( valueChanged( int ) ),
+ markerWidget, SLOT( doRepaint() ) );
+ connect( (Editor*)curView, SIGNAL( textChanged() ),
+ markerWidget, SLOT( doRepaint() ) );
+ connect( (Editor*)curView, SIGNAL( clearErrorMarker() ),
+ this, SLOT( clearErrorMarker() ) );
+ posLabel = new QLabel( this, "editor_poslabel" );
+ posLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight );
+ posLabel->setText( " Line: 1 Col: 1" );
+ posLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
+ posLabel->setLineWidth( 1 );
+ posLabel->setFixedHeight( posLabel->fontMetrics().height() );
+ layout->addWidget( posLabel );
+ connect( curView, SIGNAL( cursorPositionChanged( int, int ) ),
+ this, SLOT( cursorPositionChanged( int, int ) ) );
+}
+
+QWidget *ViewManager::currentView() const
+{
+ return curView;
+}
+
+void ViewManager::childEvent( QChildEvent *e )
+{
+ if ( e->type() == QEvent::ChildInserted && ::qt_cast<Editor*>(e->child()) )
+ addView( (QWidget*)e->child() );
+ QWidget::childEvent( e );
+}
+
+void ViewManager::setError( int line )
+{
+ QTextParagraph *p = ( (Editor*)curView )->document()->paragAt( line );
+ if ( p ) {
+ ( (Editor*)curView )->setErrorSelection( line );
+ ( (Editor*)curView )->setCursorPosition( line, 0 );
+ ( (Editor*)curView )->viewport()->setFocus();
+ ( (Editor*)curView )->makeFunctionVisible( p );
+ ParagData *paragData = (ParagData*)p->extraData();
+ if ( !paragData )
+ paragData = new ParagData;
+ paragData->marker = ParagData::Error;
+ p->setExtraData( paragData );
+ markerWidget->doRepaint();
+ }
+}
+
+void ViewManager::setStep( int line )
+{
+ QTextParagraph *p = ( (Editor*)curView )->document()->firstParagraph();
+ while ( p ) {
+ if ( p->extraData() )
+ ( (ParagData*)p->extraData() )->step = FALSE;
+ p = p->next();
+ }
+ p = ( (Editor*)curView )->document()->paragAt( line );
+ if ( p ) {
+ ( (Editor*)curView )->setStepSelection( line );
+ ( (Editor*)curView )->setCursorPosition( line, 0 );
+ ( (Editor*)curView )->viewport()->setFocus();
+ ( (Editor*)curView )->makeFunctionVisible( p );
+ ParagData *paragData = (ParagData*)p->extraData();
+ if ( !paragData )
+ paragData = new ParagData;
+ paragData->step = TRUE;
+ p->setExtraData( paragData );
+ markerWidget->doRepaint();
+ }
+}
+
+void ViewManager::clearStep()
+{
+ ( (Editor*)curView )->clearStepSelection();
+ QTextParagraph *p = ( (Editor*)curView )->document()->firstParagraph();
+ while ( p ) {
+ if ( p->extraData() )
+ ( (ParagData*)p->extraData() )->step = FALSE;
+ p = p->next();
+ }
+ markerWidget->doRepaint();
+}
+
+void ViewManager::setStackFrame( int line )
+{
+ QTextParagraph *p = ( (Editor*)curView )->document()->paragAt( line );
+ if ( p ) {
+ ( (Editor*)curView )->sync();
+ ( (Editor*)curView )->setCursorPosition( line, 0 );
+ ( (Editor*)curView )->ensureCursorVisible();
+ ( (Editor*)curView )->viewport()->setFocus();
+ ( (Editor*)curView )->makeFunctionVisible( p );
+ ParagData *paragData = (ParagData*)p->extraData();
+ if ( !paragData )
+ paragData = new ParagData;
+ paragData->stackFrame = TRUE;
+ p->setExtraData( paragData );
+ markerWidget->doRepaint();
+ }
+}
+
+void ViewManager::clearStackFrame()
+{
+ QTextParagraph *p = ( (Editor*)curView )->document()->firstParagraph();
+ while ( p ) {
+ if ( p->extraData() ) {
+ ( (ParagData*)p->extraData() )->stackFrame = FALSE;
+ if ( ( (ParagData*)p->extraData() )->marker == ParagData::Error )
+ ( (ParagData*)p->extraData() )->marker = ParagData::NoMarker;
+ }
+ p = p->next();
+ }
+ markerWidget->doRepaint();
+}
+
+void ViewManager::resizeEvent( QResizeEvent *e )
+{
+ QWidget::resizeEvent( e );
+ markerWidget->doRepaint();
+}
+
+void ViewManager::clearErrorMarker()
+{
+ QTextParagraph *p = ( (Editor*)curView )->document()->firstParagraph();
+ while ( p ) {
+ if ( p->extraData() )
+ ( (ParagData*)p->extraData() )->marker = ParagData::NoMarker;
+ p = p->next();
+ }
+ markerWidget->doRepaint();
+}
+
+void ViewManager::setBreakPoints( const QValueList<uint> &l )
+{
+ QTextParagraph *p = ( (Editor*)curView )->document()->firstParagraph();
+ int i = 0;
+ while ( p ) {
+ if ( l.find( i ) != l.end() ) {
+ if ( !p->extraData() ) {
+ ParagData *data = new ParagData;
+ p->setExtraData( data );
+ }
+ ParagData *data = (ParagData*)p->extraData();
+ data->marker = ParagData::Breakpoint;
+ } else if ( p->extraData() ) {
+ ParagData *data = (ParagData*)p->extraData();
+ data->marker = ParagData::NoMarker;
+ }
+ p = p->next();
+ ++i;
+ }
+ markerWidget->doRepaint();
+}
+
+QValueList<uint> ViewManager::breakPoints() const
+{
+ QValueList<uint> l;
+ int i = 0;
+ QTextParagraph *p = ( (Editor*)curView )->document()->firstParagraph();
+ while ( p ) {
+ if ( p->extraData() &&
+ ( (ParagData*)p->extraData() )->marker == ParagData::Breakpoint )
+ l << i;
+ p = p->next();
+ ++i;
+ }
+ return l;
+}
+
+void ViewManager::showMarkerWidget( bool b )
+{
+ if ( b )
+ markerWidget->show();
+ else
+ markerWidget->hide();
+}
+
+void ViewManager::emitMarkersChanged()
+{
+ emit markersChanged();
+}
+
+void ViewManager::cursorPositionChanged( int row, int col )
+{
+ posLabel->setText( QString( " Line: %1 Col: %2" ).arg( row + 1 ).arg( col + 1 ) );
+}
+
+void ViewManager::showMessage( const QString &msg )
+{
+ int row;
+ int col;
+ ( (QTextEdit*)currentView() )->getCursorPosition( &row, &col );
+ posLabel->setText( msg );
+ messageTimer->start( 1000, TRUE );
+}
+
+void ViewManager::clearStatusBar()
+{
+ int row;
+ int col;
+ ( (QTextEdit*)currentView() )->getCursorPosition( &row, &col );
+ posLabel->setText( QString( " Line: %1 Col: %2" ).arg( row + 1 ).arg( col + 1 ) );
+}
diff --git a/tools/designer/editor/viewmanager.h b/tools/designer/editor/viewmanager.h
new file mode 100644
index 0000000..72d9859
--- /dev/null
+++ b/tools/designer/editor/viewmanager.h
@@ -0,0 +1,100 @@
+ /**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef VIEWMANAGER_H
+#define VIEWMANAGER_H
+
+#include <qwidget.h>
+#include <qvaluelist.h>
+
+class QChildEvent;
+class MarkerWidget;
+class QVBoxLayout;
+class QDockArea;
+class QTextParagraph;
+class QLabel;
+class QTimer;
+
+class ViewManager : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ViewManager( QWidget *parent, const char *name );
+
+ void addView( QWidget *view );
+ QWidget *currentView() const;
+ void showMarkerWidget( bool );
+
+ void setError( int line );
+ void setStep( int line );
+ void setStackFrame( int line );
+ void clearStep();
+ void clearStackFrame();
+ void setBreakPoints( const QValueList<uint> &l );
+ QValueList<uint> breakPoints() const;
+
+ void emitMarkersChanged();
+ MarkerWidget *marker_widget() const { return markerWidget; }
+
+signals:
+ void markersChanged();
+ void expandFunction( QTextParagraph *p );
+ void collapseFunction( QTextParagraph *p );
+ void collapse( bool all /*else only functions*/ );
+ void expand( bool all /*else only functions*/ );
+ void editBreakPoints();
+ void isBreakpointPossible( bool &possible, const QString &code, int line );
+
+protected slots:
+ void clearErrorMarker();
+ void cursorPositionChanged( int row, int col );
+ void showMessage( const QString &msg );
+ void clearStatusBar();
+
+protected:
+ void childEvent( QChildEvent *e );
+ void resizeEvent( QResizeEvent *e );
+
+private:
+ QWidget *curView;
+ MarkerWidget *markerWidget;
+ QVBoxLayout *layout;
+ QDockArea *dockArea;
+ QLabel *posLabel;
+ QString extraText;
+ QTimer *messageTimer;
+
+};
+
+#endif
diff --git a/tools/designer/editor/yyindent.cpp b/tools/designer/editor/yyindent.cpp
new file mode 100644
index 0000000..df9a78f
--- /dev/null
+++ b/tools/designer/editor/yyindent.cpp
@@ -0,0 +1,1170 @@
+/**********************************************************************
+** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+/*
+ This file is a self-contained interactive indenter for C++ and Qt
+ Script.
+
+ The general problem of indenting a C++ program is ill posed. On the
+ one hand, an indenter has to analyze programs written in a
+ free-form formal language that is best described in terms of
+ tokens, not characters, not lines. On the other hand, indentation
+ applies to lines and white space characters matter, and otherwise
+ the programs to indent are formally invalid in general, as they are
+ begin edited.
+
+ The approach taken here works line by line. We receive a program
+ consisting of N lines or more, and we want to compute the
+ indentation appropriate for the Nth line. Lines beyond the Nth
+ lines are of no concern to us, so for simplicity we pretend the
+ program has exactly N lines and we call the Nth line the "bottom
+ line". Typically, we have to indent the bottom line when it's still
+ empty, so we concentrate our analysis on the N - 1 lines that
+ precede.
+
+ By inspecting the (N - 1)-th line, the (N - 2)-th line, ...
+ backwards, we determine the kind of the bottom line and indent it
+ accordingly.
+
+ * The bottom line is a comment line. See
+ bottomLineStartsInCComment() and
+ indentWhenBottomLineStartsInCComment().
+ * The bottom line is a continuation line. See isContinuationLine()
+ and indentForContinuationLine().
+ * The bottom line is a standalone line. See
+ indentForStandaloneLine().
+
+ Certain tokens that influence the indentation, notably braces, are
+ looked for in the lines. This is done by simple string comparison,
+ without a real tokenizer. Confusing constructs such as comments and
+ string literals are removed beforehand.
+*/
+
+#include <qregexp.h>
+
+/* qmake ignore Q_OBJECT */
+
+/*
+ The indenter avoids getting stuck in almost infinite loops by
+ imposing arbitrary limits on the number of lines it analyzes when
+ looking for a construct.
+
+ For example, the indenter never considers more than BigRoof lines
+ backwards when looking for the start of a C-style comment.
+*/
+static const int SmallRoof = 40;
+static const int BigRoof = 400;
+
+/*
+ The indenter supports a few parameters:
+
+ * ppHardwareTabSize is the size of a '\t' in your favorite editor.
+ * ppIndentSize is the size of an indentation, or software tab
+ size.
+ * ppContinuationIndentSize is the extra indent for a continuation
+ line, when there is nothing to align against on the previous
+ line.
+ * ppCommentOffset is the indentation within a C-style comment,
+ when it cannot be picked up.
+*/
+
+static int ppHardwareTabSize = 8;
+static int ppIndentSize = 4;
+static int ppContinuationIndentSize = 8;
+
+static const int ppCommentOffset = 2;
+
+void setTabSize( int size )
+{
+ ppHardwareTabSize = size;
+}
+
+void setIndentSize( int size )
+{
+ ppIndentSize = size;
+ ppContinuationIndentSize = 2 * size;
+}
+
+static QRegExp *literal = 0;
+static QRegExp *label = 0;
+static QRegExp *inlineCComment = 0;
+static QRegExp *braceX = 0;
+static QRegExp *iflikeKeyword = 0;
+
+/*
+ Returns the first non-space character in the string t, or
+ QChar::null if the string is made only of white space.
+*/
+static QChar firstNonWhiteSpace( const QString& t )
+{
+ int i = 0;
+ while ( i < (int) t.length() ) {
+ if ( !t[i].isSpace() )
+ return t[i];
+ i++;
+ }
+ return QChar::null;
+}
+
+/*
+ Returns TRUE if string t is made only of white space; otherwise
+ returns FALSE.
+*/
+static bool isOnlyWhiteSpace( const QString& t )
+{
+ return firstNonWhiteSpace( t ).isNull();
+}
+
+/*
+ Assuming string t is a line, returns the column number of a given
+ index. Column numbers and index are identical for strings that don't
+ contain '\t's.
+*/
+int columnForIndex( const QString& t, int index )
+{
+ int col = 0;
+ if ( index > (int) t.length() )
+ index = t.length();
+
+ for ( int i = 0; i < index; i++ ) {
+ if ( t[i] == QChar('\t') ) {
+ col = ( (col / ppHardwareTabSize) + 1 ) * ppHardwareTabSize;
+ } else {
+ col++;
+ }
+ }
+ return col;
+}
+
+/*
+ Returns the indentation size of string t.
+*/
+int indentOfLine( const QString& t )
+{
+ return columnForIndex( t, t.find(firstNonWhiteSpace(t)) );
+}
+
+/*
+ Replaces t[k] by ch, unless t[k] is '\t'. Tab characters are better
+ left alone since they break the "index equals column" rule. No
+ provisions are taken against '\n' or '\r', which shouldn't occur in
+ t anyway.
+*/
+static inline void eraseChar( QString& t, int k, QChar ch )
+{
+ if ( t[k] != '\t' )
+ t[k] = ch;
+}
+
+/*
+ Removes some nefast constructs from a code line and returns the
+ resulting line.
+*/
+static QString trimmedCodeLine( const QString& t )
+{
+ QString trimmed = t;
+ int k;
+
+ /*
+ Replace character and string literals by X's, since they may
+ contain confusing characters (such as '{' and ';'). "Hello!" is
+ replaced by XXXXXXXX. The literals are rigourously of the same
+ length before and after; otherwise, we would break alignment of
+ continuation lines.
+ */
+ k = 0;
+ while ( (k = trimmed.find(*literal, k)) != -1 ) {
+ for ( int i = 0; i < literal->matchedLength(); i++ )
+ eraseChar( trimmed, k + i, 'X' );
+ k += literal->matchedLength();
+ }
+
+ /*
+ Replace inline C-style comments by spaces. Other comments are
+ handled elsewhere.
+ */
+ k = 0;
+ while ( (k = trimmed.find(*inlineCComment, k)) != -1 ) {
+ for ( int i = 0; i < inlineCComment->matchedLength(); i++ )
+ eraseChar( trimmed, k + i, ' ' );
+ k += inlineCComment->matchedLength();
+ }
+
+ /*
+ Replace goto and switch labels by whitespace, but be careful
+ with this case:
+
+ foo1: bar1;
+ bar2;
+ */
+ while ( trimmed.findRev(':') != -1 && trimmed.find(*label) != -1 ) {
+ QString cap1 = label->cap( 1 );
+ int pos1 = label->pos( 1 );
+ int stop = cap1.length();
+
+ if ( pos1 + stop < (int) trimmed.length() && ppIndentSize < stop )
+ stop = ppIndentSize;
+
+ int i = 0;
+ while ( i < stop ) {
+ eraseChar( trimmed, pos1 + i, ' ' );
+ i++;
+ }
+ while ( i < (int) cap1.length() ) {
+ eraseChar( trimmed, pos1 + i, ';' );
+ i++;
+ }
+ }
+
+ /*
+ Remove C++-style comments.
+ */
+ k = trimmed.find( "//" );
+ if ( k != -1 )
+ trimmed.truncate( k );
+
+ return trimmed;
+}
+
+/*
+ Returns '(' if the last parenthesis is opening, ')' if it is
+ closing, and QChar::null if there are no parentheses in t.
+*/
+static inline QChar lastParen( const QString& t )
+{
+ int i = t.length();
+ while ( i > 0 ) {
+ i--;
+ if ( t[i] == QChar('(') || t[i] == QChar(')') )
+ return t[i];
+ }
+ return QChar::null;
+}
+
+/*
+ Returns TRUE if typedIn the same as okayCh or is null; otherwise
+ returns FALSE.
+*/
+static inline bool okay( QChar typedIn, QChar okayCh )
+{
+ return typedIn == QChar::null || typedIn == okayCh;
+}
+
+/*
+ The "linizer" is a group of functions and variables to iterate
+ through the source code of the program to indent. The program is
+ given as a list of strings, with the bottom line being the line to
+ indent. The actual program might contain extra lines, but those are
+ uninteresting and not passed over to us.
+*/
+
+struct LinizerState
+{
+ QString line;
+ int braceDepth;
+ bool leftBraceFollows;
+
+ QStringList::ConstIterator iter;
+ bool inCComment;
+ bool pendingRightBrace;
+};
+
+static QStringList *yyProgram = 0;
+static LinizerState *yyLinizerState = 0;
+
+// shorthands
+static const QString *yyLine = 0;
+static const int *yyBraceDepth = 0;
+static const bool *yyLeftBraceFollows = 0;
+
+/*
+ Saves and restores the state of the global linizer. This enables
+ backtracking.
+*/
+#define YY_SAVE() \
+ LinizerState savedState = *yyLinizerState
+#define YY_RESTORE() \
+ *yyLinizerState = savedState
+
+/*
+ Advances to the previous line in yyProgram and update yyLine
+ accordingly. yyLine is cleaned from comments and other damageable
+ constructs. Empty lines are skipped.
+*/
+static bool readLine()
+{
+ int k;
+
+ yyLinizerState->leftBraceFollows =
+ ( firstNonWhiteSpace(yyLinizerState->line) == QChar('{') );
+
+ do {
+ if ( yyLinizerState->iter == yyProgram->begin() ) {
+ yyLinizerState->line = QString::null;
+ return FALSE;
+ }
+
+ --yyLinizerState->iter;
+ yyLinizerState->line = *yyLinizerState->iter;
+
+ yyLinizerState->line = trimmedCodeLine( yyLinizerState->line );
+
+ /*
+ Remove C-style comments that span multiple lines. If the
+ bottom line starts in a C-style comment, we are not aware
+ of that and eventually yyLine will contain a slash-aster.
+
+ Notice that both if's can be executed, since
+ yyLinizerState->inCComment is potentially set to FALSE in
+ the first if. The order of the if's is also important.
+ */
+
+ if ( yyLinizerState->inCComment ) {
+ QString slashAster( "/*" );
+
+ k = yyLinizerState->line.find( slashAster );
+ if ( k == -1 ) {
+ yyLinizerState->line = QString::null;
+ } else {
+ yyLinizerState->line.truncate( k );
+ yyLinizerState->inCComment = FALSE;
+ }
+ }
+
+ if ( !yyLinizerState->inCComment ) {
+ QString asterSlash( "*/" );
+
+ k = yyLinizerState->line.find( asterSlash );
+ if ( k != -1 ) {
+ for ( int i = 0; i < k + 2; i++ )
+ eraseChar( yyLinizerState->line, i, ' ' );
+ yyLinizerState->inCComment = TRUE;
+ }
+ }
+
+ /*
+ Remove preprocessor directives.
+ */
+ k = 0;
+ while ( k < (int) yyLinizerState->line.length() ) {
+ QChar ch = yyLinizerState->line[k];
+ if ( ch == QChar('#') ) {
+ yyLinizerState->line = QString::null;
+ } else if ( !ch.isSpace() ) {
+ break;
+ }
+ k++;
+ }
+
+ /*
+ Remove trailing spaces.
+ */
+ k = yyLinizerState->line.length();
+ while ( k > 0 && yyLinizerState->line[k - 1].isSpace() )
+ k--;
+ yyLinizerState->line.truncate( k );
+
+ /*
+ '}' increment the brace depth and '{' decrements it and not
+ the other way around, as we are parsing backwards.
+ */
+ yyLinizerState->braceDepth +=
+ yyLinizerState->line.contains( '}' ) -
+ yyLinizerState->line.contains( '{' );
+
+ /*
+ We use a dirty trick for
+
+ } else ...
+
+ We don't count the '}' yet, so that it's more or less
+ equivalent to the friendly construct
+
+ }
+ else ...
+ */
+ if ( yyLinizerState->pendingRightBrace )
+ yyLinizerState->braceDepth++;
+ yyLinizerState->pendingRightBrace =
+ ( yyLinizerState->line.find(*braceX) == 0 );
+ if ( yyLinizerState->pendingRightBrace )
+ yyLinizerState->braceDepth--;
+ } while ( yyLinizerState->line.isEmpty() );
+
+ return TRUE;
+}
+
+/*
+ Resets the linizer to its initial state, with yyLine containing the
+ line above the bottom line of the program.
+*/
+static void startLinizer()
+{
+ yyLinizerState->braceDepth = 0;
+ yyLinizerState->inCComment = FALSE;
+ yyLinizerState->pendingRightBrace = FALSE;
+
+ yyLine = &yyLinizerState->line;
+ yyBraceDepth = &yyLinizerState->braceDepth;
+ yyLeftBraceFollows = &yyLinizerState->leftBraceFollows;
+
+ yyLinizerState->iter = yyProgram->end();
+ --yyLinizerState->iter;
+ yyLinizerState->line = *yyLinizerState->iter;
+ readLine();
+}
+
+/*
+ Returns TRUE if the start of the bottom line of yyProgram (and
+ potentially the whole line) is part of a C-style comment; otherwise
+ returns FALSE.
+*/
+static bool bottomLineStartsInCComment()
+{
+ QString slashAster( "/*" );
+ QString asterSlash( "*/" );
+
+ /*
+ We could use the linizer here, but that would slow us down
+ terribly. We are better to trim only the code lines we need.
+ */
+ QStringList::ConstIterator p = yyProgram->end();
+ --p; // skip bottom line
+
+ for ( int i = 0; i < BigRoof; i++ ) {
+ if ( p == yyProgram->begin() )
+ return FALSE;
+ --p;
+
+ if ( (*p).find(slashAster) != -1 || (*p).find(asterSlash) != -1 ) {
+ QString trimmed = trimmedCodeLine( *p );
+
+ if ( trimmed.find(slashAster) != -1 ) {
+ return TRUE;
+ } else if ( trimmed.find(asterSlash) != -1 ) {
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+ Returns the recommended indent for the bottom line of yyProgram
+ assuming that it starts in a C-style comment, a condition that is
+ tested elsewhere.
+
+ Essentially, we're trying to align against some text on the previous
+ line.
+*/
+static int indentWhenBottomLineStartsInCComment()
+{
+ int k = yyLine->findRev( "/*" );
+ if ( k == -1 ) {
+ /*
+ We found a normal text line in a comment. Align the
+ bottom line with the text on this line.
+ */
+ return indentOfLine( *yyLine );
+ } else {
+ /*
+ The C-style comment starts on this line. If there is
+ text on the same line, align with it. Otherwise, align
+ with the slash-aster plus a given offset.
+ */
+ int indent = columnForIndex( *yyLine, k );
+ k += 2;
+ while ( k < (int) yyLine->length() ) {
+ if ( !(*yyLine)[k].isSpace() )
+ return columnForIndex( *yyLine, k );
+ k++;
+ }
+ return indent + ppCommentOffset;
+ }
+}
+
+/*
+ A function called match...() modifies the linizer state. If it
+ returns TRUE, yyLine is the top line of the matched construct;
+ otherwise, the linizer is left in an unknown state.
+
+ A function called is...() keeps the linizer state intact.
+*/
+
+/*
+ Returns TRUE if the current line (and upwards) forms a braceless
+ control statement; otherwise returns FALSE.
+
+ The first line of the following example is a "braceless control
+ statement":
+
+ if ( x )
+ y;
+*/
+static bool matchBracelessControlStatement()
+{
+ int delimDepth = 0;
+
+ if ( yyLine->endsWith("else") )
+ return TRUE;
+
+ if ( !yyLine->endsWith(")") )
+ return FALSE;
+
+ for ( int i = 0; i < SmallRoof; i++ ) {
+ int j = yyLine->length();
+ while ( j > 0 ) {
+ j--;
+ QChar ch = (*yyLine)[j];
+
+ switch ( ch.unicode() ) {
+ case ')':
+ delimDepth++;
+ break;
+ case '(':
+ delimDepth--;
+ if ( delimDepth == 0 ) {
+ if ( yyLine->find(*iflikeKeyword) != -1 ) {
+ /*
+ We have
+
+ if ( x )
+ y
+
+ "if ( x )" is not part of the statement
+ "y".
+ */
+ return TRUE;
+ }
+ }
+ if ( delimDepth == -1 ) {
+ /*
+ We have
+
+ if ( (1 +
+ 2)
+
+ and not
+
+ if ( 1 +
+ 2 )
+ */
+ return FALSE;
+ }
+ break;
+ case '{':
+ case '}':
+ case ';':
+ /*
+ We met a statement separator, but not where we
+ expected it. What follows is probably a weird
+ continuation line. Be careful with ';' in for,
+ though.
+ */
+ if ( ch != QChar(';') || delimDepth == 0 )
+ return FALSE;
+ }
+ }
+
+ if ( !readLine() )
+ break;
+ }
+ return FALSE;
+}
+
+/*
+ Returns TRUE if yyLine is an unfinished line; otherwise returns
+ FALSE.
+
+ In many places we'll use the terms "standalone line", "unfinished
+ line" and "continuation line". The meaning of these should be
+ evident from this code example:
+
+ a = b; // standalone line
+ c = d + // unfinished line
+ e + // unfinished continuation line
+ f + // unfinished continuation line
+ g; // continuation line
+*/
+static bool isUnfinishedLine()
+{
+ bool unf = FALSE;
+
+ YY_SAVE();
+
+ if ( yyLine->isEmpty() )
+ return FALSE;
+
+ QChar lastCh = (*yyLine)[(int) yyLine->length() - 1];
+ if ( QString("{};").find(lastCh) == -1 && !yyLine->endsWith("...") ) {
+ /*
+ It doesn't end with ';' or similar. If it's neither
+ "Q_OBJECT" nor "if ( x )", it must be an unfinished line.
+ */
+ unf = ( yyLine->contains("Q_OBJECT") == 0 &&
+ !matchBracelessControlStatement() );
+ } else if ( lastCh == QChar(';') ) {
+ if ( lastParen(*yyLine) == QChar('(') ) {
+ /*
+ Exception:
+
+ for ( int i = 1; i < 10;
+ */
+ unf = TRUE;
+ } else if ( readLine() && yyLine->endsWith(";") &&
+ lastParen(*yyLine) == QChar('(') ) {
+ /*
+ Exception:
+
+ for ( int i = 1;
+ i < 10;
+ */
+ unf = TRUE;
+ }
+ }
+
+ YY_RESTORE();
+ return unf;
+}
+
+/*
+ Returns TRUE if yyLine is a continuation line; otherwise returns
+ FALSE.
+*/
+static bool isContinuationLine()
+{
+ bool cont = FALSE;
+
+ YY_SAVE();
+ if ( readLine() )
+ cont = isUnfinishedLine();
+ YY_RESTORE();
+ return cont;
+}
+
+/*
+ Returns the recommended indent for the bottom line of yyProgram,
+ assuming it's a continuation line.
+
+ We're trying to align the continuation line against some parenthesis
+ or other bracked left opened on a previous line, or some interesting
+ operator such as '='.
+*/
+static int indentForContinuationLine()
+{
+ int braceDepth = 0;
+ int delimDepth = 0;
+
+ bool leftBraceFollowed = *yyLeftBraceFollows;
+
+ for ( int i = 0; i < SmallRoof; i++ ) {
+ int hook = -1;
+
+ int j = yyLine->length();
+ while ( j > 0 && hook < 0 ) {
+ j--;
+ QChar ch = (*yyLine)[j];
+
+ switch ( ch.unicode() ) {
+ case ')':
+ case ']':
+ delimDepth++;
+ break;
+ case '}':
+ braceDepth++;
+ break;
+ case '(':
+ case '[':
+ delimDepth--;
+ /*
+ An unclosed delimiter is a good place to align at,
+ at least for some styles (including Trolltech's).
+ */
+ if ( delimDepth == -1 )
+ hook = j;
+ break;
+ case '{':
+ braceDepth--;
+ /*
+ A left brace followed by other stuff on the same
+ line is typically for an enum or an initializer.
+ Such a brace must be treated just like the other
+ delimiters.
+ */
+ if ( braceDepth == -1 ) {
+ if ( j < (int) yyLine->length() - 1 ) {
+ hook = j;
+ } else {
+ return 0; // shouldn't happen
+ }
+ }
+ break;
+ case '=':
+ /*
+ An equal sign is a very natural alignment hook
+ because it's usually the operator with the lowest
+ precedence in statements it appears in. Case in
+ point:
+
+ int x = 1 +
+ 2;
+
+ However, we have to beware of constructs such as
+ default arguments and explicit enum constant
+ values:
+
+ void foo( int x = 0,
+ int y = 0 );
+
+ And not
+
+ void foo( int x = 0,
+ int y = 0 );
+
+ These constructs are caracterized by a ',' at the
+ end of the unfinished lines or by unbalanced
+ parentheses.
+ */
+ if ( QString("!=<>").find((*yyLine)[j - 1]) == -1 &&
+ (*yyLine)[j + 1] != '=' ) {
+ if ( braceDepth == 0 && delimDepth == 0 &&
+ j < (int) yyLine->length() - 1 &&
+ !yyLine->endsWith(",") &&
+ (yyLine->contains('(') == yyLine->contains(')')) )
+ hook = j;
+ }
+ }
+ }
+
+ if ( hook >= 0 ) {
+ /*
+ Yes, we have a delimiter or an operator to align
+ against! We don't really align against it, but rather
+ against the following token, if any. In this example,
+ the following token is "11":
+
+ int x = ( 11 +
+ 2 );
+
+ If there is no such token, we use a continuation indent:
+
+ static QRegExp foo( QString(
+ "foo foo foo foo foo foo foo foo foo") );
+ */
+ hook++;
+ while ( hook < (int) yyLine->length() ) {
+ if ( !(*yyLine)[hook].isSpace() )
+ return columnForIndex( *yyLine, hook );
+ hook++;
+ }
+ return indentOfLine( *yyLine ) + ppContinuationIndentSize;
+ }
+
+ if ( braceDepth != 0 )
+ break;
+
+ /*
+ The line's delimiters are balanced. It looks like a
+ continuation line or something.
+ */
+ if ( delimDepth == 0 ) {
+ if ( leftBraceFollowed ) {
+ /*
+ We have
+
+ int main()
+ {
+
+ or
+
+ Bar::Bar()
+ : Foo( x )
+ {
+
+ The "{" should be flush left.
+ */
+ if ( !isContinuationLine() )
+ return indentOfLine( *yyLine );
+ } else if ( isContinuationLine() || yyLine->endsWith(",") ) {
+ /*
+ We have
+
+ x = a +
+ b +
+ c;
+
+ or
+
+ int t[] = {
+ 1, 2, 3,
+ 4, 5, 6
+
+ The "c;" should fall right under the "b +", and the
+ "4, 5, 6" right under the "1, 2, 3,".
+ */
+ return indentOfLine( *yyLine );
+ } else {
+ /*
+ We have
+
+ stream << 1 +
+ 2;
+
+ We could, but we don't, try to analyze which
+ operator has precedence over which and so on, to
+ obtain the excellent result
+
+ stream << 1 +
+ 2;
+
+ We do have a special trick above for the assignment
+ operator above, though.
+ */
+ return indentOfLine( *yyLine ) + ppContinuationIndentSize;
+ }
+ }
+
+ if ( !readLine() )
+ break;
+ }
+ return 0;
+}
+
+/*
+ Returns the recommended indent for the bottom line of yyProgram if
+ that line is standalone (or should be indented likewise).
+
+ Indenting a standalone line is tricky, mostly because of braceless
+ control statements. Grossly, we are looking backwards for a special
+ line, a "hook line", that we can use as a starting point to indent,
+ and then modify the indentation level according to the braces met
+ along the way to that hook.
+
+ Let's consider a few examples. In all cases, we want to indent the
+ bottom line.
+
+ Example 1:
+
+ x = 1;
+ y = 2;
+
+ The hook line is "x = 1;". We met 0 opening braces and 0 closing
+ braces. Therefore, "y = 2;" inherits the indent of "x = 1;".
+
+ Example 2:
+
+ if ( x ) {
+ y;
+
+ The hook line is "if ( x ) {". No matter what precedes it, "y;" has
+ to be indented one level deeper than the hook line, since we met one
+ opening brace along the way.
+
+ Example 3:
+
+ if ( a )
+ while ( b ) {
+ c;
+ }
+ d;
+
+ To indent "d;" correctly, we have to go as far as the "if ( a )".
+ Compare with
+
+ if ( a ) {
+ while ( b ) {
+ c;
+ }
+ d;
+
+ Still, we're striving to go back as little as possible to accomodate
+ people with irregular indentation schemes. A hook line near at hand
+ is much more reliable than a remote one.
+*/
+static int indentForStandaloneLine()
+{
+ for ( int i = 0; i < SmallRoof; i++ ) {
+ if ( !*yyLeftBraceFollows ) {
+ YY_SAVE();
+
+ if ( matchBracelessControlStatement() ) {
+ /*
+ The situation is this, and we want to indent "z;":
+
+ if ( x &&
+ y )
+ z;
+
+ yyLine is "if ( x &&".
+ */
+ return indentOfLine( *yyLine ) + ppIndentSize;
+ }
+ YY_RESTORE();
+ }
+
+ if ( yyLine->endsWith(";") || yyLine->contains('{') > 0 ) {
+ /*
+ The situation is possibly this, and we want to indent
+ "z;":
+
+ while ( x )
+ y;
+ z;
+
+ We return the indent of "while ( x )". In place of "y;",
+ any arbitrarily complex compound statement can appear.
+ */
+
+ if ( *yyBraceDepth > 0 ) {
+ do {
+ if ( !readLine() )
+ break;
+ } while ( *yyBraceDepth > 0 );
+ }
+
+ LinizerState hookState;
+
+ while ( isContinuationLine() )
+ readLine();
+ hookState = *yyLinizerState;
+
+ readLine();
+ if ( *yyBraceDepth <= 0 ) {
+ do {
+ if ( !matchBracelessControlStatement() )
+ break;
+ hookState = *yyLinizerState;
+ } while ( readLine() );
+ }
+
+ *yyLinizerState = hookState;
+
+ while ( isContinuationLine() )
+ readLine();
+
+ /*
+ Never trust lines containing only '{' or '}', as some
+ people (Richard M. Stallman) format them weirdly.
+ */
+ if ( yyLine->stripWhiteSpace().length() > 1 )
+ return indentOfLine( *yyLine ) - *yyBraceDepth * ppIndentSize;
+ }
+
+ if ( !readLine() )
+ return -*yyBraceDepth * ppIndentSize;
+ }
+ return 0;
+}
+
+/*
+ Constructs global variables used by the indenter.
+*/
+static void initializeIndenter()
+{
+ literal = new QRegExp( "([\"'])(?:\\\\.|[^\\\\])*\\1" );
+ literal->setMinimal( TRUE );
+ label = new QRegExp(
+ "^\\s*((?:case\\b([^:]|::)+|[a-zA-Z_0-9]+)(?:\\s+slots)?:)(?!:)" );
+ inlineCComment = new QRegExp( "/\\*.*\\*/" );
+ inlineCComment->setMinimal( TRUE );
+ braceX = new QRegExp( "^\\s*\\}\\s*(?:else|catch)\\b" );
+ iflikeKeyword = new QRegExp( "\\b(?:catch|do|for|if|while)\\b" );
+
+ yyLinizerState = new LinizerState;
+}
+
+/*
+ Destroys global variables used by the indenter.
+*/
+static void terminateIndenter()
+{
+ delete literal;
+ delete label;
+ delete inlineCComment;
+ delete braceX;
+ delete iflikeKeyword;
+ delete yyLinizerState;
+}
+
+/*
+ Returns the recommended indent for the bottom line of program.
+ Unless null, typedIn stores the character of yyProgram that
+ triggered reindentation.
+
+ This function works better if typedIn is set properly; it is
+ slightly more conservative if typedIn is completely wild, and
+ slighly more liberal if typedIn is always null. The user might be
+ annoyed by the liberal behavior.
+*/
+int indentForBottomLine( const QStringList& program, QChar typedIn )
+{
+ if ( program.isEmpty() )
+ return 0;
+
+ initializeIndenter();
+
+ yyProgram = new QStringList( program );
+ startLinizer();
+
+ const QString& bottomLine = program.last();
+ QChar firstCh = firstNonWhiteSpace( bottomLine );
+ int indent;
+
+ if ( bottomLineStartsInCComment() ) {
+ /*
+ The bottom line starts in a C-style comment. Indent it
+ smartly, unless the user has already played around with it,
+ in which case it's better to leave her stuff alone.
+ */
+ if ( isOnlyWhiteSpace(bottomLine) ) {
+ indent = indentWhenBottomLineStartsInCComment();
+ } else {
+ indent = indentOfLine( bottomLine );
+ }
+ } else if ( okay(typedIn, '#') && firstCh == QChar('#') ) {
+ /*
+ Preprocessor directives go flush left.
+ */
+ indent = 0;
+ } else {
+ if ( isUnfinishedLine() ) {
+ indent = indentForContinuationLine();
+ } else {
+ indent = indentForStandaloneLine();
+ }
+
+ if ( okay(typedIn, '}') && firstCh == QChar('}') ) {
+ /*
+ A closing brace is one level more to the left than the
+ code it follows.
+ */
+ indent -= ppIndentSize;
+ } else if ( okay(typedIn, ':') ) {
+ QRegExp caseLabel(
+ "\\s*(?:case\\b(?:[^:]|::)+"
+ "|(?:public|protected|private|signals|default)(?:\\s+slots)?\\s*"
+ ")?:.*" );
+
+ if ( caseLabel.exactMatch(bottomLine) ) {
+ /*
+ Move a case label (or the ':' in front of a
+ constructor initialization list) one level to the
+ left, but only if the user did not play around with
+ it yet. Some users have exotic tastes in the
+ matter, and most users probably are not patient
+ enough to wait for the final ':' to format their
+ code properly.
+
+ We don't attempt the same for goto labels, as the
+ user is probably the middle of "foo::bar". (Who
+ uses goto, anyway?)
+ */
+ if ( indentOfLine(bottomLine) <= indent )
+ indent -= ppIndentSize;
+ else
+ indent = indentOfLine( bottomLine );
+ }
+ }
+ }
+ delete yyProgram;
+ terminateIndenter();
+ return QMAX( 0, indent );
+}
+
+#ifdef Q_TEST_YYINDENT
+/*
+ Test driver.
+*/
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <errno.h>
+
+static QString fileContents( const QString& fileName )
+{
+ QFile f( fileName );
+ if ( !f.open(IO_ReadOnly) ) {
+ qWarning( "yyindent error: Cannot open file '%s' for reading: %s",
+ fileName.latin1(), strerror(errno) );
+ return QString::null;
+ }
+
+ QTextStream t( &f );
+ QString contents = t.read();
+ f.close();
+ if ( contents.isEmpty() )
+ qWarning( "yyindent error: File '%s' is empty", fileName.latin1() );
+ return contents;
+}
+
+int main( int argc, char **argv )
+{
+ if ( argc != 2 ) {
+ qWarning( "usage: yyindent file.cpp" );
+ return 1;
+ }
+
+ QString code = fileContents( argv[1] );
+ QStringList program = QStringList::split( '\n', code, TRUE );
+ QStringList p;
+ QString out;
+
+ while ( !program.isEmpty() && program.last().stripWhiteSpace().isEmpty() )
+ program.remove( program.fromLast() );
+
+ QStringList::ConstIterator line = program.begin();
+ while ( line != program.end() ) {
+ p.push_back( *line );
+ QChar typedIn = firstNonWhiteSpace( *line );
+ if ( p.last().endsWith(":") )
+ typedIn = ':';
+
+ int indent = indentForBottomLine( p, typedIn );
+
+ if ( !(*line).stripWhiteSpace().isEmpty() ) {
+ for ( int j = 0; j < indent; j++ )
+ out += " ";
+ out += (*line).stripWhiteSpace();
+ }
+ out += "\n";
+ ++line;
+ }
+
+ while ( out.endsWith("\n") )
+ out.truncate( out.length() - 1 );
+
+ printf( "%s\n", out.latin1() );
+ return 0;
+}
+#endif