From 8234858b468ea9a44b90e28adec668d23907457a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 15 Jul 2009 11:20:24 +0200 Subject: [PATCH 01/26] Register C++ header and source file icons by mime type Makes sure that all files recognized by the CppEditorFactory get the proper icon. --- src/plugins/coreplugin/fileiconprovider.cpp | 19 ++++++++-- src/plugins/coreplugin/fileiconprovider.h | 6 ++- src/plugins/cppeditor/cppplugin.cpp | 42 +++++++-------------- src/plugins/cppeditor/cppplugin.h | 3 -- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/plugins/coreplugin/fileiconprovider.cpp b/src/plugins/coreplugin/fileiconprovider.cpp index 04f5e9589d7..a52bc8ec78d 100644 --- a/src/plugins/coreplugin/fileiconprovider.cpp +++ b/src/plugins/coreplugin/fileiconprovider.cpp @@ -28,6 +28,8 @@ **************************************************************************/ #include "fileiconprovider.h" +#include "mimedatabase.h" + #include #include #include @@ -88,7 +90,9 @@ QIcon FileIconProvider::icon(const QFileInfo &fileInfo) return icon; } -// Creates a pixmap with baseicon at size and overlayous overlayIcon over it. +/*! + Creates a pixmap with baseicon at size and overlays overlayIcon over it. + */ QPixmap FileIconProvider::overlayIcon(QStyle::StandardPixmap baseIcon, const QIcon &overlayIcon, const QSize &size) const { QPixmap iconPixmap = qApp->style()->standardIcon(baseIcon).pixmap(size); @@ -99,7 +103,7 @@ QPixmap FileIconProvider::overlayIcon(QStyle::StandardPixmap baseIcon, const QIc } /*! - Registers an icon for a given suffix, overlaying the system file icon + Registers an icon for a given suffix, overlaying the system file icon. */ void FileIconProvider::registerIconOverlayForSuffix(const QIcon &icon, const QString &suffix) { @@ -117,13 +121,22 @@ void FileIconProvider::registerIconOverlayForSuffix(const QIcon &icon, const QSt m_cache.append(newEntry); } +/*! + Registers an icon for all the suffixes of a given mime type, overlaying the system file icon. + */ +void FileIconProvider::registerIconOverlayForMimeType(const QIcon &icon, const MimeType &mimeType) +{ + foreach (const QString &suffix, mimeType.suffixes()) + registerIconOverlayForSuffix(icon, suffix); +} + /*! Returns an icon for the given suffix, or an empty one if none registered. */ QIcon FileIconProvider::iconForSuffix(const QString &suffix) const { QIcon icon; -#if defined(Q_WS_WIN) || defined(Q_WS_MAC) // On windows we use the file system icons +#if defined(Q_WS_WIN) || defined(Q_WS_MAC) // On Windows and Mac we use the file system icons Q_UNUSED(suffix) #else if (suffix.isEmpty()) diff --git a/src/plugins/coreplugin/fileiconprovider.h b/src/plugins/coreplugin/fileiconprovider.h index 8d8bb7d1f0d..9ee5ed9c615 100644 --- a/src/plugins/coreplugin/fileiconprovider.h +++ b/src/plugins/coreplugin/fileiconprovider.h @@ -40,13 +40,17 @@ namespace Core { -class CORE_EXPORT FileIconProvider { +class MimeType; + +class CORE_EXPORT FileIconProvider +{ public: ~FileIconProvider(); // used to clear the cache QIcon icon(const QFileInfo &fileInfo); QPixmap overlayIcon(QStyle::StandardPixmap baseIcon, const QIcon &overlayIcon, const QSize &size) const; void registerIconOverlayForSuffix(const QIcon &icon, const QString &suffix); + void registerIconOverlayForMimeType(const QIcon &icon, const MimeType &mimeType); static FileIconProvider *instance(); diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp index b97918b2fc5..b1ee04b131e 100644 --- a/src/plugins/cppeditor/cppplugin.cpp +++ b/src/plugins/cppeditor/cppplugin.cpp @@ -65,29 +65,19 @@ CppEditorFactory::CppEditorFactory(CppPlugin *owner) : m_owner(owner) { m_mimeTypes << QLatin1String(CppEditor::Constants::C_SOURCE_MIMETYPE) - << QLatin1String(CppEditor::Constants::C_HEADER_MIMETYPE) - << QLatin1String(CppEditor::Constants::CPP_SOURCE_MIMETYPE) - << QLatin1String(CppEditor::Constants::CPP_HEADER_MIMETYPE); - Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance(); + << QLatin1String(CppEditor::Constants::C_HEADER_MIMETYPE) + << QLatin1String(CppEditor::Constants::CPP_SOURCE_MIMETYPE) + << QLatin1String(CppEditor::Constants::CPP_HEADER_MIMETYPE); + #ifndef Q_WS_MAC - // ### It would be really cool if we could get the stuff from the XML file here and not play "catch up" all the time. - QIcon cppIcon(":/cppeditor/images/qt_cpp.png"); - iconProvider->registerIconOverlayForSuffix(cppIcon, QLatin1String("cpp")); - iconProvider->registerIconOverlayForSuffix(cppIcon, QLatin1String("cp")); - iconProvider->registerIconOverlayForSuffix(cppIcon, QLatin1String("cc")); - iconProvider->registerIconOverlayForSuffix(cppIcon, QLatin1String("cxx")); - iconProvider->registerIconOverlayForSuffix(cppIcon, QLatin1String("C")); - iconProvider->registerIconOverlayForSuffix(cppIcon, QLatin1String("c++")); - iconProvider->registerIconOverlayForSuffix(QIcon(":/cppeditor/images/qt_c.png"), - QLatin1String("c")); - QIcon headerIcon(":/cppeditor/images/qt_h.png"); - iconProvider->registerIconOverlayForSuffix(headerIcon, QLatin1String("hpp")); - iconProvider->registerIconOverlayForSuffix(headerIcon, QLatin1String("hh")); - iconProvider->registerIconOverlayForSuffix(headerIcon, QLatin1String("h")); - iconProvider->registerIconOverlayForSuffix(headerIcon, QLatin1String("hxx")); - iconProvider->registerIconOverlayForSuffix(headerIcon, QLatin1String("H")); - iconProvider->registerIconOverlayForSuffix(headerIcon, QLatin1String("hp")); - iconProvider->registerIconOverlayForSuffix(headerIcon, QLatin1String("h++")); + Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance(); + Core::MimeDatabase *mimeDatabase = Core::ICore::instance()->mimeDatabase(); + iconProvider->registerIconOverlayForMimeType(QIcon(":/cppeditor/images/qt_cpp.png"), + mimeDatabase->findByType(QLatin1String(CppEditor::Constants::CPP_SOURCE_MIMETYPE))); + iconProvider->registerIconOverlayForMimeType(QIcon(":/cppeditor/images/qt_c.png"), + mimeDatabase->findByType(QLatin1String(CppEditor::Constants::C_SOURCE_MIMETYPE))); + iconProvider->registerIconOverlayForMimeType(QIcon(":/cppeditor/images/qt_h.png"), + mimeDatabase->findByType(QLatin1String(CppEditor::Constants::CPP_HEADER_MIMETYPE))); #endif } @@ -122,7 +112,6 @@ CppPlugin *CppPlugin::m_instance = 0; CppPlugin::CppPlugin() : m_actionHandler(0), - m_factory(0), m_sortedMethodOverview(false) { m_instance = this; @@ -130,8 +119,6 @@ CppPlugin::CppPlugin() : CppPlugin::~CppPlugin() { - removeObject(m_factory); - delete m_factory; delete m_actionHandler; m_instance = 0; } @@ -174,12 +161,11 @@ bool CppPlugin::sortedMethodOverview() const bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage) { Core::ICore *core = Core::ICore::instance(); + if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":/cppeditor/CppEditor.mimetypes.xml"), errorMessage)) return false; - m_factory = new CppEditorFactory(this); - addObject(m_factory); - + addAutoReleasedObject(new CppEditorFactory(this)); addAutoReleasedObject(new CppHoverHandler); CppFileWizard::BaseFileWizardParameters wizardParameters(Core::IWizard::FileWizard); diff --git a/src/plugins/cppeditor/cppplugin.h b/src/plugins/cppeditor/cppplugin.h index ce4f0d08990..9e5cc9eeade 100644 --- a/src/plugins/cppeditor/cppplugin.h +++ b/src/plugins/cppeditor/cppplugin.h @@ -44,7 +44,6 @@ namespace CppEditor { namespace Internal { class CPPEditor; -class CppEditorFactory; class CppPlugin : public ExtensionSystem::IPlugin { @@ -76,7 +75,6 @@ private slots: void jumpToDefinition(); private: - friend class CppEditorFactory; Core::IEditor *createEditor(QWidget *parent); void writeSettings(); void readSettings(); @@ -84,7 +82,6 @@ private: static CppPlugin *m_instance; TextEditor::TextEditorActionHandler *m_actionHandler; - CppEditorFactory *m_factory; bool m_sortedMethodOverview; }; From 309ee636b3939771777969dffa01aaf8aca216f8 Mon Sep 17 00:00:00 2001 From: con Date: Tue, 14 Jul 2009 18:01:25 +0200 Subject: [PATCH 02/26] Styled two-row find tool bar with better resizing behavior. For this we needed to get rid of using QToolBar. --- src/plugins/coreplugin/manhattanstyle.cpp | 2 + src/plugins/find/findtoolbar.cpp | 90 ++++++++++++--- src/plugins/find/findtoolbar.h | 4 +- src/plugins/find/findwidget.ui | 132 ++++++++++++---------- 4 files changed, 151 insertions(+), 77 deletions(-) diff --git a/src/plugins/coreplugin/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp index 4370ab49d59..171dac813f2 100644 --- a/src/plugins/coreplugin/manhattanstyle.cpp +++ b/src/plugins/coreplugin/manhattanstyle.cpp @@ -86,6 +86,8 @@ bool panelWidget(const QWidget *widget) return true; else if (qobject_cast(p) && styleEnabled(p)) return true; + else if (p->property("panelwidget").toBool()) + return true; p = p->parentWidget(); } return false; diff --git a/src/plugins/find/findtoolbar.cpp b/src/plugins/find/findtoolbar.cpp index 8b7a4bb6af0..0ddd2d259e6 100644 --- a/src/plugins/find/findtoolbar.cpp +++ b/src/plugins/find/findtoolbar.cpp @@ -32,6 +32,7 @@ #include "textfindconstants.h" #include +#include #include #include #include @@ -49,9 +50,10 @@ #include #include #include -#include #include #include +#include +#include Q_DECLARE_METATYPE(QStringList) Q_DECLARE_METATYPE(Find::IFindFilter*) @@ -68,14 +70,13 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen m_findNextAction(0), m_findPreviousAction(0), m_replaceNextAction(0), - m_widget(new QWidget), m_casesensitiveIcon(":/find/images/casesensitively.png"), m_regexpIcon(":/find/images/regexp.png"), m_wholewordsIcon(":/find/images/wholewords.png") { //setup ui - m_ui.setupUi(m_widget); - addWidget(m_widget); + m_ui.setupUi(this); + setProperty("panelwidget", true); setFocusProxy(m_ui.findEdit); setProperty("topBorder", true); m_ui.findEdit->setAttribute(Qt::WA_MacShowFocusRect, false); @@ -83,14 +84,9 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen connect(m_ui.findEdit, SIGNAL(editingFinished()), this, SLOT(invokeResetIncrementalSearch())); - QWidget *spacerItem = new QWidget; - spacerItem->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - addWidget(spacerItem); - QToolButton *close = new QToolButton; - close->setProperty("type", QLatin1String("dockbutton")); - close->setIcon(QIcon(":/core/images/closebutton.png")); - connect(close, SIGNAL(clicked()), this, SLOT(hideAndResetFocus())); - addWidget(close); + m_ui.close->setProperty("type", QLatin1String("dockbutton")); + m_ui.close->setIcon(QIcon(":/core/images/closebutton.png")); + connect(m_ui.close, SIGNAL(clicked()), this, SLOT(hideAndResetFocus())); m_ui.findPreviousButton->setProperty("type", QLatin1String("dockbutton")); m_ui.findNextButton->setProperty("type", QLatin1String("dockbutton")); @@ -110,7 +106,7 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen m_ui.findEdit->installEventFilter(this); m_ui.replaceEdit->installEventFilter(this); - m_widget->installEventFilter(this); + this->installEventFilter(this); connect(m_ui.findEdit, SIGNAL(textChanged(const QString&)), this, SLOT(invokeFindIncremental())); connect(m_ui.findEdit, SIGNAL(returnPressed()), this, SLOT(invokeFindEnter())); @@ -234,6 +230,56 @@ FindToolBar::~FindToolBar() { } +void FindToolBar::paintEvent(QPaintEvent *event) +{ + // Currently from the style + // Goal should be to migrate that into a Utils::StyledWidget class + Q_UNUSED(event) + QPainter painter(this); + + QRect selfRect = rect(); + QString key; + key.sprintf("mh_toolbar %d %d %d", selfRect.width(), selfRect.height(), StyleHelper::baseColor().rgb());; + + QPixmap pixmap; + QPainter *p = &painter; + if (StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) { + pixmap = QPixmap(selfRect.size()); + p = new QPainter(&pixmap); + selfRect = QRect(0, 0, selfRect.width(), selfRect.height()); + } + + // Map offset for global window gradient + QPoint offset = window()->mapToGlobal(selfRect.topLeft()) - + mapToGlobal(selfRect.topLeft()); + QRect gradientSpan; + gradientSpan = QRect(offset, window()->size()); + StyleHelper::horizontalGradient(p, gradientSpan, selfRect); + + p->setPen(StyleHelper::borderColor()); + + // Note: This is a hack to determine if the + // toolbar should draw the top or bottom outline + // (needed for the find toolbar for instance) + QColor lighter(255, 255, 255, 40); + if (property("topBorder").toBool()) { + p->drawLine(selfRect.topLeft(), selfRect.topRight()); + p->setPen(lighter); + p->drawLine(selfRect.topLeft() + QPoint(0, 1), selfRect.topRight() + QPoint(0, 1)); + } else { + p->drawLine(selfRect.bottomLeft(), selfRect.bottomRight()); + p->setPen(lighter); + p->drawLine(selfRect.topLeft(), selfRect.topRight()); + } + + if (StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) { + painter.drawPixmap(selfRect.topLeft(), pixmap); + p->end(); + delete p; + QPixmapCache::insert(key, pixmap); + } +} + bool FindToolBar::eventFilter(QObject *obj, QEvent *event) { if ((obj == m_ui.findEdit || obj == m_findCompleter->popup()) @@ -251,7 +297,7 @@ bool FindToolBar::eventFilter(QObject *obj, QEvent *event) return true; } } - } else if (obj == m_widget && event->type() == QEvent::ShortcutOverride) { + } else if (obj == this && event->type() == QEvent::ShortcutOverride) { QKeyEvent *ke = static_cast(event); if (ke->key() == Qt::Key_Escape && !ke->modifiers() && !m_findCompleter->popup()->isVisible() @@ -268,13 +314,13 @@ bool FindToolBar::eventFilter(QObject *obj, QEvent *event) event->accept(); return true; } - } else if (obj == m_widget && event->type() == QEvent::Hide) { + } else if (obj == this && event->type() == QEvent::Hide) { invokeClearResults(); if (m_currentDocumentFind->isEnabled()) { m_currentDocumentFind->clearFindScope(); } } - return QToolBar::eventFilter(obj, event); + return QWidget::eventFilter(obj, event); } void FindToolBar::updateActions() @@ -284,9 +330,11 @@ void FindToolBar::updateActions() m_findInDocumentAction->setEnabled(enabled); m_findNextAction->setEnabled(enabled); m_findPreviousAction->setEnabled(enabled); + m_replaceNextAction->setEnabled(replaceEnabled); m_replacePreviousAction->setEnabled(replaceEnabled); m_replaceAllAction->setEnabled(replaceEnabled); + m_caseSensitiveAction->setEnabled(enabled); m_wholeWordAction->setEnabled(enabled); m_regularExpressionAction->setEnabled(enabled); @@ -295,8 +343,16 @@ void FindToolBar::updateActions() bool replaceFocus = m_ui.replaceEdit->hasFocus(); m_ui.findEdit->setEnabled(enabled); m_ui.findLabel->setEnabled(enabled); + m_ui.replaceEdit->setEnabled(replaceEnabled); m_ui.replaceLabel->setEnabled(replaceEnabled); + m_ui.replaceEdit->setVisible(replaceEnabled); + m_ui.replaceLabel->setVisible(replaceEnabled); + m_ui.replacePreviousButton->setVisible(replaceEnabled); + m_ui.replaceNextButton->setVisible(replaceEnabled); + m_ui.replaceAllButton->setVisible(replaceEnabled); + layout()->invalidate(); + if (!replaceEnabled && enabled && replaceFocus) m_ui.findEdit->setFocus(); updateIcons(); @@ -540,7 +596,7 @@ bool FindToolBar::focusNextPrevChild(bool next) else if (!next && m_ui.findEdit->hasFocus()) m_ui.replaceAllButton->setFocus(Qt::TabFocusReason); else - return QToolBar::focusNextPrevChild(next); + return QWidget::focusNextPrevChild(next); return true; } diff --git a/src/plugins/find/findtoolbar.h b/src/plugins/find/findtoolbar.h index 4b85c1a9e83..ca1b1ba5268 100644 --- a/src/plugins/find/findtoolbar.h +++ b/src/plugins/find/findtoolbar.h @@ -44,13 +44,14 @@ namespace Internal { class FindPlugin; -class FindToolBar : public QToolBar +class FindToolBar : public QWidget { Q_OBJECT public: FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumentFind); ~FindToolBar(); + void paintEvent(QPaintEvent *event); void readSettings(); void writeSettings(); @@ -113,7 +114,6 @@ private: QAction *m_caseSensitiveAction; QAction *m_wholeWordAction; QAction *m_regularExpressionAction; - QWidget *m_widget; IFindSupport::FindFlags m_findFlags; QPixmap m_casesensitiveIcon; diff --git a/src/plugins/find/findwidget.ui b/src/plugins/find/findwidget.ui index b11792768d0..8fb5973c130 100644 --- a/src/plugins/find/findwidget.ui +++ b/src/plugins/find/findwidget.ui @@ -6,57 +6,47 @@ 0 0 - 600 - 71 + 603 + 90 Find - - - 15 - + 5 - 1 + 2 - 5 + 0 1 - + + 5 + + + 0 + + + + + Find: + + + + + + + - 2 + 3 - - - - Find: - - - - - - - - 160 - 0 - - - - - 160 - 16777215 - - - - @@ -80,36 +70,43 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + ... + + + - + + + + Replace with: + + + + + + + - 2 + 3 - - - - Replace with: - - - - - - - - 150 - 0 - - - - - 150 - 16777215 - - - - @@ -146,6 +143,19 @@ + + + + Qt::Horizontal + + + + 40 + 0 + + + + @@ -157,6 +167,12 @@
utils/fancylineedit.h
+ + findEdit + replaceEdit + close + replaceAllButton + From 3873165ef71591d6b02d7ef8d963b660d616fc6f Mon Sep 17 00:00:00 2001 From: con Date: Wed, 15 Jul 2009 12:06:21 +0200 Subject: [PATCH 03/26] Add pri file icon for Mac --- src/app/Info.plist | 2 ++ src/libs/utils/utils.pro | 8 ++++++-- src/plugins/projectexplorer/projectexplorer.pri | 1 - 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/app/Info.plist b/src/app/Info.plist index 5e8617cc865..5d37bfd27a1 100644 --- a/src/app/Info.plist +++ b/src/app/Info.plist @@ -21,6 +21,8 @@ CFBundleTypeRole Editor + CFBundleTypeIconFile + qtcreator.icns CFBundleTypeExtensions pri diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro index a52697f8909..0a90231f4af 100644 --- a/src/libs/utils/utils.pro +++ b/src/libs/utils/utils.pro @@ -29,7 +29,9 @@ SOURCES += reloadpromptutils.cpp \ uncommentselection.cpp \ parameteraction.cpp \ treewidgetcolumnstretcher.cpp \ - checkablemessagebox.cpp + checkablemessagebox.cpp \ + styledbar.cpp + win32 { SOURCES += abstractprocess_win.cpp \ consoleprocess_win.cpp \ @@ -66,7 +68,9 @@ HEADERS += utils_global.h \ parameteraction.h \ treewidgetcolumnstretcher.h \ checkablemessagebox.h \ - qtcassert.h + qtcassert.h \ + styledbar.h + FORMS += filewizardpage.ui \ projectintropage.ui \ newclasswidget.ui \ diff --git a/src/plugins/projectexplorer/projectexplorer.pri b/src/plugins/projectexplorer/projectexplorer.pri index 45d1e96374c..fa0891a5fa2 100644 --- a/src/plugins/projectexplorer/projectexplorer.pri +++ b/src/plugins/projectexplorer/projectexplorer.pri @@ -1,3 +1,2 @@ include(projectexplorer_dependencies.pri) - LIBS *= -l$$qtLibraryTarget(ProjectExplorer) From d53129d336408aa162207bb501235f8378b7a131 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 15 Jul 2009 12:24:47 +0200 Subject: [PATCH 04/26] Output filenames when doing svn update. --- src/plugins/subversion/subversionplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index dad3c37bab2..21c3e5b9a38 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -754,7 +754,7 @@ void SubversionPlugin::updateProject() QStringList args(QLatin1String("update")); args.push_back(QLatin1String(nonInteractiveOptionC)); args.append(topLevels); - runSvn(args, subversionLongTimeOut, false); + runSvn(args, subversionLongTimeOut, true); } void SubversionPlugin::annotateCurrentFile() From 18f9375501926ab637ccf68ca01bc9ea615ffced Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 15 Jul 2009 12:28:40 +0200 Subject: [PATCH 05/26] Add a CVS plugin for use with UNIX cvs or Tortoise CVS. --- src/plugins/cvs/CVS.mimetypes.xml | 7 + src/plugins/cvs/CVS.pluginspec | 27 + src/plugins/cvs/annotationhighlighter.cpp | 46 + src/plugins/cvs/annotationhighlighter.h | 55 + src/plugins/cvs/cvs.pro | 36 + src/plugins/cvs/cvs.qrc | 5 + src/plugins/cvs/cvsconstants.h | 48 + src/plugins/cvs/cvscontrol.cpp | 98 ++ src/plugins/cvs/cvscontrol.h | 70 ++ src/plugins/cvs/cvseditor.cpp | 159 +++ src/plugins/cvs/cvseditor.h | 69 ++ src/plugins/cvs/cvsoutputwindow.cpp | 127 +++ src/plugins/cvs/cvsoutputwindow.h | 84 ++ src/plugins/cvs/cvsplugin.cpp | 1228 +++++++++++++++++++++ src/plugins/cvs/cvsplugin.h | 208 ++++ src/plugins/cvs/cvssettings.cpp | 108 ++ src/plugins/cvs/cvssettings.h | 70 ++ src/plugins/cvs/cvssubmiteditor.cpp | 70 ++ src/plugins/cvs/cvssubmiteditor.h | 64 ++ src/plugins/cvs/cvsutils.cpp | 238 ++++ src/plugins/cvs/cvsutils.h | 86 ++ src/plugins/cvs/settingspage.cpp | 107 ++ src/plugins/cvs/settingspage.h | 86 ++ src/plugins/cvs/settingspage.ui | 130 +++ src/plugins/plugins.pro | 7 + 25 files changed, 3233 insertions(+) create mode 100644 src/plugins/cvs/CVS.mimetypes.xml create mode 100644 src/plugins/cvs/CVS.pluginspec create mode 100644 src/plugins/cvs/annotationhighlighter.cpp create mode 100644 src/plugins/cvs/annotationhighlighter.h create mode 100644 src/plugins/cvs/cvs.pro create mode 100644 src/plugins/cvs/cvs.qrc create mode 100644 src/plugins/cvs/cvsconstants.h create mode 100644 src/plugins/cvs/cvscontrol.cpp create mode 100644 src/plugins/cvs/cvscontrol.h create mode 100644 src/plugins/cvs/cvseditor.cpp create mode 100644 src/plugins/cvs/cvseditor.h create mode 100644 src/plugins/cvs/cvsoutputwindow.cpp create mode 100644 src/plugins/cvs/cvsoutputwindow.h create mode 100644 src/plugins/cvs/cvsplugin.cpp create mode 100644 src/plugins/cvs/cvsplugin.h create mode 100644 src/plugins/cvs/cvssettings.cpp create mode 100644 src/plugins/cvs/cvssettings.h create mode 100644 src/plugins/cvs/cvssubmiteditor.cpp create mode 100644 src/plugins/cvs/cvssubmiteditor.h create mode 100644 src/plugins/cvs/cvsutils.cpp create mode 100644 src/plugins/cvs/cvsutils.h create mode 100644 src/plugins/cvs/settingspage.cpp create mode 100644 src/plugins/cvs/settingspage.h create mode 100644 src/plugins/cvs/settingspage.ui diff --git a/src/plugins/cvs/CVS.mimetypes.xml b/src/plugins/cvs/CVS.mimetypes.xml new file mode 100644 index 00000000000..237d8aa67c0 --- /dev/null +++ b/src/plugins/cvs/CVS.mimetypes.xml @@ -0,0 +1,7 @@ + + + + CVS submit template + + + diff --git a/src/plugins/cvs/CVS.pluginspec b/src/plugins/cvs/CVS.pluginspec new file mode 100644 index 00000000000..2e28bb38c75 --- /dev/null +++ b/src/plugins/cvs/CVS.pluginspec @@ -0,0 +1,27 @@ + + Nokia Corporation + (C) 2008-2009 Nokia Corporation + +Commercial Usage + +Licensees holding valid Qt Commercial licenses may use this plugin in +accordance with the Qt Commercial License Agreement provided with the +Software or, alternatively, in accordance with the terms contained in +a written agreement between you and Nokia. + +GNU Lesser General Public License Usage + +Alternatively, this plugin may be used under the terms of the GNU Lesser +General Public License version 2.1 as published by the Free Software +Foundation. Please review the following information to +ensure the GNU Lesser General Public License version 2.1 requirements +will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + CVS integration. + http://www.qtsoftware.com + + + + + + + diff --git a/src/plugins/cvs/annotationhighlighter.cpp b/src/plugins/cvs/annotationhighlighter.cpp new file mode 100644 index 00000000000..3214068de7e --- /dev/null +++ b/src/plugins/cvs/annotationhighlighter.cpp @@ -0,0 +1,46 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include "annotationhighlighter.h" + +using namespace CVS; +using namespace CVS::Internal; + +CVSAnnotationHighlighter::CVSAnnotationHighlighter(const ChangeNumbers &changeNumbers, + QTextDocument *document) : + VCSBase::BaseAnnotationHighlighter(changeNumbers, document), + m_blank(QLatin1Char(' ')) +{ +} + +QString CVSAnnotationHighlighter::changeNumber(const QString &block) const +{ + const int pos = block.indexOf(m_blank); + return pos > 1 ? block.left(pos) : QString(); +} diff --git a/src/plugins/cvs/annotationhighlighter.h b/src/plugins/cvs/annotationhighlighter.h new file mode 100644 index 00000000000..8f52c9ba560 --- /dev/null +++ b/src/plugins/cvs/annotationhighlighter.h @@ -0,0 +1,55 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef ANNOTATIONHIGHLIGHTER_H +#define ANNOTATIONHIGHLIGHTER_H + +#include + +namespace CVS { +namespace Internal { + +// Annotation highlighter for cvs triggering on 'changenumber ' +class CVSAnnotationHighlighter : public VCSBase::BaseAnnotationHighlighter +{ + Q_OBJECT +public: + explicit CVSAnnotationHighlighter(const ChangeNumbers &changeNumbers, + QTextDocument *document = 0); + +private: + virtual QString changeNumber(const QString &block) const; + + const QChar m_blank; +}; + +} // namespace Internal +} // namespace CVS + +#endif // ANNOTATIONHIGHLIGHTER_H diff --git a/src/plugins/cvs/cvs.pro b/src/plugins/cvs/cvs.pro new file mode 100644 index 00000000000..86244a20aac --- /dev/null +++ b/src/plugins/cvs/cvs.pro @@ -0,0 +1,36 @@ +TEMPLATE = lib +TARGET = CVS + +include(../../qtcreatorplugin.pri) +include(../../plugins/projectexplorer/projectexplorer.pri) +include(../../plugins/texteditor/texteditor.pri) +include(../../plugins/coreplugin/coreplugin.pri) +include(../../plugins/vcsbase/vcsbase.pri) +include(../../libs/utils/utils.pri) + +HEADERS += annotationhighlighter.h \ + cvsplugin.h \ + cvscontrol.h \ + cvsoutputwindow.h \ + settingspage.h \ + cvseditor.h \ + cvssubmiteditor.h \ + cvssettings.h \ + cvsutils.h \ + cvsconstants.h + +SOURCES += annotationhighlighter.cpp \ + cvsplugin.cpp \ + cvscontrol.cpp \ + cvsoutputwindow.cpp \ + settingspage.cpp \ + cvseditor.cpp \ + cvssubmiteditor.cpp \ + cvssettings.cpp \ + cvsutils.cpp + +FORMS += settingspage.ui + +RESOURCES += cvs.qrc + +OTHER_FILES += CVS.pluginspec diff --git a/src/plugins/cvs/cvs.qrc b/src/plugins/cvs/cvs.qrc new file mode 100644 index 00000000000..63180dfae75 --- /dev/null +++ b/src/plugins/cvs/cvs.qrc @@ -0,0 +1,5 @@ + + + CVS.mimetypes.xml + + diff --git a/src/plugins/cvs/cvsconstants.h b/src/plugins/cvs/cvsconstants.h new file mode 100644 index 00000000000..1a2e5248c85 --- /dev/null +++ b/src/plugins/cvs/cvsconstants.h @@ -0,0 +1,48 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef CVS_CONSTANTS_H +#define CVS_CONSTANTS_H + +namespace CVS { +namespace Constants { + +const char * const CVS_SUBMIT_MIMETYPE = "application/vnd.nokia.text.cvs.submit"; +const char * const CVSEDITOR = "CVS Editor"; +const char * const CVSEDITOR_KIND = "CVS Editor"; +const char * const CVSCOMMITEDITOR = "CVS Commit Editor"; +const char * const CVSCOMMITEDITOR_KIND = "CVS Commit Editor"; +const char * const SUBMIT_CURRENT = "CVS.SubmitCurrentLog"; +const char * const DIFF_SELECTED = "CVS.DiffSelectedFilesInLog"; +enum { debug = 0 }; + +} // namespace Constants +} // namespace SubVersion + +#endif // CVS_CONSTANTS_H diff --git a/src/plugins/cvs/cvscontrol.cpp b/src/plugins/cvs/cvscontrol.cpp new file mode 100644 index 00000000000..49175e86c93 --- /dev/null +++ b/src/plugins/cvs/cvscontrol.cpp @@ -0,0 +1,98 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include "cvscontrol.h" +#include "cvsplugin.h" + +using namespace CVS; +using namespace CVS::Internal; + +CVSControl::CVSControl(CVSPlugin *plugin) : + m_enabled(true), + m_plugin(plugin) +{ +} + +QString CVSControl::name() const +{ + return QLatin1String("cvs"); +} + +bool CVSControl::isEnabled() const +{ + return m_enabled; +} + +void CVSControl::setEnabled(bool enabled) +{ + if (m_enabled != enabled) { + m_enabled = enabled; + emit enabledChanged(m_enabled); + } +} + +bool CVSControl::supportsOperation(Operation operation) const +{ + bool rc = true; + switch (operation) { + case AddOperation: + case DeleteOperation: + break; + case OpenOperation: + rc = false; + break; + } + return rc; +} + +bool CVSControl::vcsOpen(const QString & /* fileName */) +{ + // Open for edit: N/A + return true; +} + +bool CVSControl::vcsAdd(const QString &fileName) +{ + return m_plugin->vcsAdd(fileName); +} + +bool CVSControl::vcsDelete(const QString &fileName) +{ + return m_plugin->vcsDelete(fileName); +} + +bool CVSControl::managesDirectory(const QString &directory) const +{ + return m_plugin->managesDirectory(directory); +} + +QString CVSControl::findTopLevelForDirectory(const QString &directory) const +{ + return m_plugin->findTopLevelForDirectory(directory); +} diff --git a/src/plugins/cvs/cvscontrol.h b/src/plugins/cvs/cvscontrol.h new file mode 100644 index 00000000000..2249f1a8232 --- /dev/null +++ b/src/plugins/cvs/cvscontrol.h @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef CVSCONTROL_H +#define CVSCONTROL_H + +#include + +namespace CVS { +namespace Internal { + +class CVSPlugin; + +// Just a proxy for CVSPlugin +class CVSControl : public Core::IVersionControl +{ + Q_OBJECT +public: + explicit CVSControl(CVSPlugin *plugin); + virtual QString name() const; + + virtual bool isEnabled() const; + virtual void setEnabled(bool enabled); + + virtual bool managesDirectory(const QString &directory) const; + virtual QString findTopLevelForDirectory(const QString &directory) const; + + virtual bool supportsOperation(Operation operation) const; + virtual bool vcsOpen(const QString &fileName); + virtual bool vcsAdd(const QString &fileName); + virtual bool vcsDelete(const QString &filename); + +signals: + void enabledChanged(bool); + +private: + bool m_enabled; + CVSPlugin *m_plugin; +}; + +} // namespace Internal +} // namespace CVS + +#endif // CVSCONTROL_H diff --git a/src/plugins/cvs/cvseditor.cpp b/src/plugins/cvs/cvseditor.cpp new file mode 100644 index 00000000000..35b342446ed --- /dev/null +++ b/src/plugins/cvs/cvseditor.cpp @@ -0,0 +1,159 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include "cvseditor.h" + +#include "annotationhighlighter.h" +#include "cvsconstants.h" + +#include +#include + +#include +#include + +namespace CVS { +namespace Internal { + +// Match a CVS revision ("1.1.1.1") +#define CVS_REVISION_PATTERN "[\\d\\.]+" +#define CVS_REVISION_AT_START_PATTERN "^("CVS_REVISION_PATTERN") " + +CVSEditor::CVSEditor(const VCSBase::VCSBaseEditorParameters *type, + QWidget *parent) : + VCSBase::VCSBaseEditor(type, parent), + m_revisionPattern(QLatin1String(CVS_REVISION_AT_START_PATTERN".*$")) +{ + QTC_ASSERT(m_revisionPattern.isValid(), return); +} + +QSet CVSEditor::annotationChanges() const +{ + QSet changes; + const QString txt = toPlainText(); + if (txt.isEmpty()) + return changes; + // Hunt for first change number in annotation: "1.1 (author)" + QRegExp r(QLatin1String(CVS_REVISION_AT_START_PATTERN)); + QTC_ASSERT(r.isValid(), return changes); + if (r.indexIn(txt) != -1) { + changes.insert(r.cap(1)); + r.setPattern(QLatin1String("\n("CVS_REVISION_PATTERN") ")); + QTC_ASSERT(r.isValid(), return changes); + int pos = 0; + while ((pos = r.indexIn(txt, pos)) != -1) { + pos += r.matchedLength(); + changes.insert(r.cap(1)); + } + } + if (CVS::Constants::debug) + qDebug() << "CVSEditor::annotationChanges() returns #" << changes.size(); + return changes; +} + +QString CVSEditor::changeUnderCursor(const QTextCursor &c) const +{ + + // Check for a revision number at the beginning of the line. + // Note that "cursor.select(QTextCursor::WordUnderCursor)" will + // only select the part up until the dot. + // Check if we are at the beginning of a line within a reasonable offset. + const QTextBlock block = c.block(); + if (c.atBlockStart() || (c.position() - block.position() < 3)) { + const QString line = block.text(); + if (m_revisionPattern.exactMatch(line)) + return m_revisionPattern.cap(1); + } + return QString(); +} + +/* \code +cvs diff -d -u -r1.1 -r1.2: +--- mainwindow.cpp<\t>13 Jul 2009 13:50:15 -0000 <\t>1.1 ++++ mainwindow.cpp<\t>14 Jul 2009 07:09:24 -0000<\t>1.2 +@@ -6,6 +6,5 @@ +\endcode +*/ + +VCSBase::DiffHighlighter *CVSEditor::createDiffHighlighter() const +{ + const QRegExp filePattern(QLatin1String("^[-+][-+][-+] .*1\\.[\\d\\.]+$")); + QTC_ASSERT(filePattern.isValid(), /**/); + return new VCSBase::DiffHighlighter(filePattern); +} + +VCSBase::BaseAnnotationHighlighter *CVSEditor::createAnnotationHighlighter(const QSet &changes) const +{ + return new CVSAnnotationHighlighter(changes); +} + +QString CVSEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const +{ + // "+++ mainwindow.cpp<\t>13 Jul 2009 13:50:15 -0000 1.1" + // Go back chunks + const QString diffIndicator = QLatin1String("+++ "); + for (QTextBlock block = inBlock; block.isValid() ; block = block.previous()) { + QString diffFileName = block.text(); + if (diffFileName.startsWith(diffIndicator)) { + diffFileName.remove(0, diffIndicator.size()); + const int tabIndex = diffFileName.indexOf(QLatin1Char('\t')); + if (tabIndex != -1) + diffFileName.truncate(tabIndex); + // Add base dir + if (!m_diffBaseDir.isEmpty()) { + diffFileName.insert(0, QLatin1Char('/')); + diffFileName.insert(0, m_diffBaseDir); + } + + if (CVS::Constants::debug) + qDebug() << "fileNameFromDiffSpecification" << m_diffBaseDir << diffFileName; + return diffFileName; + } + } + return QString(); +} + +QString CVSEditor::diffBaseDir() const +{ + return m_diffBaseDir; +} + +void CVSEditor::setDiffBaseDir(const QString &d) +{ + m_diffBaseDir = d; +} + +void CVSEditor::setDiffBaseDir(Core::IEditor *editor, const QString &db) +{ + if (CVSEditor *cvsEditor = qobject_cast(editor->widget())) + cvsEditor->setDiffBaseDir(db); +} + +} +} diff --git a/src/plugins/cvs/cvseditor.h b/src/plugins/cvs/cvseditor.h new file mode 100644 index 00000000000..8acb42ae23b --- /dev/null +++ b/src/plugins/cvs/cvseditor.h @@ -0,0 +1,69 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef CVSEDITOR_H +#define CVSEDITOR_H + +#include + +#include + +namespace CVS { +namespace Internal { + +class CVSEditor : public VCSBase::VCSBaseEditor +{ + Q_OBJECT + +public: + explicit CVSEditor(const VCSBase::VCSBaseEditorParameters *type, + QWidget *parent); + + // Diff mode requires a base directory since CVS commands + // are run with relative paths (see plugin). + QString diffBaseDir() const; + void setDiffBaseDir(const QString &d); + + static void setDiffBaseDir(Core::IEditor *editor, const QString &db); + +private: + virtual QSet annotationChanges() const; + virtual QString changeUnderCursor(const QTextCursor &) const; + virtual VCSBase::DiffHighlighter *createDiffHighlighter() const; + virtual VCSBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet &changes) const; + virtual QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const; + + const QRegExp m_revisionPattern; + QString m_diffBaseDir; +}; + +} // namespace Internal +} // namespace CVS + +#endif // CVSEDITOR_H diff --git a/src/plugins/cvs/cvsoutputwindow.cpp b/src/plugins/cvs/cvsoutputwindow.cpp new file mode 100644 index 00000000000..2168a03d33e --- /dev/null +++ b/src/plugins/cvs/cvsoutputwindow.cpp @@ -0,0 +1,127 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include "cvsoutputwindow.h" +#include "cvsplugin.h" + +#include +#include + +using namespace CVS::Internal; + +CVSOutputWindow::CVSOutputWindow(CVSPlugin *cvsPlugin) + : m_cvsPlugin(cvsPlugin) +{ + m_outputListWidget = new QListWidget; + m_outputListWidget->setFrameStyle(QFrame::NoFrame); + m_outputListWidget->setWindowTitle(tr("CVS Output")); + m_outputListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); +} + +CVSOutputWindow::~CVSOutputWindow() +{ + delete m_outputListWidget; +} + +QWidget *CVSOutputWindow::outputWidget(QWidget *parent) +{ + m_outputListWidget->setParent(parent); + return m_outputListWidget; +} + +QString CVSOutputWindow::name() const +{ + return tr("CVS"); +} + +void CVSOutputWindow::clearContents() +{ + m_outputListWidget->clear(); +} + +int CVSOutputWindow::priorityInStatusBar() const +{ + return -1; +} + +void CVSOutputWindow::visibilityChanged(bool b) +{ + if (b) + m_outputListWidget->setFocus(); +} + +void CVSOutputWindow::append(const QString &txt, bool doPopup) +{ + const QStringList lines = txt.split(QLatin1Char('\n')); + foreach (const QString &s, lines) + m_outputListWidget->addItem(s); + m_outputListWidget->scrollToBottom(); + + if (doPopup) + popup(); +} + +bool CVSOutputWindow::canFocus() +{ + return false; +} + +bool CVSOutputWindow::hasFocus() +{ + return m_outputListWidget->hasFocus(); +} + +void CVSOutputWindow::setFocus() +{ +} + +bool CVSOutputWindow::canNext() +{ + return false; +} + +bool CVSOutputWindow::canPrevious() +{ + return false; +} + +void CVSOutputWindow::goToNext() +{ + +} + +void CVSOutputWindow::goToPrev() +{ + +} + +bool CVSOutputWindow::canNavigate() +{ + return false; +} diff --git a/src/plugins/cvs/cvsoutputwindow.h b/src/plugins/cvs/cvsoutputwindow.h new file mode 100644 index 00000000000..badb98c92bb --- /dev/null +++ b/src/plugins/cvs/cvsoutputwindow.h @@ -0,0 +1,84 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef CVSOUTPUTWINDOW_H +#define CVSOUTPUTWINDOW_H + +#include + +QT_BEGIN_NAMESPACE +class QListWidget; +QT_END_NAMESPACE + +namespace CVS { +namespace Internal { + +class CVSPlugin; + +class CVSOutputWindow : public Core::IOutputPane +{ + Q_OBJECT + +public: + CVSOutputWindow(CVSPlugin *cvsPlugin); + ~CVSOutputWindow(); + + QWidget *outputWidget(QWidget *parent); + QList toolBarWidgets() const { + return QList(); + } + + QString name() const; + void clearContents(); + int priorityInStatusBar() const; + void visibilityChanged(bool visible); + + bool canFocus(); + bool hasFocus(); + void setFocus(); + + bool canNext(); + bool canPrevious(); + void goToNext(); + void goToPrev(); + bool canNavigate(); + +public slots: + void append(const QString &txt, bool popup = false); + +private: + + CVSPlugin *m_cvsPlugin; + QListWidget *m_outputListWidget; +}; + +} // namespace CVS +} // namespace Internal + +#endif // CVSOUTPUTWINDOW_H diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp new file mode 100644 index 00000000000..c64d32b9aad --- /dev/null +++ b/src/plugins/cvs/cvsplugin.cpp @@ -0,0 +1,1228 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include "cvsplugin.h" +#include "settingspage.h" +#include "cvseditor.h" +#include "cvsoutputwindow.h" +#include "cvssubmiteditor.h" +#include "cvsconstants.h" +#include "cvscontrol.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace CVS { + namespace Internal { + +static inline QString msgCannotFindTopLevel(const QString &f) +{ + return CVSPlugin::tr("Cannot find repository for '%1'").arg(f); +} + +static inline QString msgLogParsingFailed() +{ + return CVSPlugin::tr("Parsing of the log output failed"); +} + +// Timeout for normal output commands +enum { cvsShortTimeOut = 10000 }; +// Timeout for submit, update +enum { cvsLongTimeOut = 120000 }; + +static const char * const CMD_ID_CVS_MENU = "CVS.Menu"; +static const char * const CMD_ID_ADD = "CVS.Add"; +static const char * const CMD_ID_DELETE_FILE = "CVS.Delete"; +static const char * const CMD_ID_REVERT = "CVS.Revert"; +static const char * const CMD_ID_SEPARATOR0 = "CVS.Separator0"; +static const char * const CMD_ID_DIFF_PROJECT = "CVS.DiffAll"; +static const char * const CMD_ID_DIFF_CURRENT = "CVS.DiffCurrent"; +static const char * const CMD_ID_SEPARATOR1 = "CVS.Separator1"; +static const char * const CMD_ID_COMMIT_ALL = "CVS.CommitAll"; +static const char * const CMD_ID_COMMIT_CURRENT = "CVS.CommitCurrent"; +static const char * const CMD_ID_SEPARATOR2 = "CVS.Separator2"; +static const char * const CMD_ID_FILELOG_CURRENT = "CVS.FilelogCurrent"; +static const char * const CMD_ID_ANNOTATE_CURRENT = "CVS.AnnotateCurrent"; +static const char * const CMD_ID_SEPARATOR3 = "CVS.Separator3"; +static const char * const CMD_ID_STATUS = "CVS.Status"; +static const char * const CMD_ID_UPDATE = "CVS.Update"; + +static const VCSBase::VCSBaseEditorParameters editorParameters[] = { +{ + VCSBase::RegularCommandOutput, + "CVS Command Log Editor", // kind + "CVS Command Log Editor", // context + "application/vnd.nokia.text.scs_cvs_commandlog", + "scslog"}, +{ VCSBase::LogOutput, + "CVS File Log Editor", // kind + "CVS File Log Editor", // context + "application/vnd.nokia.text.scs_cvs_filelog", + "scsfilelog"}, +{ VCSBase::AnnotateOutput, + "CVS Annotation Editor", // kind + "CVS Annotation Editor", // context + "application/vnd.nokia.text.scs_cvs_annotation", + "scsannotate"}, +{ VCSBase::DiffOutput, + "CVS Diff Editor", // kind + "CVS Diff Editor", // context + "text/x-patch","diff"} +}; + +// Utility to find a parameter set by type +static inline const VCSBase::VCSBaseEditorParameters *findType(int ie) +{ + const VCSBase::EditorContentType et = static_cast(ie); + return VCSBase::VCSBaseEditor::findType(editorParameters, sizeof(editorParameters)/sizeof(VCSBase::VCSBaseEditorParameters), et); +} + +static inline QString debugCodec(const QTextCodec *c) +{ + return c ? QString::fromAscii(c->name()) : QString::fromAscii("Null codec"); +} + +Core::IEditor* locateEditor(const char *property, const QString &entry) +{ + foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors()) + if (ed->property(property).toString() == entry) + return ed; + return 0; +} + +// ------------- CVSPlugin +CVSPlugin *CVSPlugin::m_cvsPluginInstance = 0; + +CVSPlugin::CVSPlugin() : + m_versionControl(0), + m_changeTmpFile(0), + m_cvsOutputWindow(0), + m_projectExplorer(0), + m_addAction(0), + m_deleteAction(0), + m_revertAction(0), + m_diffProjectAction(0), + m_diffCurrentAction(0), + m_commitAllAction(0), + m_commitCurrentAction(0), + m_filelogCurrentAction(0), + m_annotateCurrentAction(0), + m_statusAction(0), + m_updateProjectAction(0), + m_submitCurrentLogAction(0), + m_submitDiffAction(0), + m_submitUndoAction(0), + m_submitRedoAction(0), + m_submitActionTriggered(false) +{ +} + +CVSPlugin::~CVSPlugin() +{ + cleanChangeTmpFile(); +} + +void CVSPlugin::cleanChangeTmpFile() +{ + if (m_changeTmpFile) { + if (m_changeTmpFile->isOpen()) + m_changeTmpFile->close(); + delete m_changeTmpFile; + m_changeTmpFile = 0; + } +} + +static const VCSBase::VCSBaseSubmitEditorParameters submitParameters = { + CVS::Constants::CVS_SUBMIT_MIMETYPE, + CVS::Constants::CVSCOMMITEDITOR_KIND, + CVS::Constants::CVSCOMMITEDITOR +}; + +static inline Core::Command *createSeparator(QObject *parent, + Core::ActionManager *ami, + const char*id, + const QList &globalcontext) +{ + QAction *tmpaction = new QAction(parent); + tmpaction->setSeparator(true); + return ami->registerAction(tmpaction, id, globalcontext); +} + +bool CVSPlugin::initialize(const QStringList &arguments, QString *errorMessage) +{ + Q_UNUSED(arguments); + + typedef VCSBase::VCSSubmitEditorFactory CVSSubmitEditorFactory; + typedef VCSBase::VCSEditorFactory CVSEditorFactory; + using namespace Constants; + + using namespace Core::Constants; + using namespace ExtensionSystem; + + m_cvsPluginInstance = this; + Core::ICore *core = Core::ICore::instance(); + + if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":/trolltech.cvs/CVS.mimetypes.xml"), errorMessage)) + return false; + + + m_versionControl = new CVSControl(this); + addAutoReleasedObject(m_versionControl); + + if (QSettings *settings = core->settings()) + m_settings.fromSettings(settings); + + addAutoReleasedObject(new CoreListener(this)); + + addAutoReleasedObject(new SettingsPage); + + addAutoReleasedObject(new CVSSubmitEditorFactory(&submitParameters)); + + static const char *describeSlotC = SLOT(slotDescribe(QString,QString)); + const int editorCount = sizeof(editorParameters)/sizeof(VCSBase::VCSBaseEditorParameters); + for (int i = 0; i < editorCount; i++) + addAutoReleasedObject(new CVSEditorFactory(editorParameters + i, this, describeSlotC)); + + m_cvsOutputWindow = new CVSOutputWindow(this); + addAutoReleasedObject(m_cvsOutputWindow); + + //register actions + Core::ActionManager *ami = core->actionManager(); + Core::ActionContainer *toolsContainer = ami->actionContainer(M_TOOLS); + + Core::ActionContainer *cvsMenu = + ami->createMenu(QLatin1String(CMD_ID_CVS_MENU)); + cvsMenu->menu()->setTitle(tr("&CVS")); + toolsContainer->addMenu(cvsMenu); + if (QAction *ma = cvsMenu->menu()->menuAction()) { + ma->setEnabled(m_versionControl->isEnabled()); + connect(m_versionControl, SIGNAL(enabledChanged(bool)), ma, SLOT(setVisible(bool))); + } + + QList globalcontext; + globalcontext << core->uniqueIDManager()->uniqueIdentifier(C_GLOBAL); + + Core::Command *command; + m_addAction = new Core::Utils::ParameterAction(tr("Add"), tr("Add \"%1\""), Core::Utils::ParameterAction::EnabledWithParameter, this); + command = ami->registerAction(m_addAction, CMD_ID_ADD, + globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); +#ifndef Q_WS_MAC + command->setDefaultKeySequence(QKeySequence(tr("Alt+C,Alt+A"))); +#endif + connect(m_addAction, SIGNAL(triggered()), this, SLOT(addCurrentFile())); + cvsMenu->addAction(command); + + m_deleteAction = new Core::Utils::ParameterAction(tr("Delete"), tr("Delete \"%1\""), Core::Utils::ParameterAction::EnabledWithParameter, this); + command = ami->registerAction(m_deleteAction, CMD_ID_DELETE_FILE, + globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); + connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deleteCurrentFile())); + cvsMenu->addAction(command); + + m_revertAction = new Core::Utils::ParameterAction(tr("Revert"), tr("Revert \"%1\""), Core::Utils::ParameterAction::EnabledWithParameter, this); + command = ami->registerAction(m_revertAction, CMD_ID_REVERT, + globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); + connect(m_revertAction, SIGNAL(triggered()), this, SLOT(revertCurrentFile())); + cvsMenu->addAction(command); + + cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR0, globalcontext)); + + m_diffProjectAction = new QAction(tr("Diff Project"), this); + command = ami->registerAction(m_diffProjectAction, CMD_ID_DIFF_PROJECT, + globalcontext); + connect(m_diffProjectAction, SIGNAL(triggered()), this, SLOT(diffProject())); + cvsMenu->addAction(command); + + m_diffCurrentAction = new Core::Utils::ParameterAction(tr("Diff Current File"), tr("Diff \"%1\""), Core::Utils::ParameterAction::EnabledWithParameter, this); + command = ami->registerAction(m_diffCurrentAction, + CMD_ID_DIFF_CURRENT, globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); +#ifndef Q_WS_MAC + command->setDefaultKeySequence(QKeySequence(tr("Alt+C,Alt+D"))); +#endif + connect(m_diffCurrentAction, SIGNAL(triggered()), this, SLOT(diffCurrentFile())); + cvsMenu->addAction(command); + + cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR1, globalcontext)); + + m_commitAllAction = new QAction(tr("Commit All Files"), this); + command = ami->registerAction(m_commitAllAction, CMD_ID_COMMIT_ALL, + globalcontext); + connect(m_commitAllAction, SIGNAL(triggered()), this, SLOT(startCommitAll())); + cvsMenu->addAction(command); + + m_commitCurrentAction = new Core::Utils::ParameterAction(tr("Commit Current File"), tr("Commit \"%1\""), Core::Utils::ParameterAction::EnabledWithParameter, this); + command = ami->registerAction(m_commitCurrentAction, + CMD_ID_COMMIT_CURRENT, globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); +#ifndef Q_WS_MAC + command->setDefaultKeySequence(QKeySequence(tr("Alt+C,Alt+C"))); +#endif + connect(m_commitCurrentAction, SIGNAL(triggered()), this, SLOT(startCommitCurrentFile())); + cvsMenu->addAction(command); + + cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR2, globalcontext)); + + m_filelogCurrentAction = new Core::Utils::ParameterAction(tr("Filelog Current File"), tr("Filelog \"%1\""), Core::Utils::ParameterAction::EnabledWithParameter, this); + command = ami->registerAction(m_filelogCurrentAction, + CMD_ID_FILELOG_CURRENT, globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); + connect(m_filelogCurrentAction, SIGNAL(triggered()), this, + SLOT(filelogCurrentFile())); + cvsMenu->addAction(command); + + m_annotateCurrentAction = new Core::Utils::ParameterAction(tr("Annotate Current File"), tr("Annotate \"%1\""), Core::Utils::ParameterAction::EnabledWithParameter, this); + command = ami->registerAction(m_annotateCurrentAction, + CMD_ID_ANNOTATE_CURRENT, globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); + connect(m_annotateCurrentAction, SIGNAL(triggered()), this, + SLOT(annotateCurrentFile())); + cvsMenu->addAction(command); + + cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR3, globalcontext)); + + m_statusAction = new QAction(tr("Project Status"), this); + command = ami->registerAction(m_statusAction, CMD_ID_STATUS, + globalcontext); + connect(m_statusAction, SIGNAL(triggered()), this, SLOT(projectStatus())); + cvsMenu->addAction(command); + + m_updateProjectAction = new QAction(tr("Update Project"), this); + command = ami->registerAction(m_updateProjectAction, CMD_ID_UPDATE, globalcontext); + connect(m_updateProjectAction, SIGNAL(triggered()), this, SLOT(updateProject())); + cvsMenu->addAction(command); + + // Actions of the submit editor + QList cvscommitcontext; + cvscommitcontext << Core::UniqueIDManager::instance()->uniqueIdentifier(Constants::CVSCOMMITEDITOR); + + m_submitCurrentLogAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this); + command = ami->registerAction(m_submitCurrentLogAction, Constants::SUBMIT_CURRENT, cvscommitcontext); + connect(m_submitCurrentLogAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog())); + + m_submitDiffAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this); + command = ami->registerAction(m_submitDiffAction , Constants::DIFF_SELECTED, cvscommitcontext); + + m_submitUndoAction = new QAction(tr("&Undo"), this); + command = ami->registerAction(m_submitUndoAction, Core::Constants::UNDO, cvscommitcontext); + + m_submitRedoAction = new QAction(tr("&Redo"), this); + command = ami->registerAction(m_submitRedoAction, Core::Constants::REDO, cvscommitcontext); + + connect(Core::ICore::instance(), SIGNAL(contextChanged(Core::IContext *)), this, SLOT(updateActions())); + + return true; +} + +void CVSPlugin::extensionsInitialized() +{ + m_projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance(); + if (m_projectExplorer) { + connect(m_projectExplorer, + SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), + m_cvsPluginInstance, SLOT(updateActions())); + } + updateActions(); +} + +bool CVSPlugin::editorAboutToClose(Core::IEditor *iEditor) +{ + if (!m_changeTmpFile || !iEditor || qstrcmp(Constants::CVSCOMMITEDITOR, iEditor->kind())) + return true; + + Core::IFile *fileIFace = iEditor->file(); + const CVSSubmitEditor *editor = qobject_cast(iEditor); + if (!fileIFace || !editor) + return true; + + // Submit editor closing. Make it write out the commit message + // and retrieve files + const QFileInfo editorFile(fileIFace->fileName()); + const QFileInfo changeFile(m_changeTmpFile->fileName()); + if (editorFile.absoluteFilePath() != changeFile.absoluteFilePath()) + return true; // Oops?! + + // Prompt user. Force a prompt unless submit was actually invoked (that + // is, the editor was closed or shutdown). + CVSSettings newSettings = m_settings; + const VCSBase::VCSBaseSubmitEditor::PromptSubmitResult answer = + editor->promptSubmit(tr("Closing CVS Editor"), + tr("Do you want to commit the change?"), + tr("The commit message check failed. Do you want to commit the change?"), + &newSettings.promptToSubmit, !m_submitActionTriggered); + m_submitActionTriggered = false; + switch (answer) { + case VCSBase::VCSBaseSubmitEditor::SubmitCanceled: + return false; // Keep editing and change file + case VCSBase::VCSBaseSubmitEditor::SubmitDiscarded: + cleanChangeTmpFile(); + return true; // Cancel all + default: + break; + } + setSettings(newSettings); // in case someone turned prompting off + const QStringList fileList = editor->checkedFiles(); + bool closeEditor = true; + if (!fileList.empty()) { + // get message & commit + Core::ICore::instance()->fileManager()->blockFileChange(fileIFace); + fileIFace->save(); + Core::ICore::instance()->fileManager()->unblockFileChange(fileIFace); + closeEditor= commit(m_changeTmpFile->fileName(), fileList); + } + if (closeEditor) + cleanChangeTmpFile(); + return closeEditor; +} + +void CVSPlugin::diffFiles(const QStringList &files) +{ + cvsDiff(files); +} + +void CVSPlugin::cvsDiff(const QStringList &files, QString diffname) +{ + if (CVS::Constants::debug) + qDebug() << Q_FUNC_INFO << files << diffname; + const QString source = files.empty() ? QString() : files.front(); + QTextCodec *codec = source.isEmpty() ? static_cast(0) : VCSBase::VCSBaseEditor::getCodec(source); + + if (files.count() == 1 && diffname.isEmpty()) + diffname = QFileInfo(files.front()).fileName(); + + QStringList args(QLatin1String("diff")); + args << m_settings.cvsDiffOptions; + + // CVS returns the diff exit code (1 if files differ), which is + // undistinguishable from a "file not found" error, unfortunately. + const CVSResponse response = runCVS(args, files, cvsShortTimeOut, false, codec); + switch (response.result) { + case CVSResponse::NonNullExitCode: + case CVSResponse::Ok: + break; + case CVSResponse::OtherError: + return; + } + + QString output = fixDiffOutput(response.stdOut); + if (output.isEmpty()) + output = tr("The files do not differ."); + // diff of a single file? re-use an existing view if possible to support + // the common usage pattern of continuously changing and diffing a file + if (files.count() == 1) { + // Show in the same editor if diff has been executed before + if (Core::IEditor *editor = locateEditor("originalFileName", files.front())) { + editor->createNew(output); + Core::EditorManager::instance()->activateEditor(editor); + CVSEditor::setDiffBaseDir(editor, response.workingDirectory); + return; + } + } + const QString title = QString::fromLatin1("cvs diff %1").arg(diffname); + Core::IEditor *editor = showOutputInEditor(title, output, VCSBase::DiffOutput, source, codec); + if (files.count() == 1) + editor->setProperty("originalFileName", files.front()); + CVSEditor::setDiffBaseDir(editor, response.workingDirectory); +} + +CVSSubmitEditor *CVSPlugin::openCVSSubmitEditor(const QString &fileName) +{ + Core::IEditor *editor = Core::EditorManager::instance()->openEditor(fileName, QLatin1String(Constants::CVSCOMMITEDITOR_KIND)); + CVSSubmitEditor *submitEditor = qobject_cast(editor); + QTC_ASSERT(submitEditor, /**/); + submitEditor->registerActions(m_submitUndoAction, m_submitRedoAction, m_submitCurrentLogAction, m_submitDiffAction); + connect(submitEditor, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(diffFiles(QStringList))); + + return submitEditor; +} + +void CVSPlugin::updateActions() +{ + m_diffProjectAction->setEnabled(true); + m_commitAllAction->setEnabled(true); + m_statusAction->setEnabled(true); + + const QString fileName = currentFileName(); + const QString baseName = fileName.isEmpty() ? fileName : QFileInfo(fileName).fileName(); + + m_addAction->setParameter(baseName); + m_deleteAction->setParameter(baseName); + m_revertAction->setParameter(baseName); + m_diffCurrentAction->setParameter(baseName); + m_commitCurrentAction->setParameter(baseName); + m_filelogCurrentAction->setParameter(baseName); + m_annotateCurrentAction->setParameter(baseName); +} + +void CVSPlugin::addCurrentFile() +{ + const QString file = currentFileName(); + if (!file.isEmpty()) + vcsAdd(file); +} + +void CVSPlugin::deleteCurrentFile() +{ + const QString file = currentFileName(); + if (file.isEmpty()) + return; + if (!Core::ICore::instance()->vcsManager()->showDeleteDialog(file)) + QMessageBox::warning(0, QLatin1String("CVS remove"), tr("The file '%1' could not be deleted.").arg(file), QMessageBox::Ok); +} + +void CVSPlugin::revertCurrentFile() +{ + const QString file = currentFileName(); + if (file.isEmpty()) + return; + + const CVSResponse diffResponse = runCVS(QStringList(QLatin1String("diff")), QStringList(file), cvsShortTimeOut, false); + switch (diffResponse.result) { + case CVSResponse::Ok: + return; // Not modified, diff exit code 0 + case CVSResponse::NonNullExitCode: // Diff exit code != 0 + if (diffResponse.stdOut.isEmpty()) // Paranoia: Something else failed? + return; + break; + case CVSResponse::OtherError: + return; + } + + if (QMessageBox::warning(0, QLatin1String("CVS revert"), tr("The file has been changed. Do you want to revert it?"), + QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) + return; + + Core::FileChangeBlocker fcb(file); + + // revert + QStringList args(QLatin1String("update")); + args.push_back(QLatin1String("-C")); + + const CVSResponse revertResponse = runCVS(args, QStringList(file), cvsShortTimeOut, true); + if (revertResponse.result == CVSResponse::Ok) { + fcb.setModifiedReload(true); + } +} + +// Get a unique set of toplevel directories for the current projects. +// To be used for "diff all" or "commit all". +QStringList CVSPlugin::currentProjectsTopLevels(QString *name) const +{ + typedef QList ProjectList; + ProjectList projects; + // Compile list of projects + if (ProjectExplorer::Project *currentProject = m_projectExplorer->currentProject()) { + projects.push_back(currentProject); + } else { + if (const ProjectExplorer::SessionManager *session = m_projectExplorer->session()) + projects.append(session->projects()); + } + // Get unique set of toplevels and concat project names + QStringList toplevels; + const QChar blank(QLatin1Char(' ')); + foreach (const ProjectExplorer::Project *p, projects) { + if (name) { + if (!name->isEmpty()) + name->append(blank); + name->append(p->name()); + } + + const QString projectPath = QFileInfo(p->file()->fileName()).absolutePath(); + const QString topLevel = findTopLevelForDirectory(projectPath); + if (!topLevel.isEmpty() && !toplevels.contains(topLevel)) + toplevels.push_back(topLevel); + } + return toplevels; +} + +void CVSPlugin::diffProject() +{ + QString diffName; + const QStringList topLevels = currentProjectsTopLevels(&diffName); + if (!topLevels.isEmpty()) + cvsDiff(topLevels, diffName); +} + +void CVSPlugin::diffCurrentFile() +{ + cvsDiff(QStringList(currentFileName())); +} + +void CVSPlugin::startCommitCurrentFile() +{ + const QString file = currentFileName(); + if (!file.isEmpty()) + startCommit(file); +} + +void CVSPlugin::startCommitAll() +{ + // Make sure we have only repository for commit + const QStringList files = currentProjectsTopLevels(); + switch (files.size()) { + case 0: + break; + case 1: + startCommit(files.front()); + break; + default: { + const QString msg = tr("The commit list spans several repositories (%1). Please commit them one by one."). + arg(files.join(QString(QLatin1Char(' ')))); + QMessageBox::warning(0, QLatin1String("cvs commit"), msg, QMessageBox::Ok); + } + break; + } +} + +/* Start commit of files of a single repository by displaying + * template and files in a submit editor. On closing, the real + * commit will start. */ +void CVSPlugin::startCommit(const QString &source) +{ + if (source.isEmpty()) + return; + if (VCSBase::VCSBaseSubmitEditor::raiseSubmitEditor()) + return; + if (m_changeTmpFile) { + showOutput(tr("Another commit is currently being executed.")); + return; + } + const QFileInfo sourceFi(source); + const QString sourceDir = sourceFi.isDir() ? source : sourceFi.absolutePath(); + const QString topLevel = findTopLevelForDirectory(sourceDir); + if (topLevel.isEmpty()) { + showOutput(msgCannotFindTopLevel(source), true); + return; + } + // We need the "Examining " stderr output to tell + // where we are, so, have stdout/stderr channels merged. + QStringList args(QStringList(QLatin1String("status"))); + if (sourceDir == topLevel) { + args.push_back(QString(QLatin1Char('.'))); + } else { + args.push_back(QDir(topLevel).relativeFilePath(source)); + } + const CVSResponse response = runCVS(topLevel, args, cvsShortTimeOut, false, 0, true); + if (response.result != CVSResponse::Ok) + return; + // Get list of added/modified/deleted files + // As we run cvs in the repository directory, we need complete + // the file names by the respective directory. + const StateList statusOutput = parseStatusOutput(topLevel, response.stdOut); + if (CVS::Constants::debug) + qDebug() << Q_FUNC_INFO << '\n' << source << "top" << topLevel; + + if (statusOutput.empty()) { + showOutput(tr("There are no modified files."), true); + return; + } + + // Create a new submit change file containing the submit template + QTemporaryFile *changeTmpFile = new QTemporaryFile(this); + changeTmpFile->setAutoRemove(true); + if (!changeTmpFile->open()) { + showOutput(tr("Cannot create temporary file: %1").arg(changeTmpFile->errorString())); + delete changeTmpFile; + return; + } + m_changeTmpFile = changeTmpFile; + // TODO: Retrieve submit template from + const QString submitTemplate; + // Create a submit + m_changeTmpFile->write(submitTemplate.toUtf8()); + m_changeTmpFile->flush(); + m_changeTmpFile->seek(0); + // Create a submit editor and set file list + CVSSubmitEditor *editor = openCVSSubmitEditor(m_changeTmpFile->fileName()); + editor->setStateList(statusOutput); +} + +bool CVSPlugin::commit(const QString &messageFile, + const QStringList &fileList) +{ + if (CVS::Constants::debug) + qDebug() << Q_FUNC_INFO << messageFile << fileList; + QStringList args = QStringList(QLatin1String("commit")); + args << QLatin1String("-F") << messageFile; + const CVSResponse response = runCVS(args, fileList, cvsLongTimeOut, true); + return response.result == CVSResponse::Ok ; +} + +void CVSPlugin::filelogCurrentFile() +{ + const QString file = currentFileName(); + if (!file.isEmpty()) + filelog(file); +} + +void CVSPlugin::filelog(const QString &file) +{ + QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(file); + // no need for temp file + const CVSResponse response = runCVS(QStringList(QLatin1String("log")), QStringList(file), cvsShortTimeOut, false, codec); + if (response.result != CVSResponse::Ok) + return; + + // Re-use an existing view if possible to support + // the common usage pattern of continuously changing and diffing a file + + if (Core::IEditor *editor = locateEditor("logFileName", file)) { + editor->createNew(response.stdOut); + Core::EditorManager::instance()->activateEditor(editor); + } else { + const QString title = QString::fromLatin1("cvs log %1").arg(QFileInfo(file).fileName()); + Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, file, codec); + newEditor->setProperty("logFileName", file); + } +} + +void CVSPlugin::updateProject() +{ + const QStringList topLevels = currentProjectsTopLevels(); + if (!topLevels.empty()) { + QStringList args(QLatin1String("update")); + args.push_back(QLatin1String("-dR")); + runCVS(args, topLevels, cvsLongTimeOut, true); + } +} + +void CVSPlugin::annotateCurrentFile() +{ + const QString file = currentFileName(); + if (!file.isEmpty()) + annotate(file); +} + +void CVSPlugin::annotate(const QString &file) +{ + QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(file); + const CVSResponse response = runCVS(QStringList(QLatin1String("annotate")), QStringList(file), cvsShortTimeOut, false, codec); + if (response.result != CVSResponse::Ok) + return; + + // Re-use an existing view if possible to support + // the common usage pattern of continuously changing and diffing a file + + if (Core::IEditor *editor = locateEditor("annotateFileName", file)) { + editor->createNew(response.stdOut); + Core::EditorManager::instance()->activateEditor(editor); + } else { + const QString title = QString::fromLatin1("cvs annotate %1").arg(QFileInfo(file).fileName()); + Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, file, codec); + newEditor->setProperty("annotateFileName", file); + } +} + +void CVSPlugin::projectStatus() +{ + if (!m_projectExplorer) + return; + + const QStringList topLevels = currentProjectsTopLevels(); + if (topLevels.empty()) + return; + + const CVSResponse response = runCVS(QStringList(QLatin1String("status")), topLevels, cvsShortTimeOut, false); + if (response.result == CVSResponse::Ok) + showOutputInEditor(tr("Project status"), response.stdOut, VCSBase::RegularCommandOutput, topLevels.front(), 0); +} + +// Decrement version number "1.2" -> "1.1" +static QString previousRevision(const QString &rev) +{ + const int dotPos = rev.lastIndexOf(QLatin1Char('.')); + if (dotPos == -1) + return rev; + const int minor = rev.mid(dotPos + 1).toInt(); + return rev.left(dotPos + 1) + QString::number(minor - 1); +} + +void CVSPlugin::slotDescribe(const QString &source, const QString &changeNr) +{ + QString errorMessage; + if (!describe(source, changeNr, &errorMessage)) + showOutput(errorMessage, true); +} + +bool CVSPlugin::describe(const QString &file, const QString &changeNr, QString *errorMessage) +{ + // In CVS, revisions of files are normally unrelated, there is + // no global revision/change number. The only thing that groups + // a commit is the "commit-id" (as shown in the log). + // This function makes use of it to find all files related to + // a commit in order to emulate a "describe global change" functionality + // if desired. + if (CVS::Constants::debug) + qDebug() << Q_FUNC_INFO << file << changeNr; + const QString toplevel = findTopLevelForDirectory(QFileInfo(file).absolutePath()); + if (toplevel.isEmpty()) { + *errorMessage = msgCannotFindTopLevel(file); + return false; + } + // Number must be > 1 + if (changeNr.endsWith(QLatin1Char('1'))) { + *errorMessage = tr("The initial revision %1 cannot be described.").arg(changeNr); + return false; + } + // Run log to obtain commit id and details + QStringList args(QLatin1String("log")); + args.push_back(QLatin1String("-r") + changeNr); + const CVSResponse logResponse = runCVS(args, QStringList(file), cvsShortTimeOut, false); + if (logResponse.result != CVSResponse::Ok) { + *errorMessage = logResponse.message; + return false; + } + const QList fileLog = parseLogEntries(logResponse.stdOut, logResponse.workingDirectory); + if (fileLog.empty() || fileLog.front().revisions.empty()) { + *errorMessage = msgLogParsingFailed(); + return false; + } + if (m_settings.describeByCommitId) { + // Run a log command over the repo, filtering by the commit date + // and commit id, collecting all files touched by the commit. + const QString commitId = fileLog.front().revisions.front().commitId; + // Date range "D1 repoEntries = parseLogEntries(repoLogResponse.stdOut, QFileInfo(toplevel).absolutePath(), commitId); + if (repoEntries.empty()) { + *errorMessage = tr("Could not find commits of id '%1' on %2.").arg(commitId, dateS); + return false; + } + return describe(toplevel, repoEntries, errorMessage); + } else { + // Just describe that single entry + return describe(toplevel, fileLog, errorMessage); + } + return false; +} + +// Describe a set of files and revisions by +// concatenating log and diffs to previous revisions +bool CVSPlugin::describe(const QString &repositoryPath, QList entries, + QString *errorMessage) +{ + // Collect logs + QString output; + const QDir repository(repositoryPath); + QTextCodec *codec = 0; + const QList::iterator lend = entries.end(); + for (QList::iterator it = entries.begin(); it != lend; ++it) { + // Before fiddling file names, try to find codec + if (!codec) + codec = VCSBase::VCSBaseEditor::getCodec(it->file); + // Make the files relative to the repository directory. + it->file = repository.relativeFilePath(it->file); + // Run log + QStringList args(QLatin1String("log")); + args << (QLatin1String("-r") + it->revisions.front().revision) << it->file; + const CVSResponse logResponse = runCVS(repositoryPath, args, cvsShortTimeOut, false); + if (logResponse.result != CVSResponse::Ok) { + *errorMessage = logResponse.message; + return false; + } + output += logResponse.stdOut; + } + // Collect diffs relative to repository + for (QList::iterator it = entries.begin(); it != lend; ++it) { + const QString previousRev = previousRevision(it->revisions.front().revision); + QStringList args(QLatin1String("diff")); + args << m_settings.cvsDiffOptions << QLatin1String("-r") << previousRev + << QLatin1String("-r") << it->revisions.front().revision + << it->file; + const CVSResponse diffResponse = runCVS(repositoryPath, args, cvsShortTimeOut, false, codec); + switch (diffResponse.result) { + case CVSResponse::Ok: + case CVSResponse::NonNullExitCode: // Diff exit code != 0 + if (diffResponse.stdOut.isEmpty()) { + *errorMessage = diffResponse.message; + return false; // Something else failed. + } + break; + case CVSResponse::OtherError: + *errorMessage = diffResponse.message; + return false; + } + output += fixDiffOutput(diffResponse.stdOut); + } + + // Re-use an existing view if possible to support + // the common usage pattern of continuously changing and diffing a file + const QString commitId = entries.front().revisions.front().commitId; + if (Core::IEditor *editor = locateEditor("describeChange", commitId)) { + editor->createNew(output); + Core::EditorManager::instance()->activateEditor(editor); + CVSEditor::setDiffBaseDir(editor, repositoryPath); + } else { + const QString title = QString::fromLatin1("cvs describe %1").arg(commitId); + Core::IEditor *newEditor = showOutputInEditor(title, output, VCSBase::DiffOutput, entries.front().file, codec); + newEditor->setProperty("describeChange", commitId); + CVSEditor::setDiffBaseDir(newEditor, repositoryPath); + } + return true; +} + +void CVSPlugin::submitCurrentLog() +{ + m_submitActionTriggered = true; + Core::EditorManager::instance()->closeEditors(QList() + << Core::EditorManager::instance()->currentEditor()); +} + +QString CVSPlugin::currentFileName() const +{ + const QString fileName = Core::ICore::instance()->fileManager()->currentFile(); + if (!fileName.isEmpty()) { + const QFileInfo fi(fileName); + if (fi.exists()) + return fi.canonicalFilePath(); + } + return QString(); +} + +static inline QString processStdErr(QProcess &proc) +{ + return QString::fromLocal8Bit(proc.readAllStandardError()).remove(QLatin1Char('\r')); +} + +static inline QString processStdOut(QProcess &proc, QTextCodec *outputCodec = 0) +{ + const QByteArray stdOutData = proc.readAllStandardOutput(); + QString stdOut = outputCodec ? outputCodec->toUnicode(stdOutData) : QString::fromLocal8Bit(stdOutData); + return stdOut.remove(QLatin1Char('\r')); +} + +/* Tortoise CVS does not allow for absolute path names + * (which it claims to be CVS standard behaviour). + * So, try to figure out the common root of the file arguments, + * remove it from the files and return it as working directory for + * the process. Note that it is principle possible to have + * projects with differing repositories open in a session, + * so, trying to find a common repository is not an option. + * Usually, there is only one file argument, which is not + * problematic; it is just split using QFileInfo. */ + +// Figure out length of common start of string ("C:\a", "c:\b" -> "c:\" +static inline int commonPartSize(const QString &s1, const QString &s2) +{ + const int size = qMin(s1.size(), s2.size()); + for (int i = 0; i < size; i++) + if (s1.at(i) != s2.at(i)) + return i; + return size; +} + +static inline QString fixFileArgs(QStringList *files) +{ + switch (files->size()) { + case 0: + return QString(); + case 1: { // Easy, just one + const QFileInfo fi(files->at(0)); + (*files)[0] = fi.fileName(); + return fi.absolutePath(); + } + default: + break; + } + // Figure out common string part: "C:\foo\bar1" "C:\foo\bar2" -> "C:\foo\bar" + int commonLength = INT_MAX; + const int last = files->size() - 1; + for (int i = 0; i < last; i++) + commonLength = qMin(commonLength, commonPartSize(files->at(i), files->at(i + 1))); + if (!commonLength) + return QString(); + // Find directory part: "C:\foo\bar" -> "C:\foo" + QString common = files->at(0).left(commonLength); + int lastSlashPos = common.lastIndexOf(QLatin1Char('/')); + if (lastSlashPos == -1) + lastSlashPos = common.lastIndexOf(QLatin1Char('\\')); + if (lastSlashPos == -1) + return QString(); +#ifdef Q_OS_UNIX + if (lastSlashPos == 0) // leave "/a", "/b" untouched + return QString(); +#endif + common.truncate(lastSlashPos); + // remove up until slash from the files + commonLength = lastSlashPos + 1; + const QStringList::iterator end = files->end(); + for (QStringList::iterator it = files->begin(); it != end; ++it) { + it->remove(0, commonLength); + } + return common; +} + +// Format log entry for command +static inline QString msgExecutionLogEntry(const QString &workingDir, const QString &executable, const QStringList &arguments) +{ + const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm")); + //: Executing: + const QString args = arguments.join(QString(QLatin1Char(' '))); + if (workingDir.isEmpty()) + return CVSPlugin::tr("%1 Executing: %2 %3\n").arg(timeStamp, executable, args); + return CVSPlugin::tr("%1 Executing in %2: %3 %4\n").arg(timeStamp, workingDir, executable, args); +} + +// Figure out a working directory for the process, +// fix the file arguments accordingly and run CVS. +CVSResponse CVSPlugin::runCVS(const QStringList &arguments, + QStringList files, + int timeOut, + bool showStdOutInOutputWindow, + QTextCodec *outputCodec, + bool mergeStderr) +{ + const QString workingDirectory = fixFileArgs(&files); + return runCVS( workingDirectory, arguments + files, timeOut, showStdOutInOutputWindow, outputCodec, mergeStderr); +} + +// Run CVS. At this point, file arguments must be relative to +// the working directory (see above). +CVSResponse CVSPlugin::runCVS(const QString &workingDirectory, + const QStringList &arguments, + int timeOut, + bool showStdOutInOutputWindow, QTextCodec *outputCodec, + bool mergeStderr) +{ + const QString executable = m_settings.cvsCommand; + CVSResponse response; + if (executable.isEmpty()) { + response.result = CVSResponse::OtherError; + response.message =tr("No cvs executable specified!"); + return response; + } + // Fix files and compile complete arguments + response.workingDirectory = workingDirectory; + const QStringList allArgs = m_settings.addOptions(arguments); + + const QString outputText = msgExecutionLogEntry(response.workingDirectory, executable, allArgs); + showOutput(outputText, false); + + if (CVS::Constants::debug) + qDebug() << "runCVS" << timeOut << outputText; + + // Run, connect stderr to the output window + Core::Utils::SynchronousProcess process; + if (!response.workingDirectory.isEmpty()) + process.setWorkingDirectory(response.workingDirectory); + + if (mergeStderr) + process.setProcessChannelMode(QProcess::MergedChannels); + + process.setTimeout(timeOut); + process.setStdOutCodec(outputCodec); + + process.setStdErrBufferedSignalsEnabled(true); + connect(&process, SIGNAL(stdErrBuffered(QString,bool)), m_cvsOutputWindow, SLOT(append(QString,bool))); + + // connect stdout to the output window if desired + if (showStdOutInOutputWindow) { + process.setStdOutBufferedSignalsEnabled(true); + connect(&process, SIGNAL(stdOutBuffered(QString,bool)), m_cvsOutputWindow, SLOT(append(QString,bool))); + } + + const Core::Utils::SynchronousProcessResponse sp_resp = process.run(executable, allArgs); + response.result = CVSResponse::OtherError; + response.stdErr = sp_resp.stdErr; + response.stdOut = sp_resp.stdOut; + switch (sp_resp.result) { + case Core::Utils::SynchronousProcessResponse::Finished: + response.result = CVSResponse::Ok; + break; + case Core::Utils::SynchronousProcessResponse::FinishedError: + response.result = CVSResponse::NonNullExitCode; + response.message = tr("The process terminated with exit code %1.").arg(sp_resp.exitCode); + break; + case Core::Utils::SynchronousProcessResponse::TerminatedAbnormally: + response.message = tr("The process terminated abnormally."); + break; + case Core::Utils::SynchronousProcessResponse::StartFailed: + response.message = tr("Could not start cvs '%1'. Please check your settings in the preferences.").arg(executable); + break; + case Core::Utils::SynchronousProcessResponse::Hang: + response.message = tr("CVS did not respond within timeout limit (%1 ms).").arg(timeOut); + break; + } + if (response.result != CVSResponse::Ok) + m_cvsOutputWindow->append(response.message, true); + + return response; +} + +void CVSPlugin::showOutput(const QString &output, bool bringToForeground) +{ + m_cvsOutputWindow->append(output); + if (bringToForeground) + m_cvsOutputWindow->popup(); +} + +Core::IEditor * CVSPlugin::showOutputInEditor(const QString& title, const QString &output, + int editorType, const QString &source, + QTextCodec *codec) +{ + const VCSBase::VCSBaseEditorParameters *params = findType(editorType); + QTC_ASSERT(params, return 0); + const QString kind = QLatin1String(params->kind); + if (CVS::Constants::debug) + qDebug() << "CVSPlugin::showOutputInEditor" << title << kind << "source=" << source << "Size= " << output.size() << " Type=" << editorType << debugCodec(codec); + QString s = title; + Core::IEditor *editor = Core::EditorManager::instance()->newFile(kind, &s, output.toLocal8Bit()); + CVSEditor *e = qobject_cast(editor->widget()); + if (!e) + return 0; + s.replace(QLatin1Char(' '), QLatin1Char('_')); + e->setSuggestedFileName(s); + if (!source.isEmpty()) + e->setSource(source); + if (codec) + e->setCodec(codec); + Core::IEditor *ie = e->editableInterface(); + Core::EditorManager::instance()->activateEditor(ie); + return ie; +} + +CVSSettings CVSPlugin::settings() const +{ + return m_settings; +} + +void CVSPlugin::setSettings(const CVSSettings &s) +{ + if (s != m_settings) { + m_settings = s; + if (QSettings *settings = Core::ICore::instance()->settings()) + m_settings.toSettings(settings); + } +} + +CVSPlugin *CVSPlugin::cvsPluginInstance() +{ + QTC_ASSERT(m_cvsPluginInstance, return m_cvsPluginInstance); + return m_cvsPluginInstance; +} + +bool CVSPlugin::vcsAdd(const QString &rawFileName) +{ + const CVSResponse response = runCVS(QStringList(QLatin1String("add")), QStringList(rawFileName), cvsShortTimeOut, true); + return response.result == CVSResponse::Ok; +} + +bool CVSPlugin::vcsDelete(const QString &rawFileName) +{ + QStringList args(QLatin1String("remove")); + args << QLatin1String("-f"); + const CVSResponse response = runCVS(args, QStringList(rawFileName), cvsShortTimeOut, true); + return response.result == CVSResponse::Ok; +} + +/* CVS has a "CVS" directory in each directory it manages. The top level + * is the first directory under the directory that does not have it. */ +bool CVSPlugin::managesDirectory(const QString &directory) const +{ + const QDir dir(directory); + const bool rc = dir.exists() && managesDirectory(dir); + if (CVS::Constants::debug) + qDebug() << "CVSPlugin::managesDirectory" << directory << rc; + return rc; +} + +bool CVSPlugin::managesDirectory(const QDir &directory) const +{ + const QString cvsDir = directory.absoluteFilePath(QLatin1String("CVS")); + return QFileInfo(cvsDir).isDir(); +} + +QString CVSPlugin::findTopLevelForDirectory(const QString &directory) const +{ + // Debug wrapper + const QString rc = findTopLevelForDirectoryI(directory); + if (CVS::Constants::debug) + qDebug() << "CVSPlugin::findTopLevelForDirectory" << directory << rc; + return rc; +} + +QString CVSPlugin::findTopLevelForDirectoryI(const QString &directory) const +{ + /* Recursing up, the top level is a child of the first directory that does + * not have a "CVS" directory. The starting directory must be a managed + * one. Go up and try to find the first unmanaged parent dir. */ + QDir lastDirectory = QDir(directory); + if (!lastDirectory.exists() || !managesDirectory(lastDirectory)) + return QString(); + for (QDir parentDir = lastDirectory; parentDir.cdUp() ; lastDirectory = parentDir) { + if (!managesDirectory(parentDir)) + return lastDirectory.absolutePath(); + } + return QString(); +} + +} +} +Q_EXPORT_PLUGIN(CVS::Internal::CVSPlugin) diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h new file mode 100644 index 00000000000..ef54049e71b --- /dev/null +++ b/src/plugins/cvs/cvsplugin.h @@ -0,0 +1,208 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef CVSPLUGIN_H +#define CVSPLUGIN_H + +#include "cvssettings.h" +#include "cvsutils.h" + +#include +#include + +QT_BEGIN_NAMESPACE +class QDir; +class QAction; +class QTemporaryFile; +class QTextCodec; +QT_END_NAMESPACE + +namespace Core { + class IEditorFactory; + class IVersionControl; + namespace Utils { + class ParameterAction; + } +} + +namespace ProjectExplorer { + class ProjectExplorerPlugin; +} + +namespace CVS { +namespace Internal { + +class CVSOutputWindow; +class CVSSubmitEditor; + +struct CVSResponse +{ + enum Result { Ok, NonNullExitCode, OtherError }; + CVSResponse() : result(Ok) {} + + Result result; + QString stdOut; + QString stdErr; + QString message; + QString workingDirectory; +}; + +/* This plugin differs from the other VCS plugins in that it + * runs CVS commands from a working directory using relative + * path specifications, which is a requirement imposed by + * Tortoise CVS. This has to be taken into account; for example, + * the diff editor has an additional property specifying the + * base directory for its interaction to work. */ + +class CVSPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + +public: + CVSPlugin(); + ~CVSPlugin(); + + virtual bool initialize(const QStringList &arguments, QString *error_message); + virtual void extensionsInitialized(); + virtual bool editorAboutToClose(Core::IEditor *editor); + + void cvsDiff(const QStringList &files, QString diffname = QString()); + + CVSSubmitEditor *openCVSSubmitEditor(const QString &fileName); + + CVSSettings settings() const; + void setSettings(const CVSSettings &s); + + // IVersionControl + bool vcsAdd(const QString &fileName); + bool vcsDelete(const QString &fileName); + bool managesDirectory(const QString &directory) const; + QString findTopLevelForDirectory(const QString &directory) const; + + static CVSPlugin *cvsPluginInstance(); + +private slots: + void updateActions(); + void addCurrentFile(); + void deleteCurrentFile(); + void revertCurrentFile(); + void diffProject(); + void diffCurrentFile(); + void startCommitAll(); + void startCommitCurrentFile(); + void filelogCurrentFile(); + void annotateCurrentFile(); + void projectStatus(); + void slotDescribe(const QString &source, const QString &changeNr); + void updateProject(); + void submitCurrentLog(); + void diffFiles(const QStringList &); + +private: + QString currentFileName() const; + Core::IEditor * showOutputInEditor(const QString& title, const QString &output, + int editorType, const QString &source, + QTextCodec *codec); + CVSResponse runCVS(const QStringList &arguments, + QStringList fileArguments, + int timeOut, + bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0, + bool mergeStderr = false); + + CVSResponse runCVS(const QString &workingDirectory, + const QStringList &arguments, + int timeOut, + bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0, + bool mergeStderr = false); + + void showOutput(const QString &output, bool bringToForeground = true); + void annotate(const QString &file); + bool describe(const QString &source, const QString &changeNr, QString *errorMessage); + bool describe(const QString &repository, QList entries, QString *errorMessage); + void filelog(const QString &file); + bool managesDirectory(const QDir &directory) const; + QString findTopLevelForDirectoryI(const QString &directory) const; + QStringList currentProjectsTopLevels(QString *name = 0) const; + void startCommit(const QString &file); + bool commit(const QString &messageFile, const QStringList &subVersionFileList); + void cleanChangeTmpFile(); + + CVSSettings m_settings; + Core::IVersionControl *m_versionControl; + QTemporaryFile *m_changeTmpFile; + + CVSOutputWindow *m_cvsOutputWindow; + ProjectExplorer::ProjectExplorerPlugin *m_projectExplorer; + + Core::Utils::ParameterAction *m_addAction; + Core::Utils::ParameterAction *m_deleteAction; + Core::Utils::ParameterAction *m_revertAction; + QAction *m_diffProjectAction; + Core::Utils::ParameterAction *m_diffCurrentAction; + QAction *m_commitAllAction; + Core::Utils::ParameterAction *m_commitCurrentAction; + Core::Utils::ParameterAction *m_filelogCurrentAction; + Core::Utils::ParameterAction *m_annotateCurrentAction; + QAction *m_statusAction; + QAction *m_updateProjectAction; + + QAction *m_submitCurrentLogAction; + QAction *m_submitDiffAction; + QAction *m_submitUndoAction; + QAction *m_submitRedoAction; + bool m_submitActionTriggered; + + static CVSPlugin *m_cvsPluginInstance; +}; + +// Just a proxy for CVSPlugin +class CoreListener : public Core::ICoreListener +{ + Q_OBJECT +public: + CoreListener(CVSPlugin *plugin) : m_plugin(plugin) { } + + // Start commit when submit editor closes + bool editorAboutToClose(Core::IEditor *editor) { + return m_plugin->editorAboutToClose(editor); + } + + // TODO: how to handle that ??? + bool coreAboutToClose() { + return true; + } + +private: + CVSPlugin *m_plugin; +}; + +} // namespace CVS +} // namespace Internal + +#endif // CVSPLUGIN_H diff --git a/src/plugins/cvs/cvssettings.cpp b/src/plugins/cvs/cvssettings.cpp new file mode 100644 index 00000000000..204fbf72257 --- /dev/null +++ b/src/plugins/cvs/cvssettings.cpp @@ -0,0 +1,108 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include "cvssettings.h" + +#include +#include + +static const char *groupC = "CVS"; +static const char *commandKeyC = "Command"; +static const char *rootC = "Root"; +static const char *promptToSubmitKeyC = "PromptForSubmit"; +static const char *diffOptionsKeyC = "DiffOptions"; +static const char *describeByCommitIdKeyC = "DescribeByCommitId"; +static const char *defaultDiffOptions = "-du"; + +static QString defaultCommand() +{ + QString rc; + rc = QLatin1String("cvs"); +#if defined(Q_OS_WIN32) + rc.append(QLatin1String(".exe")); +#endif + return rc; +} + +namespace CVS { + namespace Internal { + +CVSSettings::CVSSettings() : + cvsCommand(defaultCommand()), + cvsDiffOptions(QLatin1String(defaultDiffOptions)), + promptToSubmit(true), + describeByCommitId(true) +{ +} + +void CVSSettings::fromSettings(QSettings *settings) +{ + settings->beginGroup(QLatin1String(groupC)); + cvsCommand = settings->value(QLatin1String(commandKeyC), defaultCommand()).toString(); + promptToSubmit = settings->value(QLatin1String(promptToSubmitKeyC), true).toBool(); + cvsRoot = settings->value(QLatin1String(rootC), QString()).toString(); + cvsDiffOptions = settings->value(QLatin1String(diffOptionsKeyC), QLatin1String(defaultDiffOptions)).toString(); + describeByCommitId = settings->value(QLatin1String(describeByCommitIdKeyC), true).toBool(); + settings->endGroup(); +} + +void CVSSettings::toSettings(QSettings *settings) const +{ + settings->beginGroup(QLatin1String(groupC)); + settings->setValue(QLatin1String(commandKeyC), cvsCommand); + settings->setValue(QLatin1String(promptToSubmitKeyC), promptToSubmit); + settings->setValue(QLatin1String(rootC), cvsRoot); + settings->setValue(QLatin1String(diffOptionsKeyC), cvsDiffOptions); + settings->setValue(QLatin1String(describeByCommitIdKeyC), describeByCommitId); + settings->endGroup(); +} + +bool CVSSettings::equals(const CVSSettings &s) const +{ + return promptToSubmit == promptToSubmit + && describeByCommitId == s.describeByCommitId + && cvsCommand == s.cvsCommand + && cvsRoot == s.cvsRoot + && cvsDiffOptions == s.cvsDiffOptions; +} + +QStringList CVSSettings::addOptions(const QStringList &args) const +{ + if (cvsRoot.isEmpty()) + return args; + + QStringList rc; + rc.push_back(QLatin1String("-d")); + rc.push_back(cvsRoot); + rc.append(args); + return rc; +} + +} +} diff --git a/src/plugins/cvs/cvssettings.h b/src/plugins/cvs/cvssettings.h new file mode 100644 index 00000000000..ff37307f2bb --- /dev/null +++ b/src/plugins/cvs/cvssettings.h @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef CVSSETTINGS_H +#define CVSSETTINGS_H + +#include + +QT_BEGIN_NAMESPACE +class QSettings; +QT_END_NAMESPACE + +namespace CVS { +namespace Internal { + +// Todo: Add user name and password? +struct CVSSettings +{ + CVSSettings(); + + void fromSettings(QSettings *); + void toSettings(QSettings *) const; + + // Add common options to the command line + QStringList addOptions(const QStringList &args) const; + + bool equals(const CVSSettings &s) const; + + QString cvsCommand; + QString cvsRoot; + QString cvsDiffOptions; + bool promptToSubmit; + bool describeByCommitId; +}; + +inline bool operator==(const CVSSettings &p1, const CVSSettings &p2) + { return p1.equals(p2); } +inline bool operator!=(const CVSSettings &p1, const CVSSettings &p2) + { return !p1.equals(p2); } + +} // namespace Internal +} // namespace CVS + +#endif // CVSSETTINGS_H diff --git a/src/plugins/cvs/cvssubmiteditor.cpp b/src/plugins/cvs/cvssubmiteditor.cpp new file mode 100644 index 00000000000..5e8a5a03060 --- /dev/null +++ b/src/plugins/cvs/cvssubmiteditor.cpp @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + + +#include "cvssubmiteditor.h" + +#include +#include + +using namespace CVS::Internal; + +CVSSubmitEditor::CVSSubmitEditor(const VCSBase::VCSBaseSubmitEditorParameters *parameters, + QWidget *parentWidget) : + VCSBase::VCSBaseSubmitEditor(parameters, new Core::Utils::SubmitEditorWidget(parentWidget)), + m_msgAdded(tr("Added")), + m_msgRemoved(tr("Removed")), + m_msgModified(tr("Modified")) +{ + setDisplayName(tr("CVS Submit")); +} + +QString CVSSubmitEditor::stateName(State st) const +{ + switch (st) { + case LocallyAdded: + return m_msgAdded; + case LocallyModified: + return m_msgModified; + case LocallyRemoved: + return m_msgRemoved; + } + return QString(); +} + +void CVSSubmitEditor::setStateList(const QList &statusOutput) +{ + typedef QList::const_iterator ConstIterator; + VCSBase::SubmitFileModel *model = new VCSBase::SubmitFileModel(this); + + const ConstIterator cend = statusOutput.constEnd(); + for (ConstIterator it = statusOutput.constBegin(); it != cend; ++it) + model->addFile(it->second, stateName(it->first), true); + setFileModel(model); +} diff --git a/src/plugins/cvs/cvssubmiteditor.h b/src/plugins/cvs/cvssubmiteditor.h new file mode 100644 index 00000000000..0e103513e90 --- /dev/null +++ b/src/plugins/cvs/cvssubmiteditor.h @@ -0,0 +1,64 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef CVSSUBMITEDITOR_H +#define CVSSUBMITEDITOR_H + +#include +#include + +#include + +namespace CVS { +namespace Internal { + +class CVSSubmitEditor : public VCSBase::VCSBaseSubmitEditor +{ + Q_OBJECT +public: + enum State { LocallyAdded, LocallyModified, LocallyRemoved }; + // A list of state indicators and file names. + typedef QPair StateFilePair; + + CVSSubmitEditor(const VCSBase::VCSBaseSubmitEditorParameters *parameters, + QWidget *parentWidget = 0); + + void setStateList(const QList &statusOutput); + +private: + inline QString stateName(State st) const; + const QString m_msgAdded; + const QString m_msgRemoved; + const QString m_msgModified; +}; + +} // namespace Internal +} // namespace CVS + +#endif // CVSSUBMITEDITOR_H diff --git a/src/plugins/cvs/cvsutils.cpp b/src/plugins/cvs/cvsutils.cpp new file mode 100644 index 00000000000..fcd193dd3f4 --- /dev/null +++ b/src/plugins/cvs/cvsutils.cpp @@ -0,0 +1,238 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include "cvsutils.h" + +#include +#include +#include + +namespace CVS { +namespace Internal { + +CVS_Revision::CVS_Revision(const QString &rev) : + revision(rev) +{ +} + +CVS_LogEntry::CVS_LogEntry(const QString &f) : + file(f) +{ +} + +QDebug operator<<(QDebug d, const CVS_LogEntry &e) +{ + QDebug nospace = d.nospace(); + nospace << "File: " << e.file << e.revisions.size() << '\n'; + foreach(const CVS_Revision &r, e.revisions) + nospace << " " << r.revision << ' ' << r.date << ' ' << r.commitId << '\n'; + return d; +} + +/* Parse: +\code +RCS file: /repo/foo.h +Working file: foo.h +head: 1.2 +... +---------------------------- +revision 1.2 +date: 2009-07-14 13:30:25 +0200; author: ; state: dead; lines: +0 -0; commitid: ; + +---------------------------- +revision 1.1 +... +============================================================================= +\endcode */ + +QList parseLogEntries(const QString &o, + const QString &directory, + const QString filterCommitId) +{ + enum ParseState { FileState, RevisionState, StatusLineState }; + + QList rc; + const QStringList lines = o.split(QString(QLatin1Char('\n')), QString::SkipEmptyParts); + ParseState state = FileState; + + const QString workingFilePrefix = QLatin1String("Working file: "); + const QString revisionPrefix = QLatin1String("revision "); + const QString statusPrefix = QLatin1String("date: "); + const QString commitId = QLatin1String("commitid: "); + const QRegExp statusPattern = QRegExp(QLatin1String("^date: ([\\d\\-]+) .*commitid: ([^;]+);$")); + const QRegExp revisionPattern = QRegExp(QLatin1String("^revision ([\\d\\.]+)$")); + const QChar slash = QLatin1Char('/'); + Q_ASSERT(statusPattern.isValid() && revisionPattern.isValid()); + const QString fileSeparator = QLatin1String("============================================================================="); + + // Parse using a state enumeration and regular expressions as not to fall for weird + // commit messages in state 'RevisionState' + foreach(const QString &line, lines) { + switch (state) { + case FileState: + if (line.startsWith(workingFilePrefix)) { + QString file = directory; + if (!file.isEmpty()) + file += slash; + file += line.mid(workingFilePrefix.size()).trimmed(); + rc.push_back(CVS_LogEntry(file)); + state = RevisionState; + } + break; + case RevisionState: + if (revisionPattern.exactMatch(line)) { + rc.back().revisions.push_back(CVS_Revision(revisionPattern.cap(1))); + state = StatusLineState; + } else { + if (line == fileSeparator) + state = FileState; + } + break; + case StatusLineState: + if (statusPattern.exactMatch(line)) { + const QString commitId = statusPattern.cap(2); + if (filterCommitId.isEmpty() || filterCommitId == commitId) { + rc.back().revisions.back().date = statusPattern.cap(1); + rc.back().revisions.back().commitId = commitId; + } else { + rc.back().revisions.pop_back(); + } + state = RevisionState; + } + } + } + // Purge out files with no matching commits + if (!filterCommitId.isEmpty()) { + for (QList::iterator it = rc.begin(); it != rc.end(); ) { + if (it->revisions.empty()) { + it = rc.erase(it); + } else { + ++it; + } + } + } + return rc; +} + +QString fixDiffOutput(QString d) +{ + if (d.isEmpty()) + return d; + // Kill all lines starting with '?' + const QChar questionMark = QLatin1Char('?'); + const QChar newLine = QLatin1Char('\n'); + for (int pos = 0; pos < d.size(); ) { + const int endOfLinePos = d.indexOf(newLine, pos); + if (endOfLinePos == -1) + break; + const int nextLinePos = endOfLinePos + 1; + if (d.at(pos) == questionMark) { + d.remove(pos, nextLinePos - pos); + } else { + pos = nextLinePos; + } + } + return d; +} + +// Parse "cvs status" output for added/modified/deleted files +// "File: Status: Up-to-date" +// "File: Status: Locally Modified" +// "File: no file Status: Locally Removed" +// "File: hup Status: Locally Added" +// Not handled for commit purposes: "Needs Patch/Needs Merge" +// In between, we might encounter "cvs status: Examining subdir"... +// As we run the status command from the repository directory, +// we need to add the full path, again. +// stdout/stderr need to be merged to catch directories. + +// Parse out status keywords, return state enum or -1 +inline int stateFromKeyword(const QString &s) +{ + if (s == QLatin1String("Up-to-date")) + return -1; + if (s == QLatin1String("Locally Modified")) + return CVSSubmitEditor::LocallyModified; + if (s == QLatin1String("Locally Added")) + return CVSSubmitEditor::LocallyAdded; + if (s == QLatin1String("Locally Removed")) + return CVSSubmitEditor::LocallyRemoved; + return -1; +} + +StateList parseStatusOutput(const QString &directory, const QString &output) +{ + StateList changeSet; + const QString fileKeyword = QLatin1String("File: "); + const QString statusKeyword = QLatin1String("Status: "); + const QString noFileKeyword = QLatin1String("no file "); + const QString directoryKeyword = QLatin1String("cvs status: Examining "); + const QString dotDir = QString(QLatin1Char('.')); + const QChar slash = QLatin1Char('/'); + + const QStringList list = output.split(QLatin1Char('\n'), QString::SkipEmptyParts); + + QString path = directory; + if (!path.isEmpty()) + path += slash; + foreach (const QString &l, list) { + // Status line containing file + if (l.startsWith(fileKeyword)) { + // Parse state + const int statusPos = l.indexOf(statusKeyword); + if (statusPos == -1) + continue; + const int state = stateFromKeyword(l.mid(statusPos + statusKeyword.size()).trimmed()); + if (state == -1) + continue; + // Concatenate file name, Correct "no file " + QString fileName = l.mid(fileKeyword.size(), statusPos - fileKeyword.size()).trimmed(); + if (state == CVSSubmitEditor::LocallyRemoved && fileName.startsWith(noFileKeyword)) + fileName.remove(0, noFileKeyword.size()); + changeSet.push_back(CVSSubmitEditor::StateFilePair(static_cast(state), path + fileName)); + continue; + } + // Examining a new subdirectory + if (l.startsWith(directoryKeyword)) { + path = directory; + if (!path.isEmpty()) + path += slash; + const QString newSubDir = l.mid(directoryKeyword.size()).trimmed(); + if (newSubDir != dotDir) { // Skip Examining '.' + path += newSubDir; + path += slash; + } + continue; + } + } + return changeSet; +} + +} // namespace Internal +} // namespace CVS diff --git a/src/plugins/cvs/cvsutils.h b/src/plugins/cvs/cvsutils.h new file mode 100644 index 00000000000..4515c96be33 --- /dev/null +++ b/src/plugins/cvs/cvsutils.h @@ -0,0 +1,86 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef CVSUTILS_H +#define CVSUTILS_H + +#include "cvssubmiteditor.h" + +#include +#include + +QT_BEGIN_NAMESPACE +class QDebug; +QT_END_NAMESPACE + +namespace CVS { +namespace Internal { + +// Utilities to parse output of a CVS log. + +// A revision of a file. +struct CVS_Revision +{ + CVS_Revision(const QString &rev); + + QString revision; + QString date; // ISO-Format (YYYY-MM-DD) + QString commitId; +}; + +// A log entry consisting of the file and its revisions. +struct CVS_LogEntry +{ + CVS_LogEntry(const QString &file); + + QString file; + QList revisions; +}; + +QDebug operator<<(QDebug d, const CVS_LogEntry &); + +// Parse. Pass on a directory to obtain full paths when +// running from the repository directory. +QList parseLogEntries(const QString &output, + const QString &directory = QString(), + const QString filterCommitId = QString()); + +// Tortoise CVS outputs unknown files with question marks in +// the diff output on stdout ('? foo'); remove +QString fixDiffOutput(QString d); + +// Parse the status output of CVS (stdout/stderr merged +// to catch directories). +typedef QList StateList; +StateList parseStatusOutput(const QString &directory, const QString &output); + +} // namespace Internal +} // namespace CVS + +#endif // CVSUTILS_H diff --git a/src/plugins/cvs/settingspage.cpp b/src/plugins/cvs/settingspage.cpp new file mode 100644 index 00000000000..589580859d6 --- /dev/null +++ b/src/plugins/cvs/settingspage.cpp @@ -0,0 +1,107 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include "settingspage.h" +#include "cvssettings.h" +#include "cvsplugin.h" + +#include +#include +#include +#include + +#include +#include + +using namespace CVS::Internal; +using namespace Core::Utils; + +SettingsPageWidget::SettingsPageWidget(QWidget *parent) : + QWidget(parent) +{ + m_ui.setupUi(this); + m_ui.commandPathChooser->setExpectedKind(PathChooser::Command); + m_ui.commandPathChooser->setPromptDialogTitle(tr("CVS Command")); +} + +CVSSettings SettingsPageWidget::settings() const +{ + CVSSettings rc; + rc.cvsCommand = m_ui.commandPathChooser->path(); + rc.cvsRoot = m_ui.rootLineEdit->text(); + rc.cvsDiffOptions = m_ui.diffOptionsLineEdit->text(); + rc.promptToSubmit = m_ui.promptToSubmitCheckBox->isChecked(); + rc.describeByCommitId = m_ui.describeByCommitIdCheckBox->isChecked(); + return rc; +} + +void SettingsPageWidget::setSettings(const CVSSettings &s) +{ + m_ui.commandPathChooser->setPath(s.cvsCommand); + m_ui.rootLineEdit->setText(s.cvsRoot); + m_ui.diffOptionsLineEdit->setText(s.cvsDiffOptions); + m_ui.promptToSubmitCheckBox->setChecked(s.promptToSubmit); + m_ui.describeByCommitIdCheckBox->setChecked(s.describeByCommitId); +} + +SettingsPage::SettingsPage() +{ +} + +QString SettingsPage::id() const +{ + return QLatin1String("CVS"); +} + +QString SettingsPage::trName() const +{ + return tr("CVS"); +} + +QString SettingsPage::category() const +{ + return QLatin1String(VCSBase::Constants::VCS_SETTINGS_CATEGORY); +} + +QString SettingsPage::trCategory() const +{ + return QCoreApplication::translate("VCSBase", VCSBase::Constants::VCS_SETTINGS_CATEGORY); +} + +QWidget *SettingsPage::createPage(QWidget *parent) +{ + m_widget = new SettingsPageWidget(parent); + m_widget->setSettings(CVSPlugin::cvsPluginInstance()->settings()); + return m_widget; +} + +void SettingsPage::apply() +{ + CVSPlugin::cvsPluginInstance()->setSettings(m_widget->settings()); +} diff --git a/src/plugins/cvs/settingspage.h b/src/plugins/cvs/settingspage.h new file mode 100644 index 00000000000..e96f8061043 --- /dev/null +++ b/src/plugins/cvs/settingspage.h @@ -0,0 +1,86 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#ifndef SETTINGSPAGE_H +#define SETTINGSPAGE_H + +#include "ui_settingspage.h" + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QSettings; +QT_END_NAMESPACE + +namespace CVS { +namespace Internal { + +struct CVSSettings; + +class SettingsPageWidget : public QWidget { + Q_OBJECT +public: + explicit SettingsPageWidget(QWidget *parent = 0); + + CVSSettings settings() const; + void setSettings(const CVSSettings &); + +private: + Ui::SettingsPage m_ui; +}; + + +class SettingsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + SettingsPage(); + + QString id() const; + QString trName() const; + QString category() const; + QString trCategory() const; + + QWidget *createPage(QWidget *parent); + void apply(); + void finish() { } + +private: + SettingsPageWidget* m_widget; +}; + +} // namespace CVS +} // namespace Internal + +#endif // SETTINGSPAGE_H diff --git a/src/plugins/cvs/settingspage.ui b/src/plugins/cvs/settingspage.ui new file mode 100644 index 00000000000..6798485edb1 --- /dev/null +++ b/src/plugins/cvs/settingspage.ui @@ -0,0 +1,130 @@ + + + CVS::Internal::SettingsPage + + + + 0 + 0 + 575 + 437 + + + + + + + + + + + Prompt to submit + + + + + + + + + When checked, all files touched by a commit will be displayed when clicking on a revision number in the annotation view (retrieved via commit id). Otherwise, only the respective file will be displayed. + + + Describe by commit id + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + 0 + + + + + CVS Command: + + + + + + + + + + CVS Root: + + + + + + + + + + Diff Options: + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 105 + 20 + + + + + + + + + Core::Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
+ + +
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index f50e27c328d..4ee15490856 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -14,6 +14,7 @@ SUBDIRS = plugin_coreplugin \ plugin_perforce \ plugin_subversion \ plugin_git \ + plugin_cvs \ plugin_cpptools \ plugin_qt4projectmanager \ # plugin_snippets \ # buggy and annoying @@ -73,6 +74,12 @@ plugin_git.depends = plugin_vcsbase plugin_git.depends += plugin_projectexplorer plugin_git.depends += plugin_coreplugin +plugin_cvs.subdir = cvs +plugin_cvs.depends = plugin_texteditor +plugin_cvs.depends = plugin_vcsbase +plugin_cvs.depends += plugin_projectexplorer +plugin_cvs.depends += plugin_coreplugin + plugin_subversion.subdir = subversion plugin_subversion.depends = plugin_vcsbase plugin_subversion.depends += plugin_projectexplorer From db8507c4a01dffa206e28e7310c269464347219c Mon Sep 17 00:00:00 2001 From: con Date: Wed, 15 Jul 2009 12:38:45 +0200 Subject: [PATCH 06/26] Extract the styled painting of the find bar to utils widget. --- .../coreplugin => libs/utils}/stylehelper.cpp | 0 .../coreplugin => libs/utils}/stylehelper.h | 4 +- src/libs/utils/utils.pro | 6 +- src/plugins/coreplugin/coreplugin.pro | 2 - src/plugins/coreplugin/fancytabwidget.cpp | 2 +- src/plugins/coreplugin/generalsettings.cpp | 4 +- src/plugins/coreplugin/mainwindow.cpp | 2 +- src/plugins/coreplugin/manhattanstyle.cpp | 6 +- src/plugins/coreplugin/minisplitter.cpp | 3 +- .../progressmanager/progresspie.cpp | 3 +- src/plugins/find/find_dependencies.pri | 1 + src/plugins/find/findtoolbar.cpp | 59 +------------------ src/plugins/find/findtoolbar.h | 5 +- src/plugins/projectexplorer/buildprogress.cpp | 2 +- src/plugins/texteditor/basefilefind.cpp | 2 +- src/plugins/texteditor/basetexteditor.cpp | 4 +- 16 files changed, 28 insertions(+), 77 deletions(-) rename src/{plugins/coreplugin => libs/utils}/stylehelper.cpp (100%) rename src/{plugins/coreplugin => libs/utils}/stylehelper.h (97%) diff --git a/src/plugins/coreplugin/stylehelper.cpp b/src/libs/utils/stylehelper.cpp similarity index 100% rename from src/plugins/coreplugin/stylehelper.cpp rename to src/libs/utils/stylehelper.cpp diff --git a/src/plugins/coreplugin/stylehelper.h b/src/libs/utils/stylehelper.h similarity index 97% rename from src/plugins/coreplugin/stylehelper.h rename to src/libs/utils/stylehelper.h index 4c29af0253c..e42ab67bcd7 100644 --- a/src/plugins/coreplugin/stylehelper.h +++ b/src/libs/utils/stylehelper.h @@ -30,7 +30,7 @@ #ifndef STYLEHELPER_H #define STYLEHELPER_H -#include "core_global.h" +#include "utils_global.h" #include #include @@ -40,7 +40,7 @@ // Helper class holding all custom color values -class CORE_EXPORT StyleHelper +class QTCREATOR_UTILS_EXPORT StyleHelper { public: // Height of the project explorer navigation bar diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro index 0a90231f4af..4efe18705bc 100644 --- a/src/libs/utils/utils.pro +++ b/src/libs/utils/utils.pro @@ -30,7 +30,8 @@ SOURCES += reloadpromptutils.cpp \ parameteraction.cpp \ treewidgetcolumnstretcher.cpp \ checkablemessagebox.cpp \ - styledbar.cpp + styledbar.cpp \ + stylehelper.cpp win32 { SOURCES += abstractprocess_win.cpp \ @@ -69,7 +70,8 @@ HEADERS += utils_global.h \ treewidgetcolumnstretcher.h \ checkablemessagebox.h \ qtcassert.h \ - styledbar.h + styledbar.h \ + stylehelper.h FORMS += filewizardpage.ui \ projectintropage.ui \ diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro index ae1874438fa..fbe1d6cc642 100644 --- a/src/plugins/coreplugin/coreplugin.pro +++ b/src/plugins/coreplugin/coreplugin.pro @@ -65,7 +65,6 @@ SOURCES += mainwindow.cpp \ coreimpl.cpp \ basefilewizard.cpp \ plugindialog.cpp \ - stylehelper.cpp \ inavigationwidgetfactory.cpp \ navigationwidget.cpp \ manhattanstyle.cpp \ @@ -150,7 +149,6 @@ HEADERS += mainwindow.h \ coreimpl.h \ basefilewizard.h \ plugindialog.h \ - stylehelper.h \ inavigationwidgetfactory.h \ navigationwidget.h \ manhattanstyle.h \ diff --git a/src/plugins/coreplugin/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp index cbd669d0239..1767b88febf 100644 --- a/src/plugins/coreplugin/fancytabwidget.cpp +++ b/src/plugins/coreplugin/fancytabwidget.cpp @@ -28,7 +28,7 @@ **************************************************************************/ #include "fancytabwidget.h" -#include "stylehelper.h" +#include #include diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index 5a75f4f9dfd..eb250422b3f 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -29,8 +29,8 @@ #include "generalsettings.h" -#include "stylehelper.h" -#include "utils/qtcolorbutton.h" +#include +#include #include #include #include diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index b9c3f204649..e8414794109 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -51,7 +51,6 @@ #include "scriptmanager_p.h" #include "settingsdialog.h" -#include "stylehelper.h" #include "variablemanager.h" #include "versiondialog.h" #include "viewmanager.h" @@ -68,6 +67,7 @@ #include #include #include +#include #include #include diff --git a/src/plugins/coreplugin/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp index 171dac813f2..fda4e51bab2 100644 --- a/src/plugins/coreplugin/manhattanstyle.cpp +++ b/src/plugins/coreplugin/manhattanstyle.cpp @@ -29,12 +29,14 @@ #include "manhattanstyle.h" -#include "stylehelper.h" #include "styleanimator.h" #include #include +#include +#include + #include #include #include @@ -56,8 +58,6 @@ #include #include -#include - // We define a currently unused state for indicating animations #define State_Animating 0x00000040 diff --git a/src/plugins/coreplugin/minisplitter.cpp b/src/plugins/coreplugin/minisplitter.cpp index bd1551cb7e7..2961dec153f 100644 --- a/src/plugins/coreplugin/minisplitter.cpp +++ b/src/plugins/coreplugin/minisplitter.cpp @@ -28,7 +28,8 @@ **************************************************************************/ #include "minisplitter.h" -#include "stylehelper.h" + +#include #include #include diff --git a/src/plugins/coreplugin/progressmanager/progresspie.cpp b/src/plugins/coreplugin/progressmanager/progresspie.cpp index 4f8ffa645fe..d4a16a525c6 100644 --- a/src/plugins/coreplugin/progressmanager/progresspie.cpp +++ b/src/plugins/coreplugin/progressmanager/progresspie.cpp @@ -28,7 +28,8 @@ **************************************************************************/ #include "progresspie.h" -#include "stylehelper.h" + +#include #include #include diff --git a/src/plugins/find/find_dependencies.pri b/src/plugins/find/find_dependencies.pri index a64caedc103..7f369f6326a 100644 --- a/src/plugins/find/find_dependencies.pri +++ b/src/plugins/find/find_dependencies.pri @@ -1 +1,2 @@ include(../../plugins/coreplugin/coreplugin.pri) +include(../../libs/utils/utils.pri) diff --git a/src/plugins/find/findtoolbar.cpp b/src/plugins/find/findtoolbar.cpp index 0ddd2d259e6..4e19745403a 100644 --- a/src/plugins/find/findtoolbar.cpp +++ b/src/plugins/find/findtoolbar.cpp @@ -32,15 +32,13 @@ #include "textfindconstants.h" #include -#include #include #include -#include #include #include #include - #include +#include #include #include @@ -76,7 +74,6 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen { //setup ui m_ui.setupUi(this); - setProperty("panelwidget", true); setFocusProxy(m_ui.findEdit); setProperty("topBorder", true); m_ui.findEdit->setAttribute(Qt::WA_MacShowFocusRect, false); @@ -230,56 +227,6 @@ FindToolBar::~FindToolBar() { } -void FindToolBar::paintEvent(QPaintEvent *event) -{ - // Currently from the style - // Goal should be to migrate that into a Utils::StyledWidget class - Q_UNUSED(event) - QPainter painter(this); - - QRect selfRect = rect(); - QString key; - key.sprintf("mh_toolbar %d %d %d", selfRect.width(), selfRect.height(), StyleHelper::baseColor().rgb());; - - QPixmap pixmap; - QPainter *p = &painter; - if (StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) { - pixmap = QPixmap(selfRect.size()); - p = new QPainter(&pixmap); - selfRect = QRect(0, 0, selfRect.width(), selfRect.height()); - } - - // Map offset for global window gradient - QPoint offset = window()->mapToGlobal(selfRect.topLeft()) - - mapToGlobal(selfRect.topLeft()); - QRect gradientSpan; - gradientSpan = QRect(offset, window()->size()); - StyleHelper::horizontalGradient(p, gradientSpan, selfRect); - - p->setPen(StyleHelper::borderColor()); - - // Note: This is a hack to determine if the - // toolbar should draw the top or bottom outline - // (needed for the find toolbar for instance) - QColor lighter(255, 255, 255, 40); - if (property("topBorder").toBool()) { - p->drawLine(selfRect.topLeft(), selfRect.topRight()); - p->setPen(lighter); - p->drawLine(selfRect.topLeft() + QPoint(0, 1), selfRect.topRight() + QPoint(0, 1)); - } else { - p->drawLine(selfRect.bottomLeft(), selfRect.bottomRight()); - p->setPen(lighter); - p->drawLine(selfRect.topLeft(), selfRect.topRight()); - } - - if (StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) { - painter.drawPixmap(selfRect.topLeft(), pixmap); - p->end(); - delete p; - QPixmapCache::insert(key, pixmap); - } -} - bool FindToolBar::eventFilter(QObject *obj, QEvent *event) { if ((obj == m_ui.findEdit || obj == m_findCompleter->popup()) @@ -320,7 +267,7 @@ bool FindToolBar::eventFilter(QObject *obj, QEvent *event) m_currentDocumentFind->clearFindScope(); } } - return QWidget::eventFilter(obj, event); + return Core::Utils::StyledBar::eventFilter(obj, event); } void FindToolBar::updateActions() @@ -596,7 +543,7 @@ bool FindToolBar::focusNextPrevChild(bool next) else if (!next && m_ui.findEdit->hasFocus()) m_ui.replaceAllButton->setFocus(Qt::TabFocusReason); else - return QWidget::focusNextPrevChild(next); + return Core::Utils::StyledBar::focusNextPrevChild(next); return true; } diff --git a/src/plugins/find/findtoolbar.h b/src/plugins/find/findtoolbar.h index ca1b1ba5268..f1cab5e314f 100644 --- a/src/plugins/find/findtoolbar.h +++ b/src/plugins/find/findtoolbar.h @@ -34,6 +34,8 @@ #include "ifindfilter.h" #include "currentdocumentfind.h" +#include + #include #include #include @@ -44,14 +46,13 @@ namespace Internal { class FindPlugin; -class FindToolBar : public QWidget +class FindToolBar : public Core::Utils::StyledBar { Q_OBJECT public: FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumentFind); ~FindToolBar(); - void paintEvent(QPaintEvent *event); void readSettings(); void writeSettings(); diff --git a/src/plugins/projectexplorer/buildprogress.cpp b/src/plugins/projectexplorer/buildprogress.cpp index a91c4afff66..582419431be 100644 --- a/src/plugins/projectexplorer/buildprogress.cpp +++ b/src/plugins/projectexplorer/buildprogress.cpp @@ -29,7 +29,7 @@ #include "buildprogress.h" -#include +#include #include #include diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index f94f6b789c1..c43918dfd0b 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -30,12 +30,12 @@ #include "basefilefind.h" #include -#include #include #include #include #include #include +#include #include #include diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 4fcd94e2afa..63507ae1637 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -39,14 +39,14 @@ #include "codecselector.h" #ifndef TEXTEDITOR_STANDALONE +#include #include #include #include -#include #include #include +#include -#include #endif #include #include From f3f790cec0910e2638f97e604cc059bcc0bfa77d Mon Sep 17 00:00:00 2001 From: con Date: Wed, 15 Jul 2009 12:42:09 +0200 Subject: [PATCH 07/26] Missing files --- src/libs/utils/styledbar.cpp | 65 ++++++++++++++++++++++++++++++++++++ src/libs/utils/styledbar.h | 23 +++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 src/libs/utils/styledbar.cpp create mode 100644 src/libs/utils/styledbar.h diff --git a/src/libs/utils/styledbar.cpp b/src/libs/utils/styledbar.cpp new file mode 100644 index 00000000000..39326a17cbf --- /dev/null +++ b/src/libs/utils/styledbar.cpp @@ -0,0 +1,65 @@ +#include "styledbar.h" + +#include "stylehelper.h" + +#include +#include +#include + +using namespace Core::Utils; + +StyledBar::StyledBar(QWidget *parent) + : QWidget(parent) +{ + setProperty("panelwidget", true); +} + +void StyledBar::paintEvent(QPaintEvent *event) +{ + // Currently from the style + // Goal should be to migrate that into a Utils::StyledWidget class + Q_UNUSED(event) + QPainter painter(this); + + QRect selfRect = rect(); + QString key; + key.sprintf("mh_toolbar %d %d %d", selfRect.width(), selfRect.height(), StyleHelper::baseColor().rgb());; + + QPixmap pixmap; + QPainter *p = &painter; + if (StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) { + pixmap = QPixmap(selfRect.size()); + p = new QPainter(&pixmap); + selfRect = QRect(0, 0, selfRect.width(), selfRect.height()); + } + + // Map offset for global window gradient + QPoint offset = window()->mapToGlobal(selfRect.topLeft()) - + mapToGlobal(selfRect.topLeft()); + QRect gradientSpan; + gradientSpan = QRect(offset, window()->size()); + StyleHelper::horizontalGradient(p, gradientSpan, selfRect); + + p->setPen(StyleHelper::borderColor()); + + // Note: This is a hack to determine if the + // toolbar should draw the top or bottom outline + // (needed for the find toolbar for instance) + QColor lighter(255, 255, 255, 40); + if (property("topBorder").toBool()) { + p->drawLine(selfRect.topLeft(), selfRect.topRight()); + p->setPen(lighter); + p->drawLine(selfRect.topLeft() + QPoint(0, 1), selfRect.topRight() + QPoint(0, 1)); + } else { + p->drawLine(selfRect.bottomLeft(), selfRect.bottomRight()); + p->setPen(lighter); + p->drawLine(selfRect.topLeft(), selfRect.topRight()); + } + + if (StyleHelper::usePixmapCache() && !QPixmapCache::find(key, pixmap)) { + painter.drawPixmap(selfRect.topLeft(), pixmap); + p->end(); + delete p; + QPixmapCache::insert(key, pixmap); + } +} diff --git a/src/libs/utils/styledbar.h b/src/libs/utils/styledbar.h new file mode 100644 index 00000000000..6b93ffe5568 --- /dev/null +++ b/src/libs/utils/styledbar.h @@ -0,0 +1,23 @@ +#ifndef STYLEDBAR_H +#define STYLEDBAR_H + +#include "utils_global.h" + +#include + +namespace Core { +namespace Utils { + +class QTCREATOR_UTILS_EXPORT StyledBar : public QWidget +{ +public: + StyledBar(QWidget *parent = 0); + +protected: + void paintEvent(QPaintEvent *event); +}; + +} // Utils +} // Core + +#endif // STYLEDBAR_H From 88facd8497cc2806afeb870fa5fa3c301e9b4d7a Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Wed, 15 Jul 2009 14:45:12 +0200 Subject: [PATCH 08/26] Add some icons for .pro and .pri files on Mac OS X. We now at least follow what other Mac applications do. --- src/app/Info.plist | 6 +++--- src/app/app.pro | 3 +++ src/app/prifile.icns | Bin 0 -> 121897 bytes src/app/profile.icns | Bin 0 -> 124062 bytes 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 src/app/prifile.icns create mode 100644 src/app/profile.icns diff --git a/src/app/Info.plist b/src/app/Info.plist index 5d37bfd27a1..5e1fac5c84d 100644 --- a/src/app/Info.plist +++ b/src/app/Info.plist @@ -8,7 +8,7 @@ CFBundleTypeRole Editor CFBundleTypeIconFile - qtcreator.icns + profile.icns CFBundleTypeExtensions pro @@ -22,7 +22,7 @@ CFBundleTypeRole Editor CFBundleTypeIconFile - qtcreator.icns + profile.icns CFBundleTypeExtensions pri @@ -49,7 +49,7 @@ Editor CFBundleTypeExtensions - pri + ui CFBundleTypeName Qt UI File diff --git a/src/app/app.pro b/src/app/app.pro index 4f29e1f263c..69e34dbc787 100644 --- a/src/app/app.pro +++ b/src/app/app.pro @@ -20,6 +20,9 @@ win32 { ICON = qtcreator.icns QMAKE_INFO_PLIST = Info.plist + FILETYPES.files = profile.icns prifile.icns + FILETYPES.path = Contents/Resources + QMAKE_BUNDLE_DATA += FILETYPES } else { LIBS *= -lExtensionSystem -lAggregation diff --git a/src/app/prifile.icns b/src/app/prifile.icns new file mode 100644 index 0000000000000000000000000000000000000000..96386a70aa4001592f067c64c8c8069a045d9ff9 GIT binary patch literal 121897 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 literal 0 HcmV?d00001 diff --git a/src/app/profile.icns b/src/app/profile.icns new file mode 100644 index 0000000000000000000000000000000000000000..40a881dac9eaa0994a09686ed8a9bdf13c206b55 GIT binary patch literal 124062 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 z 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 literal 0 HcmV?d00001 From c1198e5ab9802902681d04f8958917dc9fb85f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 15 Jul 2009 12:27:02 +0200 Subject: [PATCH 09/26] Added importing of customized color schemes from the ini file So people's customized color schemes don't get lost, but get converted to the new format instead. --- src/plugins/texteditor/fontsettings.cpp | 37 +++++++++++++++-- src/plugins/texteditor/fontsettings.h | 4 +- src/plugins/texteditor/fontsettingspage.cpp | 44 ++++++++++++++------- src/plugins/texteditor/fontsettingspage.h | 1 - src/plugins/texteditor/texteditorplugin.cpp | 2 +- 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/src/plugins/texteditor/fontsettings.cpp b/src/plugins/texteditor/fontsettings.cpp index 39121e545ea..5ad025d815d 100644 --- a/src/plugins/texteditor/fontsettings.cpp +++ b/src/plugins/texteditor/fontsettings.cpp @@ -77,7 +77,6 @@ void FontSettings::clear() } void FontSettings::toSettings(const QString &category, - const FormatDescriptions &descriptions, QSettings *s) const { s->beginGroup(category); @@ -111,8 +110,30 @@ bool FontSettings::fromSettings(const QString &category, m_family = s->value(group + QLatin1String(fontFamilyKey), defaultFixedFontFamily()).toString(); m_fontSize = s->value(group + QLatin1String(fontSizeKey), m_fontSize).toInt(); m_antialias = s->value(group + QLatin1String(antialiasKey), DEFAULT_ANTIALIAS).toBool(); - loadColorScheme(s->value(group + QLatin1String(schemeFileNameKey), defaultSchemeFileName()).toString(), - descriptions); + + if (s->contains(group + QLatin1String(schemeFileNameKey))) { + // Load the selected color scheme + loadColorScheme(s->value(group + QLatin1String(schemeFileNameKey), defaultSchemeFileName()).toString(), + descriptions); + } else { + // Load color scheme from ini file + foreach (const FormatDescription &desc, descriptions) { + const QString name = desc.name(); + const QString fmt = s->value(group + name, QString()).toString(); + Format format; + if (fmt.isEmpty()) { + format.setForeground(desc.foreground()); + format.setBackground(desc.background()); + format.setBold(desc.format().bold()); + format.setItalic(desc.format().italic()); + } else { + format.fromString(fmt); + } + m_scheme.setFormatFor(name, format); + } + + m_scheme.setName(QObject::tr("Customized")); + } return true; } @@ -256,10 +277,18 @@ bool FontSettings::loadColorScheme(const QString &fileName, return loaded; } +bool FontSettings::saveColorScheme(const QString &fileName) +{ + const bool saved = m_scheme.save(fileName); + if (saved) + m_schemeFileName = fileName; + return saved; +} + /** * Returns the currently active color scheme. */ -ColorScheme FontSettings::colorScheme() const +const ColorScheme &FontSettings::colorScheme() const { return m_scheme; } diff --git a/src/plugins/texteditor/fontsettings.h b/src/plugins/texteditor/fontsettings.h index 0fa93bbe7bb..9e55aed5b0e 100644 --- a/src/plugins/texteditor/fontsettings.h +++ b/src/plugins/texteditor/fontsettings.h @@ -62,7 +62,6 @@ public: inline bool isEmpty() const { return m_scheme.isEmpty(); } void toSettings(const QString &category, - const FormatDescriptions &descriptions, QSettings *s) const; bool fromSettings(const QString &category, @@ -86,8 +85,9 @@ public: QString colorSchemeFileName() const; void setColorSchemeFileName(const QString &fileName); bool loadColorScheme(const QString &fileName, const FormatDescriptions &descriptions); + bool saveColorScheme(const QString &fileName); - ColorScheme colorScheme() const; + const ColorScheme &colorScheme() const; void setColorScheme(const ColorScheme &scheme); bool equals(const FontSettings &f) const; diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp index 18c4e723e51..675ae98d6a1 100644 --- a/src/plugins/texteditor/fontsettingspage.cpp +++ b/src/plugins/texteditor/fontsettingspage.cpp @@ -90,6 +90,13 @@ Q_DECLARE_METATYPE(TextEditor::Internal::ColorSchemeEntry) using namespace TextEditor; using namespace TextEditor::Internal; +static QString customStylesPath() +{ + QString path = QFileInfo(Core::ICore::instance()->settings()->fileName()).path(); + path.append(QLatin1String("/qtcreator/styles/")); + return path; +} + // ------- FontSettingsPagePrivate FontSettingsPagePrivate::FontSettingsPagePrivate(const TextEditor::FormatDescriptions &fd, @@ -103,22 +110,38 @@ FontSettingsPagePrivate::FontSettingsPagePrivate(const TextEditor::FormatDescrip m_descriptions(fd) { bool settingsFound = false; - if (const QSettings *settings = Core::ICore::instance()->settings()) + QSettings *settings = Core::ICore::instance()->settings(); + if (settings) settingsFound = m_value.fromSettings(m_settingsGroup, m_descriptions, settings); + if (!settingsFound) { // Apply defaults foreach (const FormatDescription &f, m_descriptions) { const QString name = f.name(); - m_lastValue.formatFor(name).setForeground(f.foreground()); - m_lastValue.formatFor(name).setBackground(f.background()); - m_lastValue.formatFor(name).setBold(f.format().bold()); - m_lastValue.formatFor(name).setItalic(f.format().italic()); - m_value.formatFor(name).setForeground(f.foreground()); m_value.formatFor(name).setBackground(f.background()); m_value.formatFor(name).setBold(f.format().bold()); m_value.formatFor(name).setItalic(f.format().italic()); } + } else if (m_value.colorSchemeFileName().isEmpty()) { + // No color scheme was loaded, but one might be imported from the ini file + ColorScheme defaultScheme; + foreach (const FormatDescription &f, m_descriptions) { + const QString name = f.name(); + defaultScheme.formatFor(name).setForeground(f.foreground()); + defaultScheme.formatFor(name).setBackground(f.background()); + defaultScheme.formatFor(name).setBold(f.format().bold()); + defaultScheme.formatFor(name).setItalic(f.format().italic()); + } + if (m_value.colorScheme() != defaultScheme) { + // Save it as a color scheme file + QString stylesPath = customStylesPath(); + if (QFile::exists(stylesPath) || QDir().mkpath(stylesPath)) { + QString schemeFileName = stylesPath + QLatin1String("customized.xml"); + if (m_value.saveColorScheme(schemeFileName) && settings) + m_value.toSettings(m_category, settings); + } + } } m_lastValue = m_value; @@ -436,13 +459,6 @@ void FontSettingsPage::refreshColorSchemeList() d_ptr->ui.schemeListWidget->setCurrentIndex(s); } -QString FontSettingsPage::customStylesPath() -{ - QString path = QFileInfo(Core::ICore::instance()->settings()->fileName()).path(); - path.append(QLatin1String("/qtcreator/styles/")); - return path; -} - void FontSettingsPage::delayedChange() { emit changed(d_ptr->m_value); @@ -471,7 +487,7 @@ void FontSettingsPage::saveSettings() if (d_ptr->m_value != d_ptr->m_lastValue) { d_ptr->m_lastValue = d_ptr->m_value; if (QSettings *settings = Core::ICore::instance()->settings()) - d_ptr->m_value.toSettings(d_ptr->m_settingsGroup, d_ptr->m_descriptions, settings); + d_ptr->m_value.toSettings(d_ptr->m_settingsGroup, settings); QTimer::singleShot(0, this, SLOT(delayedChange())); } diff --git a/src/plugins/texteditor/fontsettingspage.h b/src/plugins/texteditor/fontsettingspage.h index a57761d2992..af009d75d44 100644 --- a/src/plugins/texteditor/fontsettingspage.h +++ b/src/plugins/texteditor/fontsettingspage.h @@ -119,7 +119,6 @@ private slots: private: void addColorSchemeEntry(const QString &fileName, bool readOnly); void refreshColorSchemeList(); - static QString customStylesPath(); Internal::FontSettingsPagePrivate *d_ptr; }; diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp index 86ea887bc91..5948825edaf 100644 --- a/src/plugins/texteditor/texteditorplugin.cpp +++ b/src/plugins/texteditor/texteditorplugin.cpp @@ -131,7 +131,7 @@ bool TextEditorPlugin::initialize(const QStringList &arguments, QString *errorMe #endif connect(completionShortcut, SIGNAL(activated()), this, SLOT(invokeCompletion())); - // Add shortcut for invoking automatic completion + // Add shortcut for invoking quick fix options QShortcut *quickFixShortcut = new QShortcut(core->mainWindow()); quickFixShortcut->setWhatsThis(tr("Triggers a quick fix in this scope")); // Make sure the shortcut still works when the quick fix widget is active From 472a3e635deeadad50420de46a1119b205faaba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 15 Jul 2009 14:47:40 +0200 Subject: [PATCH 10/26] Save the foreground color even if it equals the text color Not all colors inherit the color from the standard text. For example line number colors. --- src/plugins/texteditor/colorscheme.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/texteditor/colorscheme.cpp b/src/plugins/texteditor/colorscheme.cpp index 6aa4116cf69..e937d15f051 100644 --- a/src/plugins/texteditor/colorscheme.cpp +++ b/src/plugins/texteditor/colorscheme.cpp @@ -151,8 +151,7 @@ bool ColorScheme::save(const QString &fileName) const Format &format = i.next().value(); w.writeStartElement(QLatin1String("style")); w.writeAttribute(QLatin1String("name"), i.key()); - if (format.foreground().isValid() && - (i.key() == QLatin1String(Constants::C_TEXT) || format.foreground() != textFormat.foreground())) + if (format.foreground().isValid()) w.writeAttribute(QLatin1String("foreground"), format.foreground().name().toLower()); if (format.background().isValid()) w.writeAttribute(QLatin1String("background"), format.background().name().toLower()); From 41a9395d21fd8075c8edfb37a06620dad8e47c0f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 15 Jul 2009 15:18:03 +0200 Subject: [PATCH 11/26] Optionally shorten git blame output by removing date+line number. --- src/plugins/git/gitclient.cpp | 2 +- src/plugins/git/giteditor.cpp | 43 ++++++++++++++++++++++++++++++++ src/plugins/git/giteditor.h | 3 +++ src/plugins/git/gitsettings.cpp | 9 +++++-- src/plugins/git/gitsettings.h | 1 + src/plugins/git/settingspage.cpp | 4 ++- src/plugins/git/settingspage.ui | 7 ++++++ 7 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 74841b74b1b..0486522fd1e 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -493,7 +493,7 @@ GitCommand *GitClient::createCommand(const QString &workingDirectory, } } else { QTC_ASSERT(editor, /**/); - connect(command, SIGNAL(outputData(QByteArray)), editor, SLOT(setPlainTextData(QByteArray))); + connect(command, SIGNAL(outputData(QByteArray)), editor, SLOT(setPlainTextDataFiltered(QByteArray))); } if (outputWindow) diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp index bb3c4129930..62fa5688c65 100644 --- a/src/plugins/git/giteditor.cpp +++ b/src/plugins/git/giteditor.cpp @@ -33,6 +33,7 @@ #include "gitclient.h" #include "gitconstants.h" #include "gitplugin.h" +#include #include #include @@ -141,5 +142,47 @@ QString GitEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) cons return QString(); } +/* Remove the date specification from annotation, which is tabular: +\code +8ca887aa (author YYYY-MM-DD HH:MM:SS ) +\endcode */ + +static void removeAnnotationDate(QString *s) +{ + if (s->isEmpty()) + return; + // Get position of date (including blank) and the ')' + const QRegExp isoDatePattern(QLatin1String(" \\d{4}-\\d{2}-\\d{2}")); + Q_ASSERT(isoDatePattern.isValid()); + const int datePos = s->indexOf(isoDatePattern); + const int parenPos = datePos == -1 ? -1 : s->indexOf(QLatin1Char(')')); + if (parenPos == -1) + return; + // In all lines, remove the bit from datePos .. parenPos; + const int dateLength = parenPos - datePos; + const QChar newLine = QLatin1Char('\n'); + for (int pos = 0; pos < s->size(); ) { + if (pos + parenPos >s->size()) // Should not happen + break; + s->remove(pos + datePos, dateLength); + const int nextLinePos = s->indexOf(newLine, pos + datePos); + pos = nextLinePos == -1 ? s->size() : nextLinePos + 1; + } +} + +void GitEditor::setPlainTextDataFiltered(const QByteArray &a) +{ + // If desired, filter out the date from annotation + const bool omitAnnotationDate = contentType() == VCSBase::AnnotateOutput + && GitPlugin::instance()->settings().omitAnnotationDate; + if (omitAnnotationDate) { + QString text = codec()->toUnicode(a); + removeAnnotationDate(&text); + setPlainText(text); + } else { + setPlainTextData(a); + } +} + } // namespace Internal } // namespace Git diff --git a/src/plugins/git/giteditor.h b/src/plugins/git/giteditor.h index f87c1ccd480..88e349dd202 100644 --- a/src/plugins/git/giteditor.h +++ b/src/plugins/git/giteditor.h @@ -47,6 +47,9 @@ public: explicit GitEditor(const VCSBase::VCSBaseEditorParameters *type, QWidget *parent); +public slots: + void setPlainTextDataFiltered(const QByteArray &a); + private: virtual QSet annotationChanges() const; virtual QString changeUnderCursor(const QTextCursor &) const; diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp index f35bf5b7d31..2cda5834184 100644 --- a/src/plugins/git/gitsettings.cpp +++ b/src/plugins/git/gitsettings.cpp @@ -42,6 +42,7 @@ static const char *pathKeyC = "Path"; static const char *logCountKeyC = "LogCount"; static const char *timeoutKeyC = "TimeOut"; static const char *promptToSubmitKeyC = "PromptForSubmit"; +static const char *omitAnnotationDateKeyC = "OmitAnnotationDate"; enum { defaultLogCount = 10 , defaultTimeOut = 30}; @@ -52,7 +53,8 @@ GitSettings::GitSettings() : adoptPath(false), logCount(defaultLogCount), timeout(defaultTimeOut), - promptToSubmit(true) + promptToSubmit(true), + omitAnnotationDate(false) { } @@ -64,6 +66,7 @@ void GitSettings::fromSettings(QSettings *settings) logCount = settings->value(QLatin1String(logCountKeyC), defaultLogCount).toInt(); timeout = settings->value(QLatin1String(timeoutKeyC), defaultTimeOut).toInt(); promptToSubmit = settings->value(QLatin1String(promptToSubmitKeyC), true).toBool(); + omitAnnotationDate = settings->value(QLatin1String(omitAnnotationDateKeyC), false).toBool(); settings->endGroup(); } @@ -75,13 +78,15 @@ void GitSettings::toSettings(QSettings *settings) const settings->setValue(QLatin1String(logCountKeyC), logCount); settings->setValue(QLatin1String(timeoutKeyC), timeout); settings->setValue(QLatin1String(promptToSubmitKeyC), promptToSubmit); + settings->setValue(QLatin1String(omitAnnotationDateKeyC), omitAnnotationDate); settings->endGroup(); } bool GitSettings::equals(const GitSettings &s) const { return adoptPath == s.adoptPath && path == s.path && logCount == s.logCount - && timeout == s.timeout && promptToSubmit == s.promptToSubmit; + && timeout == s.timeout && promptToSubmit == s.promptToSubmit + && omitAnnotationDate == s.omitAnnotationDate; } QString GitSettings::gitBinaryPath(bool *ok, QString *errorMessage) const diff --git a/src/plugins/git/gitsettings.h b/src/plugins/git/gitsettings.h index 666e1483e3a..f65a4906b1f 100644 --- a/src/plugins/git/gitsettings.h +++ b/src/plugins/git/gitsettings.h @@ -56,6 +56,7 @@ struct GitSettings int logCount; int timeout; bool promptToSubmit; + bool omitAnnotationDate; }; inline bool operator==(const GitSettings &p1, const GitSettings &p2) diff --git a/src/plugins/git/settingspage.cpp b/src/plugins/git/settingspage.cpp index 2167bafa7ff..9a55e7330cd 100644 --- a/src/plugins/git/settingspage.cpp +++ b/src/plugins/git/settingspage.cpp @@ -54,7 +54,8 @@ GitSettings SettingsPageWidget::settings() const rc.adoptPath = m_ui.environmentGroupBox->isChecked() && !rc.path.isEmpty(); rc.logCount = m_ui.logCountSpinBox->value(); rc.timeout = m_ui.timeoutSpinBox->value(); - rc.promptToSubmit = m_ui.promptToSubmitCheckBox->isChecked(); + rc.promptToSubmit = m_ui.promptToSubmitCheckBox->isChecked(); + rc.omitAnnotationDate = m_ui.omitAnnotationDataCheckBox->isChecked(); return rc; } @@ -65,6 +66,7 @@ void SettingsPageWidget::setSettings(const GitSettings &s) m_ui.logCountSpinBox->setValue(s.logCount); m_ui.timeoutSpinBox->setValue(s.timeout); m_ui.promptToSubmitCheckBox->setChecked(s.promptToSubmit); + m_ui.omitAnnotationDataCheckBox->setChecked(s.omitAnnotationDate); } void SettingsPageWidget::setSystemPath() diff --git a/src/plugins/git/settingspage.ui b/src/plugins/git/settingspage.ui index 13884c70d1f..b5fdc24a589 100644 --- a/src/plugins/git/settingspage.ui +++ b/src/plugins/git/settingspage.ui @@ -111,6 +111,13 @@ + + + + Omit date from annotation output + + + From a5180a4ab57e8b15a44fcfea71abbc7520ae92bd Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 15 Jul 2009 15:20:10 +0200 Subject: [PATCH 12/26] Update QML front-end from qt/kinetic-declarativeui (rev bcae9d84fb5dd2bdc5a5298c8841702505a02867) --- src/plugins/duieditor/parser/qmljs.g | 205 ++- src/plugins/duieditor/parser/qmljsast.cpp | 4 +- src/plugins/duieditor/parser/qmljsast_p.h | 59 +- src/plugins/duieditor/parser/qmljsastfwd_p.h | 4 +- .../duieditor/parser/qmljsastvisitor.cpp | 4 +- .../duieditor/parser/qmljsastvisitor_p.h | 4 +- .../duieditor/parser/qmljsengine_p.cpp | 42 +- src/plugins/duieditor/parser/qmljsengine_p.h | 53 +- src/plugins/duieditor/parser/qmljsgrammar.cpp | 1458 +++++++++-------- src/plugins/duieditor/parser/qmljsgrammar_p.h | 28 +- src/plugins/duieditor/parser/qmljslexer.cpp | 8 +- src/plugins/duieditor/parser/qmljslexer_p.h | 4 +- .../duieditor/parser/qmljsmemorypool_p.h | 6 +- .../duieditor/parser/qmljsnodepool_p.h | 6 +- src/plugins/duieditor/parser/qmljsparser.cpp | 885 +++++----- src/plugins/duieditor/parser/qmljsparser_p.h | 38 +- .../duieditor/parser/qmljsprettypretty.cpp | 206 +-- .../duieditor/parser/qmljsprettypretty_p.h | 6 +- 18 files changed, 1730 insertions(+), 1290 deletions(-) diff --git a/src/plugins/duieditor/parser/qmljs.g b/src/plugins/duieditor/parser/qmljs.g index f06740c1ddf..43cce407e3e 100644 --- a/src/plugins/duieditor/parser/qmljs.g +++ b/src/plugins/duieditor/parser/qmljs.g @@ -1,9 +1,9 @@ ---------------------------------------------------------------------------- -- -- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). --- Contact: Nokia Corporation (qt-info@nokia.com) +-- Contact: Qt Software Information (qt-info@nokia.com) -- --- This file is part of the QtScript module of the Qt Toolkit. +-- This file is part of the QtDeclarative module of the Qt Toolkit. -- -- $QT_BEGIN_LICENSE:LGPL$ -- No Commercial Usage @@ -34,7 +34,7 @@ -- met: http://www.gnu.org/copyleft/gpl.html. -- -- If you are unsure which license is appropriate for your use, please --- contact the sales department at http://www.qtsoftware.com/contact. +-- contact the sales department at qt-sales@nokia.com. -- $QT_END_LICENSE$ -- -- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE @@ -84,18 +84,24 @@ --- context keywords. %token T_PUBLIC "public" %token T_IMPORT "import" +%token T_AS "as" + +--- feed tokens +%token T_FEED_UI_PROGRAM +%token T_FEED_JS_STATEMENT +%token T_FEED_JS_EXPRESSION %nonassoc SHIFT_THERE %nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY %nonassoc REDUCE_HERE -%start UiProgram +%start TopLevel /. /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -128,7 +134,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -148,7 +154,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -181,7 +187,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -254,6 +260,7 @@ public: AST::UiProgram *UiProgram; AST::UiImportList *UiImportList; AST::UiImport *UiImport; + AST::UiParameterList *UiParameterList; AST::UiPublicMember *UiPublicMember; AST::UiObjectDefinition *UiObjectDefinition; AST::UiObjectInitializer *UiObjectInitializer; @@ -270,10 +277,29 @@ public: Parser(Engine *engine); ~Parser(); - bool parse(); + // parse a UI program + bool parse() { return parse(T_FEED_UI_PROGRAM); } + bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } + bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } - AST::UiProgram *ast() - { return program; } + AST::UiProgram *ast() const + { return AST::cast(program); } + + AST::Statement *statement() const + { + if (! program) + return 0; + + return program->statementCast(); + } + + AST::ExpressionNode *expression() const + { + if (! program) + return 0; + + return program->expressionCast(); + } QList diagnosticMessages() const { return diagnostic_messages; } @@ -298,6 +324,8 @@ public: { return diagnosticMessage().loc.startColumn; } protected: + bool parse(int startToken); + void reallocateStack(); inline Value &sym(int index) @@ -316,7 +344,7 @@ protected: int *state_stack; AST::SourceLocation *location_stack; - AST::UiProgram *program; + AST::Node *program; // error recovery enum { TOKEN_BUFFER_SIZE = 3 }; @@ -437,14 +465,16 @@ AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) return 0; } -bool Parser::parse() +bool Parser::parse(int startToken) { Lexer *lexer = driver->lexer(); bool hadErrors = false; int yytoken = -1; int action = 0; - first_token = last_token = 0; + token_buffer[0].token = startToken; + first_token = &token_buffer[0]; + last_token = &token_buffer[1]; tos = -1; program = 0; @@ -492,12 +522,35 @@ bool Parser::parse() -- Declarative UI -------------------------------------------------------------------------------------------------------- +TopLevel: T_FEED_UI_PROGRAM UiProgram ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + +TopLevel: T_FEED_JS_STATEMENT Statement ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + +TopLevel: T_FEED_JS_EXPRESSION Expression ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + UiProgram: UiImportListOpt UiRootMember ; /. case $rule_number: { - program = makeAstNode (driver->nodePool(), sym(1).UiImportList, + sym(1).UiProgram = makeAstNode (driver->nodePool(), sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); - sym(1).UiProgram = program; } break; ./ @@ -536,6 +589,77 @@ case $rule_number: { } break; ./ +UiImport: T_IMPORT T_STRING_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON; +UiImport: T_IMPORT T_STRING_LITERAL T_AS JsIdentifier T_SEMICOLON; +/. +case $rule_number: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).sval); + node->importId = sym(4).sval; + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->asToken = loc(3); + node->importIdToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; +} break; +./ + +UiImport: T_IMPORT UiQualifiedId T_AUTOMATIC_SEMICOLON; +UiImport: T_IMPORT UiQualifiedId T_SEMICOLON; +/. +case $rule_number: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).UiQualifiedId->finish()); + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +UiImport: T_IMPORT UiQualifiedId T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON; +UiImport: T_IMPORT UiQualifiedId T_NUMERIC_LITERAL T_SEMICOLON; +/. +case $rule_number: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).UiQualifiedId->finish()); + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->versionToken = loc(3); + node->semicolonToken = loc(4); + sym(1).Node = node; +} break; +./ + +UiImport: T_IMPORT UiQualifiedId T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON; +UiImport: T_IMPORT UiQualifiedId T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON; +/. +case $rule_number: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).UiQualifiedId->finish()); + node->importId = sym(5).sval; + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->versionToken = loc(3); + node->asToken = loc(4); + node->importIdToken = loc(5); + node->semicolonToken = loc(6); + sym(1).Node = node; +} break; +./ + +UiImport: T_IMPORT UiQualifiedId T_AS JsIdentifier T_AUTOMATIC_SEMICOLON; +UiImport: T_IMPORT UiQualifiedId T_AS JsIdentifier T_SEMICOLON; +/. +case $rule_number: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).UiQualifiedId->finish()); + node->importId = sym(4).sval; + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->asToken = loc(3); + node->importIdToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; +} break; +./ + Empty: ; /. case $rule_number: { @@ -706,6 +830,52 @@ case $rule_number: { UiPropertyType: T_IDENTIFIER ; +UiParameterListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +UiParameterListOpt: UiParameterList ; +/. +case $rule_number: { + sym(1).Node = sym(1).UiParameterList->finish (); +} break; +./ + +UiParameterList: UiPropertyType JsIdentifier ; +/. +case $rule_number: { + AST::UiParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).sval); + node->identifierToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ; +/. +case $rule_number: { + AST::UiParameterList *node = makeAstNode (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); + node->commaToken = loc(2); + node->identifierToken = loc(4); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->parameters = sym(4).UiParameterList; + sym(1).Node = node; +} break; +./ + UiObjectMember: T_SIGNAL T_IDENTIFIER ; /. case $rule_number: { @@ -2843,7 +3013,8 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; } for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { - if (tk == T_AUTOMATIC_SEMICOLON) + if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || + tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION) continue; int a = t_action(errorState, tk); diff --git a/src/plugins/duieditor/parser/qmljsast.cpp b/src/plugins/duieditor/parser/qmljsast.cpp index 1d626fc5258..d10c07121d4 100644 --- a/src/plugins/duieditor/parser/qmljsast.cpp +++ b/src/plugins/duieditor/parser/qmljsast.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/plugins/duieditor/parser/qmljsast_p.h b/src/plugins/duieditor/parser/qmljsast_p.h index 35c289ee0b3..6d269accf8b 100644 --- a/src/plugins/duieditor/parser/qmljsast_p.h +++ b/src/plugins/duieditor/parser/qmljsast_p.h @@ -1,9 +1,9 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the QtScript module of the Qt Toolkit. +** This file is part of the QtDeclarative module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -209,6 +209,7 @@ public: Kind_UiObjectMemberList, Kind_UiArrayMemberList, Kind_UiProgram, + Kind_UiParameterList, Kind_UiPublicMember, Kind_UiQualifiedId, Kind_UiScriptBinding, @@ -2220,15 +2221,24 @@ public: QMLJS_DECLARE_AST_NODE(UiImport) UiImport(NameId *fileName) - : fileName(fileName) + : fileName(fileName), importUri(0), importId(0) + { kind = K; } + + UiImport(UiQualifiedId *uri) + : fileName(0), importUri(uri), importId(0) { kind = K; } virtual void accept0(Visitor *visitor); // attributes NameId *fileName; + UiQualifiedId *importUri; + NameId *importId; SourceLocation importToken; SourceLocation fileNameToken; + SourceLocation versionToken; + SourceLocation asToken; + SourceLocation importIdToken; SourceLocation semicolonToken; }; @@ -2351,6 +2361,42 @@ public: SourceLocation rbraceToken; }; +class UiParameterList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiParameterList) + + UiParameterList(NameId *t, NameId *n): + type (t), name (n), next (this) + { kind = K; } + + UiParameterList(UiParameterList *previous, NameId *t, NameId *n): + type (t), name (n) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~UiParameterList() {} + + virtual void accept0(Visitor *) {} + + inline UiParameterList *finish () + { + UiParameterList *front = next; + next = 0; + return front; + } + +// attributes + NameId *type; + NameId *name; + UiParameterList *next; + SourceLocation commaToken; + SourceLocation identifierToken; +}; + class UiPublicMember: public UiObjectMember { public: @@ -2358,13 +2404,13 @@ public: UiPublicMember(NameId *memberType, NameId *name) - : type(Property), memberType(memberType), name(name), expression(0), isDefaultMember(false) + : type(Property), memberType(memberType), name(name), expression(0), isDefaultMember(false), parameters(0) { kind = K; } UiPublicMember(NameId *memberType, NameId *name, ExpressionNode *expression) - : type(Property), memberType(memberType), name(name), expression(expression), isDefaultMember(false) + : type(Property), memberType(memberType), name(name), expression(expression), isDefaultMember(false), parameters(0) { kind = K; } virtual SourceLocation firstSourceLocation() const @@ -2388,6 +2434,7 @@ public: NameId *name; ExpressionNode *expression; bool isDefaultMember; + UiParameterList *parameters; SourceLocation defaultToken; SourceLocation propertyToken; SourceLocation typeToken; diff --git a/src/plugins/duieditor/parser/qmljsastfwd_p.h b/src/plugins/duieditor/parser/qmljsastfwd_p.h index ac743f4d3e7..339bea48807 100644 --- a/src/plugins/duieditor/parser/qmljsastfwd_p.h +++ b/src/plugins/duieditor/parser/qmljsastfwd_p.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/plugins/duieditor/parser/qmljsastvisitor.cpp b/src/plugins/duieditor/parser/qmljsastvisitor.cpp index 4d73d061573..642bcee26b9 100644 --- a/src/plugins/duieditor/parser/qmljsastvisitor.cpp +++ b/src/plugins/duieditor/parser/qmljsastvisitor.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/plugins/duieditor/parser/qmljsastvisitor_p.h b/src/plugins/duieditor/parser/qmljsastvisitor_p.h index fd89ab4afdf..3677b1a1fde 100644 --- a/src/plugins/duieditor/parser/qmljsastvisitor_p.h +++ b/src/plugins/duieditor/parser/qmljsastvisitor_p.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/plugins/duieditor/parser/qmljsengine_p.cpp b/src/plugins/duieditor/parser/qmljsengine_p.cpp index fc22cf99c2b..02d9b9cd74b 100644 --- a/src/plugins/duieditor/parser/qmljsengine_p.cpp +++ b/src/plugins/duieditor/parser/qmljsengine_p.cpp @@ -1,20 +1,18 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) ** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** This file is part of the QtDeclarative module of the Qt Toolkit. ** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. ** ** GNU Lesser General Public License Usage -** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the @@ -22,10 +20,24 @@ ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. ** -**************************************************************************/ +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ #include "qmljsengine_p.h" #include "qmljsnodepool_p.h" diff --git a/src/plugins/duieditor/parser/qmljsengine_p.h b/src/plugins/duieditor/parser/qmljsengine_p.h index a65f8be2538..5aea983ec62 100644 --- a/src/plugins/duieditor/parser/qmljsengine_p.h +++ b/src/plugins/duieditor/parser/qmljsengine_p.h @@ -1,20 +1,18 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) ** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** This file is part of the QtDeclarative module of the Qt Toolkit. ** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. ** ** GNU Lesser General Public License Usage -** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the @@ -22,14 +20,39 @@ ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. ** -**************************************************************************/ +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ #ifndef QMLJSENGINE_P_H #define QMLJSENGINE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include diff --git a/src/plugins/duieditor/parser/qmljsgrammar.cpp b/src/plugins/duieditor/parser/qmljsgrammar.cpp index 50d07d0a109..4fba480c9b6 100644 --- a/src/plugins/duieditor/parser/qmljsgrammar.cpp +++ b/src/plugins/duieditor/parser/qmljsgrammar.cpp @@ -2,7 +2,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,7 +35,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -51,627 +51,684 @@ const char *const QmlJSGrammar::spell [] = { "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return", ")", ";", 0, "*", "*=", "string literal", "property", "signal", "switch", "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=", - "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "public", "import", 0, - 0}; + "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "public", "import", "as", + 0, 0, 0, 0, 0}; const int QmlJSGrammar::lhs [] = { - 91, 92, 92, 95, 95, 96, 96, 94, 93, 98, - 98, 100, 100, 101, 101, 97, 99, 99, 103, 104, - 104, 99, 99, 99, 99, 99, 99, 99, 111, 111, - 111, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 102, 102, 114, 114, 114, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, - 115, 115, 115, 115, 102, 102, 117, 117, 117, 117, - 116, 116, 119, 119, 121, 121, 121, 121, 121, 121, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 123, 123, 124, 124, 124, 124, 124, 127, 127, - 128, 128, 128, 128, 126, 126, 129, 129, 130, 130, - 131, 131, 131, 132, 132, 132, 132, 132, 132, 132, - 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, - 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, - 136, 137, 137, 137, 137, 137, 137, 138, 138, 138, - 138, 138, 139, 139, 139, 139, 139, 140, 140, 141, - 141, 142, 142, 143, 143, 144, 144, 145, 145, 146, - 146, 147, 147, 148, 148, 149, 149, 150, 150, 151, - 151, 120, 120, 152, 152, 153, 153, 153, 153, 153, - 153, 153, 153, 153, 153, 153, 153, 105, 105, 154, - 154, 155, 155, 156, 156, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 106, 168, 168, 167, 167, 113, 113, 169, 169, 170, - 170, 172, 172, 171, 173, 176, 174, 174, 177, 175, - 175, 107, 108, 108, 110, 110, 158, 158, 158, 158, - 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, - 160, 161, 161, 162, 164, 178, 178, 181, 181, 179, - 179, 182, 180, 163, 163, 163, 165, 165, 166, 166, - 166, 183, 184, 109, 109, 112, 125, 188, 188, 185, - 185, 186, 186, 189, 190, 190, 191, 191, 187, 187, - 118, 118, 192}; + 95, 95, 95, 96, 99, 99, 102, 102, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 101, 100, 107, 107, 109, 109, 110, 110, 106, 108, + 108, 111, 112, 112, 108, 108, 108, 108, 108, 108, + 108, 118, 118, 118, 119, 119, 120, 120, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 105, 105, 104, 104, 104, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 105, 105, 125, 125, 125, 125, 124, 124, + 127, 127, 129, 129, 129, 129, 129, 129, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 131, + 131, 132, 132, 132, 132, 132, 135, 135, 136, 136, + 136, 136, 134, 134, 137, 137, 138, 138, 139, 139, + 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 141, 141, 141, 141, 142, 142, 142, 143, 143, + 143, 143, 144, 144, 144, 144, 144, 144, 144, 145, + 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, + 147, 147, 147, 147, 147, 148, 148, 149, 149, 150, + 150, 151, 151, 152, 152, 153, 153, 154, 154, 155, + 155, 156, 156, 157, 157, 158, 158, 159, 159, 128, + 128, 160, 160, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 98, 98, 162, 162, 163, + 163, 164, 164, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 113, 175, + 175, 174, 174, 122, 122, 176, 176, 177, 177, 179, + 179, 178, 180, 183, 181, 181, 184, 182, 182, 114, + 115, 115, 117, 117, 165, 165, 165, 165, 165, 165, + 165, 166, 166, 166, 166, 167, 167, 167, 167, 168, + 168, 169, 171, 185, 185, 188, 188, 186, 186, 189, + 187, 170, 170, 170, 172, 172, 173, 173, 173, 190, + 191, 116, 116, 121, 133, 195, 195, 192, 192, 193, + 193, 196, 197, 197, 198, 198, 194, 194, 126, 126, + 199}; const int QmlJSGrammar:: rhs[] = { - 2, 1, 1, 1, 2, 3, 3, 0, 1, 1, - 2, 1, 3, 2, 3, 2, 1, 5, 1, 2, - 2, 4, 3, 3, 3, 3, 3, 3, 1, 1, - 1, 2, 4, 4, 5, 5, 6, 6, 7, 7, + 2, 2, 2, 2, 1, 1, 1, 2, 3, 3, + 5, 5, 3, 3, 4, 4, 6, 6, 5, 5, + 0, 1, 1, 2, 1, 3, 2, 3, 2, 1, + 5, 1, 2, 2, 4, 3, 3, 3, 3, 3, + 3, 1, 1, 1, 0, 1, 2, 4, 5, 2, + 4, 4, 5, 5, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, - 5, 3, 4, 3, 1, 3, 1, 2, 3, 4, - 1, 2, 3, 5, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 3, 3, 4, 5, 3, + 4, 3, 1, 3, 1, 2, 3, 4, 1, 2, + 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 4, 3, 5, 1, 2, - 4, 4, 4, 3, 0, 1, 1, 3, 1, 1, - 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 3, 3, 3, 1, 3, 3, - 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, - 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, - 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, + 1, 1, 1, 4, 3, 5, 1, 2, 4, 4, + 4, 3, 0, 1, 1, 3, 1, 1, 1, 2, + 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 1, 3, 3, 3, 1, 3, 3, 1, 3, + 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, + 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, + 1, 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, - 5, 1, 3, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, - 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 2, 0, 1, 3, 3, 1, 1, 1, - 3, 1, 3, 2, 2, 2, 0, 1, 2, 0, - 1, 1, 2, 2, 7, 5, 7, 7, 5, 9, - 10, 7, 8, 2, 2, 3, 3, 2, 2, 3, - 3, 3, 3, 5, 5, 3, 5, 1, 2, 0, - 1, 4, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 5, 2, 2, 2, 8, 8, 1, 3, 0, - 1, 0, 1, 1, 1, 2, 1, 1, 0, 1, - 0, 1, 2}; + 3, 1, 3, 1, 3, 1, 5, 1, 5, 1, + 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 0, 1, 1, + 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, + 2, 0, 1, 3, 3, 1, 1, 1, 3, 1, + 3, 2, 2, 2, 0, 1, 2, 0, 1, 1, + 2, 2, 7, 5, 7, 7, 5, 9, 10, 7, + 8, 2, 2, 3, 3, 2, 2, 3, 3, 3, + 3, 5, 5, 3, 5, 1, 2, 0, 1, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, + 2, 2, 2, 8, 8, 1, 3, 0, 1, 0, + 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, + 2}; const int QmlJSGrammar::action_default [] = { - 8, 2, 0, 4, 3, 0, 0, 0, 6, 7, - 5, 65, 45, 46, 43, 44, 47, 9, 0, 1, - 0, 0, 16, 66, 41, 248, 0, 0, 46, 14, - 47, 249, 17, 10, 0, 0, 0, 42, 0, 31, - 30, 29, 0, 0, 35, 0, 36, 151, 218, 182, - 190, 186, 130, 202, 178, 0, 115, 49, 131, 194, - 198, 119, 148, 129, 134, 114, 168, 155, 0, 55, - 56, 52, 319, 321, 0, 0, 0, 0, 0, 0, - 50, 53, 0, 0, 54, 48, 0, 51, 0, 0, - 144, 0, 0, 131, 150, 133, 132, 0, 0, 0, - 146, 147, 145, 149, 0, 179, 0, 0, 0, 0, - 169, 0, 0, 0, 0, 0, 0, 159, 0, 0, - 0, 153, 154, 152, 157, 161, 160, 158, 156, 171, - 170, 172, 0, 187, 0, 183, 0, 0, 125, 112, - 124, 113, 81, 82, 83, 108, 84, 109, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 110, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 111, 0, 0, 123, 219, 126, 0, 127, - 0, 128, 122, 39, 40, 0, 215, 208, 206, 213, - 214, 212, 211, 217, 210, 209, 207, 216, 203, 0, - 191, 0, 0, 195, 0, 0, 199, 0, 0, 125, - 117, 0, 116, 0, 121, 135, 0, 320, 310, 311, - 0, 308, 0, 309, 0, 312, 226, 233, 232, 240, - 228, 0, 229, 313, 0, 318, 230, 231, 236, 234, - 315, 314, 317, 237, 0, 0, 0, 0, 0, 319, - 45, 0, 321, 46, 220, 262, 47, 0, 0, 0, - 0, 0, 238, 239, 227, 235, 263, 264, 307, 316, - 0, 278, 279, 280, 281, 0, 274, 275, 276, 277, - 304, 305, 0, 0, 0, 0, 0, 267, 268, 224, - 222, 184, 192, 188, 204, 180, 225, 0, 131, 196, - 200, 173, 162, 0, 0, 181, 0, 0, 0, 0, - 174, 0, 0, 0, 0, 0, 166, 164, 167, 165, - 163, 176, 175, 177, 0, 189, 0, 185, 0, 223, - 131, 0, 205, 220, 221, 0, 220, 0, 0, 270, - 0, 0, 0, 272, 0, 193, 0, 0, 197, 0, - 0, 201, 260, 0, 252, 261, 255, 0, 259, 0, - 220, 253, 0, 220, 0, 0, 271, 0, 0, 0, - 273, 320, 310, 0, 0, 312, 0, 306, 0, 296, - 0, 0, 0, 266, 0, 265, 0, 322, 0, 80, - 242, 245, 0, 81, 248, 84, 109, 86, 87, 52, - 91, 92, 45, 93, 96, 50, 53, 46, 220, 47, - 54, 99, 48, 101, 51, 103, 104, 249, 106, 107, - 111, 0, 73, 0, 0, 75, 79, 77, 63, 76, - 78, 0, 74, 62, 243, 241, 119, 120, 125, 0, - 118, 0, 295, 0, 282, 283, 0, 294, 0, 0, - 0, 285, 290, 288, 291, 0, 0, 289, 290, 0, - 286, 0, 287, 244, 293, 0, 244, 292, 0, 297, - 298, 0, 244, 299, 300, 0, 0, 301, 0, 0, - 0, 302, 303, 137, 136, 0, 0, 0, 269, 0, - 0, 0, 284, 67, 0, 0, 71, 57, 0, 59, - 69, 0, 60, 70, 72, 61, 68, 58, 0, 64, - 141, 139, 143, 140, 138, 142, 0, 0, 0, 33, - 0, 34, 0, 37, 38, 32, 15, 11, 0, 23, - 26, 24, 0, 25, 28, 244, 0, 19, 0, 27, - 22, 81, 248, 84, 109, 86, 87, 52, 91, 92, - 45, 93, 96, 50, 53, 46, 220, 47, 54, 99, - 48, 101, 51, 103, 104, 249, 106, 107, 111, 49, - 0, 12, 0, 18, 13, 20, 21, 257, 250, 0, - 258, 254, 0, 256, 246, 0, 247, 251, 323}; + 0, 0, 0, 21, 0, 169, 236, 200, 208, 204, + 148, 220, 196, 3, 133, 67, 149, 212, 216, 137, + 166, 147, 152, 132, 186, 173, 0, 73, 74, 70, + 337, 63, 339, 0, 0, 0, 0, 0, 0, 68, + 71, 0, 0, 64, 65, 72, 66, 0, 69, 0, + 0, 162, 0, 0, 149, 168, 151, 150, 0, 0, + 0, 164, 165, 163, 167, 0, 197, 0, 0, 0, + 0, 187, 0, 0, 0, 0, 0, 0, 177, 0, + 0, 0, 171, 172, 170, 175, 179, 178, 176, 174, + 189, 188, 190, 0, 205, 0, 201, 0, 0, 143, + 130, 142, 131, 99, 100, 101, 126, 102, 127, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 128, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 129, 0, 0, 141, 237, 144, 0, + 145, 0, 146, 140, 0, 233, 226, 224, 231, 232, + 230, 229, 235, 228, 227, 225, 234, 221, 0, 209, + 0, 0, 213, 0, 0, 217, 0, 0, 143, 135, + 0, 134, 0, 139, 153, 0, 338, 328, 329, 0, + 326, 0, 327, 0, 330, 244, 251, 250, 258, 246, + 0, 247, 331, 0, 336, 248, 249, 254, 252, 333, + 332, 335, 255, 0, 266, 0, 0, 0, 0, 337, + 63, 0, 339, 64, 238, 280, 65, 0, 0, 0, + 267, 0, 0, 256, 257, 0, 245, 253, 281, 282, + 325, 334, 0, 296, 297, 298, 299, 0, 292, 293, + 294, 295, 322, 323, 0, 0, 0, 0, 0, 285, + 286, 242, 240, 202, 210, 206, 222, 198, 243, 0, + 149, 214, 218, 191, 180, 0, 0, 199, 0, 0, + 0, 0, 192, 0, 0, 0, 0, 0, 184, 182, + 185, 183, 181, 194, 193, 195, 0, 207, 0, 203, + 0, 241, 149, 0, 223, 238, 239, 0, 238, 0, + 0, 288, 0, 0, 0, 290, 0, 211, 0, 0, + 215, 0, 0, 219, 278, 0, 270, 279, 273, 0, + 277, 0, 238, 271, 0, 238, 0, 0, 289, 0, + 0, 0, 291, 338, 328, 0, 0, 330, 0, 324, + 0, 314, 0, 0, 0, 284, 0, 283, 0, 340, + 0, 98, 260, 263, 0, 99, 266, 102, 127, 104, + 105, 70, 109, 110, 63, 111, 114, 68, 71, 64, + 238, 65, 72, 117, 66, 119, 69, 121, 122, 267, + 124, 125, 129, 0, 91, 0, 0, 93, 97, 95, + 81, 94, 96, 0, 92, 80, 261, 259, 137, 138, + 143, 0, 136, 0, 313, 0, 300, 301, 0, 312, + 0, 0, 0, 303, 308, 306, 309, 0, 0, 307, + 308, 0, 304, 0, 305, 262, 311, 0, 262, 310, + 0, 315, 316, 0, 262, 317, 318, 0, 0, 319, + 0, 0, 0, 320, 321, 155, 154, 0, 0, 0, + 287, 0, 0, 0, 302, 275, 268, 0, 276, 272, + 0, 274, 264, 0, 265, 269, 85, 0, 0, 89, + 75, 0, 77, 87, 0, 78, 88, 90, 79, 86, + 76, 0, 82, 159, 157, 161, 158, 156, 160, 2, + 5, 0, 7, 6, 0, 1, 83, 61, 62, 0, + 0, 0, 9, 10, 0, 11, 12, 0, 13, 0, + 0, 14, 0, 19, 20, 84, 0, 15, 16, 0, + 17, 18, 8, 22, 0, 4, 0, 29, 59, 0, + 0, 64, 27, 65, 30, 23, 0, 0, 60, 0, + 44, 43, 42, 0, 0, 53, 0, 54, 0, 57, + 58, 0, 0, 0, 51, 0, 52, 0, 55, 56, + 50, 45, 46, 0, 0, 0, 0, 48, 49, 47, + 28, 24, 0, 36, 39, 37, 0, 38, 41, 262, + 0, 32, 0, 40, 35, 99, 266, 102, 127, 104, + 105, 70, 109, 110, 63, 111, 114, 68, 71, 64, + 238, 65, 72, 117, 66, 119, 69, 121, 122, 267, + 124, 125, 129, 67, 0, 25, 0, 31, 26, 33, + 34, 341}; const int QmlJSGrammar::goto_default [] = { - 6, 5, 19, 1, 4, 3, 32, 34, 33, 570, - 22, 18, 538, 539, 231, 226, 230, 232, 229, 236, - 517, 235, 264, 57, 65, 495, 494, 388, 387, 48, - 386, 389, 140, 61, 56, 178, 63, 52, 177, 58, - 64, 90, 62, 47, 67, 66, 301, 54, 295, 49, - 291, 51, 293, 50, 292, 59, 299, 60, 300, 53, - 294, 290, 331, 443, 296, 297, 390, 237, 228, 227, - 239, 265, 238, 243, 262, 263, 392, 391, 36, 579, - 578, 353, 354, 581, 356, 580, 355, 451, 455, 458, - 454, 453, 473, 474, 220, 234, 216, 219, 233, 241, - 240, 0}; + 4, 495, 352, 190, 494, 525, 490, 493, 492, 15, + 524, 534, 536, 535, 614, 527, 582, 583, 185, 189, + 191, 188, 195, 552, 563, 562, 194, 226, 23, 468, + 467, 350, 349, 6, 348, 351, 101, 19, 14, 139, + 21, 10, 138, 16, 22, 51, 20, 5, 25, 24, + 263, 12, 257, 7, 253, 9, 255, 8, 254, 17, + 261, 18, 262, 11, 256, 252, 293, 405, 258, 259, + 196, 187, 186, 198, 227, 197, 202, 223, 224, 354, + 353, 225, 457, 456, 315, 316, 459, 318, 458, 317, + 413, 417, 420, 416, 415, 435, 436, 179, 193, 175, + 178, 192, 200, 199, 0}; const int QmlJSGrammar::action_index [] = { - 8, -91, 14, -91, -15, 296, 67, 94, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, 109, -91, - 184, 408, -91, -91, -91, -91, 45, 125, 170, -91, - 46, -91, -91, -91, 429, 171, 130, -91, 120, -91, - -91, -91, -19, 169, -91, 733, -91, 72, -91, 22, - -26, -59, 173, -91, 278, 174, -91, -91, 574, 51, - 112, 183, 177, -91, -91, -91, 412, 214, 733, -91, - -91, -91, 161, 1566, 980, 733, 733, 733, 653, 733, - -91, -91, 733, 733, -91, -91, 733, -91, 733, 733, - -91, 733, 733, 98, 235, -91, -91, 733, 733, 733, - -91, -91, -91, 230, 733, 276, 733, 733, 733, 733, - 396, 733, 733, 733, 733, 733, 733, 288, 733, 733, - 733, 88, 87, 74, 288, 288, 288, 218, 221, 486, - 372, 362, 733, 4, 733, 76, 1479, 733, 733, -91, - -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, -91, -91, 102, 733, -91, -91, 60, 3, -91, - 733, -91, -91, -91, -91, 733, -91, -91, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, -91, 733, - -6, 733, 733, 30, 32, 733, -91, 1479, 733, 733, - -91, 107, -91, -14, -91, -91, 69, -91, 191, 49, - 18, -91, 233, -91, 47, 1827, -91, -91, -91, -91, - -91, 204, -91, -91, 39, -91, -91, -91, -91, -91, - -91, 1827, -91, -91, 322, 281, 103, 1740, 50, 203, - 77, 40, 2001, 53, 733, -91, 52, 29, 733, 25, - 28, 35, -91, -91, -91, -91, -91, -91, -91, -91, - 113, -91, -91, -91, -91, 106, -91, -91, -91, -91, - -91, -91, 15, 68, 733, 135, 119, -91, -91, 897, - -91, 82, 58, 17, -91, 261, 84, 42, 494, 91, - 79, 304, 288, 208, 733, 245, 733, 733, 733, 733, - 418, 733, 733, 733, 733, 733, 288, 288, 288, 288, - 288, 343, 336, 279, 733, -57, 733, 19, 733, -91, - 574, 733, -91, 733, -7, -30, 733, -60, 1740, -91, - 733, 111, 1740, -91, 733, 2, 733, 733, 43, 37, - 733, -91, 34, 118, 23, -91, -91, 733, -91, 238, - 733, -91, -5, 733, -17, 1740, -91, 733, 133, 1740, - -91, -9, 194, -32, -8, 1827, -25, -91, 1740, -91, - 733, 100, 1740, 21, 1740, -91, 31, 26, -20, -91, - -91, 1740, -38, 283, 41, 291, 85, 733, 1740, -1, - -34, 252, 54, -27, 653, 9, 5, -91, 817, -91, - 6, -21, 7, 733, 11, -28, 733, 1, 733, -33, - -10, 733, -91, 1653, 33, -91, -91, -91, -91, -91, - -91, 733, -91, -91, -91, -91, 172, -91, 733, -24, - -91, 1740, -91, 73, -91, -91, 1740, -91, 733, 93, - 0, -91, 24, -91, 36, 122, 733, -91, 44, 48, - -91, -3, -91, 1740, -91, 110, 1740, -91, 192, -91, - -91, 124, 1740, 27, -91, -12, -29, -91, 155, -53, - -22, -91, -91, -91, -91, 733, 123, 1740, -91, 733, - 92, 1740, -91, -91, 105, 1229, -91, -91, 1146, -91, - -91, 1063, -91, -91, -91, -91, -91, -91, 90, -91, - -91, -91, -91, -91, -91, -91, 71, 70, 222, -91, - 733, -91, 164, -91, -91, -91, -91, -91, 1392, -91, - -91, -91, 268, -91, -91, 1914, 1312, -91, 75, -91, - -91, 350, 55, 303, 108, 733, 1740, 59, 38, 242, - 62, 40, 527, 63, 81, -91, 817, -91, 138, 29, - 65, 733, 78, 56, 733, 80, 733, 61, 66, 57, - 101, -91, 347, -91, -91, -91, -91, 64, -91, 140, - -91, -91, 733, -91, -91, 144, -91, -91, -91, + 236, 824, 1879, -3, 176, 80, -95, 102, 36, -14, + 266, -95, 337, 90, -95, -95, 528, 100, 78, 344, + 220, -95, -95, -95, 565, 177, 824, -95, -95, -95, + 209, -95, 1697, 1083, 824, 824, 824, 740, 824, -95, + -95, 824, 824, -95, -95, -95, -95, 824, -95, 824, + 824, -95, 824, 824, 136, 183, -95, -95, 824, 824, + 824, -95, -95, -95, 146, 824, 342, 824, 824, 690, + 824, 565, 824, 824, 824, 824, 824, 824, 156, 824, + 824, 824, 134, 124, 84, 232, 255, 261, 260, 218, + 487, 472, 565, 824, 49, 824, 73, 1606, 824, 824, + -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, + -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, + -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, + -95, -95, -95, -95, 137, 824, -95, -95, 63, 35, + -95, 824, -95, -95, 824, -95, -95, -95, -95, -95, + -95, -95, -95, -95, -95, -95, -95, -95, 824, 38, + 824, 824, 70, 62, 824, -95, 1606, 824, 824, -95, + 104, -95, 37, -95, -95, 40, -95, 198, 67, 46, + -95, 168, -95, 45, 1970, -95, -95, -95, -95, -95, + 205, -95, -95, 44, -95, -95, -95, -95, -95, -95, + 1970, -95, -95, 375, -95, 427, 82, 1879, 32, 243, + 59, 53, 2152, 74, 824, -95, 76, 58, 824, 57, + -95, 65, 64, -95, -95, 300, -95, -95, -95, -95, + -95, -95, 79, -95, -95, -95, -95, 77, -95, -95, + -95, -95, -95, -95, 50, 68, 824, 110, 72, -95, + -95, 996, -95, 60, 34, -8, -95, 421, 71, 19, + 582, 61, 92, 420, 287, 249, 824, 304, 824, 824, + 824, 824, 394, 824, 824, 824, 824, 824, 308, 279, + 286, 293, 294, 379, 373, 493, 824, -5, 824, 66, + 824, -95, 657, 824, -95, 824, 54, 30, 824, 33, + 1879, -95, 824, 117, 1879, -95, 824, 69, 824, 824, + 94, 52, 824, -95, 75, 111, 56, -95, -95, 824, + -95, 278, 824, -95, 55, 824, -15, 1879, -95, 824, + 122, 1879, -95, -22, 305, -42, -27, 1970, -51, -95, + 1879, -95, 824, 113, 1879, -1, 1879, -95, 6, 3, + -45, -95, -95, 1879, -32, 409, 14, 424, 107, 824, + 1879, 2, -34, 318, 81, -35, 740, -4, -7, -95, + 912, -95, 0, -12, 21, 824, 41, 20, 824, 43, + 824, 16, 15, 824, -95, 1788, 31, -95, -95, -95, + -95, -95, -95, 824, -95, -95, -95, -95, 269, -95, + 824, 17, -95, 1879, -95, 86, -95, -95, 1879, -95, + 824, 103, 23, -95, 42, -95, 26, 112, 824, -95, + 28, 25, -95, -25, -95, 1879, -95, 101, 1879, -95, + 281, -95, -95, 109, 1879, 9, -95, -10, 11, -95, + 272, -17, 8, -95, -95, -95, -95, 824, 99, 1879, + -95, 824, 106, 1879, -95, 22, -95, 190, -95, -95, + 824, -95, -95, 229, -95, -95, -95, 105, 1257, -95, + -95, 1344, -95, -95, 1170, -95, -95, -95, -95, -95, + -95, 97, -95, -95, -95, -95, -95, -95, -95, -95, + -95, 468, -95, -39, 334, -95, -95, -95, -95, 201, + 359, 194, -95, -95, 88, -95, -95, 202, -95, 207, + 164, -95, 129, -95, -95, -95, 181, -95, -95, 91, + -95, -95, -95, -95, 121, -95, 491, -95, -95, -9, + 225, 170, -95, 7, -95, -95, 477, 264, -95, 126, + -95, -95, -95, 5, 144, -95, 824, -95, 188, -95, + -95, 4, 13, 158, -95, 824, -95, 180, -95, -95, + 1, 133, 27, -33, 155, 127, 163, -95, -95, -95, + -95, -95, 1428, -95, -95, -95, 329, -95, -95, 2061, + 1515, -95, 125, -95, -95, 398, 51, 384, 118, 824, + 1879, 18, 24, 328, 81, 29, 740, 48, 47, -95, + 912, -95, 39, -28, -2, 824, 12, -11, 824, 10, + 824, -20, -24, -13, 115, -95, 395, -95, -95, -95, + -95, -95, - -102, -102, -102, -102, 19, 103, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -4, 249, -102, -102, -102, -102, -102, -7, -102, -102, - -102, -102, -102, -102, 257, -102, -13, -102, -11, -102, - -102, -102, -102, -102, -102, -3, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -44, -102, - -102, -102, -102, -102, -102, -102, -102, -102, 141, -102, - -102, -102, -8, -102, 0, 16, 116, 122, 129, 119, - -102, -102, 90, 64, -102, -102, 94, -102, 91, 86, - -102, 71, 79, -102, -102, -102, -102, 159, 81, 76, - -102, -102, -102, -102, 98, -102, 67, 63, 47, 163, - -102, 160, 115, 104, 105, 127, 133, -102, 151, 144, - 130, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, 145, -102, 152, -102, 162, 31, 21, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, 23, -102, -102, -102, -102, -102, - 29, -102, -102, -102, -102, 34, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, 89, - -102, 68, 36, -102, -102, 42, -102, 235, 46, 49, - -102, -102, -102, -102, -102, -102, -102, -102, 33, -102, - -102, -102, 26, -102, -102, -18, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, 53, -102, -102, 8, 20, -102, -5, -102, 32, - -102, -102, -102, -102, 39, -102, -102, -102, 37, 73, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, 40, -102, -102, -102, -102, 97, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, 41, 213, -102, 186, 199, 203, 209, - -102, 50, 51, 38, 57, 60, -102, -102, -102, -102, - -102, -102, -102, -102, 212, -102, 174, -102, 166, -102, - -102, 168, -102, 125, -102, -102, 61, -102, 1, -102, - 45, -102, -9, -102, 172, -102, 184, 176, -102, -102, - 170, -102, -102, -102, -102, -102, -102, 215, -102, 124, - 132, -102, -102, 178, -102, -29, -102, 25, -102, 2, - -102, -102, 62, -102, -102, 102, -102, -102, -28, -102, - 22, -102, -31, -102, -33, -102, -102, -102, -102, -102, - -102, -34, -102, 17, -102, 18, -102, 111, -20, -102, - -102, 24, -102, -102, 153, -102, -102, -102, 30, -102, - -102, -102, -102, 28, -102, 73, 140, -102, 205, -102, - -102, 5, -102, 44, -102, -102, -102, -102, -102, -102, - -102, 43, -102, -102, -102, -102, -102, -102, 135, -102, - -102, 7, -102, -102, -102, -102, 4, -102, 55, -102, - -102, -102, -102, -102, -25, -102, 48, -102, 9, -102, - -102, -102, -102, -69, -102, -102, -70, -102, -102, -102, - -102, -102, -102, -92, -102, -102, -12, -102, -10, -102, - -1, -102, -102, -102, -102, 11, -102, -40, -102, 14, - -102, -39, -102, -102, -102, -17, -102, -102, 54, -102, - -102, -24, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, - 3, -102, -102, -102, -102, -102, -102, -102, 267, -102, - -102, -102, 12, -102, -102, -102, 301, -102, -102, -102, - -102, -19, -102, -15, -102, 59, -64, -102, -102, -2, - -102, -102, 142, -102, -102, -102, -14, -102, -102, -102, - -102, 6, -102, 73, 52, -102, 75, -102, -102, -102, - -102, -102, 128, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -6, -102, -102, 58, -102, -102, -102}; + -105, 21, 23, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -45, -105, -105, -105, + -105, -105, -105, -105, -105, -105, 82, -105, -105, -105, + 35, -105, -105, 31, 33, 179, 161, 176, 165, -105, + -105, 183, 182, -105, -105, -105, -105, 140, -105, 143, + 139, -105, 159, 135, -105, -105, -105, -105, 156, 155, + 152, -105, -105, -105, -105, 90, -105, 126, 128, 130, + 160, -105, 169, 115, 87, 89, 124, 97, -105, 73, + 76, 39, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, 168, -105, 108, -105, 80, 74, 70, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, 62, -105, -105, -105, -105, + -105, 55, -105, -105, 66, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, 100, -105, + 148, -31, -105, -105, -33, -105, 206, 37, 103, -105, + -105, -105, -105, -105, -105, -105, -105, 22, -105, -105, + -105, 19, -105, -105, 28, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + 91, -105, -105, 64, -105, 50, -105, 41, -105, 43, + -105, -105, -105, -105, 54, -105, -105, -105, 42, 67, + -105, -105, -105, -105, -105, 4, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, 34, -105, -105, -105, + -105, 107, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, 17, 197, -105, 230, 234, + 242, 211, -105, 122, 116, 105, 96, 78, -105, -105, + -105, -105, -105, -105, -105, -105, 188, -105, 215, -105, + 214, -105, -105, 203, -105, 153, -105, -105, 273, -105, + 5, -105, 3, -105, 12, -105, 217, -105, 223, 190, + -105, -105, 187, -105, -105, -105, -105, -105, -105, 238, + -105, 129, 186, -105, -105, 189, -105, 52, -105, 53, + -105, 56, -105, -105, 137, -105, -105, 98, -105, -105, + 40, -105, 45, -105, 44, -105, 59, -105, -105, -105, + -105, -105, -105, 61, -105, 57, -105, 60, -105, 109, + 68, -105, -105, 46, -105, -105, 150, -105, -105, -105, + 29, -105, -105, -105, -105, 0, -105, 32, 86, -105, + 123, -105, -105, -6, -105, -26, -105, -105, -105, -105, + -105, -105, -105, -24, -105, -105, -105, -105, -105, -105, + 95, -105, -105, 16, -105, -105, -105, -105, 2, -105, + 8, -105, -105, -105, -105, -105, -19, -105, 75, -105, + -38, -105, -105, -105, -105, -17, -105, -105, -30, -105, + -105, -105, -105, -105, -105, -58, -105, -105, 58, -105, + 51, -105, 49, -105, -105, -105, -105, 171, -105, 72, + -105, 65, -105, 63, -105, -105, -105, -105, -105, -105, + 38, -105, -105, 184, -105, -105, -105, -105, 47, -105, + -105, 147, -105, -105, 48, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, 88, -105, 71, 85, -105, -105, -105, -105, -105, + -105, 1, -105, -105, -105, -105, -105, -4, -105, 6, + -105, -105, -105, -105, -105, -105, 7, -105, -105, -105, + -105, -105, -105, -105, -105, -105, 369, -105, -105, -105, + 10, -105, -105, -105, -105, -105, 278, -105, -105, -22, + -105, -105, -105, -105, -105, -105, 69, -105, -105, -105, + -105, -105, -105, -105, -105, 9, -105, -105, -105, -105, + -105, 24, -105, -105, 11, 18, 25, -105, -105, -105, + -105, -105, 290, -105, -105, -105, 36, -105, -105, -105, + 210, -105, -105, -105, -105, 30, -105, 26, -105, 79, + 27, -105, -105, 13, -105, -105, 77, -105, -105, -105, + 20, -105, -105, -105, -105, 14, -105, 15, 117, -105, + 104, -105, -105, -105, -105, -105, 81, -105, -105, -105, + -105, -105}; const int QmlJSGrammar::action_info [] = { - 338, 174, 289, 485, 472, 472, -89, 480, -105, 380, - 43, 472, -79, -78, -100, 448, -97, 435, -102, 134, - 304, 326, 132, 104, 478, 375, 489, 372, 374, 456, - 377, 336, 199, 452, 423, 433, 440, 384, 421, 205, - 431, 456, 132, 365, 350, 344, 214, 476, -108, 456, - 324, 357, 462, 199, 367, 463, 363, 222, 472, 446, - 441, -75, -108, 182, 485, 448, -89, 588, 180, -75, - -97, 489, -100, 2, 289, 525, 380, 104, 224, 7, - 225, 582, 134, 304, 378, -102, 289, -105, -79, 472, - -65, 283, 328, 344, 268, 326, 2, 485, 174, 518, - 174, 174, 489, 333, 284, 218, 324, 372, 174, 572, - 174, 38, 91, 498, 91, 174, 0, 466, 174, 174, - 0, 0, 0, 92, 20, 92, 359, 91, 91, 346, - 475, 174, 459, 347, 445, 444, 576, 575, 92, 92, - 95, 174, 21, 174, 476, -78, 281, 280, 585, 39, - 509, 96, 491, 450, 12, 9, 8, 573, 175, 12, - 382, 499, 201, 212, 281, 280, 202, 279, 278, 281, - 280, 342, 174, 12, 274, 273, 45, 460, 528, 360, - 288, 287, 174, 487, 12, 0, 20, 207, 136, 97, - 12, 13, 16, 369, 41, 286, 13, 16, 207, 39, - 174, 586, 584, 0, 21, 40, 208, 137, 438, 138, - 13, 16, 174, 12, 0, 0, 0, 208, 0, 209, - 12, 13, 16, 12, 0, 524, 523, 13, 16, 520, - 46, 44, 12, 0, 98, 184, 183, 12, 0, 118, - 99, 119, 97, 118, 41, 119, 118, 97, 119, 0, - 13, 16, 120, 470, 469, 40, 120, 13, 16, 120, - 13, 16, 12, 306, 307, 267, 266, 12, 0, 13, - 16, 12, 0, 0, 13, 16, 174, 0, -319, 306, - 307, 12, 0, 521, 519, 0, 0, 98, -319, 0, - 308, 309, 98, 99, 106, 107, 106, 107, 99, 13, - 16, 21, 311, 312, 13, 16, 308, 309, 13, 16, - 12, 313, 12, 118, 314, 119, 315, 0, 13, 16, - 12, 108, 109, 108, 109, 12, 120, 311, 312, 267, - 266, 0, 12, 0, 0, 0, 313, 0, 0, 314, - 0, 315, 277, 276, 272, 271, 0, 13, 16, 13, - 16, 12, 277, 276, 0, 15, 0, 13, 16, 311, - 312, 0, 13, 16, 277, 276, 311, 312, 313, 13, - 16, 314, 0, 315, 0, 313, 12, 0, 314, 12, - 315, 14, 0, 272, 271, 111, 112, 0, 13, 16, - 0, 0, 0, 113, 114, 111, 112, 115, 0, 116, - 0, 0, 0, 113, 114, 0, 15, 115, 0, 116, - 0, 272, 271, 13, 16, 0, 13, 16, 26, 111, - 112, 0, 0, 0, 0, 0, 0, 113, 114, 0, - 27, 115, 14, 116, 0, 111, 112, 12, 0, 26, - 0, 311, 312, 113, 114, 0, 0, 115, 0, 116, - 313, 27, 0, 314, 0, 315, 0, 0, 12, 0, - 0, 0, 0, 29, 0, 0, 0, 15, 0, 0, - 0, 0, 0, 0, 28, 30, 0, 0, 0, 0, - 0, 0, 31, 0, 526, 0, 0, 0, 15, 0, - 0, 25, 0, 14, 0, 28, 30, 186, 0, 0, - 0, 0, 0, 31, 0, 0, 0, 187, 0, 111, - 112, 188, 25, 0, 14, 0, 0, 113, 114, 0, - 189, 115, 190, 116, 0, 340, 0, 0, 0, 0, - 0, 0, 0, 191, 0, 192, 95, 0, 0, 69, - 70, 0, 0, 193, 0, 0, 194, 96, 0, 72, - 0, 0, 195, 0, 0, 0, 12, 0, 196, 0, - 73, 74, 0, 75, 0, 0, 0, 0, 0, 0, - 78, 0, 0, 197, 81, 0, 0, 186, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 187, 0, 0, - 0, 188, 84, 13, 16, 0, 85, 0, 0, 0, - 189, 0, 190, 0, 0, 0, 0, 80, 87, 71, - 0, 0, 0, 191, 0, 192, 95, 0, 0, 0, - 0, 0, 0, 193, 0, 0, 194, 96, 0, 0, - 0, 0, 195, 0, 0, 0, 0, 0, 196, 0, + -97, 342, 251, -115, 339, -118, 337, -96, 410, -107, + 395, 385, 451, 383, 334, 346, 447, -123, 336, -120, + -83, -126, 434, 397, 410, -107, 440, 568, -118, 438, + 424, 418, 425, 418, 544, 565, 560, 561, 393, 460, + 334, 434, 553, 442, 434, 327, -96, 418, -120, 491, + -123, 451, 447, 434, -97, -115, 414, 539, -126, 312, + 251, 266, 135, 306, 95, 342, 340, 266, 251, 164, + 288, 141, 158, 288, 65, 181, 177, 402, 184, 290, + 295, 403, 286, 408, 93, 491, 93, 329, -93, 342, + 434, 298, 319, 300, 410, 143, 306, 173, 135, 230, + 451, 447, 158, 65, 246, 135, 183, 135, 428, 135, + 0, 135, 135, 471, 135, 437, 325, 286, 135, 321, + 52, 135, 421, 616, 52, 135, 245, 95, 160, 438, + 135, 53, 161, 250, 249, 53, 509, 0, 241, 240, + 236, 235, 308, 243, 242, 135, 309, 407, 406, 506, + 505, 546, 521, 520, 526, 540, 540, 482, 58, 449, + 171, 472, 540, 412, 52, 555, 453, 422, 243, 242, + 248, 617, 322, 344, 52, 53, 621, 304, 56, 243, + 242, 79, 331, 80, 31, 53, 620, 619, 135, 57, + 514, 513, 31, 136, 81, 58, 135, 31, 463, 540, + 542, 542, 79, 59, 80, 547, 545, 542, 0, 60, + 31, 541, 541, 135, 0, 81, 0, 0, 541, 556, + 554, 43, 44, 31, 0, 518, 517, 31, 0, 43, + 44, 31, 58, 0, 43, 44, 31, 0, 31, 0, + 59, 559, 558, 79, 542, 80, 60, 43, 44, 550, + 549, 464, 462, 516, 31, 541, 81, 79, 31, 80, + 43, 44, 503, 502, 43, 44, 229, 228, 43, 44, + 81, 572, 31, 43, 44, 43, 44, 59, 31, 509, + 79, 97, 80, 60, 166, 79, 79, 80, 80, 135, + 501, 43, 44, 81, 0, 43, 44, 526, 81, 81, + 98, 31, 99, 167, 79, 400, 80, 31, 0, 43, + 44, 79, 79, 80, 80, 43, 44, 81, 79, 79, + 80, 80, 268, 269, 81, 81, 3, 2, 1, 31, + 0, 81, 81, 79, 31, 80, 0, 135, 43, 44, + 0, 0, 432, 431, 43, 44, 81, 31, 0, 270, + 271, 0, 0, 0, -337, 67, 68, 31, 0, 166, + 67, 68, 526, 31, -337, 0, 43, 44, 0, 0, + 0, 43, 44, 0, 509, 0, 0, 0, 167, 0, + 168, 0, 69, 70, 43, 44, 0, 69, 70, 0, + 229, 228, 0, 498, 43, 44, 273, 274, 0, 0, + 43, 44, 273, 274, 31, 275, 510, 0, 276, 0, + 277, 275, 0, 31, 276, 0, 277, 273, 274, 497, + 511, 508, 0, 0, 31, 0, 275, 31, 0, 276, + 0, 277, 0, 0, 0, 0, 234, 233, 31, 268, + 269, 43, 44, 273, 274, 239, 238, 0, 507, 0, + 43, 44, 275, 31, 498, 276, 31, 277, 0, 234, + 233, 43, 44, 0, 43, 44, 270, 271, 0, 0, + 234, 233, 0, 0, 0, 43, 44, 0, 0, 0, + 497, 0, 0, 0, 0, 239, 238, 529, 239, 238, + 43, 44, 0, 43, 44, 72, 73, 31, 0, 530, + 0, 529, 0, 74, 75, 0, 31, 76, 0, 77, + 72, 73, 0, 530, 0, 0, 273, 274, 74, 75, + 31, 0, 76, 0, 77, 275, 0, 498, 276, 0, + 277, 145, 570, 499, 43, 44, 498, 0, 0, 0, + 0, 146, 0, 531, 533, 147, 532, 0, 0, 0, + 498, 220, 0, 497, 148, 0, 149, 531, 533, 0, + 204, 0, 497, 0, 0, 220, 0, 150, 0, 151, + 56, 0, 0, 0, 204, 0, 497, 152, 0, 0, + 153, 57, 0, 0, 0, 145, 154, 0, 72, 73, + 0, 0, 155, 0, 0, 146, 74, 75, 0, 147, + 76, 0, 77, 0, 0, 0, 0, 156, 148, 0, + 149, 0, 0, 302, 0, 0, 0, 0, 0, 0, + 0, 150, 0, 151, 56, 0, 0, 0, 0, 0, + 0, 152, 0, 0, 153, 57, 0, 0, 0, 0, + 154, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 197, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 69, 70, 0, 0, 0, - 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, - 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, - 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, - 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, - 16, 0, 85, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 69, 70, 0, 0, 0, - 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, - 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, - 0, 0, 0, 76, 0, 77, 78, 79, 0, 0, - 81, 0, 0, 0, 82, 0, 83, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, - 16, 0, 85, 0, 86, 0, 88, 0, 89, 0, - 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, - 0, 0, 0, 0, -98, 0, 0, 0, 68, 69, - 70, 0, 0, 0, 0, 0, 0, 0, 0, 72, - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, - 73, 74, 0, 75, 0, 0, 0, 76, 0, 77, - 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 84, 13, 16, 0, 85, 0, 86, 0, - 88, 0, 89, 0, 0, 0, 0, 80, 87, 71, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 69, - 70, 0, 0, 0, 0, 0, 0, 0, 0, 72, - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, - 73, 74, 0, 75, 0, 0, 0, 76, 0, 77, - 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 84, 13, 16, 0, 85, 0, 86, 0, - 88, 303, 89, 0, 0, 0, 0, 80, 87, 71, - 0, 0, 0, 0, 0, 0, 0, 0, 496, 0, - 0, 68, 69, 70, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 0, 0, 0, 0, 0, 0, 12, - 0, 0, 0, 73, 74, 0, 75, 0, 0, 0, - 76, 0, 77, 78, 79, 0, 0, 81, 0, 0, - 0, 82, 0, 83, 0, 0, 497, 0, 0, 0, - 0, 0, 0, 0, 0, 84, 13, 16, 0, 85, - 0, 86, 0, 88, 0, 89, 0, 0, 0, 0, - 80, 87, 71, 0, 0, 0, 0, 0, 0, 0, - 0, 504, 0, 0, 68, 69, 70, 0, 0, 0, - 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, - 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, - 0, 0, 0, 76, 0, 77, 78, 79, 0, 0, - 81, 0, 0, 0, 82, 0, 83, 0, 0, 505, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, - 16, 0, 85, 0, 86, 0, 88, 0, 89, 0, - 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, - 0, 0, 0, 0, 496, 0, 0, 68, 69, 70, - 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, - 0, 0, 0, 0, 0, 12, 0, 0, 0, 73, - 74, 0, 75, 0, 0, 0, 76, 0, 77, 78, - 79, 0, 0, 81, 0, 0, 0, 82, 0, 83, - 0, 0, 502, 0, 0, 0, 0, 0, 0, 0, - 0, 84, 13, 16, 0, 85, 0, 86, 0, 88, - 0, 89, 0, 0, 0, 0, 80, 87, 71, 0, - 0, 0, 0, 0, 0, 0, 0, 504, 0, 0, - 68, 69, 70, 0, 0, 0, 0, 0, 0, 0, - 0, 72, 0, 0, 0, 0, 0, 0, 12, 0, - 0, 0, 73, 74, 0, 75, 0, 0, 0, 76, - 0, 77, 78, 79, 0, 0, 81, 0, 0, 0, - 82, 0, 83, 0, 0, 507, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 13, 16, 0, 85, 0, - 86, 0, 88, 0, 89, 0, 0, 0, 0, 80, - 87, 71, 0, 0, 0, 0, 0, 0, 0, 0, - 496, 0, 0, 68, 69, 70, 0, 0, 0, 0, - 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, - 0, 12, 0, 0, 0, 73, 74, 0, 75, 0, - 0, 0, 76, 0, 77, 78, 79, 0, 0, 81, - 0, 0, 0, 82, 0, 83, 0, 0, 497, 0, - 0, 15, 0, 0, 0, 0, 0, 84, 13, 16, - 0, 85, 0, 86, 0, 88, 0, 89, 0, 0, - 0, 0, 80, 87, 71, 0, 0, 14, 0, 0, - 0, 0, 0, 68, 69, 70, 0, 0, 0, 0, - 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, - 0, 12, 251, 0, 0, 535, 536, 0, 75, 0, - 0, 0, 76, 0, 77, 78, 79, 0, 0, 81, - 0, 0, 0, 82, 0, 83, 0, 0, 0, 0, - 0, 0, 0, 255, 0, 0, 0, 84, 13, 16, - 0, 85, 0, 86, 0, 88, 0, 89, 0, 0, - 0, 0, 80, 87, 71, 0, 246, 0, 537, 0, - 0, 0, 0, 142, 143, 144, 0, 0, 146, 148, - 149, 0, 0, 150, 0, 151, 0, 0, 0, 153, - 154, 155, 0, 0, 0, 0, 0, 0, 12, 156, - 157, 158, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, - 0, 0, 0, 0, 0, 13, 16, 163, 164, 165, - 0, 167, 168, 169, 170, 171, 172, 0, 0, 160, - 166, 152, 145, 147, 161, 0, 0, 0, 0, 0, - 142, 143, 144, 0, 0, 146, 148, 149, 0, 0, - 150, 0, 151, 0, 0, 0, 153, 154, 155, 0, - 0, 0, 0, 0, 0, 425, 156, 157, 158, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, - 0, 0, 0, 426, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, - 0, 430, 427, 429, 163, 164, 165, 0, 167, 168, - 169, 170, 171, 172, 0, 0, 160, 166, 152, 145, - 147, 161, 0, 0, 0, 0, 0, 142, 143, 144, - 0, 0, 146, 148, 149, 0, 0, 150, 0, 151, - 0, 0, 0, 153, 154, 155, 0, 0, 0, 0, - 0, 0, 425, 156, 157, 158, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, - 426, 0, 0, 0, 0, 0, 0, 0, 428, 0, - 0, 0, 162, 0, 0, 0, 0, 0, 430, 427, - 429, 163, 164, 165, 0, 167, 168, 169, 170, 171, - 172, 0, 0, 160, 166, 152, 145, 147, 161, 0, - 0, 0, 0, 0, 244, 0, 0, 0, 0, 245, - 0, 68, 69, 70, 247, 0, 0, 0, 0, 0, - 0, 248, 72, 0, 0, 0, 0, 0, 0, 250, - 251, 0, 0, 252, 74, 0, 75, 0, 0, 0, - 76, 0, 77, 78, 79, 0, 0, 81, 0, 0, - 0, 82, 0, 83, 0, 0, 0, 0, 0, 254, - 0, 255, 0, 0, 0, 84, 253, 256, 257, 85, - 258, 86, 259, 88, 31, 89, 260, 261, 0, 0, - 80, 87, 71, 25, 246, 0, 0, 0, 0, 0, - 0, 244, 0, 0, 0, 0, 245, 0, 68, 69, - 70, 247, 0, 0, 0, 0, 0, 0, 248, 249, - 0, 0, 0, 0, 0, 0, 250, 251, 0, 0, - 252, 74, 0, 75, 0, 0, 0, 76, 0, 77, - 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, - 83, 0, 0, 0, 0, 0, 254, 0, 255, 0, - 0, 0, 84, 253, 256, 257, 85, 258, 86, 259, - 88, 31, 89, 260, 261, 0, 0, 80, 87, 71, - 25, 246, 0, 0, 0, 0, 0, 0, 541, 143, - 144, 0, 0, 543, 148, 545, 69, 70, 546, 0, - 151, 0, 0, 0, 153, 548, 549, 0, 0, 0, - 0, 0, 0, 550, 551, 157, 158, 252, 74, 0, - 75, 0, 0, 0, 76, 0, 77, 552, 79, 0, - 0, 554, 0, 0, 0, 82, 0, 83, 0, 0, - 0, 0, 0, 556, 0, 255, 0, 0, 0, 558, - 555, 557, 559, 560, 561, 86, 563, 564, 565, 566, - 567, 568, 0, 0, 553, 562, 547, 542, 544, 161, - 0, 0, 0, 0, 0, 393, 143, 144, 0, 0, - 395, 148, 397, 69, 70, 398, 0, 151, 0, 0, - 0, 153, 400, 401, 0, 0, 0, 0, 0, 0, - 402, 403, 157, 158, 252, 74, 0, 75, 0, 0, - 0, 76, 0, 77, 404, 79, 0, 0, 406, 0, - 0, 0, 82, 0, 83, 0, -244, 0, 0, 0, - 408, 0, 255, 0, 0, 0, 410, 407, 409, 411, - 412, 413, 86, 415, 416, 417, 418, 419, 420, 0, - 0, 405, 414, 399, 394, 396, 161, 0, 0, 0, - 0, 0, + 145, 156, 0, 0, 0, 0, 0, 0, 0, 0, + 146, 0, 0, 0, 147, 0, 0, 0, 0, 0, + 0, 0, 0, 148, 0, 149, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 150, 0, 151, 56, + 0, 26, 27, 28, 0, 0, 152, 0, 0, 153, + 57, 0, 30, 0, 0, 154, 0, 0, 0, 31, + 0, 155, 0, 32, 33, 0, 34, 0, 0, 0, + 35, 0, 36, 37, 38, 0, 156, 40, 0, 0, + 0, 41, 0, 42, 0, 0, 0, 0, 0, 0, + 0, 0, 27, 28, 0, 45, 43, 44, 0, 46, + 0, 47, 30, 49, 0, 50, 0, 0, 0, 31, + 39, 48, 29, 32, 33, 0, 34, 0, 0, 0, + 0, 0, 0, 37, 0, 0, 0, 40, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 45, 43, 44, 0, 46, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 48, 29, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 26, 27, 28, 0, 0, + 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, + 0, 0, 0, 31, 0, 0, 0, 32, 33, 0, + 34, 0, 0, 0, 35, 0, 36, 37, 38, 0, + 0, 40, 0, 0, 0, 41, 0, 42, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, + 43, 44, 0, 46, 0, 47, 0, 49, 0, 50, + 0, 0, 0, 0, 39, 48, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -116, + 0, 0, 0, 26, 27, 28, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, + 0, 31, 0, 0, 0, 32, 33, 0, 34, 0, + 0, 0, 35, 0, 36, 37, 38, 0, 0, 40, + 0, 0, 0, 41, 0, 42, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 45, 43, 44, + 0, 46, 0, 47, 0, 49, 0, 50, 0, 0, + 0, 0, 39, 48, 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 26, 27, 28, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, + 0, 0, 0, 0, 0, 31, 0, 0, 0, 32, + 33, 0, 34, 0, 0, 0, 35, 0, 36, 37, + 38, 0, 0, 40, 0, 0, 0, 41, 0, 42, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 45, 43, 44, 0, 46, 0, 47, 0, 49, + 265, 50, 0, 0, 0, 0, 39, 48, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 469, 0, 0, 26, 27, 28, 0, 0, 0, + 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 0, 32, 33, 0, 34, + 0, 0, 0, 35, 0, 36, 37, 38, 0, 0, + 40, 0, 0, 0, 41, 0, 42, 0, 0, 470, + 0, 0, 0, 0, 0, 0, 0, 0, 45, 43, + 44, 0, 46, 0, 47, 0, 49, 0, 50, 0, + 0, 0, 0, 39, 48, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 477, 0, + 0, 26, 27, 28, 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 0, 0, 0, 0, 31, + 0, 0, 0, 32, 33, 0, 34, 0, 0, 0, + 35, 0, 36, 37, 38, 0, 0, 40, 0, 0, + 0, 41, 0, 42, 0, 0, 478, 0, 0, 0, + 0, 0, 0, 0, 0, 45, 43, 44, 0, 46, + 0, 47, 0, 49, 0, 50, 0, 0, 0, 0, + 39, 48, 29, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 477, 0, 0, 26, 27, + 28, 0, 0, 0, 0, 0, 0, 0, 0, 30, + 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, + 32, 33, 0, 34, 0, 0, 0, 35, 0, 36, + 37, 38, 0, 0, 40, 0, 0, 0, 41, 0, + 42, 0, 0, 480, 0, 0, 0, 0, 0, 0, + 0, 0, 45, 43, 44, 0, 46, 0, 47, 0, + 49, 0, 50, 0, 0, 0, 0, 39, 48, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 469, 0, 0, 26, 27, 28, 0, 0, + 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, + 0, 0, 0, 31, 0, 0, 0, 32, 33, 0, + 34, 0, 0, 0, 35, 0, 36, 37, 38, 0, + 0, 40, 0, 0, 0, 41, 0, 42, 0, 0, + 475, 0, 0, 0, 0, 0, 0, 0, 0, 45, + 43, 44, 0, 46, 0, 47, 0, 49, 0, 50, + 0, 0, 0, 0, 39, 48, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, + 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 30, 0, 0, 0, 0, 0, 0, 31, 211, 0, + 0, 579, 580, 0, 34, 0, 0, 0, 35, 0, + 36, 37, 38, 0, 0, 40, 0, 0, 0, 41, + 0, 42, 0, 0, 0, 0, 0, 0, 0, 215, + 0, 0, 0, 45, 43, 44, 0, 46, 0, 47, + 0, 49, 0, 50, 0, 0, 0, 0, 39, 48, + 29, 0, 206, 0, 581, 0, 0, 0, 0, 0, + 0, 0, 0, 469, 0, 0, 26, 27, 28, 0, + 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, + 0, 0, 0, 0, 31, 0, 0, 0, 32, 33, + 0, 34, 0, 0, 0, 35, 0, 36, 37, 38, + 0, 0, 40, 0, 0, 0, 41, 0, 42, 0, + 0, 470, 0, 0, 498, 0, 0, 0, 0, 0, + 45, 43, 44, 0, 46, 0, 47, 0, 49, 0, + 50, 0, 0, 0, 0, 39, 48, 29, 0, 0, + 497, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 103, 104, 105, 0, 0, 107, 109, 110, 0, 0, + 111, 0, 112, 0, 0, 0, 114, 115, 116, 0, + 0, 0, 0, 0, 0, 31, 117, 118, 119, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, + 0, 0, 43, 44, 124, 125, 126, 0, 128, 129, + 130, 131, 132, 133, 0, 0, 121, 127, 113, 106, + 108, 122, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 103, 104, 105, 0, 0, 107, 109, 110, 0, + 0, 111, 0, 112, 0, 0, 0, 114, 115, 116, + 0, 0, 0, 0, 0, 0, 387, 117, 118, 119, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 120, 0, 0, 0, 388, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, + 0, 0, 392, 389, 391, 124, 125, 126, 0, 128, + 129, 130, 131, 132, 133, 0, 0, 121, 127, 113, + 106, 108, 122, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 103, 104, 105, 0, 0, 107, 109, 110, + 0, 0, 111, 0, 112, 0, 0, 0, 114, 115, + 116, 0, 0, 0, 0, 0, 0, 387, 117, 118, + 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 120, 0, 0, 0, 388, 0, 0, 0, 0, + 0, 0, 0, 390, 0, 0, 0, 123, 0, 0, + 0, 0, 0, 392, 389, 391, 124, 125, 126, 0, + 128, 129, 130, 131, 132, 133, 0, 0, 121, 127, + 113, 106, 108, 122, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 203, 0, 0, 0, 0, 205, 0, + 26, 27, 28, 207, 0, 0, 0, 0, 0, 0, + 208, 30, 0, 0, 0, 0, 0, 0, 210, 211, + 0, 0, 212, 33, 0, 34, 0, 0, 0, 35, + 0, 36, 37, 38, 0, 0, 40, 0, 0, 0, + 41, 0, 42, 0, 0, 0, 0, 0, 214, 0, + 215, 0, 0, 0, 45, 213, 216, 217, 46, 218, + 47, 219, 49, 220, 50, 221, 222, 0, 0, 39, + 48, 29, 204, 206, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 203, 0, 0, 0, 0, 205, + 0, 26, 27, 28, 207, 0, 0, 0, 0, 0, + 0, 208, 209, 0, 0, 0, 0, 0, 0, 210, + 211, 0, 0, 212, 33, 0, 34, 0, 0, 0, + 35, 0, 36, 37, 38, 0, 0, 40, 0, 0, + 0, 41, 0, 42, 0, 0, 0, 0, 0, 214, + 0, 215, 0, 0, 0, 45, 213, 216, 217, 46, + 218, 47, 219, 49, 220, 50, 221, 222, 0, 0, + 39, 48, 29, 204, 206, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 585, 104, 105, 0, 0, + 587, 109, 589, 27, 28, 590, 0, 112, 0, 0, + 0, 114, 592, 593, 0, 0, 0, 0, 0, 0, + 594, 595, 118, 119, 212, 33, 0, 34, 0, 0, + 0, 35, 0, 36, 596, 38, 0, 0, 598, 0, + 0, 0, 41, 0, 42, 0, 0, 0, 0, 0, + 600, 0, 215, 0, 0, 0, 602, 599, 601, 603, + 604, 605, 47, 607, 608, 609, 610, 611, 612, 0, + 0, 597, 606, 591, 586, 588, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 355, 104, 105, 0, + 0, 357, 109, 359, 27, 28, 360, 0, 112, 0, + 0, 0, 114, 362, 363, 0, 0, 0, 0, 0, + 0, 364, 365, 118, 119, 212, 33, 0, 34, 0, + 0, 0, 35, 0, 36, 366, 38, 0, 0, 368, + 0, 0, 0, 41, 0, 42, 0, -262, 0, 0, + 0, 370, 0, 215, 0, 0, 0, 372, 369, 371, + 373, 374, 375, 47, 377, 378, 379, 380, 381, 382, + 0, 0, 367, 376, 361, 356, 358, 122, 0, 0, + 0, 0, 0, 0, 0, 0, 0, - 334, 477, 282, 482, 270, 503, 467, 464, 275, 42, - 577, 55, 506, 479, 481, 217, 516, 522, 185, 23, - 468, 217, 540, 583, 10, 486, 488, 492, 490, 493, - 508, 270, 434, 385, 422, 383, 381, 366, 379, 368, - 270, 275, 468, 275, 334, 173, 282, 217, 242, 223, - 179, 468, 176, 334, 285, 371, 221, 343, 181, 341, - 211, 282, 465, 198, 352, 204, 457, 339, 370, 449, - 447, 206, 432, 442, 424, 334, 0, 93, 179, 501, - 0, 577, 318, 500, 213, 221, 93, 0, 471, 93, - 93, 93, 130, 483, 316, 317, 93, 461, 93, 93, - 215, 319, 93, 93, 320, 514, 93, 93, 129, 17, - 93, 0, 110, 94, 93, 93, 484, 102, 93, 242, - 93, 103, 101, 203, 337, 93, 11, 484, 93, 93, - 93, 513, 483, 93, 574, 515, 298, 93, 587, 334, - 0, 302, 200, 93, 93, 105, 334, 352, 125, 126, - 93, 11, 215, 269, 93, 93, 373, 510, 93, 124, - 512, 93, 436, 511, 179, 437, 93, 0, 242, 93, - 439, 127, 93, 123, 0, 436, 0, 128, 437, 93, - 93, 483, 215, 93, 93, 139, 436, 122, 335, 437, - 93, 93, 334, 141, 121, 362, 133, 376, 93, 93, - 100, 135, 93, 0, 117, 330, 361, 330, 131, 330, - 302, 93, 302, 93, 302, 330, 302, 0, 302, 0, - 302, 0, 0, 93, 327, 93, 345, 329, 302, 332, - 302, 351, 310, 0, 0, 0, 0, 349, 93, 0, - 348, 364, 93, 302, 93, 321, 484, 302, 93, 322, - 0, 93, 93, 302, 330, 323, 302, 302, 139, 302, - 35, 305, 0, 0, 325, 527, 141, 210, 35, 0, - 24, 37, 11, 0, 0, 0, 358, 0, 24, 37, - 11, 532, 529, 531, 533, 530, 534, 0, 0, 0, + 165, 543, 163, 430, 409, 512, 303, 301, 386, 394, + 504, 411, 557, 455, 305, 515, 519, 430, 404, 551, + 569, 144, 176, 296, 13, 489, 314, 384, 182, 244, + 201, 180, 296, 433, 567, 237, 481, 247, 439, 232, + 170, 566, 341, 244, 176, 430, 345, 564, 343, 429, + 433, 584, 333, 423, 328, 176, 330, 296, 332, 237, + 441, 347, 426, 396, 466, 454, 232, 443, 452, 237, + 244, 461, 548, 232, 450, 419, 444, 134, 427, 522, + 479, 476, 54, 0, 0, 433, 84, 0, 142, 100, + 496, 0, 618, 201, 496, 137, 523, 496, 500, 157, + 201, 0, 0, 140, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 398, 102, 54, 399, 0, 54, + 82, 54, 54, 83, 174, 54, 282, 174, 140, 54, + 54, 445, 54, 54, 401, 86, 140, 87, 314, 54, + 54, 66, 172, 54, 281, 89, 180, 54, 54, 446, + 260, 54, 54, 280, 174, 264, 296, 159, 54, 54, + 54, 96, 445, 85, 279, 54, 54, 54, 446, 54, + 278, 54, 88, 54, 448, 71, 474, 90, 54, 91, + 473, 64, 54, 54, 446, 488, 54, 398, 445, 296, + 399, 54, 296, 455, 231, 54, 338, 63, 54, 54, + 62, 61, 54, 54, 54, 55, 484, 162, 54, 92, + 485, 54, 54, 398, 323, 100, 399, 78, 0, 613, + 297, 615, 54, 94, 483, 54, 54, 487, 486, 0, + 292, 54, 0, 292, 335, 264, 264, 0, 264, 0, + 54, 102, 169, 466, 287, 264, 292, 0, 0, 267, + 0, 264, 313, 324, 54, 311, 326, 292, 54, 264, + 54, 285, 264, 264, 0, 264, 54, 465, 294, 289, + 0, 264, 0, 54, 0, 307, 296, 54, 264, 291, + 272, 292, 264, 310, 283, 54, 264, 496, 537, 0, + 264, 571, 284, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 320, 528, 538, 0, 0, 573, 575, + 577, 574, 578, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 571, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 569, 0, 0, 0, 0, 0, - 493, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 299, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 496, 537, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 528, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0}; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0}; const int QmlJSGrammar::action_check [] = { - 60, 8, 36, 36, 33, 33, 7, 60, 7, 36, - 29, 33, 7, 7, 7, 36, 7, 55, 7, 78, - 1, 78, 48, 1, 36, 33, 36, 36, 60, 5, - 55, 61, 2, 33, 8, 55, 60, 16, 7, 7, - 7, 5, 48, 60, 7, 2, 60, 20, 7, 5, - 48, 17, 55, 2, 31, 7, 61, 8, 33, 7, - 7, 7, 7, 60, 36, 36, 7, 0, 8, 7, - 7, 36, 7, 88, 36, 29, 36, 1, 60, 65, - 33, 17, 78, 1, 7, 7, 36, 7, 7, 33, - 33, 76, 8, 2, 55, 78, 88, 36, 8, 29, - 8, 8, 36, 61, 36, 36, 48, 36, 8, 8, - 8, 66, 40, 8, 40, 8, -1, 7, 8, 8, - -1, -1, -1, 51, 15, 51, 8, 40, 40, 50, - 6, 8, 10, 54, 61, 62, 61, 62, 51, 51, - 42, 8, 33, 8, 20, 7, 61, 62, 8, 29, - 60, 53, 60, 60, 29, 61, 62, 56, 56, 29, - 60, 56, 50, 56, 61, 62, 54, 61, 62, 61, - 62, 60, 8, 29, 61, 62, 7, 55, 7, 61, - 61, 62, 8, 60, 29, -1, 15, 15, 15, 12, - 29, 66, 67, 60, 74, 60, 66, 67, 15, 29, - 8, 61, 62, -1, 33, 85, 34, 34, 36, 36, - 66, 67, 8, 29, -1, -1, -1, 34, -1, 36, - 29, 66, 67, 29, -1, 61, 62, 66, 67, 7, - 61, 62, 29, -1, 57, 61, 62, 29, -1, 25, - 63, 27, 12, 25, 74, 27, 25, 12, 27, -1, - 66, 67, 38, 61, 62, 85, 38, 66, 67, 38, - 66, 67, 29, 18, 19, 61, 62, 29, -1, 66, - 67, 29, -1, -1, 66, 67, 8, -1, 36, 18, - 19, 29, -1, 61, 62, -1, -1, 57, 36, -1, - 45, 46, 57, 63, 18, 19, 18, 19, 63, 66, - 67, 33, 23, 24, 66, 67, 45, 46, 66, 67, - 29, 32, 29, 25, 35, 27, 37, -1, 66, 67, - 29, 45, 46, 45, 46, 29, 38, 23, 24, 61, - 62, -1, 29, -1, -1, -1, 32, -1, -1, 35, - -1, 37, 61, 62, 61, 62, -1, 66, 67, 66, - 67, 29, 61, 62, -1, 59, -1, 66, 67, 23, - 24, -1, 66, 67, 61, 62, 23, 24, 32, 66, - 67, 35, -1, 37, -1, 32, 29, -1, 35, 29, - 37, 85, -1, 61, 62, 23, 24, -1, 66, 67, - -1, -1, -1, 31, 32, 23, 24, 35, -1, 37, - -1, -1, -1, 31, 32, -1, 59, 35, -1, 37, - -1, 61, 62, 66, 67, -1, 66, 67, 10, 23, - 24, -1, -1, -1, -1, -1, -1, 31, 32, -1, - 22, 35, 85, 37, -1, 23, 24, 29, -1, 10, - -1, 23, 24, 31, 32, -1, -1, 35, -1, 37, - 32, 22, -1, 35, -1, 37, -1, -1, 29, -1, - -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, - -1, -1, -1, -1, 66, 67, -1, -1, -1, -1, - -1, -1, 74, -1, 55, -1, -1, -1, 59, -1, - -1, 83, -1, 85, -1, 66, 67, 3, -1, -1, - -1, -1, -1, 74, -1, -1, -1, 13, -1, 23, - 24, 17, 83, -1, 85, -1, -1, 31, 32, -1, - 26, 35, 28, 37, -1, 31, -1, -1, -1, -1, - -1, -1, -1, 39, -1, 41, 42, -1, -1, 12, - 13, -1, -1, 49, -1, -1, 52, 53, -1, 22, - -1, -1, 58, -1, -1, -1, 29, -1, 64, -1, - 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, - 43, -1, -1, 79, 47, -1, -1, 3, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, - -1, 17, 65, 66, 67, -1, 69, -1, -1, -1, - 26, -1, 28, -1, -1, -1, -1, 80, 81, 82, - -1, -1, -1, 39, -1, 41, 42, -1, -1, -1, - -1, -1, -1, 49, -1, -1, 52, 53, -1, -1, - -1, -1, 58, -1, -1, -1, -1, -1, 64, -1, + 7, 36, 36, 7, 55, 7, 33, 7, 36, 7, + 55, 8, 36, 7, 36, 16, 36, 7, 60, 7, + 33, 7, 33, 55, 36, 7, 36, 60, 7, 20, + 55, 5, 7, 5, 29, 8, 29, 36, 7, 17, + 36, 33, 29, 60, 33, 60, 7, 5, 7, 88, + 7, 36, 36, 33, 7, 7, 33, 66, 7, 7, + 36, 1, 8, 2, 78, 36, 7, 1, 36, 7, + 78, 8, 2, 78, 1, 8, 36, 60, 33, 8, + 61, 7, 48, 7, 48, 88, 48, 31, 7, 36, + 33, 61, 17, 60, 36, 60, 2, 60, 8, 55, + 36, 36, 2, 1, 36, 8, 60, 8, 7, 8, + -1, 8, 8, 8, 8, 6, 61, 48, 8, 8, + 40, 8, 10, 8, 40, 8, 76, 78, 50, 20, + 8, 51, 54, 61, 62, 51, 15, -1, 61, 62, + 61, 62, 50, 61, 62, 8, 54, 61, 62, 61, + 62, 7, 61, 62, 33, 29, 29, 60, 12, 60, + 56, 56, 29, 60, 40, 7, 60, 55, 61, 62, + 60, 56, 61, 60, 40, 51, 0, 60, 42, 61, + 62, 25, 60, 27, 29, 51, 61, 62, 8, 53, + 61, 62, 29, 56, 38, 12, 8, 29, 8, 29, + 74, 74, 25, 57, 27, 61, 62, 74, -1, 63, + 29, 85, 85, 8, -1, 38, -1, -1, 85, 61, + 62, 66, 67, 29, -1, 61, 62, 29, -1, 66, + 67, 29, 12, -1, 66, 67, 29, -1, 29, -1, + 57, 61, 62, 25, 74, 27, 63, 66, 67, 61, + 62, 61, 62, 89, 29, 85, 38, 25, 29, 27, + 66, 67, 61, 62, 66, 67, 61, 62, 66, 67, + 38, 7, 29, 66, 67, 66, 67, 57, 29, 15, + 25, 15, 27, 63, 15, 25, 25, 27, 27, 8, + 89, 66, 67, 38, -1, 66, 67, 33, 38, 38, + 34, 29, 36, 34, 25, 36, 27, 29, -1, 66, + 67, 25, 25, 27, 27, 66, 67, 38, 25, 25, + 27, 27, 18, 19, 38, 38, 90, 91, 92, 29, + -1, 38, 38, 25, 29, 27, -1, 8, 66, 67, + -1, -1, 61, 62, 66, 67, 38, 29, -1, 45, + 46, -1, -1, -1, 36, 18, 19, 29, -1, 15, + 18, 19, 33, 29, 36, -1, 66, 67, -1, -1, + -1, 66, 67, -1, 15, -1, -1, -1, 34, -1, + 36, -1, 45, 46, 66, 67, -1, 45, 46, -1, + 61, 62, -1, 59, 66, 67, 23, 24, -1, -1, + 66, 67, 23, 24, 29, 32, 47, -1, 35, -1, + 37, 32, -1, 29, 35, -1, 37, 23, 24, 85, + 61, 62, -1, -1, 29, -1, 32, 29, -1, 35, + -1, 37, -1, -1, -1, -1, 61, 62, 29, 18, + 19, 66, 67, 23, 24, 61, 62, -1, 89, -1, + 66, 67, 32, 29, 59, 35, 29, 37, -1, 61, + 62, 66, 67, -1, 66, 67, 45, 46, -1, -1, + 61, 62, -1, -1, -1, 66, 67, -1, -1, -1, + 85, -1, -1, -1, -1, 61, 62, 10, 61, 62, + 66, 67, -1, 66, 67, 23, 24, 29, -1, 22, + -1, 10, -1, 31, 32, -1, 29, 35, -1, 37, + 23, 24, -1, 22, -1, -1, 23, 24, 31, 32, + 29, -1, 35, -1, 37, 32, -1, 59, 35, -1, + 37, 3, 55, 65, 66, 67, 59, -1, -1, -1, + -1, 13, -1, 66, 67, 17, 55, -1, -1, -1, + 59, 74, -1, 85, 26, -1, 28, 66, 67, -1, + 83, -1, 85, -1, -1, 74, -1, 39, -1, 41, + 42, -1, -1, -1, 83, -1, 85, 49, -1, -1, + 52, 53, -1, -1, -1, 3, 58, -1, 23, 24, + -1, -1, 64, -1, -1, 13, 31, 32, -1, 17, + 35, -1, 37, -1, -1, -1, -1, 79, 26, -1, + 28, -1, -1, 31, -1, -1, -1, -1, -1, -1, + -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, + -1, 49, -1, -1, 52, 53, -1, -1, -1, -1, + 58, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 79, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, -1, 69, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, - -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, + 3, 79, -1, -1, -1, -1, -1, -1, -1, -1, + 13, -1, -1, -1, 17, -1, -1, -1, -1, -1, + -1, -1, -1, 26, -1, 28, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 39, -1, 41, 42, + -1, 11, 12, 13, -1, -1, 49, -1, -1, 52, + 53, -1, 22, -1, -1, 58, -1, -1, -1, 29, + -1, 64, -1, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, 79, 47, -1, -1, + -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, + -1, -1, 12, 13, -1, 65, 66, 67, -1, 69, + -1, 71, 22, 73, -1, 75, -1, -1, -1, 29, + 80, 81, 82, 33, 34, -1, 36, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 80, 81, 82, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, + -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, + 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, + -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, + -1, -1, -1, -1, 80, 81, 82, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, + -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, + -1, -1, 80, 81, 82, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, + 74, 75, -1, -1, -1, -1, 80, 81, 82, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, - 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, + 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, - -1, -1, -1, -1, 7, -1, -1, -1, 11, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, - 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, - -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, - 73, 74, 75, -1, -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, @@ -681,73 +738,77 @@ const int QmlJSGrammar::action_check [] = { -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, -1, -1, -1, - -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, - 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, - -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, - -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, - -1, 75, -1, -1, -1, -1, 80, 81, 82, -1, - -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, - 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, - -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, - -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, - -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, - 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, - -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, - 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, - 81, 82, -1, -1, -1, -1, -1, -1, -1, -1, - 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, - -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, - -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, - -1, -1, 80, 81, 82, -1, -1, 85, -1, -1, - -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, - -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, - -1, -1, 80, 81, 82, -1, 84, -1, 86, -1, - -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, - 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, - 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, - 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, - -1, -1, -1, -1, -1, 66, 67, 68, 69, 70, - -1, 72, 73, 74, 75, 76, 77, -1, -1, 80, - 81, 82, 83, 84, 85, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, + 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, + -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, + 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, + 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, + 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, + -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, + 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, + -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, + 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, + -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, + 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, + 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, + -1, -1, -1, -1, 80, 81, 82, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, + 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, + -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, + -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, + -1, 73, -1, 75, -1, -1, -1, -1, 80, 81, + 82, -1, 84, -1, 86, -1, -1, -1, -1, -1, + -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, + -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, + -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, 56, -1, -1, 59, -1, -1, -1, -1, -1, + 65, 66, 67, -1, 69, -1, 71, -1, 73, -1, + 75, -1, -1, -1, -1, 80, 81, 82, -1, -1, + 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, - -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, + -1, -1, 66, 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, - 84, 85, -1, -1, -1, -1, -1, 4, 5, 6, - -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, - -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, - -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, - -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, - 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, - 77, -1, -1, 80, 81, 82, 83, 84, 85, -1, + 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, + -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, + -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, + -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, + 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, + 83, 84, 85, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, + -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, + 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, + 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, + -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, + -1, -1, -1, 65, 66, 67, 68, 69, 70, -1, + 72, 73, 74, 75, 76, 77, -1, -1, 80, 81, + 82, 83, 84, 85, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, + 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, + 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, + -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, + -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, + 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, + 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, -1, -1, 80, + 81, 82, 83, 84, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, @@ -757,73 +818,72 @@ const int QmlJSGrammar::action_check [] = { -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, 84, -1, -1, -1, -1, -1, - -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, - 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, - -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, - -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, - 83, 84, -1, -1, -1, -1, -1, -1, 4, 5, - 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, - 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, - -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, - 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, -1, -1, 80, 81, 82, 83, 84, 85, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, - -1, -1, 51, -1, 53, -1, 55, -1, -1, -1, + -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, 84, 85, -1, -1, -1, - -1, -1, + -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, + -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, + -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, + -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, 55, -1, -1, + -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + -1, -1, 80, 81, 82, 83, 84, 85, -1, -1, + -1, -1, -1, -1, -1, -1, -1, - 14, 93, 66, 15, 23, 29, 76, 76, 23, 20, - 23, 14, 29, 23, 15, 23, 23, 14, 62, 23, - 14, 23, 10, 29, 5, 14, 66, 66, 14, 29, - 14, 23, 66, 66, 29, 66, 14, 66, 66, 14, - 23, 23, 14, 23, 14, 14, 66, 23, 66, 23, - 29, 14, 29, 14, 14, 23, 23, 66, 29, 14, - 14, 66, 14, 29, 23, 29, 91, 66, 66, 14, - 66, 29, 29, 66, 30, 14, -1, 39, 29, 25, - -1, 23, 44, 29, 35, 23, 39, -1, 15, 39, - 39, 39, 45, 41, 44, 44, 39, 88, 39, 39, - 41, 44, 39, 39, 44, 41, 39, 39, 45, 6, - 39, -1, 45, 42, 39, 39, 41, 41, 39, 66, - 39, 42, 41, 55, 63, 39, 23, 41, 39, 39, - 39, 41, 41, 39, 6, 41, 39, 39, 80, 14, - -1, 44, 53, 39, 39, 47, 14, 23, 44, 44, - 39, 23, 41, 100, 39, 39, 94, 41, 39, 44, - 41, 39, 33, 41, 29, 36, 39, -1, 66, 39, - 35, 44, 39, 43, -1, 33, -1, 44, 36, 39, - 39, 41, 41, 39, 39, 23, 33, 43, 63, 36, - 39, 39, 14, 31, 43, 63, 51, 95, 39, 39, - 41, 49, 39, -1, 44, 39, 82, 39, 45, 39, - 44, 39, 44, 39, 44, 39, 44, -1, 44, -1, - 44, -1, -1, 39, 50, 39, 54, 61, 44, 61, - 44, 61, 46, -1, -1, -1, -1, 61, 39, -1, - 56, 63, 39, 44, 39, 46, 41, 44, 39, 46, - -1, 39, 39, 44, 39, 46, 44, 44, 23, 44, - 11, 48, -1, -1, 52, 8, 31, 32, 11, -1, - 21, 22, 23, -1, -1, -1, 61, -1, 21, 22, - 23, 14, 15, 16, 17, 18, 19, -1, -1, -1, + 33, 23, 33, 3, 2, 9, 3, 2, 34, 33, + 9, 3, 3, 9, 2, 9, 9, 3, 2, 9, + 9, 66, 9, 3, 3, 2, 9, 33, 9, 2, + 2, 9, 3, 18, 9, 9, 3, 3, 96, 9, + 3, 23, 2, 2, 9, 3, 2, 23, 3, 79, + 18, 15, 9, 91, 2, 9, 3, 3, 2, 9, + 9, 2, 79, 2, 33, 2, 9, 18, 3, 9, + 2, 33, 3, 9, 2, 94, 18, 3, 3, 8, + 33, 33, 43, -1, -1, 18, 47, -1, 33, 9, + 9, -1, 11, 2, 9, 33, 11, 9, 10, 33, + 2, -1, -1, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 37, 35, 43, 40, -1, 43, + 47, 43, 43, 47, 45, 43, 48, 45, 33, 43, + 43, 45, 43, 43, 39, 48, 33, 48, 9, 43, + 43, 51, 39, 43, 48, 48, 9, 43, 43, 45, + 43, 43, 43, 48, 45, 48, 3, 57, 43, 43, + 43, 53, 45, 48, 48, 43, 43, 43, 45, 43, + 48, 43, 48, 43, 3, 49, 29, 49, 43, 49, + 33, 46, 43, 43, 45, 45, 43, 37, 45, 3, + 40, 43, 3, 9, 103, 43, 98, 45, 43, 43, + 45, 45, 43, 43, 43, 46, 45, 59, 43, 49, + 45, 43, 43, 37, 85, 9, 40, 48, -1, 9, + 67, 11, 43, 55, 45, 43, 43, 45, 45, -1, + 43, 43, -1, 43, 97, 48, 48, -1, 48, -1, + 43, 35, 36, 33, 56, 48, 43, -1, -1, 52, + -1, 48, 65, 67, 43, 65, 67, 43, 43, 48, + 43, 50, 48, 48, -1, 48, 43, 83, 65, 54, + -1, 48, -1, 43, -1, 58, 3, 43, 48, 65, + 50, 43, 48, 60, 50, 43, 48, 9, 10, -1, + 48, 13, 50, 3, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 65, 26, 27, -1, -1, 18, 19, + 20, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, - 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 9, 10, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 26, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1}; + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1}; diff --git a/src/plugins/duieditor/parser/qmljsgrammar_p.h b/src/plugins/duieditor/parser/qmljsgrammar_p.h index ff948613d1d..da42f8c4123 100644 --- a/src/plugins/duieditor/parser/qmljsgrammar_p.h +++ b/src/plugins/duieditor/parser/qmljsgrammar_p.h @@ -2,7 +2,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,7 +35,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -59,11 +59,12 @@ class QmlJSGrammar public: enum { EOF_SYMBOL = 0, - REDUCE_HERE = 90, - SHIFT_THERE = 89, + REDUCE_HERE = 94, + SHIFT_THERE = 93, T_AND = 1, T_AND_AND = 2, T_AND_EQ = 3, + T_AS = 89, T_AUTOMATIC_SEMICOLON = 62, T_BREAK = 4, T_CASE = 5, @@ -84,6 +85,9 @@ public: T_EQ_EQ = 18, T_EQ_EQ_EQ = 19, T_FALSE = 82, + T_FEED_JS_EXPRESSION = 92, + T_FEED_JS_STATEMENT = 91, + T_FEED_UI_PROGRAM = 90, T_FINALLY = 20, T_FOR = 21, T_FUNCTION = 22, @@ -150,15 +154,15 @@ public: T_XOR = 78, T_XOR_EQ = 79, - ACCEPT_STATE = 588, - RULE_COUNT = 323, - STATE_COUNT = 589, - TERMINAL_COUNT = 91, - NON_TERMINAL_COUNT = 102, + ACCEPT_STATE = 621, + RULE_COUNT = 341, + STATE_COUNT = 622, + TERMINAL_COUNT = 95, + NON_TERMINAL_COUNT = 105, - GOTO_INDEX_OFFSET = 589, - GOTO_INFO_OFFSET = 2092, - GOTO_CHECK_OFFSET = 2092 + GOTO_INDEX_OFFSET = 622, + GOTO_INFO_OFFSET = 2247, + GOTO_CHECK_OFFSET = 2247 }; static const char *const spell []; diff --git a/src/plugins/duieditor/parser/qmljslexer.cpp b/src/plugins/duieditor/parser/qmljslexer.cpp index c5e4dbc655b..a22169dda00 100644 --- a/src/plugins/duieditor/parser/qmljslexer.cpp +++ b/src/plugins/duieditor/parser/qmljslexer.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the QtScript module of the Qt Toolkit. +** This file is part of the QtDeclarative module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -159,6 +159,8 @@ int Lexer::findReservedWord(const QChar *c, int size) const return QmlJSGrammar::T_IF; else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')) return QmlJSGrammar::T_IN; + else if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('s')) + return QmlJSGrammar::T_AS; } break; case 3: { diff --git a/src/plugins/duieditor/parser/qmljslexer_p.h b/src/plugins/duieditor/parser/qmljslexer_p.h index e46aec3a65f..e1ff23e0536 100644 --- a/src/plugins/duieditor/parser/qmljslexer_p.h +++ b/src/plugins/duieditor/parser/qmljslexer_p.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/plugins/duieditor/parser/qmljsmemorypool_p.h b/src/plugins/duieditor/parser/qmljsmemorypool_p.h index fc35b5a8b36..6bd21f8b4f4 100644 --- a/src/plugins/duieditor/parser/qmljsmemorypool_p.h +++ b/src/plugins/duieditor/parser/qmljsmemorypool_p.h @@ -1,9 +1,9 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the QtScript module of the Qt Toolkit. +** This file is part of the QtDeclarative module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/plugins/duieditor/parser/qmljsnodepool_p.h b/src/plugins/duieditor/parser/qmljsnodepool_p.h index 7cb62bae65d..e2f0a3c1eaf 100644 --- a/src/plugins/duieditor/parser/qmljsnodepool_p.h +++ b/src/plugins/duieditor/parser/qmljsnodepool_p.h @@ -1,9 +1,9 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the QtScript module of the Qt Toolkit. +** This file is part of the QtDeclarative module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/plugins/duieditor/parser/qmljsparser.cpp b/src/plugins/duieditor/parser/qmljsparser.cpp index 91bf7831e3c..08a424eaad0 100644 --- a/src/plugins/duieditor/parser/qmljsparser.cpp +++ b/src/plugins/duieditor/parser/qmljsparser.cpp @@ -3,7 +3,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -36,7 +36,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -143,14 +143,16 @@ AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) return 0; } -bool Parser::parse() +bool Parser::parse(int startToken) { Lexer *lexer = driver->lexer(); bool hadErrors = false; int yytoken = -1; int action = 0; - first_token = last_token = 0; + token_buffer[0].token = startToken; + first_token = &token_buffer[0]; + last_token = &token_buffer[1]; tos = -1; program = 0; @@ -194,25 +196,39 @@ bool Parser::parse() switch (r) { case 0: { - program = makeAstNode (driver->nodePool(), sym(1).UiImportList, - sym(2).UiObjectMemberList->finish()); - sym(1).UiProgram = program; + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; + +case 1: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; } break; case 2: { - sym(1).Node = sym(1).UiImportList->finish(); + sym(1).Node = sym(2).Node; + program = sym(1).Node; } break; case 3: { + sym(1).UiProgram = makeAstNode (driver->nodePool(), sym(1).UiImportList, + sym(2).UiObjectMemberList->finish()); +} break; + +case 5: { + sym(1).Node = sym(1).UiImportList->finish(); +} break; + +case 6: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiImport); } break; -case 4: { +case 7: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiImportList, sym(2).UiImport); } break; -case 6: { +case 9: { AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).sval); node->importToken = loc(1); node->fileNameToken = loc(2); @@ -220,56 +236,107 @@ case 6: { sym(1).Node = node; } break; -case 7: { +case 11: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).sval); + node->importId = sym(4).sval; + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->asToken = loc(3); + node->importIdToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; +} break; + +case 13: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).UiQualifiedId->finish()); + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 15: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).UiQualifiedId->finish()); + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->versionToken = loc(3); + node->semicolonToken = loc(4); + sym(1).Node = node; +} break; + +case 17: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).UiQualifiedId->finish()); + node->importId = sym(5).sval; + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->versionToken = loc(3); + node->asToken = loc(4); + node->importIdToken = loc(5); + node->semicolonToken = loc(6); + sym(1).Node = node; +} break; + +case 19: { + AST::UiImport *node = makeAstNode(driver->nodePool(), sym(2).UiQualifiedId->finish()); + node->importId = sym(4).sval; + node->importToken = loc(1); + node->fileNameToken = loc(2); + node->asToken = loc(3); + node->importIdToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; +} break; + +case 20: { sym(1).Node = 0; } break; -case 8: { +case 21: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); } break; -case 9: { +case 22: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); } break; -case 10: { +case 23: { AST::UiObjectMemberList *node = makeAstNode (driver->nodePool(), sym(1).UiObjectMemberList, sym(2).UiObjectMember); sym(1).Node = node; } break; -case 11: { +case 24: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).UiObjectMember); } break; -case 12: { +case 25: { AST::UiArrayMemberList *node = makeAstNode (driver->nodePool(), sym(1).UiArrayMemberList, sym(3).UiObjectMember); node->commaToken = loc(2); sym(1).Node = node; } break; -case 13: { +case 26: { AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), (AST::UiObjectMemberList*)0); node->lbraceToken = loc(1); node->rbraceToken = loc(2); sym(1).Node = node; } break; -case 14: { +case 27: { AST::UiObjectInitializer *node = makeAstNode (driver->nodePool(), sym(2).UiObjectMemberList->finish()); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 15: { +case 28: { AST::UiObjectDefinition *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(2).UiObjectInitializer); sym(1).Node = node; } break; -case 17: { +case 30: { AST::UiArrayBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); @@ -278,19 +345,19 @@ case 17: { sym(1).Node = node; } break; -case 18: { +case 31: { AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 20: { +case 33: { AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 21: { +case 34: { if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) { AST::UiObjectBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer); @@ -305,7 +372,7 @@ case 21: { return false; // ### recover } } break; -case 22:case 23:case 24:case 25:case 26:case 27: +case 35:case 36:case 37:case 38:case 39:case 40: { AST::UiScriptBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(3).Statement); @@ -313,14 +380,45 @@ case 22:case 23:case 24:case 25:case 26:case 27: sym(1).Node = node; } break; -case 28: +case 41: -case 29: { +case 42: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); break; } -case 31: { +case 44: { + sym(1).Node = 0; +} break; + +case 45: { + sym(1).Node = sym(1).UiParameterList->finish (); +} break; + +case 46: { + AST::UiParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).sval); + node->identifierToken = loc(2); + sym(1).Node = node; +} break; + +case 47: { + AST::UiParameterList *node = makeAstNode (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); + node->commaToken = loc(2); + node->identifierToken = loc(4); + sym(1).Node = node; +} break; + +case 48: { + AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->parameters = sym(4).UiParameterList; + sym(1).Node = node; +} break; + +case 49: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); @@ -329,7 +427,7 @@ case 31: { sym(1).Node = node; } break; -case 33: { +case 51: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval); node->propertyToken = loc(1); node->typeToken = loc(2); @@ -338,7 +436,7 @@ case 33: { sym(1).Node = node; } break; -case 35: { +case 53: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval); node->isDefaultMember = true; node->defaultToken = loc(1); @@ -349,7 +447,7 @@ case 35: { sym(1).Node = node; } break; -case 37: { +case 55: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval, sym(5).Expression); node->propertyToken = loc(1); @@ -360,7 +458,7 @@ case 37: { sym(1).Node = node; } break; -case 39: { +case 57: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, sym(6).Expression); node->isDefaultMember = true; @@ -373,76 +471,76 @@ case 39: { sym(1).Node = node; } break; -case 40: { +case 58: { sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); } break; -case 41: { +case 59: { sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); } break; -case 42: -case 43: +case 60: +case 61: { AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 45: { +case 63: { QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 46: { +case 64: { QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 47: { +case 65: { AST::ThisExpression *node = makeAstNode (driver->nodePool()); node->thisToken = loc(1); sym(1).Node = node; } break; -case 48: { +case 66: { AST::IdentifierExpression *node = makeAstNode (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 49: { +case 67: { AST::NullExpression *node = makeAstNode (driver->nodePool()); node->nullToken = loc(1); sym(1).Node = node; } break; -case 50: { +case 68: { AST::TrueLiteral *node = makeAstNode (driver->nodePool()); node->trueToken = loc(1); sym(1).Node = node; } break; -case 51: { +case 69: { AST::FalseLiteral *node = makeAstNode (driver->nodePool()); node->falseToken = loc(1); sym(1).Node = node; } break; -case 52: { +case 70: { AST::NumericLiteral *node = makeAstNode (driver->nodePool(), sym(1).dval, lexer->flags); node->literalToken = loc(1); sym(1).Node = node; } break; -case 53: { +case 71: { AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 54: { +case 72: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -453,7 +551,7 @@ case 54: { sym(1).Node = node; } break; -case 55: { +case 73: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -464,28 +562,28 @@ case 55: { sym(1).Node = node; } break; -case 56: { +case 74: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), (AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; -case 57: { +case 75: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 58: { +case 76: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 59: { +case 77: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); @@ -494,7 +592,7 @@ case 59: { sym(1).Node = node; } break; -case 60: { +case 78: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); @@ -503,7 +601,7 @@ case 60: { sym(1).Node = node; } break; -case 61: { +case 79: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = makeAstNode (driver->nodePool(), @@ -515,7 +613,7 @@ case 61: { sym(1).Node = node; } break; -case 62: { +case 80: { AST::ObjectLiteral *node = makeAstNode (driver->nodePool(), sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); @@ -523,67 +621,67 @@ case 62: { sym(1).Node = node; } break; -case 63: { +case 81: { AST::NestedExpression *node = makeAstNode(driver->nodePool(), sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; -case 64: { +case 82: { AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 65: { +case 83: { AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 66: { +case 84: { sym(1).Node = makeAstNode (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); } break; -case 67: { +case 85: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); } break; -case 68: { +case 86: { AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 69: { +case 87: { AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 70: { +case 88: { AST::Elision *node = makeAstNode (driver->nodePool()); node->commaToken = loc(1); sym(1).Node = node; } break; -case 71: { +case 89: { AST::Elision *node = makeAstNode (driver->nodePool(), sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; -case 72: { +case 90: { AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; -case 73: { +case 91: { AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); @@ -591,72 +689,36 @@ case 73: { sym(1).Node = node; } break; -case 74: { +case 92: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 75: -case 76: { +case 93: +case 94: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 77: { +case 95: { AST::StringLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 78: { +case 96: { AST::NumericLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 79: { +case 97: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 80: - -case 81: - -case 82: - -case 83: - -case 84: - -case 85: - -case 86: - -case 87: - -case 88: - -case 89: - -case 90: - -case 91: - -case 92: - -case 93: - -case 94: - -case 95: - -case 96: - -case 97: - case 98: case 99: @@ -682,25 +744,61 @@ case 108: case 109: case 110: + +case 111: + +case 112: + +case 113: + +case 114: + +case 115: + +case 116: + +case 117: + +case 118: + +case 119: + +case 120: + +case 121: + +case 122: + +case 123: + +case 124: + +case 125: + +case 126: + +case 127: + +case 128: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); } break; -case 115: { +case 133: { AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 116: { +case 134: { AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 117: { +case 135: { AST::NewMemberExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); @@ -708,505 +806,505 @@ case 117: { sym(1).Node = node; } break; -case 119: { +case 137: { AST::NewExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; -case 120: { +case 138: { AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 121: { +case 139: { AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 122: { +case 140: { AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 123: { +case 141: { AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 124: { +case 142: { sym(1).Node = 0; } break; -case 125: { +case 143: { sym(1).Node = sym(1).ArgumentList->finish(); } break; -case 126: { +case 144: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Expression); } break; -case 127: { +case 145: { AST::ArgumentList *node = makeAstNode (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 131: { +case 149: { AST::PostIncrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; -case 132: { +case 150: { AST::PostDecrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; -case 134: { +case 152: { AST::DeleteExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; -case 135: { +case 153: { AST::VoidExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; -case 136: { +case 154: { AST::TypeOfExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; -case 137: { +case 155: { AST::PreIncrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; -case 138: { +case 156: { AST::PreDecrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; -case 139: { +case 157: { AST::UnaryPlusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; -case 140: { +case 158: { AST::UnaryMinusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; -case 141: { +case 159: { AST::TildeExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; -case 142: { +case 160: { AST::NotExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; -case 144: { +case 162: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 145: { +case 163: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 146: { +case 164: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 148: { +case 166: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 149: { +case 167: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 151: { +case 169: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 152: { +case 170: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 153: { +case 171: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 155: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 156: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 157: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 158: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 159: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 160: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::In, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 162: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 163: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 164: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 165: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 166: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 168: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 169: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 170: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 171: { - AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - case 173: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Equal, sym(3).Expression); + QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 174: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); + QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 175: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); + QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 176: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 177: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 178: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); + QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 180: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 181: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 182: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 183: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 184: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); + QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 186: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 187: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 188: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); + QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 190: { +case 189: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::And, sym(3).Expression); + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 191: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 192: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::And, sym(3).Expression); + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 193: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 194: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Or, sym(3).Expression); + QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 196: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - QSOperator::Or, sym(3).Expression); + QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 198: { - AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); sym(1).Node = node; } break; case 200: { - AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); sym(1).Node = node; } break; case 202: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, - sym(2).ival, sym(3).Expression); + QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 204: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 206: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 208: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 210: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 212: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 214: { + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 216: { + AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; + +case 218: { + AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; + +case 220: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 205: { - sym(1).ival = QSOperator::Assign; -} break; - -case 206: { - sym(1).ival = QSOperator::InplaceMul; -} break; - -case 207: { - sym(1).ival = QSOperator::InplaceDiv; -} break; - -case 208: { - sym(1).ival = QSOperator::InplaceMod; -} break; - -case 209: { - sym(1).ival = QSOperator::InplaceAdd; -} break; - -case 210: { - sym(1).ival = QSOperator::InplaceSub; -} break; - -case 211: { - sym(1).ival = QSOperator::InplaceLeftShift; -} break; - -case 212: { - sym(1).ival = QSOperator::InplaceRightShift; -} break; - -case 213: { - sym(1).ival = QSOperator::InplaceURightShift; -} break; - -case 214: { - sym(1).ival = QSOperator::InplaceAnd; -} break; - -case 215: { - sym(1).ival = QSOperator::InplaceXor; -} break; - -case 216: { - sym(1).ival = QSOperator::InplaceOr; -} break; - -case 218: { - AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 219: { - sym(1).Node = 0; -} break; - case 222: { - AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); + AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); sym(1).Node = node; } break; case 223: { + sym(1).ival = QSOperator::Assign; +} break; + +case 224: { + sym(1).ival = QSOperator::InplaceMul; +} break; + +case 225: { + sym(1).ival = QSOperator::InplaceDiv; +} break; + +case 226: { + sym(1).ival = QSOperator::InplaceMod; +} break; + +case 227: { + sym(1).ival = QSOperator::InplaceAdd; +} break; + +case 228: { + sym(1).ival = QSOperator::InplaceSub; +} break; + +case 229: { + sym(1).ival = QSOperator::InplaceLeftShift; +} break; + +case 230: { + sym(1).ival = QSOperator::InplaceRightShift; +} break; + +case 231: { + sym(1).ival = QSOperator::InplaceURightShift; +} break; + +case 232: { + sym(1).ival = QSOperator::InplaceAnd; +} break; + +case 233: { + sym(1).ival = QSOperator::InplaceXor; +} break; + +case 234: { + sym(1).ival = QSOperator::InplaceOr; +} break; + +case 236: { + AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 237: { sym(1).Node = 0; } break; case 240: { + AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 241: { + sym(1).Node = 0; +} break; + +case 258: { AST::Block *node = makeAstNode (driver->nodePool(), sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 241: { +case 259: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); } break; -case 242: { +case 260: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).StatementList, sym(2).Statement); } break; -case 243: { +case 261: { sym(1).Node = 0; } break; -case 244: { +case 262: { sym(1).Node = sym(1).StatementList->finish (); } break; -case 246: { +case 264: { AST::VariableStatement *node = makeAstNode (driver->nodePool(), sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); @@ -1214,76 +1312,76 @@ case 246: { sym(1).Node = node; } break; -case 247: { +case 265: { sym(1).ival = T_CONST; } break; -case 248: { +case 266: { sym(1).ival = T_VAR; } break; -case 249: { +case 267: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 250: { +case 268: { AST::VariableDeclarationList *node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; -case 251: { +case 269: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 252: { +case 270: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; -case 253: { +case 271: { AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 254: { +case 272: { AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 255: { +case 273: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 256: { +case 274: { sym(1).Node = 0; } break; -case 258: { +case 276: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 259: { +case 277: { sym(1).Node = 0; } break; -case 261: { +case 279: { AST::EmptyStatement *node = makeAstNode (driver->nodePool()); node->semicolonToken = loc(1); sym(1).Node = node; } break; -case 263: { +case 281: { AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 264: { +case 282: { AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1292,7 +1390,7 @@ case 264: { sym(1).Node = node; } break; -case 265: { +case 283: { AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1300,7 +1398,7 @@ case 265: { sym(1).Node = node; } break; -case 267: { +case 285: { AST::DoWhileStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); @@ -1310,7 +1408,7 @@ case 267: { sym(1).Node = node; } break; -case 268: { +case 286: { AST::WhileStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); @@ -1318,7 +1416,7 @@ case 268: { sym(1).Node = node; } break; -case 269: { +case 287: { AST::ForStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); @@ -1329,7 +1427,7 @@ case 269: { sym(1).Node = node; } break; -case 270: { +case 288: { AST::LocalForStatement *node = makeAstNode (driver->nodePool(), sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); @@ -1342,7 +1440,7 @@ case 270: { sym(1).Node = node; } break; -case 271: { +case 289: { AST:: ForEachStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); @@ -1352,7 +1450,7 @@ case 271: { sym(1).Node = node; } break; -case 272: { +case 290: { AST::LocalForEachStatement *node = makeAstNode (driver->nodePool(), sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); @@ -1363,14 +1461,14 @@ case 272: { sym(1).Node = node; } break; -case 274: { +case 292: { AST::ContinueStatement *node = makeAstNode (driver->nodePool()); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 276: { +case 294: { AST::ContinueStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); node->continueToken = loc(1); node->identifierToken = loc(2); @@ -1378,14 +1476,14 @@ case 276: { sym(1).Node = node; } break; -case 278: { +case 296: { AST::BreakStatement *node = makeAstNode (driver->nodePool()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 280: { +case 298: { AST::BreakStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); node->breakToken = loc(1); node->identifierToken = loc(2); @@ -1393,14 +1491,14 @@ case 280: { sym(1).Node = node; } break; -case 282: { +case 300: { AST::ReturnStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 283: { +case 301: { AST::WithStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); @@ -1408,7 +1506,7 @@ case 283: { sym(1).Node = node; } break; -case 284: { +case 302: { AST::SwitchStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); @@ -1416,90 +1514,90 @@ case 284: { sym(1).Node = node; } break; -case 285: { +case 303: { AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 286: { +case 304: { AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; -case 287: { +case 305: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClause); } break; -case 288: { +case 306: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); } break; -case 289: { +case 307: { sym(1).Node = 0; } break; -case 290: { +case 308: { sym(1).Node = sym(1).CaseClauses->finish (); } break; -case 291: { +case 309: { AST::CaseClause *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; -case 292: { +case 310: { AST::DefaultClause *node = makeAstNode (driver->nodePool(), sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 293: -case 294: { +case 311: +case 312: { AST::LabelledStatement *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 295: { +case 313: { AST::LabelledStatement *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 297: { +case 315: { AST::ThrowStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 298: { +case 316: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; -case 299: { +case 317: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 300: { +case 318: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 301: { +case 319: { AST::Catch *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); @@ -1508,20 +1606,20 @@ case 301: { sym(1).Node = node; } break; -case 302: { +case 320: { AST::Finally *node = makeAstNode (driver->nodePool(), sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; -case 304: { +case 322: { AST::DebuggerStatement *node = makeAstNode (driver->nodePool()); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 305: { +case 323: { AST::FunctionDeclaration *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); @@ -1532,7 +1630,7 @@ case 305: { sym(1).Node = node; } break; -case 306: { +case 324: { AST::FunctionExpression *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (sym(2).sval) @@ -1544,56 +1642,56 @@ case 306: { sym(1).Node = node; } break; -case 307: { +case 325: { AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 308: { +case 326: { AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 309: { +case 327: { sym(1).Node = 0; } break; -case 310: { +case 328: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; -case 311: { +case 329: { sym(1).Node = 0; } break; -case 313: { +case 331: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); } break; -case 314: { +case 332: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElement); } break; -case 315: { +case 333: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); } break; -case 316: { +case 334: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); } break; -case 317: { +case 335: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).FunctionDeclaration); } break; -case 318: { +case 336: { sym(1).sval = 0; } break; -case 320: { +case 338: { sym(1).Node = 0; } break; @@ -1687,7 +1785,8 @@ case 320: { } for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { - if (tk == T_AUTOMATIC_SEMICOLON) + if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || + tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION) continue; int a = t_action(errorState, tk); diff --git a/src/plugins/duieditor/parser/qmljsparser_p.h b/src/plugins/duieditor/parser/qmljsparser_p.h index 35c0cd9e4e5..92730399524 100644 --- a/src/plugins/duieditor/parser/qmljsparser_p.h +++ b/src/plugins/duieditor/parser/qmljsparser_p.h @@ -3,7 +3,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtScript module of the Qt Toolkit. ** @@ -36,7 +36,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -109,6 +109,7 @@ public: AST::UiProgram *UiProgram; AST::UiImportList *UiImportList; AST::UiImport *UiImport; + AST::UiParameterList *UiParameterList; AST::UiPublicMember *UiPublicMember; AST::UiObjectDefinition *UiObjectDefinition; AST::UiObjectInitializer *UiObjectInitializer; @@ -125,10 +126,29 @@ public: Parser(Engine *engine); ~Parser(); - bool parse(); + // parse a UI program + bool parse() { return parse(T_FEED_UI_PROGRAM); } + bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } + bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } - AST::UiProgram *ast() - { return program; } + AST::UiProgram *ast() const + { return AST::cast(program); } + + AST::Statement *statement() const + { + if (! program) + return 0; + + return program->statementCast(); + } + + AST::ExpressionNode *expression() const + { + if (! program) + return 0; + + return program->expressionCast(); + } QList diagnosticMessages() const { return diagnostic_messages; } @@ -153,6 +173,8 @@ public: { return diagnosticMessage().loc.startColumn; } protected: + bool parse(int startToken); + void reallocateStack(); inline Value &sym(int index) @@ -171,7 +193,7 @@ protected: int *state_stack; AST::SourceLocation *location_stack; - AST::UiProgram *program; + AST::Node *program; // error recovery enum { TOKEN_BUFFER_SIZE = 3 }; @@ -197,9 +219,9 @@ protected: -#define J_SCRIPT_REGEXPLITERAL_RULE1 54 +#define J_SCRIPT_REGEXPLITERAL_RULE1 72 -#define J_SCRIPT_REGEXPLITERAL_RULE2 55 +#define J_SCRIPT_REGEXPLITERAL_RULE2 73 QT_END_NAMESPACE diff --git a/src/plugins/duieditor/parser/qmljsprettypretty.cpp b/src/plugins/duieditor/parser/qmljsprettypretty.cpp index 3a89206ffab..b6733e556fd 100644 --- a/src/plugins/duieditor/parser/qmljsprettypretty.cpp +++ b/src/plugins/duieditor/parser/qmljsprettypretty.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the QtScript module of the Qt Toolkit. +** This file is part of the QtDeclarative module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -170,14 +170,14 @@ void PrettyPretty::accept(AST::Node *node) bool PrettyPretty::visit(AST::ThisExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "this"; return true; } void PrettyPretty::endVisit(AST::ThisExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::IdentifierExpression *node) @@ -188,43 +188,43 @@ bool PrettyPretty::visit(AST::IdentifierExpression *node) void PrettyPretty::endVisit(AST::IdentifierExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::NullExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "null"; return false; } void PrettyPretty::endVisit(AST::NullExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::TrueLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "true"; return false; } void PrettyPretty::endVisit(AST::TrueLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::FalseLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "false"; return false; } void PrettyPretty::endVisit(AST::FalseLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::StringLiteral *node) @@ -237,7 +237,7 @@ bool PrettyPretty::visit(AST::StringLiteral *node) void PrettyPretty::endVisit(AST::StringLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::NumericLiteral *node) @@ -248,7 +248,7 @@ bool PrettyPretty::visit(AST::NumericLiteral *node) void PrettyPretty::endVisit(AST::NumericLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::RegExpLiteral *node) @@ -262,7 +262,7 @@ bool PrettyPretty::visit(AST::RegExpLiteral *node) void PrettyPretty::endVisit(AST::RegExpLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ArrayLiteral *node) @@ -276,7 +276,7 @@ bool PrettyPretty::visit(AST::ArrayLiteral *node) void PrettyPretty::endVisit(AST::ArrayLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ObjectLiteral *node) @@ -300,7 +300,7 @@ bool PrettyPretty::visit(AST::ObjectLiteral *node) void PrettyPretty::endVisit(AST::ObjectLiteral *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ElementList *node) @@ -317,7 +317,7 @@ bool PrettyPretty::visit(AST::ElementList *node) void PrettyPretty::endVisit(AST::ElementList *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::Elision *node) @@ -330,7 +330,7 @@ bool PrettyPretty::visit(AST::Elision *node) void PrettyPretty::endVisit(AST::Elision *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::PropertyNameAndValueList *node) @@ -343,7 +343,7 @@ bool PrettyPretty::visit(AST::PropertyNameAndValueList *node) void PrettyPretty::endVisit(AST::PropertyNameAndValueList *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::IdentifierPropertyName *node) @@ -354,7 +354,7 @@ bool PrettyPretty::visit(AST::IdentifierPropertyName *node) void PrettyPretty::endVisit(AST::IdentifierPropertyName *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::StringLiteralPropertyName *node) @@ -367,7 +367,7 @@ bool PrettyPretty::visit(AST::StringLiteralPropertyName *node) void PrettyPretty::endVisit(AST::StringLiteralPropertyName *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::NumericLiteralPropertyName *node) @@ -378,7 +378,7 @@ bool PrettyPretty::visit(AST::NumericLiteralPropertyName *node) void PrettyPretty::endVisit(AST::NumericLiteralPropertyName *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ArrayMemberExpression *node) @@ -392,7 +392,7 @@ bool PrettyPretty::visit(AST::ArrayMemberExpression *node) void PrettyPretty::endVisit(AST::ArrayMemberExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::FieldMemberExpression *node) @@ -404,7 +404,7 @@ bool PrettyPretty::visit(AST::FieldMemberExpression *node) void PrettyPretty::endVisit(AST::FieldMemberExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::NewMemberExpression *node) @@ -419,19 +419,19 @@ bool PrettyPretty::visit(AST::NewMemberExpression *node) void PrettyPretty::endVisit(AST::NewMemberExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::NewExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "new "; return true; } void PrettyPretty::endVisit(AST::NewExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::CallExpression *node) @@ -445,7 +445,7 @@ bool PrettyPretty::visit(AST::CallExpression *node) void PrettyPretty::endVisit(AST::CallExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ArgumentList *node) @@ -460,91 +460,91 @@ bool PrettyPretty::visit(AST::ArgumentList *node) void PrettyPretty::endVisit(AST::ArgumentList *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::PostIncrementExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::PostIncrementExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "++"; } bool PrettyPretty::visit(AST::PostDecrementExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::PostDecrementExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "--"; } bool PrettyPretty::visit(AST::DeleteExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "delete "; return true; } void PrettyPretty::endVisit(AST::DeleteExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::VoidExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "void "; return true; } void PrettyPretty::endVisit(AST::VoidExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::TypeOfExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "typeof "; return true; } void PrettyPretty::endVisit(AST::TypeOfExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::PreIncrementExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "++"; return true; } void PrettyPretty::endVisit(AST::PreIncrementExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::PreDecrementExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "--"; return true; } void PrettyPretty::endVisit(AST::PreDecrementExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::UnaryPlusExpression *node) @@ -561,7 +561,7 @@ bool PrettyPretty::visit(AST::UnaryPlusExpression *node) void PrettyPretty::endVisit(AST::UnaryPlusExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::UnaryMinusExpression *node) @@ -578,7 +578,7 @@ bool PrettyPretty::visit(AST::UnaryMinusExpression *node) void PrettyPretty::endVisit(AST::UnaryMinusExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::TildeExpression *node) @@ -595,7 +595,7 @@ bool PrettyPretty::visit(AST::TildeExpression *node) void PrettyPretty::endVisit(AST::TildeExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::NotExpression *node) @@ -612,7 +612,7 @@ bool PrettyPretty::visit(AST::NotExpression *node) void PrettyPretty::endVisit(AST::NotExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::BinaryExpression *node) @@ -712,7 +712,7 @@ bool PrettyPretty::visit(AST::BinaryExpression *node) void PrettyPretty::endVisit(AST::BinaryExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ConditionalExpression *node) @@ -727,7 +727,7 @@ bool PrettyPretty::visit(AST::ConditionalExpression *node) void PrettyPretty::endVisit(AST::ConditionalExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::Expression *node) @@ -740,18 +740,18 @@ bool PrettyPretty::visit(AST::Expression *node) void PrettyPretty::endVisit(AST::Expression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::Block *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::Block *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::StatementList *node) @@ -766,7 +766,7 @@ bool PrettyPretty::visit(AST::StatementList *node) void PrettyPretty::endVisit(AST::StatementList *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::VariableDeclarationList *node) @@ -785,19 +785,19 @@ bool PrettyPretty::visit(AST::VariableDeclarationList *node) void PrettyPretty::endVisit(AST::VariableDeclarationList *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::VariableStatement *node) { out << "var "; - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::VariableStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << ";"; } @@ -813,19 +813,19 @@ bool PrettyPretty::visit(AST::VariableDeclaration *node) void PrettyPretty::endVisit(AST::VariableDeclaration *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::EmptyStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << ";"; return true; } void PrettyPretty::endVisit(AST::EmptyStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ExpressionStatement *node) @@ -837,7 +837,7 @@ bool PrettyPretty::visit(AST::ExpressionStatement *node) void PrettyPretty::endVisit(AST::ExpressionStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::IfStatement *node) @@ -855,7 +855,7 @@ bool PrettyPretty::visit(AST::IfStatement *node) void PrettyPretty::endVisit(AST::IfStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::DoWhileStatement *node) @@ -870,7 +870,7 @@ bool PrettyPretty::visit(AST::DoWhileStatement *node) void PrettyPretty::endVisit(AST::DoWhileStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::WhileStatement *node) @@ -884,7 +884,7 @@ bool PrettyPretty::visit(AST::WhileStatement *node) void PrettyPretty::endVisit(AST::WhileStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ForStatement *node) @@ -902,7 +902,7 @@ bool PrettyPretty::visit(AST::ForStatement *node) void PrettyPretty::endVisit(AST::ForStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::LocalForStatement *node) @@ -920,7 +920,7 @@ bool PrettyPretty::visit(AST::LocalForStatement *node) void PrettyPretty::endVisit(AST::LocalForStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ForEachStatement *node) @@ -936,7 +936,7 @@ bool PrettyPretty::visit(AST::ForEachStatement *node) void PrettyPretty::endVisit(AST::ForEachStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::LocalForEachStatement *node) @@ -952,7 +952,7 @@ bool PrettyPretty::visit(AST::LocalForEachStatement *node) void PrettyPretty::endVisit(AST::LocalForEachStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ContinueStatement *node) @@ -967,7 +967,7 @@ bool PrettyPretty::visit(AST::ContinueStatement *node) void PrettyPretty::endVisit(AST::ContinueStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::BreakStatement *node) @@ -982,7 +982,7 @@ bool PrettyPretty::visit(AST::BreakStatement *node) void PrettyPretty::endVisit(AST::BreakStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ReturnStatement *node) @@ -998,7 +998,7 @@ bool PrettyPretty::visit(AST::ReturnStatement *node) void PrettyPretty::endVisit(AST::ReturnStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::WithStatement *node) @@ -1012,7 +1012,7 @@ bool PrettyPretty::visit(AST::WithStatement *node) void PrettyPretty::endVisit(AST::WithStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::SwitchStatement *node) @@ -1026,7 +1026,7 @@ bool PrettyPretty::visit(AST::SwitchStatement *node) void PrettyPretty::endVisit(AST::SwitchStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::CaseBlock *node) @@ -1045,7 +1045,7 @@ bool PrettyPretty::visit(AST::CaseBlock *node) void PrettyPretty::endVisit(AST::CaseBlock *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::CaseClauses *node) @@ -1060,7 +1060,7 @@ bool PrettyPretty::visit(AST::CaseClauses *node) void PrettyPretty::endVisit(AST::CaseClauses *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::CaseClause *node) @@ -1077,12 +1077,12 @@ bool PrettyPretty::visit(AST::CaseClause *node) void PrettyPretty::endVisit(AST::CaseClause *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::DefaultClause *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "default:"; newlineAndIndent(); return true; @@ -1090,7 +1090,7 @@ bool PrettyPretty::visit(AST::DefaultClause *node) void PrettyPretty::endVisit(AST::DefaultClause *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::LabelledStatement *node) @@ -1101,12 +1101,12 @@ bool PrettyPretty::visit(AST::LabelledStatement *node) void PrettyPretty::endVisit(AST::LabelledStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::ThrowStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "throw "; accept(node->expression); out << ";"; @@ -1115,7 +1115,7 @@ bool PrettyPretty::visit(AST::ThrowStatement *node) void PrettyPretty::endVisit(AST::ThrowStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::TryStatement *node) @@ -1135,30 +1135,30 @@ bool PrettyPretty::visit(AST::TryStatement *node) void PrettyPretty::endVisit(AST::TryStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::Catch *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::Catch *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::Finally *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "finally "; return true; } void PrettyPretty::endVisit(AST::Finally *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::FunctionDeclaration *node) @@ -1197,7 +1197,7 @@ bool PrettyPretty::visit(AST::FunctionDeclaration *node) void PrettyPretty::endVisit(AST::FunctionDeclaration *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::FunctionExpression *node) @@ -1236,45 +1236,45 @@ bool PrettyPretty::visit(AST::FunctionExpression *node) void PrettyPretty::endVisit(AST::FunctionExpression *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::FormalParameterList *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::FormalParameterList *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::FunctionBody *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::FunctionBody *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::Program *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::Program *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::SourceElements *node) { - Q_UNUSED(node) + Q_UNUSED(node); accept(node->element); for (node = node->next; node != 0; node = node->next) { newlineAndIndent(); @@ -1285,47 +1285,47 @@ bool PrettyPretty::visit(AST::SourceElements *node) void PrettyPretty::endVisit(AST::SourceElements *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::FunctionSourceElement *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::FunctionSourceElement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::StatementSourceElement *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } void PrettyPretty::endVisit(AST::StatementSourceElement *node) { - Q_UNUSED(node) + Q_UNUSED(node); } bool PrettyPretty::visit(AST::DebuggerStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << "debugger"; return true; } void PrettyPretty::endVisit(AST::DebuggerStatement *node) { - Q_UNUSED(node) + Q_UNUSED(node); out << ";"; } bool PrettyPretty::preVisit(AST::Node *node) { - Q_UNUSED(node) + Q_UNUSED(node); return true; } diff --git a/src/plugins/duieditor/parser/qmljsprettypretty_p.h b/src/plugins/duieditor/parser/qmljsprettypretty_p.h index e0fe1f8491e..3227e7d4e0e 100644 --- a/src/plugins/duieditor/parser/qmljsprettypretty_p.h +++ b/src/plugins/duieditor/parser/qmljsprettypretty_p.h @@ -1,9 +1,9 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the QtScript module of the Qt Toolkit. +** This file is part of the QtDeclarative module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ From 90a5f271ee351266ca5ecae1b30e2ba1e6cd831c Mon Sep 17 00:00:00 2001 From: con Date: Wed, 15 Jul 2009 15:24:39 +0200 Subject: [PATCH 13/26] Guard against endless loop a bit. --- src/plugins/find/basetextfind.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/find/basetextfind.cpp b/src/plugins/find/basetextfind.cpp index da3c1de3d9d..d4c245ad3f8 100644 --- a/src/plugins/find/basetextfind.cpp +++ b/src/plugins/find/basetextfind.cpp @@ -216,7 +216,8 @@ int BaseTextFind::replaceAll(const QString &before, const QString &after, regexp.setPatternSyntax(usesRegExp ? QRegExp::RegExp : QRegExp::FixedString); regexp.setCaseSensitivity((findFlags & IFindSupport::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive); QTextCursor found = document()->find(regexp, editCursor, IFindSupport::textDocumentFlagsForFindFlags(findFlags)); - while (!found.isNull() && inScope(found.selectionStart(), found.selectionEnd())) { + while (!found.isNull() && found.selectionStart() < found.selectionEnd() + && inScope(found.selectionStart(), found.selectionEnd())) { ++count; editCursor.setPosition(found.selectionStart()); editCursor.setPosition(found.selectionEnd(), QTextCursor::KeepAnchor); From 3607ad172e5b1a1bcb4090d95b28d05f34d1a0ef Mon Sep 17 00:00:00 2001 From: dt Date: Wed, 15 Jul 2009 15:29:09 +0200 Subject: [PATCH 14/26] Fix opening files from search results didn't get the correct encoding. Patch based on the analysis by Grigory Zagorodnev. Task-number: 253974 --- src/libs/utils/filesearch.cpp | 5 ++--- src/plugins/find/searchresulttreemodel.cpp | 3 ++- src/plugins/find/searchresultwindow.cpp | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp index 2676d06c691..109e4248f26 100644 --- a/src/libs/utils/filesearch.cpp +++ b/src/libs/utils/filesearch.cpp @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -158,7 +157,7 @@ void runFileSearch(QFutureInterface &future, int n = 0; while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256) res.append(startOfLastLine[i++]); - future.reportResult(FileSearchResult(QDir::toNativeSeparators(s), lineNr, QString(res), + future.reportResult(FileSearchResult(s, lineNr, QString(res), regionPtr - startOfLastLine, sa.length())); ++numMatches; } @@ -204,7 +203,7 @@ void runFileSearchRegExp(QFutureInterface &future, line = stream.readLine(); int pos = 0; while ((pos = expression.indexIn(line, pos)) != -1) { - future.reportResult(FileSearchResult(QDir::toNativeSeparators(s), lineNr, line, + future.reportResult(FileSearchResult(s, lineNr, line, pos, expression.matchedLength())); pos += expression.matchedLength(); } diff --git a/src/plugins/find/searchresulttreemodel.cpp b/src/plugins/find/searchresulttreemodel.cpp index a53b8fe5951..ddb934c1a1f 100644 --- a/src/plugins/find/searchresulttreemodel.cpp +++ b/src/plugins/find/searchresulttreemodel.cpp @@ -33,6 +33,7 @@ #include #include +#include using namespace Find::Internal; @@ -187,7 +188,7 @@ QVariant SearchResultTreeModel::data(const SearchResultFile *file, int role) con result = QColor(qRgb(245, 245, 245)); break; case Qt::DisplayRole: - result = QString(file->fileName() + result = QString(QDir::toNativeSeparators(file->fileName()) + " (" + QString::number(file->childrenCount()) + ")"); break; case ItemDataRoles::FileNameRole: diff --git a/src/plugins/find/searchresultwindow.cpp b/src/plugins/find/searchresultwindow.cpp index d4ae8d926d8..7b160a36798 100644 --- a/src/plugins/find/searchresultwindow.cpp +++ b/src/plugins/find/searchresultwindow.cpp @@ -153,6 +153,7 @@ void SearchResultWindow::handleJumpToSearchResult(int index, const QString &file ResultWindowItem *SearchResultWindow::addResult(const QString &fileName, int lineNumber, const QString &rowText, int searchTermStart, int searchTermLength) { + qDebug()<<"###"<setCurrentWidget(m_searchResultTreeView); int index = m_items.size(); ResultWindowItem *item = new ResultWindowItem; From 96bff6ea90c5495e6c8e7e1da9dd8d35ba9cbef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 15 Jul 2009 15:39:35 +0200 Subject: [PATCH 15/26] Cleaned up creation of new color scheme files The creation of the styles directory was in two places and the importing of an old customized style didn't have any safety when the name 'customized.xml' already existed. --- src/plugins/texteditor/fontsettingspage.cpp | 58 ++++++++++++--------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp index 675ae98d6a1..6698230b874 100644 --- a/src/plugins/texteditor/fontsettingspage.cpp +++ b/src/plugins/texteditor/fontsettingspage.cpp @@ -97,6 +97,28 @@ static QString customStylesPath() return path; } +static QString createColorSchemeFileName(const QString &pattern) +{ + const QString stylesPath = customStylesPath(); + QString baseFileName = stylesPath; + baseFileName += pattern; + + // Find an available file name + int i = 1; + QString fileName; + do { + fileName = baseFileName.arg((i == 1) ? QString() : QString::number(i)); + ++i; + } while (QFile::exists(fileName)); + + // Create the base directory when it doesn't exist + if (!QFile::exists(stylesPath) && !QDir().mkpath(stylesPath)) { + qWarning() << "Failed to create color scheme directory:" << stylesPath; + return QString(); + } + + return fileName; +} // ------- FontSettingsPagePrivate FontSettingsPagePrivate::FontSettingsPagePrivate(const TextEditor::FormatDescriptions &fd, @@ -135,9 +157,8 @@ FontSettingsPagePrivate::FontSettingsPagePrivate(const TextEditor::FormatDescrip } if (m_value.colorScheme() != defaultScheme) { // Save it as a color scheme file - QString stylesPath = customStylesPath(); - if (QFile::exists(stylesPath) || QDir().mkpath(stylesPath)) { - QString schemeFileName = stylesPath + QLatin1String("customized.xml"); + QString schemeFileName = createColorSchemeFileName(QLatin1String("customized%1.xml")); + if (!schemeFileName.isEmpty()) { if (m_value.saveColorScheme(schemeFileName) && settings) m_value.toSettings(m_category, settings); } @@ -335,31 +356,18 @@ void FontSettingsPage::cloneColorScheme() if (!d_ptr->m_value.loadColorScheme(entry.fileName, d_ptr->m_descriptions)) return; - QString baseDir = customStylesPath(); - QString baseFileName = baseDir; - baseFileName.append(QFileInfo(entry.fileName).completeBaseName()); + QString baseFileName = QFileInfo(entry.fileName).completeBaseName(); + baseFileName += QLatin1String("_copy%1.xml"); + QString fileName = createColorSchemeFileName(baseFileName); - // Find an available file name - int i = 1; - QString fileName; - do { - fileName = baseFileName; - fileName.append(QString("_copy%1.xml").arg((i == 1) ? QString() : QString::number(i))); - ++i; - } while (QFile::exists(fileName)); + if (!fileName.isEmpty()) { + ColorScheme scheme = d_ptr->m_value.colorScheme(); + scheme.setName(tr("%1 (copy)").arg(scheme.name())); + scheme.save(fileName); + d_ptr->m_value.setColorSchemeFileName(fileName); - // Create the base directory when it doesn't exist - if (!QFile::exists(baseDir) && !QDir().mkpath(baseDir)) { - qWarning() << "Failed to create color scheme directory:" << baseDir; - return; + refreshColorSchemeList(); } - - ColorScheme scheme = d_ptr->m_value.colorScheme(); - scheme.setName(tr("%1 (copy)").arg(scheme.name())); - scheme.save(fileName); - d_ptr->m_value.setColorSchemeFileName(fileName); - - refreshColorSchemeList(); } void FontSettingsPage::deleteColorScheme() From 7a847df2b7a53686334b561bab3a099aec180587 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 15 Jul 2009 16:07:57 +0200 Subject: [PATCH 16/26] Fix CDB/output dumperversion correctly, dump maps correctly. --- share/qtcreator/gdbmacros/gdbmacros.cpp | 2 +- src/plugins/debugger/watchutils.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index b3361414bcb..b93bb69a4a3 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -3480,7 +3480,7 @@ void *qDumpObjectData440( "\"").put(((QT_VERSION >> 8) & 255)).put("\"," "\"").put(((QT_VERSION) & 255)).put("\"]"); d.put(",namespace=\""NS"\","); - d.put(",dumperversion=\"1.3\","); + d.put("dumperversion=\"1.3\","); // Dump out size information d.put("sizes={"); d.put("int=\"").put(sizeof(int)).put("\",") diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index cd6c7e21b32..d6daad15514 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -546,18 +546,22 @@ QList QtDumperResult::toWatchData(int source) const WatchData &wchild = rc.back(); wchild.source = source; wchild.iname = iname; - wchild.iname += dot; - wchild.iname += dchild.name; + // Name can be empty for array-like things + const QString iname = dchild.name.isEmpty() ? QString::number(c) : dchild.name; // Use key entry as name (which is used for map nodes) if (dchild.key.isEmpty()) { - wchild.name = dchild.name; + wchild.name = iname; } else { + // Do not use map keys as iname since they might contain quotes. wchild.name = decodeData(dchild.key, dchild.keyEncoded); if (wchild.name.size() > 13) { wchild.name.truncate(12); wchild.name += QLatin1String("..."); } } + // Append iname to total iname. + wchild.iname += dot; + wchild.iname += iname; wchild.exp = dchild.exp; if (dchild.valueEncountered) { wchild.valuedisabled = dchild.valuedisabled; @@ -1349,7 +1353,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data, case QAbstractItemType: inner = data.addr.mid(1); break; - case QVectorType: + case QVectorType: if (m_qtVersion >= 0x040600) extraArgs[1] = QString("(char*)&((%1).p->array)-(char*)((%2).p)") .arg(data.exp).arg(data.exp); From 609e3c7f6b9496e6e3de8355037b108c1fec66ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 15 Jul 2009 16:10:15 +0200 Subject: [PATCH 17/26] Update the current line highlight when its color might have changed Fixes the issue where it would stay the color of the previous color scheme until you change the cursor position. --- src/plugins/texteditor/basetexteditor.cpp | 34 +++++++++++++---------- src/plugins/texteditor/basetexteditor.h | 1 + 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 63507ae1637..414e5c7bb26 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1245,7 +1245,7 @@ bool BaseTextEditor::isParenthesesMatchingEnabled() const void BaseTextEditor::setHighlightCurrentLine(bool b) { d->m_highlightCurrentLine = b; - slotCursorPositionChanged(); + updateCurrentLineHighlight(); } bool BaseTextEditor::highlightCurrentLine() const @@ -2582,6 +2582,22 @@ void BaseTextEditor::saveCurrentCursorPositionForNavigation() d->m_tempNavigationState = saveState(); } +void BaseTextEditor::updateCurrentLineHighlight() +{ + QList extraSelections; + + if (d->m_highlightCurrentLine) { + QTextEdit::ExtraSelection sel; + sel.format.setBackground(d->m_currentLineFormat.background()); + sel.format.setProperty(QTextFormat::FullWidthSelection, true); + sel.cursor = textCursor(); + sel.cursor.clearSelection(); + extraSelections.append(sel); + } + + setExtraSelections(CurrentLineSelection, extraSelections); +} + void BaseTextEditor::slotCursorPositionChanged() { if (!d->m_contentsChanged && d->m_lastCursorChangeWasInteresting) { @@ -2602,18 +2618,7 @@ void BaseTextEditor::slotCursorPositionChanged() } } - QList extraSelections; - - if (d->m_highlightCurrentLine) { - QTextEdit::ExtraSelection sel; - sel.format.setBackground(d->m_currentLineFormat.background()); - sel.format.setProperty(QTextFormat::FullWidthSelection, true); - sel.cursor = textCursor(); - sel.cursor.clearSelection(); - extraSelections.append(sel); - } - - setExtraSelections(CurrentLineSelection, extraSelections); + updateCurrentLineHighlight(); if (d->m_displaySettings.m_highlightBlocks) { QTextCursor cursor = textCursor(); @@ -3898,7 +3903,8 @@ void BaseTextEditor::setFontSettings(const TextEditor::FontSettings &fs) d->m_matchFormat.setForeground(parenthesesFormat.foreground()); d->m_rangeFormat.setBackground(parenthesesFormat.background()); - slotUpdateExtraAreaWidth(); + slotUpdateExtraAreaWidth(); // Adjust to new font width + updateCurrentLineHighlight(); // Make sure it takes the new color } void BaseTextEditor::setTabSettings(const TabSettings &ts) diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index 9dd92405791..5bcf962ed9e 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -526,6 +526,7 @@ private: void moveLineUpDown(bool up); void copyLineUpDown(bool up); void saveCurrentCursorPositionForNavigation(); + void updateCurrentLineHighlight(); void drawFoldingMarker(QPainter *painter, const QPalette &pal, const QRect &rect, From e63578f2daf8e9f0122df19670ab82f94938b864 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 15 Jul 2009 16:19:16 +0200 Subject: [PATCH 18/26] Make Designer Form Class and App-Wizard use 'ui' as member variable. --- src/plugins/designer/cpp/formclasswizardparameters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/designer/cpp/formclasswizardparameters.cpp b/src/plugins/designer/cpp/formclasswizardparameters.cpp index 4f0881d9481..baa9c2d9751 100644 --- a/src/plugins/designer/cpp/formclasswizardparameters.cpp +++ b/src/plugins/designer/cpp/formclasswizardparameters.cpp @@ -39,7 +39,7 @@ #include #include -static const char *uiMemberC = "m_ui"; +static const char *uiMemberC = "ui"; static const char *uiNamespaceC = "Ui"; static const char *formClassWizardPageGroupC = "FormClassWizardPage"; From b2ec44ba907bdcf2b6e15b2d1641af108b2956fa Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 15 Jul 2009 16:50:18 +0200 Subject: [PATCH 19/26] Debugger/CDB: Do not disable dumpers on a C++ exception. --- src/plugins/debugger/cdb/cdbexceptionutils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/debugger/cdb/cdbexceptionutils.cpp b/src/plugins/debugger/cdb/cdbexceptionutils.cpp index 3839ee82272..1988cf8f6b5 100644 --- a/src/plugins/debugger/cdb/cdbexceptionutils.cpp +++ b/src/plugins/debugger/cdb/cdbexceptionutils.cpp @@ -271,6 +271,7 @@ bool isFatalException(LONG code) case startupCompleteTrap: // Mysterious exception at start of application case rpcServerUnavailableExceptionCode: case dllNotFoundExceptionCode: + case cppExceptionCode: return false; default: break; From e917eeacb9c2f0f245607724920da0aad52e23ec Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 15 Jul 2009 16:50:49 +0200 Subject: [PATCH 20/26] Debugger: Alert on stop in the debugger manager. --- src/plugins/debugger/debuggermanager.cpp | 3 ++- src/plugins/debugger/gdb/gdbengine.cpp | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 15c586b5bba..d403b1f3ec8 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -1236,11 +1236,12 @@ void DebuggerManager::setStatus(int status) || status == DebuggerInferiorStopRequested || status == DebuggerInferiorStopped; - //const bool starting = status == DebuggerProcessStartingUp; const bool running = status == DebuggerInferiorRunning; const bool ready = status == DebuggerInferiorStopped && startMode() != AttachCore; + if (ready) + QApplication::alert(mainWindow(), 3000); m_watchAction->setEnabled(ready); m_breakAction->setEnabled(true); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index fa8f9d7a0a2..f48f3d14196 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -62,7 +62,7 @@ #include #include -#include +#include #include #include #include @@ -1146,7 +1146,6 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) m_currentFrame = _(frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'); - QApplication::alert(q->mainWindow(), 3000); if (theDebuggerAction(ListSourceFiles)->value().toBool()) reloadSourceFiles(); postCommand(_("-break-list"), CB(handleBreakList)); @@ -2800,7 +2799,7 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos, //: Variable static const QString strNotInScope = - QApplication::translate("Debugger::Internal::GdbEngine", ""); + QCoreApplication::translate("Debugger::Internal::GdbEngine", ""); static void setWatchDataValue(WatchData &data, const GdbMi &mi, From 4c561414a6f23885df7f46cc8acd8aaaed58cc25 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 15 Jul 2009 09:58:56 +0200 Subject: [PATCH 21/26] optimize low-level pro reader code avoid qstring functions. instead, use preallocated strings and pointers. now the majority of the parsing time is spent in qt (qfile and qtextcodec). --- src/shared/proparser/profileevaluator.cpp | 200 +++++++++++++--------- 1 file changed, 121 insertions(+), 79 deletions(-) diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 4f309d914cc..46734d78e4d 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -140,7 +140,7 @@ public: ProBlock *currentBlock(); void updateItem(); bool parseLine(const QString &line); - void insertVariable(const QString &line, int *i); + void insertVariable(const ushort **pCur, const ushort *end); void insertOperator(const char op); void insertComment(const QString &comment); void enterScope(bool multiLine); @@ -153,11 +153,14 @@ public: ProItem *m_commentItem; QString m_proitem; QString m_pendingComment; + ushort *m_proitemPtr; bool m_syntaxError; bool m_contNextLine; bool m_inQuote; int m_parens; + enum StrState { NotStarted, Started, PutSpace }; + /////////////// Evaluating pro file contents // implementation of AbstractProItemVisitor @@ -304,32 +307,36 @@ bool ProFileEvaluator::Private::read(ProFile *pro, QTextStream *ts) return true; } -bool ProFileEvaluator::Private::parseLine(const QString &line0) +bool ProFileEvaluator::Private::parseLine(const QString &line) { if (m_blockstack.isEmpty()) return false; + const ushort *cur = (const ushort *)line.unicode(), + *end = cur + line.length(); int parens = m_parens; bool inQuote = m_inQuote; bool escaped = false; - QString line = line0.simplified(); - for (int i = 0; !m_syntaxError && i < line.length(); ++i) { - ushort c = line.at(i).unicode(); + m_proitem.reserve(line.length()); + m_proitemPtr = (ushort *)m_proitem.unicode(); + nextItem: + ushort *ptr = m_proitemPtr; + StrState sts = NotStarted; + while (cur < end) { + ushort c = *cur++; if (c == '#') { // Yep - no escaping possible - insertComment(line.mid(i + 1)); - escaped = m_contNextLine; - break; + m_proitemPtr = ptr; + insertComment(line.right(end - cur).simplified()); + goto done; } if (!escaped) { if (c == '\\') { escaped = true; - m_proitem += c; - continue; + goto putch; } else if (c == '"') { inQuote = !inQuote; - m_proitem += c; - continue; + goto putch; } } else { escaped = false; @@ -341,52 +348,70 @@ bool ProFileEvaluator::Private::parseLine(const QString &line0) --parens; } else if (!parens) { if (m_block && (m_block->blockKind() & ProBlock::VariableKind)) { - if (c == ' ') + if (c == ' ' || c == '\t') { + m_proitemPtr = ptr; updateItem(); - else - m_proitem += c; - continue; - } - if (c == ':') { - enterScope(false); - continue; - } - if (c == '{') { - enterScope(true); - continue; - } - if (c == '}') { - leaveScope(); - continue; - } - if (c == '=') { - insertVariable(line, &i); - continue; - } - if (c == '|' || c == '!') { - insertOperator(c); - continue; + goto nextItem; + } + } else { + if (c == ':') { + m_proitemPtr = ptr; + enterScope(false); + goto nextItem; + } + if (c == '{') { + m_proitemPtr = ptr; + enterScope(true); + goto nextItem; + } + if (c == '}') { + m_proitemPtr = ptr; + leaveScope(); + if (m_syntaxError) + goto done1; + goto nextItem; + } + if (c == '=') { + m_proitemPtr = ptr; + insertVariable(&cur, end); + goto nextItem; + } + if (c == '|' || c == '!') { + m_proitemPtr = ptr; + insertOperator(c); + goto nextItem; + } } } } - m_proitem += c; + if (c == ' ' || c == '\t') { + if (sts == Started) + sts = PutSpace; + } else { + putch: + if (sts == PutSpace) + *ptr++ = ' '; + *ptr++ = c; + sts = Started; + } } + m_proitemPtr = ptr; + done1: + m_contNextLine = escaped; + done: m_inQuote = inQuote; m_parens = parens; - m_contNextLine = escaped; - if (escaped) { - m_proitem.chop(1); - updateItem(); - return true; - } else { - if (!m_syntaxError) { - updateItem(); - finalizeBlock(); - return true; - } + if (m_syntaxError) return false; + if (escaped) { + --m_proitemPtr; + updateItem(); + } else { + updateItem(); + finalizeBlock(); } + return true; } void ProFileEvaluator::Private::finalizeBlock() @@ -401,37 +426,44 @@ void ProFileEvaluator::Private::finalizeBlock() } } -void ProFileEvaluator::Private::insertVariable(const QString &line, int *i) +void ProFileEvaluator::Private::insertVariable(const ushort **pCur, const ushort *end) { ProVariable::VariableOperator opkind; + ushort *uc = (ushort *)m_proitem.unicode(); + ushort *ptr = m_proitemPtr; - if (m_proitem.isEmpty()) // Line starting with '=', like a conflict marker + if (ptr == uc) // Line starting with '=', like a conflict marker return; - switch (m_proitem.at(m_proitem.length() - 1).unicode()) { + switch (*(ptr - 1)) { case '+': - m_proitem.chop(1); + --ptr; opkind = ProVariable::AddOperator; break; case '-': - m_proitem.chop(1); + --ptr; opkind = ProVariable::RemoveOperator; break; case '*': - m_proitem.chop(1); + --ptr; opkind = ProVariable::UniqueAddOperator; break; case '~': - m_proitem.chop(1); + --ptr; opkind = ProVariable::ReplaceOperator; break; default: opkind = ProVariable::SetOperator; } + while (ptr != uc && *(ptr - 1) == ' ') + --ptr; + m_proitem.resize(ptr - uc); + QString proVar = m_proitem; + proVar.detach(); + ProBlock *block = m_blockstack.top(); - m_proitem = m_proitem.trimmed(); - ProVariable *variable = new ProVariable(m_proitem, block); + ProVariable *variable = new ProVariable(proVar, block); variable->setLineNumber(m_lineNo); variable->setVariableOperator(opkind); block->appendItem(variable); @@ -443,26 +475,31 @@ void ProFileEvaluator::Private::insertVariable(const QString &line, int *i) } m_commentItem = variable; - m_proitem.clear(); - if (opkind == ProVariable::ReplaceOperator) { // skip util end of line or comment - while (1) { - ++(*i); - - // end of line? - if (*i >= line.count()) + StrState sts = NotStarted; + ptr = uc; + const ushort *cur = *pCur; + while (cur < end) { + ushort c = *cur; + if (c == '#') // comment? break; + ++cur; - // comment? - if (line.at(*i).unicode() == '#') { - --(*i); - break; + if (c == ' ' || c == '\t') { + if (sts == Started) + sts = PutSpace; + } else { + if (sts == PutSpace) + *ptr++ = ' '; + *ptr++ = c; + sts = Started; } - - m_proitem += line.at(*i); } - m_proitem = m_proitem.trimmed(); + *pCur = cur; + m_proitemPtr = ptr; + } else { + m_proitemPtr = uc; } } @@ -563,22 +600,27 @@ ProBlock *ProFileEvaluator::Private::currentBlock() void ProFileEvaluator::Private::updateItem() { - m_proitem = m_proitem.trimmed(); - if (m_proitem.isEmpty()) + ushort *uc = (ushort *)m_proitem.unicode(); + ushort *ptr = m_proitemPtr; + + if (ptr == uc) return; + m_proitem.resize(ptr - uc); + m_proitemPtr = uc; + QString proItem = m_proitem; + proItem.detach(); + ProBlock *block = currentBlock(); if (block->blockKind() & ProBlock::VariableKind) { - m_commentItem = new ProValue(m_proitem, static_cast(block)); - } else if (m_proitem.endsWith(QLatin1Char(')'))) { - m_commentItem = new ProFunction(m_proitem); + m_commentItem = new ProValue(proItem, static_cast(block)); + } else if (proItem.endsWith(QLatin1Char(')'))) { + m_commentItem = new ProFunction(proItem); } else { - m_commentItem = new ProCondition(m_proitem); + m_commentItem = new ProCondition(proItem); } m_commentItem->setLineNumber(m_lineNo); block->appendItem(m_commentItem); - - m_proitem.clear(); } From 54bbcc4a7c7043f1ee94a9d014b5a71b254033ae Mon Sep 17 00:00:00 2001 From: dt Date: Wed, 15 Jul 2009 17:41:45 +0200 Subject: [PATCH 22/26] Mention possible locations of the debugging helper in the error dialog Requires a lot of trivial forwarding. --- .../cmakerunconfiguration.cpp | 6 +++++ .../cmakerunconfiguration.h | 1 + src/plugins/debugger/cdb/cdbdebugengine.cpp | 5 ++-- src/plugins/debugger/debuggermanager.cpp | 14 +++++++++++ src/plugins/debugger/debuggermanager.h | 4 ++++ src/plugins/debugger/debuggerrunner.cpp | 1 + src/plugins/debugger/gdb/gdbengine.cpp | 4 +++- .../applicationrunconfiguration.h | 1 + .../customexecutablerunconfiguration.cpp | 6 +++++ .../customexecutablerunconfiguration.h | 1 + .../projectexplorer/debugginghelper.cpp | 23 ++++++++++++++++++- src/plugins/projectexplorer/debugginghelper.h | 11 +++++++-- src/plugins/qmlprojectmanager/qmlproject.cpp | 5 ++++ src/plugins/qmlprojectmanager/qmlproject.h | 1 + .../qt4projectmanager/qt4runconfiguration.cpp | 7 ++++++ .../qt4projectmanager/qt4runconfiguration.h | 1 + .../qt4projectmanager/qtversionmanager.cpp | 8 +++++++ .../qt4projectmanager/qtversionmanager.h | 1 + 18 files changed, 94 insertions(+), 6 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index ae30132b3bc..40767c41baf 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -170,6 +170,12 @@ QString CMakeRunConfiguration::dumperLibrary() const return dhl; } +QStringList CMakeRunConfiguration::dumperLibraryLocations() const +{ + QString qmakePath = ProjectExplorer::DebuggingHelperLibrary::findSystemQt(environment()); + return ProjectExplorer::DebuggingHelperLibrary::debuggingHelperLibraryLocations(qmakePath); +} + ProjectExplorer::Environment CMakeRunConfiguration::baseEnvironment() const { ProjectExplorer::Environment env; diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h index 57c09a3e4ab..35be599c57d 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h @@ -70,6 +70,7 @@ public: virtual void save(ProjectExplorer::PersistentSettingsWriter &writer) const; virtual void restore(const ProjectExplorer::PersistentSettingsReader &reader); virtual QString dumperLibrary() const; + virtual QStringList dumperLibraryLocations() const; virtual ProjectExplorer::ToolChain::ToolChainType toolChainType() const; signals: diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index 798f5234ff4..365252f876a 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -539,12 +539,13 @@ bool CdbDebugEngine::startDebugger(const QSharedPointer const QString dumperLibName = QDir::toNativeSeparators(m_d->m_debuggerManagerAccess->qtDumperLibraryName()); bool dumperEnabled = mode != AttachCore && mode != AttachCrashedExternal - && !dumperLibName.isEmpty() && m_d->m_debuggerManagerAccess->qtDumperLibraryEnabled(); if (dumperEnabled) { const QFileInfo fi(dumperLibName); if (!fi.isFile()) { - const QString msg = tr("The dumper library '%1' does not exist.").arg(dumperLibName); + const QStringList &locations = m_d->m_debuggerManagerAccess->qtDumperLibraryLocations(); + const QString loc = locations.join(QLatin1String(", ")); + const QString msg = tr("The dumper library was not found at %1.").arg(loc); m_d->m_debuggerManagerAccess->showQtDumperLibraryWarning(msg); dumperEnabled = false; } diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 15c586b5bba..87571d84027 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -1004,6 +1004,11 @@ void DebuggerManager::setQtDumperLibraryName(const QString &dl) m_dumperLib = dl; } +void DebuggerManager::setQtDumperLibraryLocations(const QStringList &dl) +{ + m_dumperLibLocations = dl; +} + qint64 DebuggerManager::inferiorPid() const { return m_inferiorPid; @@ -1518,6 +1523,15 @@ QString DebuggerManager::qtDumperLibraryName() const return m_dumperLib; } +QStringList DebuggerManager::qtDumperLibraryLocations() const +{ + if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) + return QStringList() << + ( theDebuggerAction(CustomDebuggingHelperLocation)->value().toString() + + tr(" (explicitly set in the Debugger Options)")); + return m_dumperLibLocations; +} + void DebuggerManager::showQtDumperLibraryWarning(const QString &details) { QMessageBox dialog(mainWindow()); diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index c153465c884..cc09c8f6bb4 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -236,6 +236,7 @@ private: virtual bool qtDumperLibraryEnabled() const = 0; virtual QString qtDumperLibraryName() const = 0; + virtual QStringList qtDumperLibraryLocations() const = 0; virtual void showQtDumperLibraryWarning(const QString &details = QString()) = 0; virtual bool isReverseDebugging() const = 0; @@ -272,6 +273,7 @@ public slots: virtual qint64 inferiorPid() const; void setQtDumperLibraryName(const QString &dl); // Run Control + void setQtDumperLibraryLocations(const QStringList &dl); void setSimpleDockWidgetArrangement(); void setLocked(bool locked); @@ -376,6 +378,7 @@ private: virtual bool qtDumperLibraryEnabled() const; virtual QString qtDumperLibraryName() const; + virtual QStringList qtDumperLibraryLocations() const; virtual void showQtDumperLibraryWarning(const QString &details = QString()); virtual bool isReverseDebugging() const; @@ -434,6 +437,7 @@ private: QSharedPointer m_startParameters; DebuggerRunControl *m_runControl; QString m_dumperLib; + QStringList m_dumperLibLocations; qint64 m_inferiorPid; diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 4b151c52cfa..b1d531493e4 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -158,6 +158,7 @@ void DebuggerRunControl::start() break; } m_manager->setQtDumperLibraryName(rc->dumperLibrary()); + m_manager->setQtDumperLibraryLocations(rc->dumperLibraryLocations()); if (const ProjectExplorer::Project *project = rc->project()) { m_startParameters->buildDir = project->buildDirectory(project->activeBuildConfiguration()); } diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index fa8f9d7a0a2..917d68c597c 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3855,11 +3855,13 @@ void GdbEngine::tryLoadDebuggingHelpers() if (!qq->qtDumperLibraryEnabled()) return; const QString lib = qq->qtDumperLibraryName(); + const QStringList &locations = qq->qtDumperLibraryLocations(); //qDebug() << "DUMPERLIB:" << lib; // @TODO: same in CDB engine... const QFileInfo fi(lib); if (!fi.exists()) { - const QString msg = tr("The dumper library '%1' does not exist.").arg(lib); + const QString loc = locations.join(QLatin1String(", ")); + const QString msg = tr("The dumper library was not found at %1.").arg(loc); debugMessage(msg); qq->showQtDumperLibraryWarning(msg); return; diff --git a/src/plugins/projectexplorer/applicationrunconfiguration.h b/src/plugins/projectexplorer/applicationrunconfiguration.h index 6d347c0ab62..0f4315844c1 100644 --- a/src/plugins/projectexplorer/applicationrunconfiguration.h +++ b/src/plugins/projectexplorer/applicationrunconfiguration.h @@ -57,6 +57,7 @@ public: virtual QStringList commandLineArguments() const = 0; virtual Environment environment() const = 0; virtual QString dumperLibrary() const = 0; + virtual QStringList dumperLibraryLocations() const = 0; virtual ProjectExplorer::ToolChain::ToolChainType toolChainType() const = 0; virtual void save(PersistentSettingsWriter &writer) const; diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp index 97de1178176..ad516a218a4 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp @@ -459,6 +459,12 @@ QString CustomExecutableRunConfiguration::dumperLibrary() const return ProjectExplorer::DebuggingHelperLibrary::debuggingHelperLibrary(qmakePath); } +QStringList CustomExecutableRunConfiguration::dumperLibraryLocations() const +{ + QString qmakePath = ProjectExplorer::DebuggingHelperLibrary::findSystemQt(environment()); + return ProjectExplorer::DebuggingHelperLibrary::debuggingHelperLibraryLocations(qmakePath); +} + ProjectExplorer::ToolChain::ToolChainType CustomExecutableRunConfiguration::toolChainType() const { return ProjectExplorer::ToolChain::UNKNOWN; diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.h b/src/plugins/projectexplorer/customexecutablerunconfiguration.h index 894116fc08e..81db5a1fa77 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.h +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.h @@ -89,6 +89,7 @@ public: virtual QWidget *configurationWidget(); virtual QString dumperLibrary() const; + virtual QStringList dumperLibraryLocations() const; virtual ProjectExplorer::ToolChain::ToolChainType toolChainType() const; diff --git a/src/plugins/projectexplorer/debugginghelper.cpp b/src/plugins/projectexplorer/debugginghelper.cpp index fbbab7f5f3a..8af5ba30456 100644 --- a/src/plugins/projectexplorer/debugginghelper.cpp +++ b/src/plugins/projectexplorer/debugginghelper.cpp @@ -66,11 +66,16 @@ QStringList DebuggingHelperLibrary::debuggingHelperLibraryDirectories(const QStr QStringList directories; directories << (qtInstallData + "/qtc-debugging-helper/") - << (QApplication::applicationDirPath() + "/../qtc-debugging-helper/" + QString::number(hash)) + "/" + << QDir::cleanPath((QApplication::applicationDirPath() + "/../qtc-debugging-helper/" + QString::number(hash))) + "/" << (QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/qtc-debugging-helper/" + QString::number(hash)) + "/"; return directories; } +QStringList DebuggingHelperLibrary::debuggingHelperLibraryLocations(const QString &qmakePath) +{ + return debuggingHelperLibraryLocations(qtInstallDataDir(qmakePath), qtDir(qmakePath)); +} + QString DebuggingHelperLibrary::debuggingHelperLibrary(const QString &qmakePath) { return debuggingHelperLibrary(qtInstallDataDir(qmakePath), qtDir(qmakePath)); @@ -94,6 +99,22 @@ QString DebuggingHelperLibrary::qtDir(const QString &qmakePath) // Debugging Helper Library +QStringList DebuggingHelperLibrary::debuggingHelperLibraryLocations(const QString &qtInstallData, const QString &qtpath) +{ + QStringList result; + foreach(const QString &directory, debuggingHelperLibraryDirectories(qtInstallData, qtpath)) { +#if defined(Q_OS_WIN) + QFileInfo fi(directory + "debug/gdbmacros.dll"); +#elif defined(Q_OS_MAC) + QFileInfo fi(directory + "libgdbmacros.dylib"); +#else // generic UNIX + QFileInfo fi(directory + "libgdbmacros.so"); +#endif + result << fi.filePath(); + } + return result; +} + QString DebuggingHelperLibrary::debuggingHelperLibrary(const QString &qtInstallData, const QString &qtpath) { foreach(const QString &directory, debuggingHelperLibraryDirectories(qtInstallData, qtpath)) { diff --git a/src/plugins/projectexplorer/debugginghelper.h b/src/plugins/projectexplorer/debugginghelper.h index 3717e32b85d..a98ab2a6166 100644 --- a/src/plugins/projectexplorer/debugginghelper.h +++ b/src/plugins/projectexplorer/debugginghelper.h @@ -49,11 +49,18 @@ public: static QString qtVersionForQMake(const QString &qmakePath); static bool hasDebuggingHelperLibrary(const QString &qmakePath); + static QString debuggingHelperLibrary(const QString &qmakePath); - static QString buildDebuggingHelperLibrary(const QString &qmakePath, const QString &make, const Environment &env); static QString debuggingHelperLibrary(const QString &qtInstallData, const QString &qtpath); - static QString copyDebuggingHelperLibrary(const QString &qtInstallData, const QString &qtdir); + + static QString buildDebuggingHelperLibrary(const QString &qmakePath, const QString &make, const Environment &env); static QString buildDebuggingHelperLibrary(const QString &directory, const QString &makeCommand, const QString &qmakeCommand, const QString &mkspec, const Environment &env); + + static QStringList debuggingHelperLibraryLocations(const QString &qmakePath); + static QStringList debuggingHelperLibraryLocations(const QString &qtInstallData, const QString &qtpath); + + static QString copyDebuggingHelperLibrary(const QString &qtInstallData, const QString &qtdir); + private: static QStringList debuggingHelperLibraryDirectories(const QString &qtInstallData, const QString &qtpath); static QString qtInstallDataDir(const QString &qmakePath); diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 0c9670ca6bf..b9a7d2e5d2b 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -381,6 +381,11 @@ QString QmlRunConfiguration::dumperLibrary() const return QString(); } +QStringList QmlRunConfiguration::dumperLibraryLocations() const +{ + return QStringList(); +} + QWidget *QmlRunConfiguration::configurationWidget() { QWidget *config = new QWidget; diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index b540f85c0f9..662abdeb882 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -150,6 +150,7 @@ public: virtual QStringList commandLineArguments() const; virtual ProjectExplorer::Environment environment() const; virtual QString dumperLibrary() const; + virtual QStringList dumperLibraryLocations() const; virtual QWidget *configurationWidget(); ProjectExplorer::ToolChain::ToolChainType toolChainType() const { return ProjectExplorer::ToolChain::OTHER; } diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp index 8d07707e7f8..953f90a9ab9 100644 --- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp @@ -637,6 +637,13 @@ QString Qt4RunConfiguration::dumperLibrary() const return version->debuggingHelperLibrary(); } +QStringList Qt4RunConfiguration::dumperLibraryLocations() const +{ + Qt4Project *pro = qobject_cast(project()); + QtVersion *version = pro->qtVersion(pro->activeBuildConfiguration()); + return version->debuggingHelperLibraryLocations();; +} + void Qt4RunConfiguration::setBaseEnvironmentBase(BaseEnvironmentBase env) { if (m_baseEnvironmentBase == env) diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.h b/src/plugins/qt4projectmanager/qt4runconfiguration.h index db7b015d42b..e2fb3845114 100644 --- a/src/plugins/qt4projectmanager/qt4runconfiguration.h +++ b/src/plugins/qt4projectmanager/qt4runconfiguration.h @@ -74,6 +74,7 @@ public: virtual QStringList commandLineArguments() const; virtual ProjectExplorer::Environment environment() const; virtual QString dumperLibrary() const; + virtual QStringList dumperLibraryLocations() const; virtual ProjectExplorer::ToolChain::ToolChainType toolChainType() const; bool isUsingDyldImageSuffix() const; diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 6e49ff08dd2..0005049ad4e 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -1102,6 +1102,14 @@ QString QtVersion::debuggingHelperLibrary() const return DebuggingHelperLibrary::debuggingHelperLibrary(qtInstallData, path()); } +QStringList QtVersion::debuggingHelperLibraryLocations() const +{ + QString qtInstallData = versionInfo().value("QT_INSTALL_DATA"); + if (qtInstallData.isEmpty()) + qtInstallData = path(); + return DebuggingHelperLibrary::debuggingHelperLibraryLocations(qtInstallData, path()); +} + bool QtVersion::hasDocumentation() const { updateVersionInfo(); diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h index 6debdcc9d24..f76dd602ea9 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.h +++ b/src/plugins/qt4projectmanager/qtversionmanager.h @@ -96,6 +96,7 @@ public: bool hasDebuggingHelper() const; QString debuggingHelperLibrary() const; + QStringList debuggingHelperLibraryLocations() const; // Builds a debugging library // returns the output of the commands From 7af43dd95a8bcffd3129c6bec22ecf5caaeec0d5 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 15 Jul 2009 13:48:14 +0200 Subject: [PATCH 23/26] dbugger: switch back to 'not running' when executable could not be started --- src/plugins/debugger/gdb/gdbengine.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index a836dcab8d1..c6611fb4841 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1301,7 +1301,8 @@ void GdbEngine::handleFileExecAndSymbols(const GdbResultRecord &response, const QMessageBox::critical(q->mainWindow(), tr("Error"), tr("Starting executable failed:\n") + msg); QTC_ASSERT(q->status() == DebuggerInferiorRunning, /**/); - interruptInferior(); + //interruptInferior(); + qq->notifyInferiorExited(); } } @@ -1320,7 +1321,8 @@ void GdbEngine::handleExecRun(const GdbResultRecord &response, const QVariant &) QMessageBox::critical(q->mainWindow(), tr("Error"), tr("Starting executable failed:\n") + QString::fromLocal8Bit(msg)); QTC_ASSERT(q->status() == DebuggerInferiorRunning, /**/); - interruptInferior(); + //interruptInferior(); + qq->notifyInferiorExited(); } } } @@ -1588,7 +1590,7 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) QFileInfo fi2(sp->coreFile); // quoting core name below fails in gdb 6.8-debian QString coreName = fi2.absoluteFilePath(); - postCommand(_("-file-exec-and-symbols ") + fileName); + postCommand(_("-file-exec-and-symbols ") + fileName, CB(handleFileExecAndSymbols)); postCommand(_("target core ") + coreName, CB(handleTargetCore)); qq->breakHandler()->removeAllBreakpoints(); } else if (q->startMode() == StartRemote) { @@ -1597,7 +1599,7 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) //QFileInfo fi(sp->executable); //QString fileName = fi.absoluteFileName(); QString fileName = sp->executable; - postCommand(_("-file-exec-and-symbols \"%1\"").arg(fileName)); + postCommand(_("-file-exec-and-symbols \"%1\"").arg(fileName), CB(handleFileExecAndSymbols)); // works only for > 6.8 postCommand(_("set target-async on"), CB(handleSetTargetAsync)); } else if (sp->useTerminal) { From 05b474abfcd90013994d51a47e79169cab8ad39e Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 15 Jul 2009 14:21:26 +0200 Subject: [PATCH 24/26] debugger: start on manual test for TRK parts --- tests/manual/trk/adapter.cpp | 289 +++++++++++++++++++++++++++++++++ tests/manual/trk/adapter.pro | 6 + tests/manual/trk/run.sh | 35 ++++ tests/manual/trk/trk.pro | 7 + tests/manual/trk/trkserver.cpp | 136 ++++++++++++++++ tests/manual/trk/trkserver.pro | 6 + 6 files changed, 479 insertions(+) create mode 100644 tests/manual/trk/adapter.cpp create mode 100644 tests/manual/trk/adapter.pro create mode 100755 tests/manual/trk/run.sh create mode 100644 tests/manual/trk/trk.pro create mode 100644 tests/manual/trk/trkserver.cpp create mode 100644 tests/manual/trk/trkserver.pro diff --git a/tests/manual/trk/adapter.cpp b/tests/manual/trk/adapter.cpp new file mode 100644 index 00000000000..c14878b3b12 --- /dev/null +++ b/tests/manual/trk/adapter.cpp @@ -0,0 +1,289 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#ifdef Q_OS_UNIX + +#include + +void signalHandler(int) +{ + qApp->exit(1); +} + +#endif + + +class Adapter : public QObject +{ + Q_OBJECT + +public: + Adapter(); + ~Adapter(); + void setGdbServerName(const QString &name); + void setTrkServerName(const QString &name) { m_trkServerName = name; } + void startServer(); + +public slots: + void handleGdbConnection(); + void readFromGdb(); + void readFromTrk(); + +private: + void handleGdbResponse(const QByteArray &ba); + void writeToGdb(const QByteArray &msg); + void writeAckToGdb(); + void logMessage(const QString &msg); + + QLocalSocket *m_trkClient; + QTcpServer *m_gdbServer; + QTcpSocket *m_gdbConnection; + QString m_trkServerName; + QString m_gdbServerName; + quint16 m_gdbServerPort; + QByteArray m_gdbReadBuffer; + QByteArray m_trkReadBuffer; +}; + +Adapter::Adapter() +{ + m_trkClient = new QLocalSocket(this); + m_gdbServer = new QTcpServer(this); + m_gdbConnection = 0; +} + +Adapter::~Adapter() +{ + m_gdbServer->close(); + logMessage("Shutting down"); +} + +void Adapter::setGdbServerName(const QString &name) +{ + int pos = name.indexOf(':'); + if (pos == -1) { + m_gdbServerPort = 0; + m_gdbServerName = name; + } else { + m_gdbServerPort = name.mid(pos + 1).toInt(); + m_gdbServerName = name.left(pos); + } +} + +void Adapter::startServer() +{ + if (!m_gdbServer->listen(QHostAddress(m_gdbServerName), m_gdbServerPort)) { + logMessage(QString("Unable to start the gdb server at %1:%2: %3.") + .arg(m_gdbServerName).arg(m_gdbServerPort) + .arg(m_gdbServer->errorString())); + return; + } + + logMessage(QString("Gdb server runnung on port %1. Run the Gdb Client now.") + .arg(m_gdbServer->serverPort())); + + connect(m_gdbServer, SIGNAL(newConnection()), this, SLOT(handleGdbConnection())); +} + +void Adapter::logMessage(const QString &msg) +{ + qDebug() << "ADAPTER: " << qPrintable(msg); +} + +void Adapter::handleGdbConnection() +{ + logMessage("HANDLING GDB CONNECTION"); + + m_gdbConnection = m_gdbServer->nextPendingConnection(); + connect(m_gdbConnection, SIGNAL(disconnected()), + m_gdbConnection, SLOT(deleteLater())); + connect(m_gdbConnection, SIGNAL(readyRead()), + this, SLOT(readFromGdb())); +} + +void Adapter::readFromGdb() +{ + QByteArray packet = m_gdbConnection->readAll(); + m_gdbReadBuffer.append(packet); + + logMessage("gdb: -> " + packet); + if (packet != m_gdbReadBuffer) + logMessage("buffer: " + m_gdbReadBuffer); + + QByteArray &ba = m_gdbReadBuffer; + while (ba.size()) { + char code = ba.at(0); + ba = ba.mid(1); + + if (code == '+') { + logMessage("ACK"); + continue; + } + + if (code == '-') { + logMessage("NAK: Retransmission requested"); + continue; + } + + if (code != '$') { + logMessage("Broken package (2) " + ba); + continue; + } + + int pos = ba.indexOf('#'); + if (pos == -1) { + logMessage("Invalid checksum format in " + ba); + continue; + } + + bool ok = false; + uint checkSum = ba.mid(pos + 1, 2).toInt(&ok, 16); + if (!ok) { + logMessage("Invalid checksum format 2 in " + ba); + return; + } + + logMessage(QString("Packet checksum: %1").arg(checkSum)); + uint sum = 0; + for (int i = 0; i < pos; ++i) + sum += ba.at(i); + + if (sum % 256 != checkSum) { + logMessage(QString("Packet checksum wrong: %1 %2 in " + ba) + .arg(checkSum).arg(sum % 256)); + } + + QByteArray response = ba.left(pos); + ba = ba.mid(pos + 3); + handleGdbResponse(response); + } +} + +void Adapter::writeAckToGdb() +{ + QByteArray packet = "+"; + logMessage("gdb: <- " + packet); + m_gdbConnection->write(packet); +} + +void Adapter::writeToGdb(const QByteArray &msg) +{ + uint sum = 0; + for (int i = 0; i != msg.size(); ++i) + sum += msg.at(i); + QByteArray checkSum = QByteArray::number(sum % 256, 16); + //logMessage(QString("Packet checksum: %1").arg(sum)); + + QByteArray packet; + packet.append("+$"); + packet.append(msg); + packet.append('#'); + if (checkSum.size() < 2) + packet.append('0'); + packet.append(checkSum); + logMessage("gdb: <- " + packet); + m_gdbConnection->write(packet); +} + +void Adapter::handleGdbResponse(const QByteArray &response) +{ + // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html + if (response == "qSupported") { + //$qSupported#37 + logMessage("Handling 'qSupported'"); + writeAckToGdb(); + writeToGdb(QByteArray()); + } + + else if (response.startsWith("Hc")) { + // Set thread for subsequent operations (`m', `M', `g', `G', et.al.). + // for step and continue operations + writeAckToGdb(); + } + + else if (response.startsWith("Hg")) { + // Set thread for subsequent operations (`m', `M', `g', `G', et.al.). + // for 'other operations + //$Hg0#df + writeAckToGdb(); + } + + + else if (response.startsWith("?")) { + // Indicate the reason the target halted. + // The reply is the same as for step and continue. + + //$?#3f + //$Hc-1#09 + //$qC#b4 + //$qAttached#8f + //$qOffsets#4b + //$qOffsets#4b + + else { + logMessage("FIXME unknown" + response); + } +} + +void Adapter::readFromTrk() +{ + //QByteArray ba = m_gdbConnection->readAll(); + //logMessage("Read from gdb: " + ba); +} + +int main(int argc, char *argv[]) +{ + if (argc < 3) { + qDebug() << "Usage: " << argv[0] << " "; + return 1; + } + +#ifdef Q_OS_UNIX + signal(SIGUSR1, signalHandler); +#endif + + QCoreApplication app(argc, argv); + + Adapter adapter; + adapter.setTrkServerName(argv[1]); + adapter.setGdbServerName(argv[2]); + adapter.startServer(); + + return app.exec(); +} + +#include "adapter.moc" diff --git a/tests/manual/trk/adapter.pro b/tests/manual/trk/adapter.pro new file mode 100644 index 00000000000..fb8cadede6a --- /dev/null +++ b/tests/manual/trk/adapter.pro @@ -0,0 +1,6 @@ + +TEMPLATE = app + +QT = core network + +SOURCES += adapter.cpp diff --git a/tests/manual/trk/run.sh b/tests/manual/trk/run.sh new file mode 100755 index 00000000000..66d5dc97d5c --- /dev/null +++ b/tests/manual/trk/run.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +make || exit 1 + +killall -s USR1 adapter trkserver > /dev/null 2>&1 +killall adapter trkserver > /dev/null 2>&1 + +trkservername="TRKSERVER-2"; +gdbserverip=127.0.0.1 +gdbserverport=2225 + +./trkserver ${trkservername} & +trkserverpid=$! + +sleep 1 + +./adapter ${trkservername} ${gdbserverip}:${gdbserverport} & +adapterpid=$! + +echo " +file filebrowseapp.sym +target remote ${gdbserverip}:${gdbserverport} +quit +" > gdb.txt + +./arm-gdb -x gdb.txt + +#sleep 4 + +kill -s USR1 ${adapterpid} +kill -s USR1 ${trkserverpid} + +echo + +#killall arm-gdb diff --git a/tests/manual/trk/trk.pro b/tests/manual/trk/trk.pro new file mode 100644 index 00000000000..7d5f33e4eab --- /dev/null +++ b/tests/manual/trk/trk.pro @@ -0,0 +1,7 @@ + +TEMPLATE = subdirs + +SUBDIRS = trkserver adapter + +trkserver.file = trkserver.pro +adapter.file = adapter.pro diff --git a/tests/manual/trk/trkserver.cpp b/tests/manual/trk/trkserver.cpp new file mode 100644 index 00000000000..67a0fc5476a --- /dev/null +++ b/tests/manual/trk/trkserver.cpp @@ -0,0 +1,136 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** +**************************************************************************/ + +#include +#include + +#include +#include + + +#ifdef Q_OS_UNIX + +#include + +void signalHandler(int) +{ + qApp->exit(1); +} + +#endif + + +class TrkServer : public QObject +{ + Q_OBJECT + +public: + TrkServer(const QString &serverName); + ~TrkServer(); + +private slots: + void handleConnection(); + +private: + void logMessage(const QString &msg); + + QList m_data; + QLocalServer *m_server; + int m_lastSent; +}; + +TrkServer::TrkServer(const QString &serverName) +{ + QFile file("dump.pro"); + m_data = file.readAll().split('\n'); + logMessage(QString("Read %1 lines of data").arg(m_data.size())); + + m_server = new QLocalServer(this); + m_lastSent = 0; + if (!m_server->listen(serverName)) { + logMessage(QString("Error: Unable to start the TRK server %1: %2.") + .arg(serverName).arg(m_server->errorString())); + return; + } + + logMessage("The TRK server is running. Run the adapter now."); + connect(m_server, SIGNAL(newConnection()), this, SLOT(handleConnection())); +} + +TrkServer::~TrkServer() +{ + logMessage("Shutting down"); + m_server->close(); +} + +void TrkServer::logMessage(const QString &msg) +{ + qDebug() << "TRKSERV: " << qPrintable(msg); +} + +void TrkServer::handleConnection() +{ + QByteArray block; + + QByteArray msg = m_data[m_lastSent ++]; + + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_0); + out << (quint16)0; + out << m_data; + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + QLocalSocket *clientConnection = m_server->nextPendingConnection(); + connect(clientConnection, SIGNAL(disconnected()), + clientConnection, SLOT(deleteLater())); + + clientConnection->write(block); + clientConnection->flush(); + //clientConnection->disconnectFromHost(); +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + qDebug() << "Usage: " << argv[0] << " "; + return 1; + } + +#ifdef Q_OS_UNIX + signal(SIGUSR1, signalHandler); +#endif + + QCoreApplication app(argc, argv); + QString serverName = argv[1]; + TrkServer server(serverName); + return app.exec(); +} + +#include "trkserver.moc" diff --git a/tests/manual/trk/trkserver.pro b/tests/manual/trk/trkserver.pro new file mode 100644 index 00000000000..e782ab2d230 --- /dev/null +++ b/tests/manual/trk/trkserver.pro @@ -0,0 +1,6 @@ + +TEMPLATE = app + +QT = core network + +SOURCES += trkserver.cpp From 1f525f929d180dfef4d008a2a231ff7cc3c06a53 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 16 Jul 2009 14:53:41 +1000 Subject: [PATCH 25/26] Fix auto-indentation for dui editor This patch should fix auto-indentation (Ctrl+I) for the most usual cases. Before this patch, lines were never dedented, resulting in e.g. Rect { Item { } Item { } --- src/plugins/duieditor/duieditor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/duieditor/duieditor.cpp b/src/plugins/duieditor/duieditor.cpp index 9300ba45f36..58624f55617 100644 --- a/src/plugins/duieditor/duieditor.cpp +++ b/src/plugins/duieditor/duieditor.cpp @@ -617,8 +617,10 @@ void ScriptEditor::indentBlock(QTextDocument *, QTextBlock block, QChar typedCha { TextEditor::TabSettings ts = tabSettings(); - if (typedChar == QLatin1Char('}')) { - QTextCursor tc = textCursor(); + if (typedChar == QLatin1Char('}') + || ((typedChar == QChar::Null) && block.text().trimmed() == "}")) { + + QTextCursor tc(block); if (TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tc)) { const QString text = tc.block().text(); int indent = ts.columnAt(text, ts.firstNonSpace(text)); From e5f322e4722717383eb394bb8705d0a259fd9c82 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 16 Jul 2009 09:24:44 +0200 Subject: [PATCH 26/26] CVS: Fix gcc 3.3 compilation; do not describe first revision --- src/plugins/cvs/cvsplugin.cpp | 45 +++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index c64d32b9aad..8e0e4785a1e 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -653,7 +653,7 @@ void CVSPlugin::startCommit(const QString &source) } // We need the "Examining " stderr output to tell // where we are, so, have stdout/stderr channels merged. - QStringList args(QStringList(QLatin1String("status"))); + QStringList args = QStringList(QLatin1String("status")); if (sourceDir == topLevel) { args.push_back(QString(QLatin1Char('.'))); } else { @@ -794,6 +794,12 @@ static QString previousRevision(const QString &rev) return rev.left(dotPos + 1) + QString::number(minor - 1); } +// Is "[1.2...].1"? +static inline bool isFirstRevision(const QString &r) +{ + return r.endsWith(QLatin1Char('1')); +} + void CVSPlugin::slotDescribe(const QString &source, const QString &changeNr) { QString errorMessage; @@ -817,7 +823,7 @@ bool CVSPlugin::describe(const QString &file, const QString &changeNr, QString * return false; } // Number must be > 1 - if (changeNr.endsWith(QLatin1Char('1'))) { + if (isFirstRevision(changeNr)) { *errorMessage = tr("The initial revision %1 cannot be described.").arg(changeNr); return false; } @@ -891,25 +897,28 @@ bool CVSPlugin::describe(const QString &repositoryPath, QList entr } // Collect diffs relative to repository for (QList::iterator it = entries.begin(); it != lend; ++it) { - const QString previousRev = previousRevision(it->revisions.front().revision); - QStringList args(QLatin1String("diff")); - args << m_settings.cvsDiffOptions << QLatin1String("-r") << previousRev - << QLatin1String("-r") << it->revisions.front().revision - << it->file; - const CVSResponse diffResponse = runCVS(repositoryPath, args, cvsShortTimeOut, false, codec); - switch (diffResponse.result) { - case CVSResponse::Ok: - case CVSResponse::NonNullExitCode: // Diff exit code != 0 - if (diffResponse.stdOut.isEmpty()) { + const QString &revision = it->revisions.front().revision; + if (!isFirstRevision(revision)) { + const QString previousRev = previousRevision(revision); + QStringList args(QLatin1String("diff")); + args << m_settings.cvsDiffOptions << QLatin1String("-r") << previousRev + << QLatin1String("-r") << it->revisions.front().revision + << it->file; + const CVSResponse diffResponse = runCVS(repositoryPath, args, cvsShortTimeOut, false, codec); + switch (diffResponse.result) { + case CVSResponse::Ok: + case CVSResponse::NonNullExitCode: // Diff exit code != 0 + if (diffResponse.stdOut.isEmpty()) { + *errorMessage = diffResponse.message; + return false; // Something else failed. + } + break; + case CVSResponse::OtherError: *errorMessage = diffResponse.message; - return false; // Something else failed. + return false; } - break; - case CVSResponse::OtherError: - *errorMessage = diffResponse.message; - return false; + output += fixDiffOutput(diffResponse.stdOut); } - output += fixDiffOutput(diffResponse.stdOut); } // Re-use an existing view if possible to support