diff options
author | Rohan McGovern <rohan.mcgovern@nokia.com> | 2011-09-14 07:45:44 (GMT) |
---|---|---|
committer | Rohan McGovern <rohan.mcgovern@nokia.com> | 2011-09-14 07:45:44 (GMT) |
commit | 1b30b3a6726adf806ae221357393e562285e8346 (patch) | |
tree | c650ff836d3abdf5890726354ee6e2b9bce11304 /tools | |
parent | 1c1a5fe0e2d9e28be5e0e14732d79d34c9bb2a74 (diff) | |
parent | 704dd92581783d91ccd234d58896d7078eed14a5 (diff) | |
download | Qt-1b30b3a6726adf806ae221357393e562285e8346.zip Qt-1b30b3a6726adf806ae221357393e562285e8346.tar.gz Qt-1b30b3a6726adf806ae221357393e562285e8346.tar.bz2 |
Merge remote branch 'origin/4.8' into 4.8-from-4.7
Conflicts:
src/gui/text/qtextengine_p.h
src/network/ssl/qsslsocket_openssl.cpp
Diffstat (limited to 'tools')
313 files changed, 18486 insertions, 10174 deletions
diff --git a/tools/activeqt/dumpcpp/main.cpp b/tools/activeqt/dumpcpp/main.cpp index 90f6ae4..e8b0285 100644 --- a/tools/activeqt/dumpcpp/main.cpp +++ b/tools/activeqt/dumpcpp/main.cpp @@ -48,6 +48,7 @@ #include <QStringList> #include <QUuid> #include <QWidget> +#include <QFileInfo> #include <qt_windows.h> #include <ocidl.h> @@ -129,10 +130,10 @@ void writeEnums(QTextStream &out, const QMetaObject *mo) } } -void writeHeader(QTextStream &out, const QByteArray &nameSpace) +void writeHeader(QTextStream &out, const QByteArray &nameSpace, const QString &outFileName) { - out << "#ifndef QAX_DUMPCPP_" << nameSpace.toUpper() << "_H" << endl; - out << "#define QAX_DUMPCPP_" << nameSpace.toUpper() << "_H" << endl; + out << "#ifndef QAX_DUMPCPP_" << outFileName.toUpper() << "_H" << endl; + out << "#define QAX_DUMPCPP_" << outFileName.toUpper() << "_H" << endl; out << endl; out << "// Define this symbol to __declspec(dllexport) or __declspec(dllimport)" << endl; out << "#ifndef " << nameSpace.toUpper() << "_EXPORT" << endl; @@ -880,7 +881,7 @@ bool generateClass(QAxObject *object, const QByteArray &className, const QByteAr out << "****************************************************************************/" << endl; out << endl; - writeHeader(out, nameSpace); + writeHeader(out, nameSpace, outfile.fileName()); generateNameSpace(out, mo, nameSpace); // close namespace file @@ -1040,7 +1041,8 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O declOut << "****************************************************************************/" << endl; declOut << endl; - writeHeader(declOut, libName.toLatin1()); + QFileInfo cppFileInfo(cppFile); + writeHeader(declOut, libName.toLatin1(), cppFileInfo.fileName()); UINT typeCount = typelib->GetTypeInfoCount(); if (declFile.isOpen()) { diff --git a/tools/activeqt/testcon/changeproperties.cpp b/tools/activeqt/testcon/changeproperties.cpp index 4b27132..67bd10d 100644 --- a/tools/activeqt/testcon/changeproperties.cpp +++ b/tools/activeqt/testcon/changeproperties.cpp @@ -108,7 +108,7 @@ void ChangeProperties::on_buttonSet_clicked() QColor col; col.setNamedColor(editValue->text()); if (col.isValid()) { - value = qVariantFromValue(col); + value = QVariant::fromValue(col); } else { QMessageBox::warning(this, tr("Can't parse input"), tr("Failed to create a color from %1\n" @@ -122,7 +122,7 @@ void ChangeProperties::on_buttonSet_clicked() { QFont fnt; if (fnt.fromString(editValue->text())) { - value = qVariantFromValue(fnt); + value = QVariant::fromValue(fnt); } else { QMessageBox::warning(this, tr("Can't parse input"), tr("Failed to create a font from %1\n" @@ -141,7 +141,7 @@ void ChangeProperties::on_buttonSet_clicked() if (pm.isNull()) return; - value = qVariantFromValue(pm); + value = QVariant::fromValue(pm); } break; case QVariant::Bool: diff --git a/tools/assistant/lib/fulltextsearch/fulltextsearch.pro b/tools/assistant/lib/fulltextsearch/fulltextsearch.pro index 4d2fddb..d0e7a87 100644 --- a/tools/assistant/lib/fulltextsearch/fulltextsearch.pro +++ b/tools/assistant/lib/fulltextsearch/fulltextsearch.pro @@ -23,7 +23,7 @@ contains(QT_CONFIG, reduce_exports) { linux*-g++*:DEFINES += _GLIBCXX_EXTERN_TEMPLATE=0 } -unix:QMAKE_PKGCONFIG_REQUIRES = QtCore +unix|win32-g++*:QMAKE_PKGCONFIG_REQUIRES = QtCore # impossible to disable exceptions in clucene atm CONFIG(exceptions_off) { diff --git a/tools/assistant/lib/fulltextsearch/qanalyzer.cpp b/tools/assistant/lib/fulltextsearch/qanalyzer.cpp index d6b00a0..71dd2c9 100644 --- a/tools/assistant/lib/fulltextsearch/qanalyzer.cpp +++ b/tools/assistant/lib/fulltextsearch/qanalyzer.cpp @@ -96,6 +96,11 @@ QCLuceneStandardAnalyzer::QCLuceneStandardAnalyzer(const QStringList &stopWords) tArray[stopWords.count()] = 0; d->analyzer = new lucene::analysis::standard::StandardAnalyzer(tArray); + + for (int i = 0; i < stopWords.count(); ++i) + delete [] tArray[i]; + + delete [] tArray; } @@ -147,6 +152,11 @@ QCLuceneStopAnalyzer::QCLuceneStopAnalyzer(const QStringList &stopWords) tArray[stopWords.count()] = 0; d->analyzer = new lucene::analysis::StopAnalyzer(tArray); + + for (int i = 0; i < stopWords.count(); ++i) + delete [] tArray[i]; + + delete [] tArray; } QStringList QCLuceneStopAnalyzer::englishStopWords() const diff --git a/tools/assistant/lib/lib.pro b/tools/assistant/lib/lib.pro index 26d3456..d6c3fce 100644 --- a/tools/assistant/lib/lib.pro +++ b/tools/assistant/lib/lib.pro @@ -1,5 +1,4 @@ QT += sql \ - xml \ network TEMPLATE = lib TARGET = QtHelp @@ -19,7 +18,7 @@ if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { win32:qclucene = $${qclucene}d } linux-lsb-g++:LIBS_PRIVATE += --lsb-shared-libs=$$qclucene -unix:QMAKE_PKGCONFIG_REQUIRES += QtNetwork \ +unix|win32-g++*:QMAKE_PKGCONFIG_REQUIRES += QtNetwork \ QtSql \ QtXml LIBS_PRIVATE += -l$$qclucene diff --git a/tools/assistant/lib/qhelpsearchquerywidget.cpp b/tools/assistant/lib/qhelpsearchquerywidget.cpp index 6040423..9307638 100644 --- a/tools/assistant/lib/qhelpsearchquerywidget.cpp +++ b/tools/assistant/lib/qhelpsearchquerywidget.cpp @@ -215,37 +215,36 @@ private: queryHist->curQuery += addend; const QList<QHelpSearchQuery> &query = - queryHist->queries.at(queryHist->curQuery); + queryHist->queries.at(queryHist->curQuery); foreach (const QHelpSearchQuery &queryPart, query) { - QLineEdit *lineEdit = 0; - switch (queryPart.fieldName) { + if (QLineEdit *lineEdit = lineEditFor(queryPart.fieldName)) + lineEdit->setText(queryPart.wordList.join(" ")); + } + + if (queryHist->curQuery == maxOrMinIndex) + thisButton->setEnabled(false); + otherButton->setEnabled(true); + } + + QLineEdit* lineEditFor(const QHelpSearchQuery::FieldName &fieldName) const + { + switch (fieldName) { case QHelpSearchQuery::DEFAULT: - lineEdit = defaultQuery; - break; + return defaultQuery; case QHelpSearchQuery::ALL: - lineEdit = allQuery; - break; + return allQuery; case QHelpSearchQuery::ATLEAST: - lineEdit = atLeastQuery; - break; + return atLeastQuery; case QHelpSearchQuery::FUZZY: - lineEdit = similarQuery; - break; + return similarQuery; case QHelpSearchQuery::WITHOUT: - lineEdit = withoutQuery; - break; + return withoutQuery; case QHelpSearchQuery::PHRASE: - lineEdit = exactQuery; - break; + return exactQuery; default: Q_ASSERT(0); - } - lineEdit->setText(queryPart.wordList.join(" ")); } - - if (queryHist->curQuery == maxOrMinIndex) - thisButton->setEnabled(false); - otherButton->setEnabled(true); + return 0; } void enableOrDisableToolButtons() @@ -512,8 +511,31 @@ QHelpSearchQueryWidget::~QHelpSearchQueryWidget() } /*! + \since 4.8 + + Expands the search query widget so that the extended search fields are shown. +*/ +void QHelpSearchQueryWidget::expandExtendedSearch() +{ + if (d->simpleSearch) + d->showHideAdvancedSearch(); +} + +/*! + \since 4.8 + + Collapses the search query widget so that only the default search field is + shown. +*/ +void QHelpSearchQueryWidget::collapseExtendedSearch() +{ + if (!d->simpleSearch) + d->showHideAdvancedSearch(); +} + +/*! Returns a list of queries to use in combination with the search engines - search(QList<QHelpSearchQuery> &query) function. + search(QList<QHelpSearchQuery> &queryList) function. */ QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const { @@ -524,6 +546,30 @@ QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const } /*! + \since 4.8 + + Sets the QHelpSearchQueryWidget input fields to the values specified by + \a queryList search field name. Please note that one has to call the search + engine's search(QList<QHelpSearchQuery> &queryList) function to perform the + actual search. +*/ +void QHelpSearchQueryWidget::setQuery(const QList<QHelpSearchQuery> &queryList) +{ + QList<QLineEdit *> lineEdits; + lineEdits << d->defaultQuery << d->allQuery << d->atLeastQuery + << d->similarQuery << d->withoutQuery << d->exactQuery; + foreach (QLineEdit *lineEdit, lineEdits) + lineEdit->clear(); + + const QLatin1String space(" "); + foreach (const QHelpSearchQuery &q, queryList) { + if (QLineEdit *lineEdit = d->lineEditFor(q.fieldName)) + lineEdit->setText(lineEdit->text() + q.wordList.join(space) + space); + } + d->searchRequested(); +} + +/*! \reimp */ void QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent) diff --git a/tools/assistant/lib/qhelpsearchquerywidget.h b/tools/assistant/lib/qhelpsearchquerywidget.h index 291c827..7a654cc 100644 --- a/tools/assistant/lib/qhelpsearchquerywidget.h +++ b/tools/assistant/lib/qhelpsearchquerywidget.h @@ -68,7 +68,11 @@ public: QHelpSearchQueryWidget(QWidget *parent = 0); ~QHelpSearchQueryWidget(); + void expandExtendedSearch(); + void collapseExtendedSearch(); + QList<QHelpSearchQuery> query() const; + void setQuery(const QList<QHelpSearchQuery> &queryList); Q_SIGNALS: void search(); diff --git a/tools/assistant/tools/assistant/aboutdialog.cpp b/tools/assistant/tools/assistant/aboutdialog.cpp index c25d7de..31cb41e 100644 --- a/tools/assistant/tools/assistant/aboutdialog.cpp +++ b/tools/assistant/tools/assistant/aboutdialog.cpp @@ -38,6 +38,9 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + +#include "aboutdialog.h" + #include "helpviewer.h" #include "tracer.h" @@ -51,8 +54,6 @@ #include <QtGui/QMessageBox> #include <QtGui/QDesktopServices> -#include "aboutdialog.h" - QT_BEGIN_NAMESPACE AboutLabel::AboutLabel(QWidget *parent) @@ -96,8 +97,8 @@ QVariant AboutLabel::loadResource(int type, const QUrl &name) void AboutLabel::setSource(const QUrl &url) { TRACE_OBJ - if (url.isValid() && (!AbstractHelpViewer::isLocalUrl(url) - || !AbstractHelpViewer::canOpenPage(url.path()))) { + if (url.isValid() && (!HelpViewer::isLocalUrl(url) + || !HelpViewer::canOpenPage(url.path()))) { if (!QDesktopServices::openUrl(url)) { QMessageBox::warning(this, tr("Warning"), tr("Unable to launch external application.\n"), tr("OK")); diff --git a/tools/assistant/tools/assistant/assistant.pro b/tools/assistant/tools/assistant/assistant.pro index d9aff7a..7f0fdd1 100644 --- a/tools/assistant/tools/assistant/assistant.pro +++ b/tools/assistant/tools/assistant/assistant.pro @@ -12,6 +12,8 @@ DESTDIR = ../../../../bin target.path = $$[QT_INSTALL_BINS] INSTALLS += target DEPENDPATH += ../shared +DEPENDPATH += . +INCLUDEPATH += . # ## Work around a qmake issue when statically linking to # ## not-yet-installed plugins @@ -30,6 +32,7 @@ HEADERS += aboutdialog.h \ filternamedialog.h \ helpenginewrapper.h \ helpviewer.h \ + helpviewer_p.h \ indexwindow.h \ installdialog.h \ mainwindow.h \ @@ -40,12 +43,12 @@ HEADERS += aboutdialog.h \ topicchooser.h \ tracer.h \ xbelsupport.h \ - ../shared/collectionconfiguration.h -contains(QT_CONFIG, webkit) { - HEADERS += helpviewer_qwv.h -} else { - HEADERS += helpviewer_qtb.h - } + ../shared/collectionconfiguration.h \ + openpagesmodel.h \ + globalactions.h \ + openpageswidget.h \ + openpagesmanager.h \ + openpagesswitcher.h win32:HEADERS += remotecontrol_win.h SOURCES += aboutdialog.cpp \ @@ -72,8 +75,13 @@ SOURCES += aboutdialog.cpp \ searchwidget.cpp \ topicchooser.cpp \ xbelsupport.cpp \ - ../shared/collectionconfiguration.cpp - contains(QT_CONFIG, webkit) { + ../shared/collectionconfiguration.cpp \ + openpagesmodel.cpp \ + globalactions.cpp \ + openpageswidget.cpp \ + openpagesmanager.cpp \ + openpagesswitcher.cpp +contains(QT_CONFIG, webkit) { SOURCES += helpviewer_qwv.cpp } else { SOURCES += helpviewer_qtb.cpp diff --git a/tools/assistant/tools/assistant/assistant_images.qrc b/tools/assistant/tools/assistant/assistant_images.qrc index 34918c0..b4f2523 100644 --- a/tools/assistant/tools/assistant/assistant_images.qrc +++ b/tools/assistant/tools/assistant/assistant_images.qrc @@ -1,11 +1,10 @@ <RCC> - <qresource prefix="/trolltech/assistant" > + <qresource prefix="/trolltech/assistant"> <file>images/trolltech-logo.png</file> <file>images/assistant-128.png</file> <file>images/assistant.png</file> <file>images/wrap.png</file> <file>images/bookmark.png</file> -#mac <file>images/mac/addtab.png</file> <file>images/mac/book.png</file> <file>images/mac/closetab.png</file> @@ -19,7 +18,6 @@ <file>images/mac/zoomin.png</file> <file>images/mac/zoomout.png</file> <file>images/mac/resetzoom.png</file> -#win <file>images/win/addtab.png</file> <file>images/win/book.png</file> <file>images/win/closetab.png</file> @@ -33,5 +31,7 @@ <file>images/win/zoomin.png</file> <file>images/win/zoomout.png</file> <file>images/win/resetzoom.png</file> + <file>images/closebutton.png</file> + <file>images/darkclosebutton.png</file> </qresource> </RCC> diff --git a/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp b/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp index e94b89c..41b42d4 100644 --- a/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp +++ b/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp @@ -50,11 +50,29 @@ BookmarkFilterModel::BookmarkFilterModel(QObject *parent) { } -void -BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel) +void BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel) { beginResetModel(); + if (sourceModel) { + disconnect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), + this, SLOT(changed(QModelIndex, QModelIndex))); + disconnect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)), + this, SLOT(rowsInserted(QModelIndex, int, int))); + disconnect(sourceModel, + SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this, + SLOT(rowsAboutToBeRemoved(QModelIndex, int, int))); + disconnect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), + this, SLOT(rowsRemoved(QModelIndex, int, int))); + disconnect(sourceModel, SIGNAL(layoutAboutToBeChanged()), this, + SLOT(layoutAboutToBeChanged())); + disconnect(sourceModel, SIGNAL(layoutChanged()), this, + SLOT(layoutChanged())); + disconnect(sourceModel, SIGNAL(modelAboutToBeReset()), this, + SLOT(modelAboutToBeReset())); + disconnect(sourceModel, SIGNAL(modelReset()), this, SLOT(modelReset())); + } + QAbstractProxyModel::setSourceModel(sourceModel); sourceModel = qobject_cast<BookmarkModel*> (_sourceModel); @@ -79,20 +97,18 @@ BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel) connect(sourceModel, SIGNAL(modelReset()), this, SLOT(modelReset())); if (sourceModel) - setupCache(sourceModel->index(0, 0, QModelIndex())); + setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); endResetModel(); } -int -BookmarkFilterModel::rowCount(const QModelIndex &index) const +int BookmarkFilterModel::rowCount(const QModelIndex &index) const { Q_UNUSED(index) return cache.count(); } -int -BookmarkFilterModel::columnCount(const QModelIndex &index) const +int BookmarkFilterModel::columnCount(const QModelIndex &index) const { Q_UNUSED(index) if (sourceModel) @@ -100,8 +116,7 @@ BookmarkFilterModel::columnCount(const QModelIndex &index) const return 0; } -QModelIndex -BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const +QModelIndex BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const { const int row = proxyIndex.row(); if (proxyIndex.isValid() && row >= 0 && row < cache.count()) @@ -109,21 +124,19 @@ BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const return QModelIndex(); } -QModelIndex -BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const +QModelIndex BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const { return index(cache.indexOf(sourceIndex), 0, QModelIndex()); } -QModelIndex -BookmarkFilterModel::parent(const QModelIndex &child) const +QModelIndex BookmarkFilterModel::parent(const QModelIndex &child) const { Q_UNUSED(child) return QModelIndex(); } -QModelIndex -BookmarkFilterModel::index(int row, int column, const QModelIndex &index) const +QModelIndex BookmarkFilterModel::index(int row, int column, + const QModelIndex &index) const { Q_UNUSED(index) if (row < 0 || column < 0 || cache.count() <= row @@ -133,32 +146,28 @@ BookmarkFilterModel::index(int row, int column, const QModelIndex &index) const return createIndex(row, 0); } -Qt::DropActions -BookmarkFilterModel::supportedDropActions () const +Qt::DropActions BookmarkFilterModel::supportedDropActions () const { if (sourceModel) return sourceModel->supportedDropActions(); return Qt::IgnoreAction; } -Qt::ItemFlags -BookmarkFilterModel::flags(const QModelIndex &index) const +Qt::ItemFlags BookmarkFilterModel::flags(const QModelIndex &index) const { if (sourceModel) return sourceModel->flags(index); return Qt::NoItemFlags; } -QVariant -BookmarkFilterModel::data(const QModelIndex &index, int role) const +QVariant BookmarkFilterModel::data(const QModelIndex &index, int role) const { if (sourceModel) return sourceModel->data(mapToSource(index), role); return QVariant(); } -bool -BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value, +bool BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (sourceModel) @@ -166,37 +175,34 @@ BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value, return false; } -void -BookmarkFilterModel::filterBookmarks() +void BookmarkFilterModel::filterBookmarks() { if (sourceModel) { beginResetModel(); hideBookmarks = true; - setupCache(sourceModel->index(0, 0, QModelIndex())); + setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); endResetModel(); } } -void -BookmarkFilterModel::filterBookmarkFolders() +void BookmarkFilterModel::filterBookmarkFolders() { if (sourceModel) { beginResetModel(); hideBookmarks = false; - setupCache(sourceModel->index(0, 0, QModelIndex())); + setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); endResetModel(); } } -void -BookmarkFilterModel::changed(const QModelIndex &topLeft, +void BookmarkFilterModel::changed(const QModelIndex &topLeft, const QModelIndex &bottomRight) { emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight)); } -void -BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start, int end) +void BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start, + int end) { if (!sourceModel) return; @@ -218,15 +224,16 @@ BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start, int end) const bool isFolder = newIndex.data(UserRoleFolder).toBool(); if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) { beginInsertRows(mapFromSource(parent), start, end); - cache.insert(cache.indexOf(cachePrevious) + 1, newIndex); + const int index = cache.indexOf(cachePrevious) + 1; + if (cache.value(index, QPersistentModelIndex()) != newIndex) + cache.insert(index, newIndex); endInsertRows(); } } } -void -BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent, int start, - int end) +void BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent, + int start, int end) { if (!sourceModel) return; @@ -240,8 +247,7 @@ BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent, int start, } } -void -BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int) +void BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int) { if (cache.contains(indexToRemove)) { cache.removeAll(indexToRemove); @@ -249,41 +255,36 @@ BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int) } } -void -BookmarkFilterModel::layoutAboutToBeChanged() +void BookmarkFilterModel::layoutAboutToBeChanged() { // TODO: ??? } -void -BookmarkFilterModel::layoutChanged() +void BookmarkFilterModel::layoutChanged() { // TODO: ??? } -void -BookmarkFilterModel::modelAboutToBeReset() +void BookmarkFilterModel::modelAboutToBeReset() { beginResetModel(); } -void -BookmarkFilterModel::modelReset() +void BookmarkFilterModel::modelReset() { if (sourceModel) - setupCache(sourceModel->index(0, 0, QModelIndex())); + setupCache(sourceModel->index(0, 0, QModelIndex()).parent()); endResetModel(); } -void -BookmarkFilterModel::setupCache(const QModelIndex &parent) +void BookmarkFilterModel::setupCache(const QModelIndex &parent) { cache.clear(); - collectItems(parent); + for (int i = 0; i < sourceModel->rowCount(parent); ++i) + collectItems(sourceModel->index(i, 0, parent)); } -void -BookmarkFilterModel::collectItems(const QModelIndex &parent) +void BookmarkFilterModel::collectItems(const QModelIndex &parent) { if (parent.isValid()) { bool isFolder = sourceModel->data(parent, UserRoleFolder).toBool(); @@ -304,14 +305,12 @@ BookmarkTreeModel::BookmarkTreeModel(QObject *parent) { } -int -BookmarkTreeModel::columnCount(const QModelIndex &parent) const +int BookmarkTreeModel::columnCount(const QModelIndex &parent) const { return qMin(1, QSortFilterProxyModel::columnCount(parent)); } -bool -BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const +bool BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const { Q_UNUSED(row) BookmarkModel *model = qobject_cast<BookmarkModel*> (sourceModel()); diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp index da92843..c5db6c3 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.cpp +++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp @@ -53,6 +53,7 @@ #include <QtGui/QKeyEvent> #include <QtGui/QMessageBox> #include <QtGui/QSortFilterProxyModel> +#include <QtGui/QToolBar> QT_BEGIN_NAMESPACE @@ -136,11 +137,18 @@ QWidget* BookmarkManager::bookmarkDockWidget() const return 0; } -void BookmarkManager::takeBookmarksMenu(QMenu* menu) +void BookmarkManager::setBookmarksMenu(QMenu* menu) { TRACE_OBJ bookmarkMenu = menu; - refeshBookmarkMenu(); + refreshBookmarkMenu(); +} + +void BookmarkManager::setBookmarksToolbar(QToolBar *toolBar) +{ + TRACE_OBJ + m_toolBar = toolBar; + refreshBookmarkToolBar(); } // -- public slots @@ -157,7 +165,10 @@ void BookmarkManager::addBookmark(const QString &title, const QString &url) BookmarkManager::BookmarkManager() : typeAndSearch(false) , bookmarkMenu(0) + , m_toolBar(0) , bookmarkModel(new BookmarkModel) + , bookmarkFilterModel(0) + , typeAndSearchModel(0) , bookmarkWidget(new BookmarkWidget) , bookmarkTreeView(new BookmarkTreeView) , bookmarkManagerWidget(0) @@ -186,11 +197,18 @@ BookmarkManager::BookmarkManager() connect(&HelpEngineWrapper::instance(), SIGNAL(setupFinished()), this, SLOT(setupFinished())); connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, - SLOT(refeshBookmarkMenu())); + SLOT(refreshBookmarkMenu())); + connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, + SLOT(refreshBookmarkMenu())); + connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, + SLOT(refreshBookmarkMenu())); + + connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, + SLOT(refreshBookmarkToolBar())); connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, - SLOT(refeshBookmarkMenu())); + SLOT(refreshBookmarkToolBar())); connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, - SLOT(refeshBookmarkMenu())); + SLOT(refreshBookmarkToolBar())); } BookmarkManager::~BookmarkManager() @@ -283,7 +301,7 @@ void BookmarkManager::buildBookmarksMenu(const QModelIndex &index, QMenu* menu) return; const QString &text = index.data().toString(); - const QIcon &icon = qVariantValue<QIcon>(index.data(Qt::DecorationRole)); + const QIcon &icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole)); if (index.data(UserRoleFolder).toBool()) { if (QMenu* subMenu = menu->addMenu(icon, text)) { for (int i = 0; i < bookmarkModel->rowCount(index); ++i) @@ -310,17 +328,20 @@ void BookmarkManager::setupFinished() bookmarkModel->setBookmarks(HelpEngineWrapper::instance().bookmarks()); bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView); - refeshBookmarkMenu(); + refreshBookmarkMenu(); + refreshBookmarkToolBar(); bookmarkTreeView->hideColumn(1); bookmarkTreeView->header()->setVisible(false); bookmarkTreeView->header()->setStretchLastSection(true); - bookmarkFilterModel = new BookmarkFilterModel(this); + if (!bookmarkFilterModel) + bookmarkFilterModel = new BookmarkFilterModel(this); bookmarkFilterModel->setSourceModel(bookmarkModel); bookmarkFilterModel->filterBookmarkFolders(); - typeAndSearchModel = new QSortFilterProxyModel(this); + if (!typeAndSearchModel) + typeAndSearchModel = new QSortFilterProxyModel(this); typeAndSearchModel->setDynamicSortFilter(true); typeAndSearchModel->setSourceModel(bookmarkFilterModel); } @@ -354,7 +375,7 @@ void BookmarkManager::manageBookmarks() bookmarkManagerWidget->raise(); } -void BookmarkManager::refeshBookmarkMenu() +void BookmarkManager::refreshBookmarkMenu() { TRACE_OBJ if (!bookmarkMenu) @@ -365,11 +386,16 @@ void BookmarkManager::refeshBookmarkMenu() bookmarkMenu->addAction(tr("Manage Bookmarks..."), this, SLOT(manageBookmarks())); bookmarkMenu->addAction(QIcon::fromTheme("bookmark-new"), - tr("Add Bookmark..."), this, SLOT(addBookmark()), - QKeySequence(tr("Ctrl+D"))); + tr("Add Bookmark..."), this, SLOT(addBookmark()), QKeySequence(tr("Ctrl+D"))); + bookmarkMenu->addSeparator(); - const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex()); + QModelIndex root = bookmarkModel->index(0, 0, QModelIndex()).parent(); + buildBookmarksMenu(bookmarkModel->index(0, 0, root), bookmarkMenu); + + bookmarkMenu->addSeparator(); + + root = bookmarkModel->index(1, 0, QModelIndex()); for (int i = 0; i < bookmarkModel->rowCount(root); ++i) buildBookmarksMenu(bookmarkModel->index(i, 0, root), bookmarkMenu); @@ -377,6 +403,41 @@ void BookmarkManager::refeshBookmarkMenu() SLOT(setSourceFromAction(QAction*))); } +void BookmarkManager::refreshBookmarkToolBar() +{ + TRACE_OBJ + if (!m_toolBar) + return; + + m_toolBar->clear(); + m_toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + + const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex()); + for (int i = 0; i < bookmarkModel->rowCount(root); ++i) { + const QModelIndex &index = bookmarkModel->index(i, 0, root); + if (index.data(UserRoleFolder).toBool()) { + QToolButton *button = new QToolButton(m_toolBar); + button->setPopupMode(QToolButton::InstantPopup); + button->setText(index.data().toString()); + QMenu *menu = new QMenu(button); + for (int j = 0; j < bookmarkModel->rowCount(index); ++j) + buildBookmarksMenu(bookmarkModel->index(j, 0, index), menu); + connect(menu, SIGNAL(triggered(QAction*)), this, + SLOT(setSourceFromAction(QAction*))); + button->setMenu(menu); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + button->setIcon(qvariant_cast<QIcon>(index.data(Qt::DecorationRole))); + QAction *a = m_toolBar->addWidget(button); + a->setText(index.data().toString()); + } else { + QAction *action = m_toolBar->addAction( + qvariant_cast<QIcon>(index.data(Qt::DecorationRole)), + index.data().toString(), this, SLOT(setSourceFromAction())); + action->setData(index.data(UserRoleUrl).toString()); + } + } +} + void BookmarkManager::renameBookmark(const QModelIndex &index) { // check if we should rename the "Bookmarks Menu", bail @@ -388,13 +449,21 @@ void BookmarkManager::renameBookmark(const QModelIndex &index) bookmarkModel->setItemsEditable(false); } -void BookmarkManager::setSourceFromAction(QAction *action) + +void BookmarkManager::setSourceFromAction() { TRACE_OBJ - const QVariant &data = action->data(); + setSourceFromAction(qobject_cast<QAction*> (sender())); +} - if (data.canConvert<QUrl>()) - emit setSource(data.toUrl()); +void BookmarkManager::setSourceFromAction(QAction *action) +{ + TRACE_OBJ + if (action) { + const QVariant &data = action->data(); + if (data.canConvert<QUrl>()) + emit setSource(data.toUrl()); + } } void BookmarkManager::setSourceFromIndex(const QModelIndex &index, bool newTab) diff --git a/tools/assistant/tools/assistant/bookmarkmanager.h b/tools/assistant/tools/assistant/bookmarkmanager.h index 5d1b300..20f56ea 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.h +++ b/tools/assistant/tools/assistant/bookmarkmanager.h @@ -53,6 +53,7 @@ class BookmarkModel; class BookmarkFilterModel; class QKeyEvent; class QSortFilterProxyModel; +class QToolBar; class BookmarkManager : public QObject { @@ -67,7 +68,8 @@ public: static void destroy(); QWidget* bookmarkDockWidget() const; - void takeBookmarksMenu(QMenu* menu); + void setBookmarksMenu(QMenu* menu); + void setBookmarksToolbar(QToolBar *toolBar); public slots: void addBookmark(const QString &title, const QString &url); @@ -92,9 +94,11 @@ private slots: void addBookmark(); void removeBookmark(); void manageBookmarks(); - void refeshBookmarkMenu(); + void refreshBookmarkMenu(); + void refreshBookmarkToolBar(); void renameBookmark(const QModelIndex &index); + void setSourceFromAction(); void setSourceFromAction(QAction *action); void setSourceFromIndex(const QModelIndex &index, bool newTab = false); @@ -110,6 +114,7 @@ private: static BookmarkManager *bookmarkManager; QMenu *bookmarkMenu; + QToolBar *m_toolBar; BookmarkModel *bookmarkModel; BookmarkFilterModel *bookmarkFilterModel; diff --git a/tools/assistant/tools/assistant/bookmarkmodel.cpp b/tools/assistant/tools/assistant/bookmarkmodel.cpp index 4974216..bc4a321 100644 --- a/tools/assistant/tools/assistant/bookmarkmodel.cpp +++ b/tools/assistant/tools/assistant/bookmarkmodel.cpp @@ -48,6 +48,7 @@ #include <QtGui/QStyle> #include <QtGui/QTreeView> +const quint32 VERSION = 0xe53798; const QLatin1String MIMETYPE("application/bookmarks.assistant"); BookmarkModel::BookmarkModel() @@ -68,8 +69,9 @@ BookmarkModel::bookmarks() const { QByteArray ba; QDataStream stream(&ba, QIODevice::WriteOnly); + stream << qint32(VERSION); - const QModelIndex &root = index(0,0, QModelIndex()); + const QModelIndex &root = index(0,0, QModelIndex()).parent(); for (int i = 0; i < rowCount(root); ++i) collectItems(index(i, 0, root), 0, &stream); @@ -87,24 +89,35 @@ BookmarkModel::setBookmarks(const QByteArray &bookmarks) rootItem = new BookmarkItem(DataVector() << tr("Name") << tr("Address") << true); - BookmarkItem* item = new BookmarkItem(DataVector() << tr("Bookmarks Menu") - << QLatin1String("Folder") << true); - rootItem->addChild(item); QStack<BookmarkItem*> parents; - parents.push(item); + QDataStream stream(bookmarks); + + qint32 version; + stream >> version; + if (version < VERSION) { + stream.device()->seek(0); + BookmarkItem* toolbar = new BookmarkItem(DataVector() << tr("Toolbar Menu") + << QLatin1String("Folder") << true); + rootItem->addChild(toolbar); + + BookmarkItem* menu = new BookmarkItem(DataVector() << tr("Bookmarks Menu") + << QLatin1String("Folder") << true); + rootItem->addChild(menu); + parents.push(menu); + } else { + parents.push(rootItem); + } qint32 depth; bool expanded; QString name, url; - QDataStream stream(bookmarks); while (!stream.atEnd()) { stream >> depth >> name >> url >> expanded; - while ((parents.count() - 1) != depth) parents.pop(); - item = new BookmarkItem(DataVector() << name << url << expanded); + BookmarkItem *item = new BookmarkItem(DataVector() << name << url << expanded); if (url == QLatin1String("Folder")) { parents.top()->addChild(item); parents.push(item); @@ -114,11 +127,7 @@ BookmarkModel::setBookmarks(const QByteArray &bookmarks) } cache.clear(); - const QModelIndex &root = index(0,0, QModelIndex()); - - setupCache(root); - cache.insert(static_cast<BookmarkItem*> (root.internalPointer()), root); - + setupCache(index(0,0, QModelIndex().parent())); endResetModel(); } diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index 2bd09e7..37eaaca 100644 --- a/tools/assistant/tools/assistant/centralwidget.cpp +++ b/tools/assistant/tools/assistant/centralwidget.cpp @@ -38,966 +38,514 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" #include "centralwidget.h" + #include "findwidget.h" #include "helpenginewrapper.h" -#include "searchwidget.h" -#include "mainwindow.h" +#include "helpviewer.h" +#include "openpagesmanager.h" +#include "tracer.h" #include "../shared/collectionconfiguration.h" -#if defined(QT_NO_WEBKIT) -#include "helpviewer_qtb.h" -#else -#include "helpviewer_qwv.h" -#endif // QT_NO_WEBKIT - #include <QtCore/QTimer> -#include <QtGui/QApplication> #include <QtGui/QKeyEvent> -#include <QtGui/QLayout> #include <QtGui/QMenu> -#include <QtGui/QPrinter> -#include <QtGui/QTabBar> -#include <QtGui/QTabWidget> -#include <QtGui/QTextBrowser> -#include <QtGui/QToolButton> #include <QtGui/QPageSetupDialog> #include <QtGui/QPrintDialog> #include <QtGui/QPrintPreviewDialog> +#include <QtGui/QPrinter> +#include <QtGui/QStackedWidget> +#include <QtGui/QTextBrowser> +#include <QtGui/QVBoxLayout> #include <QtHelp/QHelpSearchEngine> QT_BEGIN_NAMESPACE namespace { - HelpViewer* helpViewerFromTabPosition(const QTabWidget *widget, - const QPoint &point) - { - TRACE_OBJ - QTabBar *tabBar = qFindChild<QTabBar*>(widget); - for (int i = 0; i < tabBar->count(); ++i) { - if (tabBar->tabRect(i).contains(point)) - return qobject_cast<HelpViewer*>(widget->widget(i)); - } - return 0; - } CentralWidget *staticCentralWidget = 0; } -// -- CentralWidget +// -- TabBar -CentralWidget::CentralWidget(MainWindow *parent) - : QWidget(parent) - , lastTabPage(0) - , tabWidget(0) - , findWidget(0) - , printer(0) - , usesDefaultCollection(parent->usesDefaultCollection()) - , m_searchWidget(0) +TabBar::TabBar(QWidget *parent) + : QTabBar(parent) { TRACE_OBJ - globalActionList.clear(); - staticCentralWidget = this; - QVBoxLayout *vboxLayout = new QVBoxLayout(this); - QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); - - vboxLayout->setMargin(0); - tabWidget = new QTabWidget(this); -#ifndef Q_OS_MAC - resourcePath.append(QLatin1String("win")); -#else - resourcePath.append(QLatin1String("mac")); - tabWidget->setDocumentMode(true); -#endif - - connect(tabWidget, SIGNAL(currentChanged(int)), this, - SLOT(currentPageChanged(int))); - - QToolButton *newTabButton = new QToolButton(this); - newTabButton->setAutoRaise(true); - newTabButton->setToolTip(tr("Add new page")); - newTabButton->setIcon(QIcon(resourcePath + QLatin1String("/addtab.png"))); - - tabWidget->setCornerWidget(newTabButton, Qt::TopLeftCorner); - connect(newTabButton, SIGNAL(clicked()), this, SLOT(newTab())); - - QToolButton *closeTabButton = new QToolButton(this); - closeTabButton->setEnabled(false); - closeTabButton->setAutoRaise(true); - closeTabButton->setToolTip(tr("Close current page")); - closeTabButton->setIcon(QIcon(resourcePath + QLatin1String("/closetab.png"))); - - tabWidget->setCornerWidget(closeTabButton, Qt::TopRightCorner); - connect(closeTabButton, SIGNAL(clicked()), this, SLOT(closeTab())); - - vboxLayout->addWidget(tabWidget); - - findWidget = new FindWidget(this); - vboxLayout->addWidget(findWidget); - findWidget->hide(); - - connect(findWidget, SIGNAL(findNext()), this, SLOT(findNext())); - connect(findWidget, SIGNAL(findPrevious()), this, SLOT(findPrevious())); - connect(findWidget, SIGNAL(find(QString, bool)), this, - SLOT(find(QString, bool))); - connect(findWidget, SIGNAL(escapePressed()), this, SLOT(activateTab())); - - QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); - if (tabBar) { - tabBar->installEventFilter(this); - tabBar->setContextMenuPolicy(Qt::CustomContextMenu); - connect(tabBar, SIGNAL(customContextMenuRequested(QPoint)), this, - SLOT(showTabBarContextMenu(QPoint))); - } - -#if defined(QT_NO_WEBKIT) - QPalette p = palette(); - p.setColor(QPalette::Inactive, QPalette::Highlight, - p.color(QPalette::Active, QPalette::Highlight)); - p.setColor(QPalette::Inactive, QPalette::HighlightedText, - p.color(QPalette::Active, QPalette::HighlightedText)); - setPalette(p); +#ifdef Q_OS_MAC + setDocumentMode(true); #endif + setMovable(true); + setShape(QTabBar::RoundedNorth); + setContextMenuPolicy(Qt::CustomContextMenu); + setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred, + QSizePolicy::TabWidget)); + connect(this, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentChanged(int))); + connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(slotTabCloseRequested(int))); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(slotCustomContextMenuRequested(QPoint))); } -CentralWidget::~CentralWidget() +TabBar::~TabBar() { TRACE_OBJ -#ifndef QT_NO_PRINTER - delete printer; -#endif - - QStringList zoomFactors; - QStringList currentPages; - bool searchAttached = m_searchWidget->isAttached(); - - int i = searchAttached ? 1 : 0; - for (; i < tabWidget->count(); ++i) { - HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i)); - if (viewer && viewer->source().isValid()) { - currentPages << viewer->source().toString(); - zoomFactors << QString::number(viewer->scale()); - } - } - - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - helpEngine.setLastTabPage(tabWidget->currentIndex()); - helpEngine.setLastShownPages(currentPages); - helpEngine.setSearchWasAttached(searchAttached); - helpEngine.setLastZoomFactors(zoomFactors); } -CentralWidget *CentralWidget::instance() +int TabBar::addNewTab(const QString &title) { TRACE_OBJ - return staticCentralWidget; + const int index = addTab(title); + setTabsClosable(count() > 1); + return index; } -void CentralWidget::newTab() +void TabBar::setCurrent(HelpViewer *viewer) { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); -#if !defined(QT_NO_WEBKIT) - if (viewer && viewer->hasLoadFinished()) -#else - if (viewer) -#endif - setSourceInNewTab(viewer->source()); -} - -void CentralWidget::zoomIn() -{ - TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->scaleUp(); - - if (tabWidget->currentWidget() == m_searchWidget) - m_searchWidget->zoomIn(); + for (int i = 0; i < count(); ++i) { + HelpViewer *data = tabData(i).value<HelpViewer*>(); + if (data == viewer) { + setCurrentIndex(i); + break; + } + } } -void CentralWidget::zoomOut() +void TabBar::removeTabAt(HelpViewer *viewer) { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->scaleDown(); - - if (tabWidget->currentWidget() == m_searchWidget) - m_searchWidget->zoomOut(); + for (int i = 0; i < count(); ++i) { + HelpViewer *data = tabData(i).value<HelpViewer*>(); + if (data == viewer) { + removeTab(i); + break; + } + } + setTabsClosable(count() > 1); } -void CentralWidget::nextPage() +void TabBar::titleChanged() { TRACE_OBJ - int index = tabWidget->currentIndex() + 1; - if (index >= tabWidget->count()) - index = 0; - tabWidget->setCurrentIndex(index); + for (int i = 0; i < count(); ++i) { + HelpViewer *data = tabData(i).value<HelpViewer*>(); + QString title = data->title(); + title.replace(QLatin1Char('&'), QLatin1String("&&")); + setTabText(i, title.isEmpty() ? tr("(Untitled)") : title); + } } -void CentralWidget::resetZoom() +void TabBar::slotCurrentChanged(int index) { TRACE_OBJ - if (HelpViewer *viewer = currentHelpViewer()) - viewer->resetScale(); - - if (tabWidget->currentWidget() == m_searchWidget) - m_searchWidget->resetZoom(); + emit currentTabChanged(tabData(index).value<HelpViewer*>()); } -void CentralWidget::previousPage() +void TabBar::slotTabCloseRequested(int index) { TRACE_OBJ - int index = tabWidget->currentIndex() -1; - if (index < 0) - index = tabWidget->count() -1; - tabWidget->setCurrentIndex(index); + OpenPagesManager::instance()->closePage(tabData(index).value<HelpViewer*>()); } -void CentralWidget::closeTab() +void TabBar::slotCustomContextMenuRequested(const QPoint &pos) { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (!viewer|| tabWidget->count() == 1) + const int tab = tabAt(pos); + if (tab < 0) return; - tabWidget->removeTab(tabWidget->indexOf(viewer)); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); + QMenu menu(QLatin1String(""), this); + menu.addAction(tr("New &Tab"), OpenPagesManager::instance(), SLOT(createPage())); + + const bool enableAction = count() > 1; + QAction *closePage = menu.addAction(tr("&Close Tab")); + closePage->setEnabled(enableAction); + + QAction *closePages = menu.addAction(tr("Close Other Tabs")); + closePages->setEnabled(enableAction); + + menu.addSeparator(); + + HelpViewer *viewer = tabData(tab).value<HelpViewer*>(); + QAction *newBookmark = menu.addAction(tr("Add Bookmark for this Page...")); + const QString &url = viewer->source().toString(); + if (url.isEmpty() || url == QLatin1String("about:blank")) + newBookmark->setEnabled(false); + + QAction *pickedAction = menu.exec(mapToGlobal(pos)); + if (pickedAction == closePage) + slotTabCloseRequested(tab); + else if (pickedAction == closePages) { + for (int i = count() - 1; i >= 0; --i) { + if (i != tab) + slotTabCloseRequested(i); + } + } else if (pickedAction == newBookmark) + emit addBookmark(viewer->title(), url); } -void CentralWidget::setSource(const QUrl &url) +// -- CentralWidget + +CentralWidget::CentralWidget(QWidget *parent) + : QWidget(parent) +#ifndef QT_NO_PRINTER + , m_printer(0) +#endif + , m_findWidget(new FindWidget(this)) + , m_stackedWidget(new QStackedWidget(this)) + , m_tabBar(new TabBar(this)) { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - HelpViewer *lastViewer = - qobject_cast<HelpViewer*>(tabWidget->widget(lastTabPage)); - - if (!viewer && !lastViewer) { - viewer = new HelpViewer(this); - viewer->installEventFilter(this); - lastTabPage = tabWidget->addTab(viewer, QString()); - tabWidget->setCurrentIndex(lastTabPage); - connectSignals(); - } else { - viewer = lastViewer; - } + staticCentralWidget = this; + QVBoxLayout *vboxLayout = new QVBoxLayout(this); - viewer->setSource(url); - currentPageChanged(lastTabPage); - viewer->setFocus(Qt::OtherFocusReason); - tabWidget->setCurrentIndex(lastTabPage); - tabWidget->setTabText(lastTabPage, quoteTabTitle(viewer->documentTitle())); + vboxLayout->setMargin(0); + vboxLayout->setSpacing(0); + vboxLayout->addWidget(m_tabBar); + m_tabBar->setVisible(HelpEngineWrapper::instance().showTabs()); + vboxLayout->addWidget(m_stackedWidget); + vboxLayout->addWidget(m_findWidget); + m_findWidget->hide(); + + connect(m_findWidget, SIGNAL(findNext()), this, SLOT(findNext())); + connect(m_findWidget, SIGNAL(findPrevious()), this, SLOT(findPrevious())); + connect(m_findWidget, SIGNAL(find(QString, bool, bool)), this, + SLOT(find(QString, bool, bool))); + connect(m_findWidget, SIGNAL(escapePressed()), this, SLOT(activateTab())); + connect(m_tabBar, SIGNAL(addBookmark(QString, QString)), this, + SIGNAL(addBookmark(QString, QString))); } -void CentralWidget::setupWidget() +CentralWidget::~CentralWidget() { TRACE_OBJ - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - int option = helpEngine.startOption(); - if (option != ShowLastPages) { - QString homePage; - if (option == ShowHomePage) - homePage = helpEngine.homePage(); - else if (option == ShowBlankPage) - homePage = QLatin1String("about:blank"); - setSource(homePage); - } else { - setLastShownPages(); + QStringList zoomFactors; + QStringList currentPages; + for (int i = 0; i < m_stackedWidget->count(); ++i) { + const HelpViewer * const viewer = viewerAt(i); + const QUrl &source = viewer->source(); + if (source.isValid()) { + currentPages << source.toString(); + zoomFactors << QString::number(viewer->scale()); + } } -} -void CentralWidget::setLastShownPages() -{ - TRACE_OBJ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - const QStringList &lastShownPageList = helpEngine.lastShownPages(); - const int pageCount = lastShownPageList.count(); - if (pageCount == 0) { - if (usesDefaultCollection) - setSource(QUrl(QLatin1String("help"))); - else - setSource(QUrl(QLatin1String("about:blank"))); - return; - } - QStringList zoomFactors = helpEngine.lastZoomFactors(); - while (zoomFactors.count() < pageCount) - zoomFactors.append(CollectionConfiguration::DefaultZoomFactor); - - const bool searchIsAttached = m_searchWidget->isAttached(); - const bool searchWasAttached = helpEngine.searchWasAttached(); - int tabToShow = helpEngine.lastTabPage(); - if (searchWasAttached && !searchIsAttached && tabToShow != 0) - --tabToShow; - else if (!searchWasAttached && searchIsAttached) - ++tabToShow; - - for (int curTab = 0; curTab < pageCount; ++curTab) { - const QString &curFile = lastShownPageList.at(curTab); - if (helpEngine.findFile(curFile).isValid() - || curFile == QLatin1String("about:blank")) { - setSourceInNewTab(curFile, zoomFactors.at(curTab).toFloat()); - } else if (curTab + searchIsAttached <= tabToShow) - --tabToShow; - } + helpEngine.setLastShownPages(currentPages); + helpEngine.setLastZoomFactors(zoomFactors); + helpEngine.setLastTabPage(m_stackedWidget->currentIndex()); - tabWidget->setCurrentIndex(tabToShow); +#ifndef QT_NO_PRINTER + delete m_printer; +#endif } -bool CentralWidget::hasSelection() const +CentralWidget *CentralWidget::instance() { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - return viewer ? viewer->hasSelection() : false; + return staticCentralWidget; } QUrl CentralWidget::currentSource() const { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - return viewer->source(); - - return QUrl(); + return currentHelpViewer()->source(); } QString CentralWidget::currentTitle() const { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - return viewer->documentTitle(); - - return QString(); + return currentHelpViewer()->title(); } -void CentralWidget::copySelection() +bool CentralWidget::hasSelection() const { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->copy(); + return !currentHelpViewer()->selectedText().isEmpty(); } -void CentralWidget::showTextSearch() +bool CentralWidget::isForwardAvailable() const { TRACE_OBJ - findWidget->show(); + return currentHelpViewer()->isForwardAvailable(); } -void CentralWidget::initPrinter() +bool CentralWidget::isBackwardAvailable() const { TRACE_OBJ -#ifndef QT_NO_PRINTER - if (!printer) - printer = new QPrinter(QPrinter::HighResolution); -#endif + return currentHelpViewer()->isBackwardAvailable(); } -void CentralWidget::print() +HelpViewer* CentralWidget::viewerAt(int index) const { TRACE_OBJ -#ifndef QT_NO_PRINTER - HelpViewer *viewer = currentHelpViewer(); - if (!viewer) - return; - - initPrinter(); - - QPrintDialog dlg(printer, this); -#if defined(QT_NO_WEBKIT) - if (viewer->textCursor().hasSelection()) - dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection); -#endif - dlg.addEnabledOption(QAbstractPrintDialog::PrintPageRange); - dlg.addEnabledOption(QAbstractPrintDialog::PrintCollateCopies); - dlg.setWindowTitle(tr("Print Document")); - if (dlg.exec() == QDialog::Accepted) { - viewer->print(printer); - } -#endif + return static_cast<HelpViewer*>(m_stackedWidget->widget(index)); } -void CentralWidget::printPreview() +HelpViewer* CentralWidget::currentHelpViewer() const { TRACE_OBJ -#ifndef QT_NO_PRINTER - initPrinter(); - QPrintPreviewDialog preview(printer, this); - connect(&preview, SIGNAL(paintRequested(QPrinter*)), - SLOT(printPreview(QPrinter*))); - preview.exec(); -#endif + return static_cast<HelpViewer *>(m_stackedWidget->currentWidget()); } -void CentralWidget::printPreview(QPrinter *p) +void CentralWidget::addPage(HelpViewer *page, bool fromSearch) { TRACE_OBJ -#ifndef QT_NO_PRINTER - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->print(p); -#endif -} + page->installEventFilter(this); + page->setFocus(Qt::OtherFocusReason); + connectSignals(page); + const int index = m_stackedWidget->addWidget(page); + m_tabBar->setTabData(m_tabBar->addNewTab(page->title()), + QVariant::fromValue(viewerAt(index))); + connect (page, SIGNAL(titleChanged()), m_tabBar, SLOT(titleChanged())); -void CentralWidget::pageSetup() -{ - TRACE_OBJ -#ifndef QT_NO_PRINTER - initPrinter(); - QPageSetupDialog dlg(printer); - dlg.exec(); -#endif + if (fromSearch) { + connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, + SLOT(highlightSearchTerms())); + } } -bool CentralWidget::isHomeAvailable() const +void CentralWidget::removePage(int index) { TRACE_OBJ - return currentHelpViewer() ? true : false; + const bool currentChanged = index == currentIndex(); + m_tabBar->removeTabAt(viewerAt(index)); + m_stackedWidget->removeWidget(m_stackedWidget->widget(index)); + if (currentChanged) + emit currentViewerChanged(); } -void CentralWidget::home() +int CentralWidget::currentIndex() const { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->home(); + return m_stackedWidget->currentIndex(); } -bool CentralWidget::isForwardAvailable() const +void CentralWidget::setCurrentPage(HelpViewer *page) { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - return viewer->isForwardAvailable(); - - return false; + m_tabBar->setCurrent(page); + m_stackedWidget->setCurrentWidget(page); + emit currentViewerChanged(); } -void CentralWidget::forward() +void CentralWidget::connectTabBar() { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->forward(); + connect(m_tabBar, SIGNAL(currentTabChanged(HelpViewer*)), + OpenPagesManager::instance(), SLOT(setCurrentPage(HelpViewer*))); } -bool CentralWidget::isBackwardAvailable() const -{ - TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - return viewer->isBackwardAvailable(); - - return false; -} +// -- public slots -void CentralWidget::backward() +void CentralWidget::copy() { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (viewer) - viewer->backward(); + currentHelpViewer()->copy(); } - -QList<QAction*> CentralWidget::globalActions() const +void CentralWidget::home() { TRACE_OBJ - return globalActionList; + currentHelpViewer()->home(); } -void CentralWidget::setGlobalActions(const QList<QAction*> &actions) +void CentralWidget::zoomIn() { TRACE_OBJ - globalActionList = actions; + currentHelpViewer()->scaleUp(); } -void CentralWidget::setSourceInNewTab(const QUrl &url, qreal zoom) +void CentralWidget::zoomOut() { TRACE_OBJ - if (HelpViewer *viewer = currentHelpViewer()) { - if (viewer->launchWithExternalApp(url)) - return; - } - - HelpViewer *viewer = new HelpViewer(this, zoom); - viewer->installEventFilter(this); - viewer->setSource(url); - viewer->setFocus(Qt::OtherFocusReason); - tabWidget->setCurrentIndex(tabWidget->addTab(viewer, - quoteTabTitle(viewer->documentTitle()))); - connectSignals(); + currentHelpViewer()->scaleDown(); } -HelpViewer *CentralWidget::newEmptyTab() +void CentralWidget::resetZoom() { TRACE_OBJ - HelpViewer *viewer = new HelpViewer(this); - viewer->installEventFilter(this); - viewer->setFocus(Qt::OtherFocusReason); -#if defined(QT_NO_WEBKIT) - viewer->setDocumentTitle(tr("unknown")); -#endif - tabWidget->setCurrentIndex(tabWidget->addTab(viewer, tr("unknown"))); - - connectSignals(); - return viewer; + currentHelpViewer()->resetScale(); } -void CentralWidget::connectSignals() +void CentralWidget::forward() { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) { - connect(viewer, SIGNAL(copyAvailable(bool)), this, - SIGNAL(copyAvailable(bool))); - connect(viewer, SIGNAL(forwardAvailable(bool)), this, - SIGNAL(forwardAvailable(bool))); - connect(viewer, SIGNAL(backwardAvailable(bool)), this, - SIGNAL(backwardAvailable(bool))); - connect(viewer, SIGNAL(sourceChanged(QUrl)), this, - SIGNAL(sourceChanged(QUrl))); - connect(viewer, SIGNAL(highlighted(QString)), this, - SIGNAL(highlighted(QString))); - connect(viewer, SIGNAL(sourceChanged(QUrl)), this, - SLOT(setTabTitle(QUrl))); - connect(viewer, SIGNAL(printRequested()), this, SLOT(print())); - } + currentHelpViewer()->forward(); } -HelpViewer* CentralWidget::viewerAt(int index) const +void CentralWidget::nextPage() { TRACE_OBJ - return qobject_cast<HelpViewer*>(tabWidget->widget(index)); + m_stackedWidget->setCurrentIndex((m_stackedWidget->currentIndex() + 1) + % m_stackedWidget->count()); } -HelpViewer* CentralWidget::currentHelpViewer() const +void CentralWidget::backward() { TRACE_OBJ - return qobject_cast<HelpViewer*>(tabWidget->currentWidget()); + currentHelpViewer()->backward(); } -void CentralWidget::activateTab(bool onlyHelpViewer) +void CentralWidget::previousPage() { TRACE_OBJ - if (currentHelpViewer()) { - currentHelpViewer()->setFocus(); - } else { - int idx = 0; - if (onlyHelpViewer) - idx = lastTabPage; - tabWidget->setCurrentIndex(idx); - tabWidget->currentWidget()->setFocus(); - } + m_stackedWidget->setCurrentIndex((m_stackedWidget->currentIndex() - 1) + % m_stackedWidget->count()); } -void CentralWidget::setTabTitle(const QUrl &url) +void CentralWidget::print() { TRACE_OBJ - Q_UNUSED(url) -#if !defined(QT_NO_WEBKIT) - QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); - for (int tab = 0; tab < tabBar->count(); ++tab) { - HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(tab)); - if (viewer) { - tabWidget->setTabText(tab, - quoteTabTitle(viewer->documentTitle().trimmed())); - } - } -#else - HelpViewer *viewer = currentHelpViewer(); - if (viewer) { - tabWidget->setTabText(lastTabPage, - quoteTabTitle(viewer->documentTitle().trimmed())); - } +#ifndef QT_NO_PRINTER + initPrinter(); + QPrintDialog dlg(m_printer, this); + + if (!currentHelpViewer()->selectedText().isEmpty()) + dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection); + dlg.addEnabledOption(QAbstractPrintDialog::PrintPageRange); + dlg.addEnabledOption(QAbstractPrintDialog::PrintCollateCopies); + dlg.setWindowTitle(tr("Print Document")); + if (dlg.exec() == QDialog::Accepted) + currentHelpViewer()->print(m_printer); #endif } -void CentralWidget::currentPageChanged(int index) +void CentralWidget::pageSetup() { TRACE_OBJ - const HelpViewer *viewer = currentHelpViewer(); - if (viewer) - lastTabPage = index; - - QWidget *widget = tabWidget->cornerWidget(Qt::TopRightCorner); - widget->setEnabled(viewer && enableTabCloseAction()); - - widget = tabWidget->cornerWidget(Qt::TopLeftCorner); - widget->setEnabled(viewer ? true : false); - - emit currentViewerChanged(); +#ifndef QT_NO_PRINTER + initPrinter(); + QPageSetupDialog dlg(m_printer); + dlg.exec(); +#endif } -void CentralWidget::showTabBarContextMenu(const QPoint &point) +void CentralWidget::printPreview() { TRACE_OBJ - HelpViewer *viewer = helpViewerFromTabPosition(tabWidget, point); - if (!viewer) - return; - - QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); - - QMenu menu(QLatin1String(""), tabBar); - QAction *newPage = menu.addAction(tr("Add New Page")); - - bool enableAction = enableTabCloseAction(); - QAction *closePage = menu.addAction(tr("Close This Page")); - closePage->setEnabled(enableAction); - - QAction *closePages = menu.addAction(tr("Close Other Pages")); - closePages->setEnabled(enableAction); - - menu.addSeparator(); - - QAction *newBookmark = menu.addAction(tr("Add Bookmark for this Page...")); - const QString &url = viewer->source().toString(); - if (url.isEmpty() || url == QLatin1String("about:blank")) - newBookmark->setEnabled(false); - - QAction *pickedAction = menu.exec(tabBar->mapToGlobal(point)); - if (pickedAction == newPage) - setSourceInNewTab(viewer->source()); - - if (pickedAction == closePage) { - tabWidget->removeTab(tabWidget->indexOf(viewer)); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); - } - - if (pickedAction == closePages) { - int currentPage = tabWidget->indexOf(viewer); - for (int i = tabBar->count() -1; i >= 0; --i) { - viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i)); - if (i != currentPage && viewer) { - tabWidget->removeTab(i); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); - - if (i < currentPage) - --currentPage; - } - } - } - - if (pickedAction == newBookmark) - emit addBookmark(viewer->documentTitle(), viewer->source().toString()); +#ifndef QT_NO_PRINTER + initPrinter(); + QPrintPreviewDialog preview(m_printer, this); + connect(&preview, SIGNAL(paintRequested(QPrinter*)), + SLOT(printPreview(QPrinter*))); + preview.exec(); +#endif } -bool CentralWidget::eventFilter(QObject *object, QEvent *e) +void CentralWidget::setSource(const QUrl &url) { TRACE_OBJ - if (e->type() == QEvent::KeyPress) { - QKeyEvent *ke = static_cast<QKeyEvent*>(e); - switch (ke->key()) { - default: { - return QWidget::eventFilter(object, e); - } break; - - case Qt::Key_Backspace: { - HelpViewer *viewer = currentHelpViewer(); - if (viewer == object) { -#if defined(QT_NO_WEBKIT) - if (viewer->isBackwardAvailable()) { -#else - if (viewer->isBackwardAvailable() && !viewer->hasFocus()) { -#endif - viewer->backward(); - return true; - } - } - } break; - } - } - - if (qobject_cast<QTabBar*>(object)) { - const bool dblClick = e->type() == QEvent::MouseButtonDblClick; - if ((e->type() == QEvent::MouseButtonRelease) || dblClick) { - QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(e); - HelpViewer *viewer = helpViewerFromTabPosition(tabWidget, - mouseEvent->pos()); - if (viewer) { - if ((mouseEvent->button() == Qt::MidButton) || dblClick) { - if (availableHelpViewer() > 1) { - tabWidget->removeTab(tabWidget->indexOf(viewer)); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); - currentPageChanged(tabWidget->currentIndex()); - return true; - } - } - } - } - } - - return QWidget::eventFilter(object, e); + HelpViewer *viewer = currentHelpViewer(); + viewer->setSource(url); + viewer->setFocus(Qt::OtherFocusReason); } -void CentralWidget::keyPressEvent(QKeyEvent *e) +void CentralWidget::setSourceFromSearch(const QUrl &url) { TRACE_OBJ - const QString &text = e->text(); - if (text.startsWith(QLatin1Char('/'))) { - if (!findWidget->isVisible()) { - findWidget->showAndClear(); - } else { - findWidget->show(); - } - } else { - QWidget::keyPressEvent(e); - } + connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, + SLOT(highlightSearchTerms())); + currentHelpViewer()->setSource(url); + currentHelpViewer()->setFocus(Qt::OtherFocusReason); } void CentralWidget::findNext() { TRACE_OBJ - find(findWidget->text(), true); + find(m_findWidget->text(), true, false); } void CentralWidget::findPrevious() { TRACE_OBJ - find(findWidget->text(), false); + find(m_findWidget->text(), false, false); } -void CentralWidget::find(const QString &ttf, bool forward) +void CentralWidget::find(const QString &ttf, bool forward, bool incremental) { TRACE_OBJ bool found = false; -#if defined(QT_NO_WEBKIT) - found = findInTextBrowser(ttf, forward); -#else - found = findInWebPage(ttf, forward); -#endif + if (HelpViewer *viewer = currentHelpViewer()) { + HelpViewer::FindFlags flags = 0; + if (!forward) + flags |= HelpViewer::FindBackward; + if (m_findWidget->caseSensitive()) + flags |= HelpViewer::FindCaseSensitively; + found = viewer->findText(ttf, flags, incremental, false); + } if (!found && ttf.isEmpty()) found = true; // the line edit is empty, no need to mark it red... - if (!findWidget->isVisible()) - findWidget->show(); - findWidget->setPalette(found); + if (!m_findWidget->isVisible()) + m_findWidget->show(); + m_findWidget->setPalette(found); } -bool CentralWidget::findInWebPage(const QString &ttf, bool forward) +void CentralWidget::activateTab() { TRACE_OBJ -#if !defined(QT_NO_WEBKIT) - if (HelpViewer *viewer = currentHelpViewer()) { - bool found = false; - QWebPage::FindFlags options; - if (!ttf.isEmpty()) { - if (!forward) - options |= QWebPage::FindBackward; - - if (findWidget->caseSensitive()) - options |= QWebPage::FindCaseSensitively; - - found = viewer->findText(ttf, options); - findWidget->setTextWrappedVisible(false); - - if (!found) { - options |= QWebPage::FindWrapsAroundDocument; - found = viewer->findText(ttf, options); - if (found) - findWidget->setTextWrappedVisible(true); - } - } - // force highlighting of all other matches, also when empty (clear) - options = QWebPage::HighlightAllOccurrences; - if (findWidget->caseSensitive()) - options |= QWebPage::FindCaseSensitively; - viewer->findText(QLatin1String(""), options); - viewer->findText(ttf, options); - return found; - } - - // this needs to stay, case for active search results page - return findInTextBrowser(ttf, forward); -#else - Q_UNUSED(ttf); - Q_UNUSED(forward); -#endif - return false; + currentHelpViewer()->setFocus(); } -bool CentralWidget::findInTextBrowser(const QString &ttf, bool forward) +void CentralWidget::showTextSearch() { TRACE_OBJ - QTextBrowser *browser = qobject_cast<QTextBrowser*>(currentHelpViewer()); - if (tabWidget->currentWidget() == m_searchWidget) - browser = qFindChild<QTextBrowser*>(m_searchWidget); - - if (!browser || ttf.isEmpty()) - return false; - - QTextDocument *doc = browser->document(); - QTextCursor cursor = browser->textCursor(); - - if (!doc || cursor.isNull()) - return false; - - QTextDocument::FindFlags options; - - if (cursor.hasSelection()) { - cursor.setPosition(forward ? cursor.position() : cursor.anchor(), - QTextCursor::MoveAnchor); - } - - if (!forward) - options |= QTextDocument::FindBackward; - - if (findWidget->caseSensitive()) - options |= QTextDocument::FindCaseSensitively; - - findWidget->setTextWrappedVisible(false); - - bool found = true; - QTextCursor newCursor = doc->find(ttf, cursor, options); - if (newCursor.isNull()) { - QTextCursor ac(doc); - ac.movePosition(options & QTextDocument::FindBackward - ? QTextCursor::End : QTextCursor::Start); - newCursor = doc->find(ttf, ac, options); - if (newCursor.isNull()) { - found = false; - newCursor = cursor; - } else { - findWidget->setTextWrappedVisible(true); - } - } - browser->setTextCursor(newCursor); - return found; + m_findWidget->show(); } void CentralWidget::updateBrowserFont() { TRACE_OBJ - const bool searchAttached = searchWidgetAttached(); - if (searchAttached) { - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - m_searchWidget->setFont(helpEngine.usesBrowserFont() - ? helpEngine.browserFont() : qApp->font()); - } - - const int count = tabWidget->count(); - if (HelpViewer* viewer = viewerAt(count - 1)) { - const QFont &font = viewer->viewerFont(); - for (int i = searchAttached ? 1 : 0; i < count; ++i) - viewerAt(i)->setViewerFont(font); - } -} - -bool CentralWidget::searchWidgetAttached() const -{ - TRACE_OBJ - return m_searchWidget && m_searchWidget->isAttached(); + const int count = m_stackedWidget->count(); + const QFont &font = viewerAt(count - 1)->viewerFont(); + for (int i = 0; i < count; ++i) + viewerAt(i)->setViewerFont(font); } -void CentralWidget::createSearchWidget(QHelpSearchEngine *searchEngine) +void CentralWidget::updateUserInterface() { - TRACE_OBJ - if (m_searchWidget) - return; - - m_searchWidget = new SearchWidget(searchEngine, this); - connect(m_searchWidget, SIGNAL(requestShowLink(QUrl)), this, - SLOT(setSourceFromSearch(QUrl))); - connect(m_searchWidget, SIGNAL(requestShowLinkInNewTab(QUrl)), this, - SLOT(setSourceFromSearchInNewTab(QUrl))); - - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - m_searchWidget->setFont(!helpEngine.usesBrowserFont() ? qApp->font() - : helpEngine.browserFont()); + m_tabBar->setVisible(HelpEngineWrapper::instance().showTabs()); } -void CentralWidget::activateSearchWidget(bool updateLastTabPage) -{ - TRACE_OBJ - if (!m_searchWidget) - createSearchWidget(HelpEngineWrapper::instance().searchEngine()); - - if (!m_searchWidget->isAttached()) { - tabWidget->insertTab(0, m_searchWidget, tr("Search")); - m_searchWidget->setAttached(true); +// -- protected - if (updateLastTabPage) - lastTabPage++; - } - - tabWidget->setCurrentWidget(m_searchWidget); - m_searchWidget->setFocus(); -} - -void CentralWidget::removeSearchWidget() +void CentralWidget::keyPressEvent(QKeyEvent *e) { TRACE_OBJ - if (searchWidgetAttached()) { - tabWidget->removeTab(0); - m_searchWidget->setAttached(false); + const QString &text = e->text(); + if (text.startsWith(QLatin1Char('/'))) { + if (!m_findWidget->isVisible()) { + m_findWidget->showAndClear(); + } else { + m_findWidget->show(); + } + } else { + QWidget::keyPressEvent(e); } } -int CentralWidget::availableHelpViewer() const -{ - TRACE_OBJ - int count = tabWidget->count(); - if (searchWidgetAttached()) - count--; - return count; -} - -bool CentralWidget::enableTabCloseAction() const -{ - TRACE_OBJ - int minTabCount = 1; - if (searchWidgetAttached()) - minTabCount = 2; - - return (tabWidget->count() > minTabCount); -} - -QString CentralWidget::quoteTabTitle(const QString &title) const -{ - TRACE_OBJ - QString s = title; - return s.replace(QLatin1Char('&'), QLatin1String("&&")); -} - -void -CentralWidget::setSourceFromSearch(const QUrl &url) +void CentralWidget::focusInEvent(QFocusEvent * /* event */) { TRACE_OBJ - setSource(url); -#if defined(QT_NO_WEBKIT) - highlightSearchTerms(); -#else - connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, - SLOT(highlightSearchTerms())); -#endif + // If we have a current help viewer then this is the 'focus proxy', + // otherwise it's the central widget. This is needed, so an embedding + // program can just set the focus to the central widget and it does + // The Right Thing(TM) + QObject *receiver = m_stackedWidget; + if (HelpViewer *viewer = currentHelpViewer()) + receiver = viewer; + QTimer::singleShot(1, receiver, SLOT(setFocus())); } -void -CentralWidget::setSourceFromSearchInNewTab(const QUrl &url) -{ - TRACE_OBJ - setSourceInNewTab(url); -#if defined(QT_NO_WEBKIT) - highlightSearchTerms(); -#else - connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, - SLOT(highlightSearchTerms())); -#endif -} +// -- private slots -void -CentralWidget::highlightSearchTerms() +void CentralWidget::highlightSearchTerms() { TRACE_OBJ - HelpViewer *viewer = currentHelpViewer(); - if (!viewer) - return; - QHelpSearchEngine *searchEngine = HelpEngineWrapper::instance().searchEngine(); QList<QHelpSearchQuery> queryList = searchEngine->query(); @@ -1016,91 +564,73 @@ CentralWidget::highlightSearchTerms() } } -#if defined(QT_NO_WEBKIT) - viewer->viewport()->setUpdatesEnabled(false); - - QTextCharFormat marker; - marker.setForeground(Qt::red); - - QTextCursor firstHit; - - QTextCursor c = viewer->textCursor(); - c.beginEditBlock(); - foreach (const QString& term, terms) { - c.movePosition(QTextCursor::Start); - viewer->setTextCursor(c); - - while (viewer->find(term, QTextDocument::FindWholeWords)) { - QTextCursor hit = viewer->textCursor(); - if (firstHit.isNull() || hit.position() < firstHit.position()) - firstHit = hit; - - hit.mergeCharFormat(marker); - } - } - - if (firstHit.isNull()) { - firstHit = viewer->textCursor(); - firstHit.movePosition(QTextCursor::Start); - } - firstHit.clearSelection(); - c.endEditBlock(); - viewer->setTextCursor(firstHit); - - viewer->viewport()->setUpdatesEnabled(true); -#else - viewer->findText("", QWebPage::HighlightAllOccurrences); - // clears existing selections + HelpViewer *viewer = currentHelpViewer(); foreach (const QString& term, terms) - viewer->findText(term, QWebPage::HighlightAllOccurrences); - + viewer->findText(term, 0, false, true); disconnect(viewer, SIGNAL(loadFinished(bool)), this, SLOT(highlightSearchTerms())); +} + +void CentralWidget::printPreview(QPrinter *p) +{ + TRACE_OBJ +#ifndef QT_NO_PRINTER + currentHelpViewer()->print(p); #endif } +void CentralWidget::handleSourceChanged(const QUrl &url) +{ + TRACE_OBJ + if (sender() == currentHelpViewer()) + emit sourceChanged(url); +} -void CentralWidget::closeOrReloadTabs(const QList<int> &indices, bool tryReload) +// -- private + +void CentralWidget::initPrinter() { TRACE_OBJ - QList<int> sortedIndices = indices; - qSort(sortedIndices); - for (int i = sortedIndices.count(); --i >= 0;) { - const int tab = sortedIndices.at(i); - bool close = true; - if (tryReload) { - HelpViewer *viewer = - qobject_cast<HelpViewer*>(tabWidget->widget(tab)); - if (HelpEngineWrapper::instance().findFile(viewer->source()).isValid()) { - viewer->reload(); - close = false; - } - } - if (close) - closeTabAt(tab); - } - if (availableHelpViewer() == 0) - setSource(QUrl(QLatin1String("about:blank"))); +#ifndef QT_NO_PRINTER + if (!m_printer) + m_printer = new QPrinter(QPrinter::HighResolution); +#endif } -void CentralWidget::closeTabAt(int index) +void CentralWidget::connectSignals(HelpViewer *page) { TRACE_OBJ - HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(index)); - tabWidget->removeTab(index); - QTimer::singleShot(0, viewer, SLOT(deleteLater())); + connect(page, SIGNAL(copyAvailable(bool)), this, + SIGNAL(copyAvailable(bool))); + connect(page, SIGNAL(forwardAvailable(bool)), this, + SIGNAL(forwardAvailable(bool))); + connect(page, SIGNAL(backwardAvailable(bool)), this, + SIGNAL(backwardAvailable(bool))); + connect(page, SIGNAL(sourceChanged(QUrl)), this, + SLOT(handleSourceChanged(QUrl))); + connect(page, SIGNAL(highlighted(QString)), this, + SIGNAL(highlighted(QString))); + connect(page, SIGNAL(printRequested()), this, SLOT(print())); } -QMap<int, QString> CentralWidget::currentSourceFileList() const +bool CentralWidget::eventFilter(QObject *object, QEvent *e) { TRACE_OBJ - QMap<int, QString> sourceList; - for (int i = 0; i < tabWidget->count(); ++i) { - HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i)); - if (viewer && viewer->source().isValid()) - sourceList.insert(i, viewer->source().host()); + if (e->type() != QEvent::KeyPress) + return QWidget::eventFilter(object, e); + + HelpViewer *viewer = currentHelpViewer(); + QKeyEvent *keyEvent = static_cast<QKeyEvent*> (e); + if (viewer == object && keyEvent->key() == Qt::Key_Backspace) { + if (viewer->isBackwardAvailable()) { +#if !defined(QT_NO_WEBKIT) + // this helps in case there is an html <input> field + if (!viewer->hasFocus()) +#endif + viewer->backward(); + } } - return sourceList; + return QWidget::eventFilter(object, e); } QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/centralwidget.h b/tools/assistant/tools/assistant/centralwidget.h index bb400f6..dac92e3 100644 --- a/tools/assistant/tools/assistant/centralwidget.h +++ b/tools/assistant/tools/assistant/centralwidget.h @@ -38,80 +38,102 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #ifndef CENTRALWIDGET_H #define CENTRALWIDGET_H #include <QtCore/QUrl> + +#include <QtGui/QTabBar> #include <QtGui/QWidget> QT_BEGIN_NAMESPACE class FindWidget; class HelpViewer; -class MainWindow; -class QHelpSearchEngine; -class QTabWidget; -class SearchWidget; +class QStackedWidget; + +class TabBar : public QTabBar +{ + Q_OBJECT +public: + TabBar(QWidget *parent = 0); + ~TabBar(); + + int addNewTab(const QString &title); + void setCurrent(HelpViewer *viewer); + void removeTabAt(HelpViewer *viewer); + +public slots: + void titleChanged(); + +signals: + void currentTabChanged(HelpViewer *viewer); + void addBookmark(const QString &title, const QString &url); + +private slots: + void slotCurrentChanged(int index); + void slotTabCloseRequested(int index); + void slotCustomContextMenuRequested(const QPoint &pos); +}; class CentralWidget : public QWidget { Q_OBJECT public: - CentralWidget(MainWindow *parent); + CentralWidget(QWidget *parent = 0); ~CentralWidget(); - void setupWidget(); - bool hasSelection() const; + static CentralWidget *instance(); + QUrl currentSource() const; QString currentTitle() const; - bool isHomeAvailable() const; + + bool hasSelection() const; bool isForwardAvailable() const; bool isBackwardAvailable() const; - QList<QAction*> globalActions() const; - void setGlobalActions(const QList<QAction*> &actions); HelpViewer *viewerAt(int index) const; HelpViewer *currentHelpViewer() const; - bool searchWidgetAttached() const; - void createSearchWidget(QHelpSearchEngine *searchEngine); - void activateSearchWidget(bool updateLastTabPage = false); - void removeSearchWidget(); - - int availableHelpViewer() const; - bool enableTabCloseAction() const; + void addPage(HelpViewer *page, bool fromSearch = false); + void removePage(int index); - void closeOrReloadTabs(const QList<int> &indices, bool tryReload); - void closeTabAt(int index); - QMap<int, QString> currentSourceFileList() const; + int currentIndex() const; + void setCurrentPage(HelpViewer *page); - static CentralWidget *instance(); + void connectTabBar(); public slots: + void copy(); + void home(); + void zoomIn(); void zoomOut(); - void nextPage(); void resetZoom(); + + void forward(); + void nextPage(); + + void backward(); void previousPage(); - void copySelection(); - void showTextSearch(); + void print(); void pageSetup(); void printPreview(); - void updateBrowserFont(); - void setSource(const QUrl &url); - void setSourceInNewTab(const QUrl &url, qreal zoom = 0.0); - HelpViewer *newEmptyTab(); - void home(); - void forward(); - void backward(); - void activateTab(bool onlyHelpViewer = false); + void setSource(const QUrl &url); + void setSourceFromSearch(const QUrl &url); void findNext(); void findPrevious(); - void find(const QString &text, bool forward); + void find(const QString &text, bool forward, bool incremental); + + void activateTab(); + void showTextSearch(); + void updateBrowserFont(); + void updateUserInterface(); signals: void currentViewerChanged(); @@ -124,37 +146,25 @@ signals: protected: void keyPressEvent(QKeyEvent *); + void focusInEvent(QFocusEvent *event); private slots: - void newTab(); - void closeTab(); - void setTabTitle(const QUrl& url); - void currentPageChanged(int index); - void showTabBarContextMenu(const QPoint &point); - void printPreview(QPrinter *printer); - void setSourceFromSearch(const QUrl &url); - void setSourceFromSearchInNewTab(const QUrl &url); void highlightSearchTerms(); + void printPreview(QPrinter *printer); + void handleSourceChanged(const QUrl &url); private: - void connectSignals(); - bool eventFilter(QObject *object, QEvent *e); - bool findInWebPage(const QString &ttf, bool forward); - bool findInTextBrowser(const QString &ttf, bool forward); void initPrinter(); - QString quoteTabTitle(const QString &title) const; - void setLastShownPages(); + void connectSignals(HelpViewer *page); + bool eventFilter(QObject *object, QEvent *e); private: - int lastTabPage; - QList<QAction*> globalActionList; - - QTabWidget *tabWidget; - FindWidget *findWidget; - QPrinter *printer; - bool usesDefaultCollection; - - SearchWidget *m_searchWidget; +#ifndef QT_NO_PRINTER + QPrinter *m_printer; +#endif + FindWidget *m_findWidget; + QStackedWidget *m_stackedWidget; + TabBar *m_tabBar; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/contentwindow.cpp b/tools/assistant/tools/assistant/contentwindow.cpp index a5fbc04..e83cf90 100644 --- a/tools/assistant/tools/assistant/contentwindow.cpp +++ b/tools/assistant/tools/assistant/contentwindow.cpp @@ -38,12 +38,14 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" #include "contentwindow.h" + #include "centralwidget.h" #include "helpenginewrapper.h" #include "helpviewer.h" +#include "openpagesmanager.h" +#include "tracer.h" #include <QtGui/QLayout> #include <QtGui/QFocusEvent> @@ -146,8 +148,8 @@ bool ContentWindow::eventFilter(QObject *o, QEvent *e) qobject_cast<QHelpContentModel*>(m_contentWidget->model()); if (contentModel) { QHelpContentItem *itm = contentModel->contentItemAt(index); - if (itm && AbstractHelpViewer::canOpenPage(itm->url().path())) - CentralWidget::instance()->setSourceInNewTab(itm->url()); + if (itm && HelpViewer::canOpenPage(itm->url().path())) + OpenPagesManager::instance()->createPage(itm->url()); } } else if (button == Qt::LeftButton) { itemClicked(index); @@ -172,7 +174,7 @@ void ContentWindow::showContextMenu(const QPoint &pos) QMenu menu; QAction *curTab = menu.addAction(tr("Open Link")); QAction *newTab = menu.addAction(tr("Open Link in New Tab")); - if (!AbstractHelpViewer::canOpenPage(itm->url().path())) + if (!HelpViewer::canOpenPage(itm->url().path())) newTab->setEnabled(false); menu.move(m_contentWidget->mapToGlobal(pos)); @@ -181,7 +183,7 @@ void ContentWindow::showContextMenu(const QPoint &pos) if (curTab == action) emit linkActivated(itm->url()); else if (newTab == action) - CentralWidget::instance()->setSourceInNewTab(itm->url()); + OpenPagesManager::instance()->createPage(itm->url()); } void ContentWindow::itemClicked(const QModelIndex &index) diff --git a/tools/assistant/tools/assistant/contentwindow.h b/tools/assistant/tools/assistant/contentwindow.h index 495d079..2baf518 100644 --- a/tools/assistant/tools/assistant/contentwindow.h +++ b/tools/assistant/tools/assistant/contentwindow.h @@ -76,7 +76,6 @@ private: void focusInEvent(QFocusEvent *e); void keyPressEvent(QKeyEvent *e); bool eventFilter(QObject *o, QEvent *e); - bool isPdfFile(QHelpContentItem *item) const; QHelpContentWidget * const m_contentWidget; int m_expandDepth; diff --git a/tools/assistant/tools/assistant/doc/assistant.qdocconf b/tools/assistant/tools/assistant/doc/assistant.qdocconf index 45ad76a..4bd3842 100644 --- a/tools/assistant/tools/assistant/doc/assistant.qdocconf +++ b/tools/assistant/tools/assistant/doc/assistant.qdocconf @@ -12,5 +12,5 @@ HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ "<td width=\"30%\" align=\"left\">Copyright © 2011 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ "<td width=\"40%\" align=\"center\">Trademarks</td>\n" \ - "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.7.4</div></td>\n" \ + "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.8.0</div></td>\n" \ "</tr></table></div></address>" diff --git a/tools/assistant/tools/assistant/findwidget.cpp b/tools/assistant/tools/assistant/findwidget.cpp index dacd44a..5a6cc09 100644 --- a/tools/assistant/tools/assistant/findwidget.cpp +++ b/tools/assistant/tools/assistant/findwidget.cpp @@ -203,7 +203,7 @@ void FindWidget::updateButtons() void FindWidget::textChanged(const QString &text) { TRACE_OBJ - emit find(text, true); + emit find(text, true, true); } bool FindWidget::eventFilter(QObject *object, QEvent *e) diff --git a/tools/assistant/tools/assistant/findwidget.h b/tools/assistant/tools/assistant/findwidget.h index 58470d2..95c9e8f 100644 --- a/tools/assistant/tools/assistant/findwidget.h +++ b/tools/assistant/tools/assistant/findwidget.h @@ -67,11 +67,10 @@ public: void setTextWrappedVisible(bool visible); signals: - void escapePressed(); - void findNext(); void findPrevious(); - void find(const QString &text, bool forward); + void escapePressed(); + void find(const QString &text, bool forward, bool incremental); protected: void hideEvent(QHideEvent* event); diff --git a/tools/assistant/tools/assistant/globalactions.cpp b/tools/assistant/tools/assistant/globalactions.cpp new file mode 100644 index 0000000..fb1e4e4 --- /dev/null +++ b/tools/assistant/tools/assistant/globalactions.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "globalactions.h" + +#include "centralwidget.h" +#include "helpviewer.h" +#include "tracer.h" + +#include <QtGui/QAction> +#include <QtGui/QMenu> + +#if !defined(QT_NO_WEBKIT) +#include <QtWebKit/QWebHistory> +#endif + +GlobalActions *GlobalActions::instance(QObject *parent) +{ + Q_ASSERT(!m_instance != !parent); + if (!m_instance) + m_instance = new GlobalActions(parent); + return m_instance; +} + +GlobalActions::GlobalActions(QObject *parent) : QObject(parent) +{ + TRACE_OBJ + + // TODO: Put resource path in misc class + QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); +#ifdef Q_OS_MAC + resourcePath.append(QLatin1String("mac")); +#else + resourcePath.append(QLatin1String("win")); +#endif + CentralWidget *centralWidget = CentralWidget::instance(); + + m_backAction = new QAction(tr("&Back"), parent); + m_backAction->setEnabled(false); + m_backAction->setShortcuts(QKeySequence::Back); + m_backAction->setIcon(QIcon(resourcePath + QLatin1String("/previous.png"))); + connect(m_backAction, SIGNAL(triggered()), centralWidget, SLOT(backward())); + m_actionList << m_backAction; + + m_nextAction = new QAction(tr("&Forward"), parent); + m_nextAction->setPriority(QAction::LowPriority); + m_nextAction->setEnabled(false); + m_nextAction->setShortcuts(QKeySequence::Forward); + m_nextAction->setIcon(QIcon(resourcePath + QLatin1String("/next.png"))); + connect(m_nextAction, SIGNAL(triggered()), centralWidget, SLOT(forward())); + m_actionList << m_nextAction; + + setupNavigationMenus(m_backAction, m_nextAction, centralWidget); + + m_homeAction = new QAction(tr("&Home"), parent); + m_homeAction->setShortcut(tr("ALT+Home")); + m_homeAction->setIcon(QIcon(resourcePath + QLatin1String("/home.png"))); + connect(m_homeAction, SIGNAL(triggered()), centralWidget, SLOT(home())); + m_actionList << m_homeAction; + + QAction *separator = new QAction(parent); + separator->setSeparator(true); + m_actionList << separator; + + m_zoomInAction = new QAction(tr("Zoom &in"), parent); + m_zoomInAction->setPriority(QAction::LowPriority); + m_zoomInAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomin.png"))); + m_zoomInAction->setShortcut(QKeySequence::ZoomIn); + connect(m_zoomInAction, SIGNAL(triggered()), centralWidget, SLOT(zoomIn())); + m_actionList << m_zoomInAction; + + m_zoomOutAction = new QAction(tr("Zoom &out"), parent); + m_zoomOutAction->setPriority(QAction::LowPriority); + m_zoomOutAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomout.png"))); + m_zoomOutAction->setShortcut(QKeySequence::ZoomOut); + connect(m_zoomOutAction, SIGNAL(triggered()), centralWidget, SLOT(zoomOut())); + m_actionList << m_zoomOutAction; + + separator = new QAction(parent); + separator->setSeparator(true); + m_actionList << separator; + + m_copyAction = new QAction(tr("&Copy selected Text"), parent); + m_copyAction->setPriority(QAction::LowPriority); + m_copyAction->setIconText("&Copy"); + m_copyAction->setIcon(QIcon(resourcePath + QLatin1String("/editcopy.png"))); + m_copyAction->setShortcuts(QKeySequence::Copy); + m_copyAction->setEnabled(false); + connect(m_copyAction, SIGNAL(triggered()), centralWidget, SLOT(copy())); + m_actionList << m_copyAction; + + m_printAction = new QAction(tr("&Print..."), parent); + m_printAction->setPriority(QAction::LowPriority); + m_printAction->setIcon(QIcon(resourcePath + QLatin1String("/print.png"))); + m_printAction->setShortcut(QKeySequence::Print); + connect(m_printAction, SIGNAL(triggered()), centralWidget, SLOT(print())); + m_actionList << m_printAction; + + m_findAction = new QAction(tr("&Find in Text..."), parent); + m_findAction->setIconText(tr("&Find")); + m_findAction->setIcon(QIcon(resourcePath + QLatin1String("/find.png"))); + m_findAction->setShortcuts(QKeySequence::Find); + connect(m_findAction, SIGNAL(triggered()), centralWidget, SLOT(showTextSearch())); + m_actionList << m_findAction; + +#ifdef Q_WS_X11 + m_backAction->setIcon(QIcon::fromTheme("go-previous" , m_backAction->icon())); + m_nextAction->setIcon(QIcon::fromTheme("go-next" , m_nextAction->icon())); + m_zoomInAction->setIcon(QIcon::fromTheme("zoom-in" , m_zoomInAction->icon())); + m_zoomOutAction->setIcon(QIcon::fromTheme("zoom-out" , m_zoomOutAction->icon())); + m_copyAction->setIcon(QIcon::fromTheme("edit-copy" , m_copyAction->icon())); + m_findAction->setIcon(QIcon::fromTheme("edit-find" , m_findAction->icon())); + m_homeAction->setIcon(QIcon::fromTheme("go-home" , m_homeAction->icon())); + m_printAction->setIcon(QIcon::fromTheme("document-print" , m_printAction->icon())); +#endif +} + +void GlobalActions::updateActions() +{ + TRACE_OBJ + CentralWidget *centralWidget = CentralWidget::instance(); + m_copyAction->setEnabled(centralWidget->hasSelection()); + m_nextAction->setEnabled(centralWidget->isForwardAvailable()); + m_backAction->setEnabled(centralWidget->isBackwardAvailable()); +} + +void GlobalActions::setCopyAvailable(bool available) +{ + TRACE_OBJ + m_copyAction->setEnabled(available); +} + +#if !defined(QT_NO_WEBKIT) + +void GlobalActions::slotAboutToShowBackMenu() +{ + TRACE_OBJ + m_backMenu->clear(); + if (QWebHistory *history = CentralWidget::instance()->currentHelpViewer()->history()) { + const int currentItemIndex = history->currentItemIndex(); + QList<QWebHistoryItem> items = history->backItems(history->count()); + for (int i = items.count() - 1; i >= 0; --i) { + QAction *action = new QAction(this); + action->setText(items.at(i).title()); + action->setData(-1 * (currentItemIndex - i)); + m_backMenu->addAction(action); + } + } +} + +void GlobalActions::slotAboutToShowNextMenu() +{ + TRACE_OBJ + m_nextMenu->clear(); + if (QWebHistory *history = CentralWidget::instance()->currentHelpViewer()->history()) { + const int count = history->count(); + QList<QWebHistoryItem> items = history->forwardItems(count); + for (int i = 0; i < items.count(); ++i) { + QAction *action = new QAction(this); + action->setData(count - i); + action->setText(items.at(i).title()); + m_nextMenu->addAction(action); + } + } +} + +void GlobalActions::slotOpenActionUrl(QAction *action) +{ + TRACE_OBJ + if (HelpViewer* viewer = CentralWidget::instance()->currentHelpViewer()) { + const int offset = action->data().toInt(); + QWebHistory *history = viewer->history(); + if (offset > 0) { + history->goToItem(history->forwardItems(history->count() + - offset + 1).back()); // forward + } else if (offset < 0) { + history->goToItem(history->backItems(-1 * offset).first()); // back + } + } +} + +#endif + +void GlobalActions::setupNavigationMenus(QAction *back, QAction *next, + QWidget *parent) +{ +#if !defined(QT_NO_WEBKIT) + m_backMenu = new QMenu(parent); + connect(m_backMenu, SIGNAL(aboutToShow()), this, + SLOT(slotAboutToShowBackMenu())); + connect(m_backMenu, SIGNAL(triggered(QAction*)), this, + SLOT(slotOpenActionUrl(QAction*))); + back->setMenu(m_backMenu); + + m_nextMenu = new QMenu(parent); + connect(m_nextMenu, SIGNAL(aboutToShow()), this, + SLOT(slotAboutToShowNextMenu())); + connect(m_nextMenu, SIGNAL(triggered(QAction*)), this, + SLOT(slotOpenActionUrl(QAction*))); + next->setMenu(m_nextMenu); +#else + Q_UNUSED(back) + Q_UNUSED(next) + Q_UNUSED(parent) +#endif +} + +GlobalActions *GlobalActions::m_instance = 0; diff --git a/tools/qtconfig/mainwindowbase.h b/tools/assistant/tools/assistant/globalactions.h index f44246c..1613d85 100644 --- a/tools/qtconfig/mainwindowbase.h +++ b/tools/assistant/tools/assistant/globalactions.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the tools applications of the Qt Toolkit. +** This file is part of the Assistant module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage @@ -39,57 +39,67 @@ ** ****************************************************************************/ -#ifndef MAINWINDOWBASE_H -#define MAINWINDOWBASE_H +#ifndef GLOBALACTION_H +#define GLOBALACTION_H -#include "ui_mainwindowbase.h" -#include <QVariant> +#include <QtCore/QList> +#include <QtCore/QObject> QT_BEGIN_NAMESPACE -class ColorButton; -class PreviewFrame; +class QAction; +class QMenu; -class MainWindowBase : public Q3MainWindow, public Ui::MainWindowBase +class GlobalActions : public QObject { Q_OBJECT - + Q_DISABLE_COPY(GlobalActions) public: - MainWindowBase(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = Qt::Window); - ~MainWindowBase(); - -public slots: - virtual void addFontpath(); - virtual void addSubstitute(); - virtual void browseFontpath(); - virtual void buildFont(); - virtual void buildPalette(); - virtual void downFontpath(); - virtual void downSubstitute(); - virtual void familySelected( const QString & ); - virtual void fileExit(); - virtual void fileSave(); - virtual void helpAbout(); - virtual void helpAboutQt(); - virtual void new_slot(); - virtual void pageChanged( QWidget * ); - virtual void paletteSelected( int ); - virtual void removeFontpath(); - virtual void removeSubstitute(); - virtual void somethingModified(); - virtual void styleSelected( const QString & ); - virtual void substituteSelected( const QString & ); - virtual void tunePalette(); - virtual void upFontpath(); - virtual void upSubstitute(); - -protected slots: - virtual void languageChange(); - - virtual void init(); - virtual void destroy(); + static GlobalActions *instance(QObject *parent = 0); + + QList<QAction *> actionList() const { return m_actionList; } + QAction *backAction() const { return m_backAction; } + QAction *nextAction() const { return m_nextAction; } + QAction *homeAction() const { return m_homeAction; } + QAction *zoomInAction() const { return m_zoomInAction; } + QAction *zoomOutAction() const { return m_zoomOutAction; } + QAction *copyAction() const { return m_copyAction; } + QAction *printAction() const { return m_printAction; } + QAction *findAction() const { return m_findAction; } + + Q_SLOT void updateActions(); + Q_SLOT void setCopyAvailable(bool available); + +#if !defined(QT_NO_WEBKIT) +private slots: + void slotAboutToShowBackMenu(); + void slotAboutToShowNextMenu(); + void slotOpenActionUrl(QAction *action); +#endif + +private: + void setupNavigationMenus(QAction *back, QAction *next, QWidget *parent); + +private: + GlobalActions(QObject *parent); + + static GlobalActions *m_instance; + + QAction *m_backAction; + QAction *m_nextAction; + QAction *m_homeAction; + QAction *m_zoomInAction; + QAction *m_zoomOutAction; + QAction *m_copyAction; + QAction *m_printAction; + QAction *m_findAction; + + QList<QAction *> m_actionList; + + QMenu *m_backMenu; + QMenu *m_nextMenu; }; QT_END_NAMESPACE -#endif // MAINWINDOWBASE_H +#endif // GLOBALACTION_H diff --git a/tools/assistant/tools/assistant/helpenginewrapper.cpp b/tools/assistant/tools/assistant/helpenginewrapper.cpp index 0ca4c56..6c32d7b 100644 --- a/tools/assistant/tools/assistant/helpenginewrapper.cpp +++ b/tools/assistant/tools/assistant/helpenginewrapper.cpp @@ -72,6 +72,7 @@ namespace { const QString UseBrowserFontKey(QLatin1String("useBrowserFont")); const QString VersionKey(QString(QLatin1String("qtVersion%1$$$%2")). arg(QLatin1String(QT_VERSION_STR))); + const QString ShowTabsKey(QLatin1String("showTabs")); } // anonymous namespace class TimeoutForwarder : public QObject @@ -147,7 +148,7 @@ HelpEngineWrapper::HelpEngineWrapper(const QString &collectionFile) * because we will start to index them, only to be interrupted * by the next request. Also, there is a nasty SQLITE bug that will * cause the application to hang for minutes in that case. - * This call is reverted by initalDocSetupDone(), which must be + * This call is reverted by initialDocSetupDone(), which must be * called after the new docs have been installed. */ disconnect(d->m_helpEngine, SIGNAL(setupFinished()), @@ -569,18 +570,6 @@ void HelpEngineWrapper::setLastTabPage(int lastPage) CollectionConfiguration::setLastTabPage(*d->m_helpEngine, lastPage); } -bool HelpEngineWrapper::searchWasAttached() const -{ - TRACE_OBJ - return d->m_helpEngine->customValue(SearchWasAttachedKey).toBool(); -} - -void HelpEngineWrapper::setSearchWasAttached(bool attached) -{ - TRACE_OBJ - d->m_helpEngine->setCustomValue(SearchWasAttachedKey, attached); -} - int HelpEngineWrapper::startOption() const { TRACE_OBJ @@ -655,7 +644,7 @@ void HelpEngineWrapper::setUseBrowserFont(bool useBrowserFont) const QFont HelpEngineWrapper::appFont() const { TRACE_OBJ - return qVariantValue<QFont>(d->m_helpEngine->customValue(AppFontKey)); + return qvariant_cast<QFont>(d->m_helpEngine->customValue(AppFontKey)); } void HelpEngineWrapper::setAppFont(const QFont &font) @@ -680,7 +669,7 @@ void HelpEngineWrapper::setAppWritingSystem(QFontDatabase::WritingSystem system) const QFont HelpEngineWrapper::browserFont() const { TRACE_OBJ - return qVariantValue<QFont>(d->m_helpEngine->customValue(BrowserFontKey)); + return qvariant_cast<QFont>(d->m_helpEngine->customValue(BrowserFontKey)); } void HelpEngineWrapper::setBrowserFont(const QFont &font) @@ -704,11 +693,31 @@ void HelpEngineWrapper::setBrowserWritingSystem(QFontDatabase::WritingSystem sys void HelpEngineWrapper::handleCurrentFilterChanged(const QString &filter) { + TRACE_OBJ const QString &filterToReport = filter == Unfiltered ? TrUnfiltered : filter; emit currentFilterChanged(filterToReport); } +bool HelpEngineWrapper::showTabs() const +{ + TRACE_OBJ + return d->m_helpEngine->customValue(ShowTabsKey, false).toBool(); +} + +void HelpEngineWrapper::setShowTabs(bool show) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(ShowTabsKey, show); +} + +bool HelpEngineWrapper::fullTextSearchFallbackEnabled() const +{ + TRACE_OBJ + return CollectionConfiguration::fullTextSearchFallbackEnabled(*d->m_helpEngine); +} + +// -- TimeoutForwarder TimeoutForwarder::TimeoutForwarder(const QString &fileName) : m_fileName(fileName) @@ -722,6 +731,7 @@ void TimeoutForwarder::forward() HelpEngineWrapper::instance().d->qchFileChanged(m_fileName, true); } +// -- HelpEngineWrapperPrivate HelpEngineWrapperPrivate::HelpEngineWrapperPrivate(const QString &collectionFile) : m_helpEngine(new QHelpEngine(collectionFile, this)), @@ -829,7 +839,6 @@ void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName, m_recentQchUpdates.erase(it); } - QT_END_NAMESPACE #include "helpenginewrapper.moc" diff --git a/tools/assistant/tools/assistant/helpenginewrapper.h b/tools/assistant/tools/assistant/helpenginewrapper.h index 4054e98..fee18e0 100644 --- a/tools/assistant/tools/assistant/helpenginewrapper.h +++ b/tools/assistant/tools/assistant/helpenginewrapper.h @@ -170,9 +170,6 @@ public: int startOption() const; void setStartOption(int option); - bool searchWasAttached() const; - void setSearchWasAttached(bool attached); - bool hasFontSettings() const; bool usesAppFont() const; void setUseAppFont(bool useAppFont); @@ -187,8 +184,13 @@ public: QFontDatabase::WritingSystem browserWritingSystem() const; void setBrowserWritingSystem(QFontDatabase::WritingSystem system); + bool showTabs() const; + void setShowTabs(bool show); + static const QString TrUnfiltered; + bool fullTextSearchFallbackEnabled() const; + signals: // For asynchronous doc updates triggered by external actions. diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp index 1f7d394..c6aef1e 100644 --- a/tools/assistant/tools/assistant/helpviewer.cpp +++ b/tools/assistant/tools/assistant/helpviewer.cpp @@ -38,7 +38,10 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "helpviewer.h" +#include "helpviewer_p.h" + #include "helpenginewrapper.h" #include "tracer.h" @@ -49,18 +52,21 @@ #include <QtCore/QUrl> #include <QtGui/QDesktopServices> +#include <QtGui/QMouseEvent> + +#include <QtHelp/QHelpEngineCore> QT_BEGIN_NAMESPACE -const QLatin1String AbstractHelpViewer::DocPath("qthelp://com.trolltech."); +const QString HelpViewer::DocPath = QLatin1String("qthelp://com.trolltech."); -const QString AbstractHelpViewer::AboutBlank = +const QString HelpViewer::AboutBlank = QCoreApplication::translate("HelpViewer", "<title>about:blank</title>"); -const QString AbstractHelpViewer::LocalHelpFile = QLatin1String("qthelp://" +const QString HelpViewer::LocalHelpFile = QLatin1String("qthelp://" "com.trolltech.com.assistantinternal-1.0.0/assistant/assistant.html"); -const QString AbstractHelpViewer::PageNotFoundMessage = +const QString HelpViewer::PageNotFoundMessage = QCoreApplication::translate("HelpViewer", "<title>Error 404...</title><div " "align=\"center\"><br><br><h1>The page could not be found</h1><br><h3>'%1'" "</h3></div>"); @@ -102,17 +108,13 @@ struct ExtensionMap { { 0, 0 } }; -// -- AbstractHelpViewer - -AbstractHelpViewer::AbstractHelpViewer() -{ -} - -AbstractHelpViewer::~AbstractHelpViewer() +HelpViewer::~HelpViewer() { + TRACE_OBJ + delete d; } -bool AbstractHelpViewer::isLocalUrl(const QUrl &url) +bool HelpViewer::isLocalUrl(const QUrl &url) { TRACE_OBJ const QString &scheme = url.scheme(); @@ -124,13 +126,13 @@ bool AbstractHelpViewer::isLocalUrl(const QUrl &url) || scheme == QLatin1String("about"); } -bool AbstractHelpViewer::canOpenPage(const QString &url) +bool HelpViewer::canOpenPage(const QString &url) { TRACE_OBJ return !mimeFromUrl(url).isEmpty(); } -QString AbstractHelpViewer::mimeFromUrl(const QUrl &url) +QString HelpViewer::mimeFromUrl(const QUrl &url) { TRACE_OBJ const QString &path = url.path(); @@ -146,7 +148,7 @@ QString AbstractHelpViewer::mimeFromUrl(const QUrl &url) return QLatin1String(""); } -bool AbstractHelpViewer::launchWithExternalApp(const QUrl &url) +bool HelpViewer::launchWithExternalApp(const QUrl &url) { TRACE_OBJ if (isLocalUrl(url)) { @@ -177,4 +179,43 @@ bool AbstractHelpViewer::launchWithExternalApp(const QUrl &url) return false; } +// -- public slots + +void HelpViewer::home() +{ + TRACE_OBJ + setSource(HelpEngineWrapper::instance().homePage()); +} + +// -- private slots + +void HelpViewer::setLoadStarted() +{ + d->m_loadFinished = false; +} + +void HelpViewer::setLoadFinished(bool ok) +{ + d->m_loadFinished = ok; + emit sourceChanged(source()); +} + +// -- private + +bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *event) +{ + TRACE_OBJ + if (event->button() == Qt::XButton1) { + backward(); + return true; + } + + if (event->button() == Qt::XButton2) { + forward(); + return true; + } + + return false; +} + QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer.h b/tools/assistant/tools/assistant/helpviewer.h index 5b7fffb..784ba308 100644 --- a/tools/assistant/tools/assistant/helpviewer.h +++ b/tools/assistant/tools/assistant/helpviewer.h @@ -38,36 +38,69 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #ifndef HELPVIEWER_H #define HELPVIEWER_H +#include <QtCore/qglobal.h> #include <QtCore/QString> +#include <QtCore/QUrl> +#include <QtCore/QVariant> +#include <QtGui/QAction> #include <QtGui/QFont> -QT_BEGIN_NAMESPACE +#if defined(QT_NO_WEBKIT) +#include <QtGui/QTextBrowser> +#else +#include <QtWebKit/QWebView> +#endif -class QMouseEvent; -class QUrl; +QT_BEGIN_NAMESPACE -class AbstractHelpViewer +#if !defined(QT_NO_WEBKIT) +class HelpViewer : public QWebView +#else +class HelpViewer : public QTextBrowser +#endif { + Q_OBJECT + class HelpViewerPrivate; + Q_DISABLE_COPY(HelpViewer) + public: - AbstractHelpViewer(); - virtual ~AbstractHelpViewer(); + enum FindFlag { + FindBackward = 0x01, + FindCaseSensitively = 0x02 + }; + Q_DECLARE_FLAGS(FindFlags, FindFlag) + + HelpViewer(qreal zoom, QWidget *parent = 0); + ~HelpViewer(); + + QFont viewerFont() const; + void setViewerFont(const QFont &font); + + void scaleUp(); + void scaleDown(); + + void resetScale(); + qreal scale() const; - virtual QFont viewerFont() const = 0; - virtual void setViewerFont(const QFont &font) = 0; + QString title() const; + void setTitle(const QString &title); - virtual void scaleUp() = 0; - virtual void scaleDown() = 0; - - virtual void resetScale() = 0; - virtual qreal scale() const = 0; + QUrl source() const; + void setSource(const QUrl &url); - virtual bool handleForwardBackwardMouseButtons(QMouseEvent *e) = 0; + QString selectedText() const; + bool isForwardAvailable() const; + bool isBackwardAvailable() const; - static const QLatin1String DocPath; + bool findText(const QString &text, FindFlags flags, bool incremental, + bool fromSearch); + + static const QString DocPath; static const QString AboutBlank; static const QString LocalHelpFile; static const QString PageNotFoundMessage; @@ -76,8 +109,50 @@ public: static bool canOpenPage(const QString &url); static QString mimeFromUrl(const QUrl &url); static bool launchWithExternalApp(const QUrl &url); + +public slots: + void copy(); + void home(); + + void forward(); + void backward(); + +signals: + void titleChanged(); +#if !defined(QT_NO_WEBKIT) + void copyAvailable(bool yes); + void sourceChanged(const QUrl &url); + void forwardAvailable(bool enabled); + void backwardAvailable(bool enabled); + void highlighted(const QString &link); + void printRequested(); +#else + void loadStarted(); + void loadFinished(bool finished); +#endif + +protected: + void keyPressEvent(QKeyEvent *e); + void wheelEvent(QWheelEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private slots: + void actionChanged(); + void setLoadStarted(); + void setLoadFinished(bool ok); + +private: + bool eventFilter(QObject *obj, QEvent *event); + void contextMenuEvent(QContextMenuEvent *event); + QVariant loadResource(int type, const QUrl &name); + bool handleForwardBackwardMouseButtons(QMouseEvent *e); + +private: + HelpViewerPrivate *d; }; QT_END_NAMESPACE +Q_DECLARE_METATYPE(HelpViewer*) #endif // HELPVIEWER_H diff --git a/tools/assistant/tools/assistant/helpviewer_qtb.h b/tools/assistant/tools/assistant/helpviewer_p.h index 6778763..a001b19 100644 --- a/tools/assistant/tools/assistant/helpviewer_qtb.h +++ b/tools/assistant/tools/assistant/helpviewer_p.h @@ -38,76 +38,86 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef HELPVIEWERQTB_H -#define HELPVIEWERQTB_H -#include "helpviewer.h" +#ifndef HELPVIEWERPRIVATE_H +#define HELPVIEWERPRIVATE_H -#include <QtCore/QUrl> -#include <QtCore/QVariant> +#include "centralwidget.h" +#include "helpviewer.h" +#include "openpagesmanager.h" +#include <QtCore/QObject> +#ifdef QT_NO_WEBKIT #include <QtGui/QTextBrowser> +#endif QT_BEGIN_NAMESPACE -class CentralWidget; -class HelpEngineWrapper; -class QContextMenuEvent; -class QKeyEvent; -class QMouseEvent; - -class HelpViewer : public QTextBrowser, public AbstractHelpViewer +class HelpViewer::HelpViewerPrivate : public QObject { Q_OBJECT public: - explicit HelpViewer(CentralWidget *parent, qreal zoom = 0.0); - ~HelpViewer(); - - QFont viewerFont() const; - void setViewerFont(const QFont &font); - - void scaleUp(); - void scaleDown(); - void resetScale(); - qreal scale() const { return zoomCount; } - - bool handleForwardBackwardMouseButtons(QMouseEvent *e); - - void setSource(const QUrl &url); - - inline bool hasSelection() const - { return textCursor().hasSelection(); } +#ifdef QT_NO_WEBKIT + HelpViewerPrivate(int zoom) + : zoomCount(zoom) + , forceFont(false) + , lastAnchor(QString()) +#else + HelpViewerPrivate() +#endif + { + m_loadFinished = false; + } + +#ifdef QT_NO_WEBKIT + bool hasAnchorAt(QTextBrowser *browser, const QPoint& pos) + { + lastAnchor = browser->anchorAt(pos); + if (lastAnchor.isEmpty()) + return false; + + lastAnchor = browser->source().resolved(lastAnchor).toString(); + if (lastAnchor.at(0) == QLatin1Char('#')) { + QString src = browser->source().toString(); + int hsh = src.indexOf(QLatin1Char('#')); + lastAnchor = (hsh >= 0 ? src.left(hsh) : src) + lastAnchor; + } + return true; + } + + void openLink(bool newPage) + { + if(lastAnchor.isEmpty()) + return; + if (newPage) + OpenPagesManager::instance()->createPage(lastAnchor); + else + CentralWidget::instance()->setSource(lastAnchor); + lastAnchor.clear(); + } + +public slots: + void openLink() + { + openLink(false); + } + + void openLinkInNewPage() + { + openLink(true); + } -public Q_SLOTS: - void home(); - -protected: - void wheelEvent(QWheelEvent *e); - bool eventFilter(QObject *obj, QEvent *event); - -private: - QVariant loadResource(int type, const QUrl &name); - void openLinkInNewTab(const QString &link); - bool hasAnchorAt(const QPoint& pos); - void contextMenuEvent(QContextMenuEvent *e); - void mouseReleaseEvent(QMouseEvent *e); - void keyPressEvent(QKeyEvent *e); - void mousePressEvent(QMouseEvent *e); - -private slots: - void openLinkInNewTab(); - -private: +public: int zoomCount; - bool controlPressed; + bool forceFont; QString lastAnchor; - CentralWidget* parentWidget; - HelpEngineWrapper &helpEngine; +#endif // QT_NO_WEBKIT - bool forceFont; +public: + bool m_loadFinished; }; QT_END_NAMESPACE -#endif // HELPVIEWERQTB_H +#endif // HELPVIEWERPRIVATE_H diff --git a/tools/assistant/tools/assistant/helpviewer_qtb.cpp b/tools/assistant/tools/assistant/helpviewer_qtb.cpp index be2c95a..93e8079 100644 --- a/tools/assistant/tools/assistant/helpviewer_qtb.cpp +++ b/tools/assistant/tools/assistant/helpviewer_qtb.cpp @@ -38,10 +38,13 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "helpviewer_qtb.h" -#include "centralwidget.h" +#include "helpviewer.h" + +#include "globalactions.h" #include "helpenginewrapper.h" +#include "helpviewer_p.h" +#include "openpagesmanager.h" #include "tracer.h" #include <QtCore/QStringBuilder> @@ -53,34 +56,34 @@ QT_BEGIN_NAMESPACE -HelpViewer::HelpViewer(CentralWidget *parent, qreal zoom) +HelpViewer::HelpViewer(qreal zoom, QWidget *parent) : QTextBrowser(parent) - , zoomCount(zoom) - , controlPressed(false) - , lastAnchor(QString()) - , parentWidget(parent) - , helpEngine(HelpEngineWrapper::instance()) - , forceFont(false) + , d(new HelpViewerPrivate(zoom)) { TRACE_OBJ + QPalette p = palette(); + p.setColor(QPalette::Inactive, QPalette::Highlight, + p.color(QPalette::Active, QPalette::Highlight)); + p.setColor(QPalette::Inactive, QPalette::HighlightedText, + p.color(QPalette::Active, QPalette::HighlightedText)); + setPalette(p); + installEventFilter(this); document()->setDocumentMargin(8); QFont font = viewerFont(); font.setPointSize(int(font.pointSize() + zoom)); setViewerFont(font); -} -HelpViewer::~HelpViewer() -{ - TRACE_OBJ + connect(this, SIGNAL(sourceChanged(QUrl)), this, SIGNAL(titleChanged())); + connect(this, SIGNAL(loadFinished(bool)), this, SLOT(setLoadFinished(bool))); } QFont HelpViewer::viewerFont() const { TRACE_OBJ if (HelpEngineWrapper::instance().usesBrowserFont()) - return helpEngine.browserFont(); + return HelpEngineWrapper::instance().browserFont(); return qApp->font(); } @@ -88,185 +91,183 @@ void HelpViewer::setViewerFont(const QFont &newFont) { TRACE_OBJ if (font() != newFont) { - forceFont = true; + d->forceFont = true; setFont(newFont); - forceFont = false; + d->forceFont = false; } } void HelpViewer::scaleUp() { TRACE_OBJ - if (zoomCount < 10) { - ++zoomCount; - forceFont = true; + if (d->zoomCount < 10) { + d->zoomCount++; + d->forceFont = true; zoomIn(); - forceFont = false; + d->forceFont = false; } } void HelpViewer::scaleDown() { TRACE_OBJ - if (zoomCount > -5) { - --zoomCount; - forceFont = true; + if (d->zoomCount > -5) { + d->zoomCount--; + d->forceFont = true; zoomOut(); - forceFont = false; + d->forceFont = false; } } void HelpViewer::resetScale() { TRACE_OBJ - if (zoomCount != 0) { - forceFont = true; - zoomOut(zoomCount); - forceFont = false; + if (d->zoomCount != 0) { + d->forceFont = true; + zoomOut(d->zoomCount); + d->forceFont = false; } - zoomCount = 0; + d->zoomCount = 0; } -bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *e) +qreal HelpViewer::scale() const { - if (e->button() == Qt::XButton1) { - QTextBrowser::backward(); - return true; - } + TRACE_OBJ + return d->zoomCount; +} - if (e->button() == Qt::XButton2) { - QTextBrowser::forward(); - return true; - } - return false; +QString HelpViewer::title() const +{ + TRACE_OBJ + return documentTitle(); +} + +void HelpViewer::setTitle(const QString &title) +{ + TRACE_OBJ + setDocumentTitle(title); +} + +QUrl HelpViewer::source() const +{ + TRACE_OBJ + return QTextBrowser::source(); } void HelpViewer::setSource(const QUrl &url) { TRACE_OBJ - const QString &string = url.toString(); - if (url.isValid() && string != QLatin1String("help")) { - if (launchWithExternalApp(url)) - return; - - const QUrl &resolvedUrl = helpEngine.findFile(url); - if (resolvedUrl.isValid()) { - QTextBrowser::setSource(resolvedUrl); - return; - } - } + if (launchWithExternalApp(url)) + return; - if (string != QLatin1String("help")) { - QTextBrowser::setSource(url); + emit loadStarted(); + QString string = url.toString(); + const HelpEngineWrapper &engine = HelpEngineWrapper::instance(); + const QUrl &resolvedUrl = (string == QLatin1String("help") ? LocalHelpFile : + engine.findFile(string)); + QTextBrowser::setSource(resolvedUrl); + if (!url.isValid()) { setHtml(string == QLatin1String("about:blank") ? AboutBlank : PageNotFoundMessage.arg(url.toString())); - emit sourceChanged(url); - } else { - QTextBrowser::setSource(LocalHelpFile); } + emit loadFinished(true); } -QVariant HelpViewer::loadResource(int type, const QUrl &name) +QString HelpViewer::selectedText() const { TRACE_OBJ - QByteArray ba; - if (type < 4) { - ba = helpEngine.fileData(name); - if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) { - QImage image; - image.loadFromData(ba, "svg"); - if (!image.isNull()) - return image; - } - } - return ba; + return textCursor().selectedText(); } -void HelpViewer::openLinkInNewTab() +bool HelpViewer::isForwardAvailable() const { TRACE_OBJ - if(lastAnchor.isEmpty()) - return; - - parentWidget->setSourceInNewTab(QUrl(lastAnchor)); - lastAnchor.clear(); + return QTextBrowser::isForwardAvailable(); } -void HelpViewer::openLinkInNewTab(const QString &link) +bool HelpViewer::isBackwardAvailable() const { TRACE_OBJ - lastAnchor = link; - openLinkInNewTab(); + return QTextBrowser::isBackwardAvailable(); } -bool HelpViewer::hasAnchorAt(const QPoint& pos) +bool HelpViewer::findText(const QString &text, FindFlags flags, bool incremental, + bool fromSearch) { TRACE_OBJ - lastAnchor = anchorAt(pos); - if (lastAnchor.isEmpty()) + QTextDocument *doc = document(); + QTextCursor cursor = textCursor(); + if (!doc || cursor.isNull()) return false; - lastAnchor = source().resolved(lastAnchor).toString(); - if (lastAnchor.at(0) == QLatin1Char('#')) { - QString src = source().toString(); - int hsh = src.indexOf(QLatin1Char('#')); - lastAnchor = (hsh>=0 ? src.left(hsh) : src) + lastAnchor; + const int position = cursor.selectionStart(); + if (incremental) + cursor.setPosition(position); + + QTextDocument::FindFlags textDocFlags; + if (flags & HelpViewer::FindBackward) + textDocFlags |= QTextDocument::FindBackward; + if (flags & HelpViewer::FindCaseSensitively) + textDocFlags |= QTextDocument::FindCaseSensitively; + + QTextCursor found = doc->find(text, cursor, textDocFlags); + if (found.isNull()) { + if ((flags & HelpViewer::FindBackward) == 0) + cursor.movePosition(QTextCursor::Start); + else + cursor.movePosition(QTextCursor::End); + found = doc->find(text, cursor, textDocFlags); } - return true; -} + if (fromSearch) { + cursor.beginEditBlock(); + viewport()->setUpdatesEnabled(false); -void HelpViewer::contextMenuEvent(QContextMenuEvent *e) -{ - TRACE_OBJ - QMenu menu(QLatin1String(""), 0); + QTextCharFormat marker; + marker.setForeground(Qt::red); + cursor.movePosition(QTextCursor::Start); + setTextCursor(cursor); - QUrl link; - QAction *copyAnchorAction = 0; - if (hasAnchorAt(e->pos())) { - link = anchorAt(e->pos()); - if (link.isRelative()) - link = source().resolved(link); - copyAnchorAction = menu.addAction(tr("Copy &Link Location")); - copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid()); + while (find(text)) { + QTextCursor hit = textCursor(); + hit.mergeCharFormat(marker); + } - menu.addAction(tr("Open Link in New Tab\tCtrl+LMB"), this, - SLOT(openLinkInNewTab())); - menu.addSeparator(); + viewport()->setUpdatesEnabled(true); + cursor.endEditBlock(); } - menu.addActions(parentWidget->globalActions()); - QAction *action = menu.exec(e->globalPos()); - if (action == copyAnchorAction) - QApplication::clipboard()->setText(link.toString()); + + bool cursorIsNull = found.isNull(); + if (cursorIsNull) { + found = textCursor(); + found.setPosition(position); + } + setTextCursor(found); + return !cursorIsNull; } -void HelpViewer::mouseReleaseEvent(QMouseEvent *e) +// -- public slots + +void HelpViewer::copy() { TRACE_OBJ -#ifndef Q_OS_LINUX - if (handleForwardBackwardMouseButtons(e)) - return; -#endif - - controlPressed = e->modifiers() & Qt::ControlModifier; - if ((controlPressed && hasAnchorAt(e->pos())) || - (e->button() == Qt::MidButton && hasAnchorAt(e->pos()))) { - openLinkInNewTab(); - return; - } + QTextBrowser::copy(); +} - QTextBrowser::mouseReleaseEvent(e); +void HelpViewer::forward() +{ + TRACE_OBJ + QTextBrowser::forward(); } -void HelpViewer::mousePressEvent(QMouseEvent *e) +void HelpViewer::backward() { -#ifdef Q_OS_LINUX - if (handleForwardBackwardMouseButtons(e)) - return; -#endif - QTextBrowser::mousePressEvent(e); + TRACE_OBJ + QTextBrowser::backward(); } +// -- protected + void HelpViewer::keyPressEvent(QKeyEvent *e) { TRACE_OBJ @@ -279,11 +280,6 @@ void HelpViewer::keyPressEvent(QKeyEvent *e) QTextBrowser::keyPressEvent(e); } -void HelpViewer::home() -{ - TRACE_OBJ - setSource(helpEngine.homePage()); -} void HelpViewer::wheelEvent(QWheelEvent *e) { @@ -296,12 +292,93 @@ void HelpViewer::wheelEvent(QWheelEvent *e) } } +void HelpViewer::mousePressEvent(QMouseEvent *e) +{ + TRACE_OBJ +#ifdef Q_OS_LINUX + if (handleForwardBackwardMouseButtons(e)) + return; +#endif + + QTextBrowser::mousePressEvent(e); +} + +void HelpViewer::mouseReleaseEvent(QMouseEvent *e) +{ + TRACE_OBJ +#ifndef Q_OS_LINUX + if (handleForwardBackwardMouseButtons(e)) + return; +#endif + + bool controlPressed = e->modifiers() & Qt::ControlModifier; + if ((controlPressed && d->hasAnchorAt(this, e->pos())) || + (e->button() == Qt::MidButton && d->hasAnchorAt(this, e->pos()))) { + d->openLinkInNewPage(); + return; + } + + QTextBrowser::mouseReleaseEvent(e); +} + +// -- private slots + +void HelpViewer::actionChanged() +{ + // stub + TRACE_OBJ +} + +// -- private + bool HelpViewer::eventFilter(QObject *obj, QEvent *event) { TRACE_OBJ - if (event->type() == QEvent::FontChange && !forceFont) + if (event->type() == QEvent::FontChange && !d->forceFont) return true; return QTextBrowser::eventFilter(obj, event); } +void HelpViewer::contextMenuEvent(QContextMenuEvent *event) +{ + TRACE_OBJ + + QMenu menu(QString(), 0); + QUrl link; + QAction *copyAnchorAction = 0; + if (d->hasAnchorAt(this, event->pos())) { + link = anchorAt(event->pos()); + if (link.isRelative()) + link = source().resolved(link); + menu.addAction(tr("Open Link"), d, SLOT(openLink())); + menu.addAction(tr("Open Link in New Tab\tCtrl+LMB"), d, SLOT(openLinkInNewPage())); + + if (!link.isEmpty() && link.isValid()) + copyAnchorAction = menu.addAction(tr("Copy &Link Location")); + } else if (!selectedText().isEmpty()) { + menu.addAction(tr("Copy"), this, SLOT(copy())); + } else { + menu.addAction(tr("Reload"), this, SLOT(reload())); + } + + if (copyAnchorAction == menu.exec(event->globalPos())) + QApplication::clipboard()->setText(link.toString()); +} + +QVariant HelpViewer::loadResource(int type, const QUrl &name) +{ + TRACE_OBJ + QByteArray ba; + if (type < 4) { + ba = HelpEngineWrapper::instance().fileData(name); + if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) { + QImage image; + image.loadFromData(ba, "svg"); + if (!image.isNull()) + return image; + } + } + return ba; +} + QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer_qwv.cpp b/tools/assistant/tools/assistant/helpviewer_qwv.cpp index 4ead873..193b013 100644 --- a/tools/assistant/tools/assistant/helpviewer_qwv.cpp +++ b/tools/assistant/tools/assistant/helpviewer_qwv.cpp @@ -39,25 +39,31 @@ ** ****************************************************************************/ -#include "helpviewer_qwv.h" +#include "helpviewer.h" +#include "helpviewer_p.h" #include "centralwidget.h" #include "helpenginewrapper.h" +#include "openpagesmanager.h" #include "tracer.h" #include <QtCore/QFileInfo> #include <QtCore/QString> -#include <QtCore/QStringBuilder> #include <QtCore/QTimer> +#include <QtGui/QApplication> #include <QtGui/QWheelEvent> +#include <QtHelp/QHelpEngineCore> + #include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkRequest> QT_BEGIN_NAMESPACE +// -- HelpNetworkReply + class HelpNetworkReply : public QNetworkReply { public: @@ -109,6 +115,8 @@ qint64 HelpNetworkReply::readData(char *buffer, qint64 maxlen) return len; } +// -- HelpNetworkAccessManager + class HelpNetworkAccessManager : public QNetworkAccessManager { public: @@ -130,15 +138,14 @@ QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/, { TRACE_OBJ QString url = request.url().toString(); - HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - + const HelpEngineWrapper &engine = HelpEngineWrapper::instance(); // TODO: For some reason the url to load is already wrong (passed from webkit) // though the css file and the references inside should work that way. One // possible problem might be that the css is loaded at the same level as the // html, thus a path inside the css like (../images/foo.png) might cd out of // the virtual folder - if (!helpEngine.findFile(url).isValid()) { - if (url.startsWith(AbstractHelpViewer::DocPath)) { + if (!engine.findFile(url).isValid()) { + if (url.startsWith(HelpViewer::DocPath)) { QUrl newUrl = request.url(); if (!newUrl.path().startsWith(QLatin1String("/qdoc/"))) { newUrl.setPath(QLatin1String("qdoc") + newUrl.path()); @@ -147,18 +154,20 @@ QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/, } } - const QString &mimeType = AbstractHelpViewer::mimeFromUrl(url); - const QByteArray &data = helpEngine.findFile(url).isValid() - ? helpEngine.fileData(url) - : AbstractHelpViewer::PageNotFoundMessage.arg(url).toUtf8(); + const QString &mimeType = HelpViewer::mimeFromUrl(url); + const QByteArray &data = engine.findFile(url).isValid() ? engine.fileData(url) + : HelpViewer::PageNotFoundMessage.arg(url).toUtf8(); + return new HelpNetworkReply(request, data, mimeType.isEmpty() ? QLatin1String("application/octet-stream") : mimeType); } +// -- HelpPage + class HelpPage : public QWebPage { public: - HelpPage(CentralWidget *central, QObject *parent); + HelpPage(QObject *parent); protected: virtual QWebPage *createWindow(QWebPage::WebWindowType); @@ -168,7 +177,6 @@ protected: const QNetworkRequest &request, NavigationType type); private: - CentralWidget *centralWidget; bool closeNewTabIfNeeded; friend class HelpViewer; @@ -177,9 +185,8 @@ private: Qt::KeyboardModifiers m_keyboardModifiers; }; -HelpPage::HelpPage(CentralWidget *central, QObject *parent) +HelpPage::HelpPage(QObject *parent) : QWebPage(parent) - , centralWidget(central) , closeNewTabIfNeeded(false) , m_pressedButtons(Qt::NoButton) , m_keyboardModifiers(Qt::NoModifier) @@ -190,9 +197,9 @@ HelpPage::HelpPage(CentralWidget *central, QObject *parent) QWebPage *HelpPage::createWindow(QWebPage::WebWindowType) { TRACE_OBJ - HelpPage* newPage = static_cast<HelpPage*>(centralWidget->newEmptyTab()->page()); - if (newPage) - newPage->closeNewTabIfNeeded = closeNewTabIfNeeded; + HelpPage* newPage = static_cast<HelpPage*>(OpenPagesManager::instance() + ->createPage()->page()); + newPage->closeNewTabIfNeeded = closeNewTabIfNeeded; closeNewTabIfNeeded = false; return newPage; } @@ -217,19 +224,17 @@ bool HelpPage::acceptNavigationRequest(QWebFrame *, closeNewTabIfNeeded = false; const QUrl &url = request.url(); - if (AbstractHelpViewer::launchWithExternalApp(url)) { + if (HelpViewer::launchWithExternalApp(url)) { if (closeNewTab) - QMetaObject::invokeMethod(centralWidget, "closeTab"); + QMetaObject::invokeMethod(OpenPagesManager::instance(), "closeCurrentPage"); return false; } if (type == QWebPage::NavigationTypeLinkClicked - && (m_keyboardModifiers & Qt::ControlModifier - || m_pressedButtons == Qt::MidButton)) { - if (centralWidget->newEmptyTab()) - centralWidget->setSource(url); + && (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton)) { m_pressedButtons = Qt::NoButton; m_keyboardModifiers = Qt::NoModifier; + OpenPagesManager::instance()->createPage(url); return false; } @@ -243,23 +248,20 @@ bool HelpPage::acceptNavigationRequest(QWebFrame *, // -- HelpViewer -HelpViewer::HelpViewer(CentralWidget *parent, qreal zoom) +HelpViewer::HelpViewer(qreal zoom, QWidget *parent) : QWebView(parent) - , parentWidget(parent) - , loadFinished(false) - , helpEngine(HelpEngineWrapper::instance()) + , d(new HelpViewerPrivate) { TRACE_OBJ setAcceptDrops(false); + settings()->setAttribute(QWebSettings::JavaEnabled, false); + settings()->setAttribute(QWebSettings::PluginsEnabled, false); - setPage(new HelpPage(parent, this)); - + setPage(new HelpPage(this)); page()->setNetworkAccessManager(new HelpNetworkAccessManager(this)); QAction* action = pageAction(QWebPage::OpenLinkInNewWindow); - action->setText(tr("Open Link in New Tab")); - if (!parent) - action->setVisible(false); + action->setText(tr("Open Link in New Page")); pageAction(QWebPage::DownloadLinkToDisk)->setVisible(false); pageAction(QWebPage::DownloadImageToDisk)->setVisible(false); @@ -271,27 +273,23 @@ HelpViewer::HelpViewer(CentralWidget *parent, qreal zoom) SLOT(actionChanged())); connect(pageAction(QWebPage::Forward), SIGNAL(changed()), this, SLOT(actionChanged())); - connect(page(), SIGNAL(linkHovered(QString,QString,QString)), this, + connect(page(), SIGNAL(linkHovered(QString, QString, QString)), this, SIGNAL(highlighted(QString))); connect(this, SIGNAL(urlChanged(QUrl)), this, SIGNAL(sourceChanged(QUrl))); connect(this, SIGNAL(loadStarted()), this, SLOT(setLoadStarted())); connect(this, SIGNAL(loadFinished(bool)), this, SLOT(setLoadFinished(bool))); + connect(this, SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged())); connect(page(), SIGNAL(printRequested(QWebFrame*)), this, SIGNAL(printRequested())); setFont(viewerFont()); setTextSizeMultiplier(zoom == 0.0 ? 1.0 : zoom); } -HelpViewer::~HelpViewer() -{ - TRACE_OBJ -} - QFont HelpViewer::viewerFont() const { TRACE_OBJ - if (helpEngine.usesBrowserFont()) - return helpEngine.browserFont(); + if (HelpEngineWrapper::instance().usesBrowserFont()) + return HelpEngineWrapper::instance().browserFont(); QWebSettings *webSettings = QWebSettings::globalSettings(); return QFont(webSettings->fontFamily(QWebSettings::StandardFont), @@ -324,26 +322,29 @@ void HelpViewer::resetScale() setTextSizeMultiplier(1.0); } -bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *e) +qreal HelpViewer::scale() const { TRACE_OBJ - if (e->button() == Qt::XButton1) { - triggerPageAction(QWebPage::Back); - return true; - } + return textSizeMultiplier(); +} - if (e->button() == Qt::XButton2) { - triggerPageAction(QWebPage::Forward); - return true; - } +QString HelpViewer::title() const +{ + TRACE_OBJ + return QWebView::title(); +} - return false; +void HelpViewer::setTitle(const QString &title) +{ + TRACE_OBJ + Q_UNUSED(title) } QUrl HelpViewer::source() const { + TRACE_OBJ HelpPage *currentPage = static_cast<HelpPage*> (page()); - if (currentPage && !hasLoadFinished()) { + if (currentPage && !d->m_loadFinished) { // see HelpPage::acceptNavigationRequest(...) return currentPage->m_loadingUrl; } @@ -356,44 +357,84 @@ void HelpViewer::setSource(const QUrl &url) load(url.toString() == QLatin1String("help") ? LocalHelpFile : url); } -void HelpViewer::home() +QString HelpViewer::selectedText() const { TRACE_OBJ - setSource(helpEngine.homePage()); + return QWebView::selectedText(); } -void HelpViewer::wheelEvent(QWheelEvent *e) +bool HelpViewer::isForwardAvailable() const { TRACE_OBJ - if (e->modifiers()& Qt::ControlModifier) { - e->accept(); - e->delta() > 0 ? scaleUp() : scaleDown(); - } else { - QWebView::wheelEvent(e); - } + return pageAction(QWebPage::Forward)->isEnabled(); } -void HelpViewer::mouseReleaseEvent(QMouseEvent *e) +bool HelpViewer::isBackwardAvailable() const { TRACE_OBJ -#ifndef Q_OS_LINUX - if (handleForwardBackwardMouseButtons(e)) - return; -#endif + return pageAction(QWebPage::Back)->isEnabled(); +} - QWebView::mouseReleaseEvent(e); +bool HelpViewer::findText(const QString &text, FindFlags flags, bool incremental, + bool fromSearch) +{ + TRACE_OBJ + Q_UNUSED(incremental); Q_UNUSED(fromSearch); + QWebPage::FindFlags options = QWebPage::FindWrapsAroundDocument; + if (flags & FindBackward) + options |= QWebPage::FindBackward; + if (flags & FindCaseSensitively) + options |= QWebPage::FindCaseSensitively; + + bool found = QWebView::findText(text, options); + options = QWebPage::HighlightAllOccurrences; + QWebView::findText(QLatin1String(""), options); // clear first + QWebView::findText(text, options); // force highlighting of all other matches + return found; } -void HelpViewer::actionChanged() +// -- public slots + +void HelpViewer::copy() { TRACE_OBJ - QAction *a = qobject_cast<QAction *>(sender()); - if (a == pageAction(QWebPage::Copy)) - emit copyAvailable(a->isEnabled()); - else if (a == pageAction(QWebPage::Back)) - emit backwardAvailable(a->isEnabled()); - else if (a == pageAction(QWebPage::Forward)) - emit forwardAvailable(a->isEnabled()); + triggerPageAction(QWebPage::Copy); +} + +void HelpViewer::forward() +{ + TRACE_OBJ + QWebView::forward(); +} + +void HelpViewer::backward() +{ + TRACE_OBJ + back(); +} + +// -- protected + +void HelpViewer::keyPressEvent(QKeyEvent *e) +{ + TRACE_OBJ + // TODO: remove this once we support multiple keysequences per command + if (e->key() == Qt::Key_Insert && e->modifiers() == Qt::CTRL) { + if (!selectedText().isEmpty()) + copy(); + } + QWebView::keyPressEvent(e); +} + +void HelpViewer::wheelEvent(QWheelEvent *event) +{ + TRACE_OBJ + if (event->modifiers()& Qt::ControlModifier) { + event->accept(); + event->delta() > 0 ? scaleUp() : scaleDown(); + } else { + QWebView::wheelEvent(event); + } } void HelpViewer::mousePressEvent(QMouseEvent *event) @@ -404,24 +445,51 @@ void HelpViewer::mousePressEvent(QMouseEvent *event) return; #endif - HelpPage *currentPage = static_cast<HelpPage*>(page()); - if (currentPage) { + if (HelpPage *currentPage = static_cast<HelpPage*> (page())) { currentPage->m_pressedButtons = event->buttons(); currentPage->m_keyboardModifiers = event->modifiers(); } + QWebView::mousePressEvent(event); } -void HelpViewer::setLoadStarted() +void HelpViewer::mouseReleaseEvent(QMouseEvent *event) { - loadFinished = false; + TRACE_OBJ +#ifndef Q_OS_LINUX + if (handleForwardBackwardMouseButtons(event)) + return; +#endif + + QWebView::mouseReleaseEvent(event); +} + +// -- private slots + +void HelpViewer::actionChanged() +{ + TRACE_OBJ + QAction *a = qobject_cast<QAction *>(sender()); + if (a == pageAction(QWebPage::Copy)) + emit copyAvailable(a->isEnabled()); + else if (a == pageAction(QWebPage::Back)) + emit backwardAvailable(a->isEnabled()); + else if (a == pageAction(QWebPage::Forward)) + emit forwardAvailable(a->isEnabled()); +} + +// -- private + +bool HelpViewer::eventFilter(QObject *obj, QEvent *event) +{ + TRACE_OBJ + return QWebView::eventFilter(obj, event); } -void HelpViewer::setLoadFinished(bool ok) +void HelpViewer::contextMenuEvent(QContextMenuEvent *event) { TRACE_OBJ - loadFinished = ok; - emit sourceChanged(url()); + QWebView::contextMenuEvent(event); } QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer_qwv.h b/tools/assistant/tools/assistant/helpviewer_qwv.h deleted file mode 100644 index ac34723..0000000 --- a/tools/assistant/tools/assistant/helpviewer_qwv.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Qt Assistant of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HELPVIEWERQWV_H -#define HELPVIEWERQWV_H - -#include "helpviewer.h" - -#include <QtGui/QAction> -#include <QtWebKit/QWebView> - -QT_BEGIN_NAMESPACE - -class CentralWidget; -class HelpEngineWrapper; -class QMouseEvent; - -class HelpViewer : public QWebView, public AbstractHelpViewer -{ - Q_OBJECT - -public: - explicit HelpViewer(CentralWidget *parent, qreal zoom = 0.0); - ~HelpViewer(); - - QFont viewerFont() const; - void setViewerFont(const QFont &font); - - void scaleUp(); - void scaleDown(); - void resetScale(); - qreal scale() const { return textSizeMultiplier(); } - - bool handleForwardBackwardMouseButtons(QMouseEvent *e); - - QUrl source() const; - void setSource(const QUrl &url); - - inline QString documentTitle() const - { return title(); } - - inline bool hasSelection() const - { return !selectedText().isEmpty(); } // ### this is suboptimal - - inline void copy() - { return triggerPageAction(QWebPage::Copy); } - - inline bool isForwardAvailable() const - { return pageAction(QWebPage::Forward)->isEnabled(); } - inline bool isBackwardAvailable() const - { return pageAction(QWebPage::Back)->isEnabled(); } - inline bool hasLoadFinished() const - { return loadFinished; } - -public Q_SLOTS: - void home(); - void backward() { back(); } - -Q_SIGNALS: - void copyAvailable(bool enabled); - void forwardAvailable(bool enabled); - void backwardAvailable(bool enabled); - void highlighted(const QString &); - void sourceChanged(const QUrl &); - void printRequested(); - -protected: - virtual void wheelEvent(QWheelEvent *); - void mouseReleaseEvent(QMouseEvent *e); - void mousePressEvent(QMouseEvent *event); - -private Q_SLOTS: - void actionChanged(); - void setLoadStarted(); - void setLoadFinished(bool ok); - -private: - CentralWidget* parentWidget; - bool loadFinished; - HelpEngineWrapper &helpEngine; -}; - -QT_END_NAMESPACE - -#endif // HELPVIEWERQWV_H diff --git a/tools/assistant/tools/assistant/images/closebutton.png b/tools/assistant/tools/assistant/images/closebutton.png Binary files differnew file mode 100644 index 0000000..c978cf5 --- /dev/null +++ b/tools/assistant/tools/assistant/images/closebutton.png diff --git a/tools/assistant/tools/assistant/images/darkclosebutton.png b/tools/assistant/tools/assistant/images/darkclosebutton.png Binary files differnew file mode 100644 index 0000000..1077663 --- /dev/null +++ b/tools/assistant/tools/assistant/images/darkclosebutton.png diff --git a/tools/assistant/tools/assistant/indexwindow.cpp b/tools/assistant/tools/assistant/indexwindow.cpp index ed67490..dd2db51 100644 --- a/tools/assistant/tools/assistant/indexwindow.cpp +++ b/tools/assistant/tools/assistant/indexwindow.cpp @@ -38,13 +38,15 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" #include "indexwindow.h" + #include "centralwidget.h" #include "helpenginewrapper.h" #include "helpviewer.h" +#include "openpagesmanager.h" #include "topicchooser.h" +#include "tracer.h" #include <QtGui/QLayout> #include <QtGui/QLabel> @@ -219,10 +221,10 @@ void IndexWindow::open(QHelpIndexWidget* indexWidget, const QModelIndex &index) return; } - if (!AbstractHelpViewer::canOpenPage(url.path())) + if (!HelpViewer::canOpenPage(url.path())) CentralWidget::instance()->setSource(url); else - CentralWidget::instance()->setSourceInNewTab(url); + OpenPagesManager::instance()->createPage(url); } } diff --git a/tools/assistant/tools/assistant/main.cpp b/tools/assistant/tools/assistant/main.cpp index 831c754..117b869 100644 --- a/tools/assistant/tools/assistant/main.cpp +++ b/tools/assistant/tools/assistant/main.cpp @@ -292,7 +292,8 @@ void setupTranslation(const QString &fileName, const QString &dir) QTranslator *translator = new QTranslator(QCoreApplication::instance()); if (translator->load(fileName, dir)) { QCoreApplication::installTranslator(translator); - } else if (!fileName.endsWith(QLatin1String("en_US"))) { + } else if (!fileName.endsWith(QLatin1String("en_US")) + && !fileName.endsWith(QLatin1String("_C"))) { qWarning("Could not load translation file %s in directory %s.", qPrintable(fileName), qPrintable(dir)); } diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp index fd48e3c..138b8e1 100644 --- a/tools/assistant/tools/assistant/mainwindow.cpp +++ b/tools/assistant/tools/assistant/mainwindow.cpp @@ -38,57 +38,58 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" #include "mainwindow.h" +#include "aboutdialog.h" #include "bookmarkmanager.h" #include "centralwidget.h" -#include "indexwindow.h" -#include "topicchooser.h" +#include "cmdlineparser.h" #include "contentwindow.h" -#include "preferencesdialog.h" +#include "globalactions.h" #include "helpenginewrapper.h" +#include "indexwindow.h" +#include "openpagesmanager.h" +#include "preferencesdialog.h" +#include "qtdocinstaller.h" #include "remotecontrol.h" -#include "cmdlineparser.h" -#include "aboutdialog.h" #include "searchwidget.h" -#include "qtdocinstaller.h" - -// #define TRACING_REQUESTED +#include "topicchooser.h" +#include "tracer.h" -#include <QtCore/QDir> -#include <QtCore/QTimer> +#include <QtCore/QByteArray> #include <QtCore/QDateTime> #include <QtCore/QDebug> -#include <QtCore/QFileSystemWatcher> +#include <QtCore/QDir> #include <QtCore/QPair> #include <QtCore/QResource> -#include <QtCore/QByteArray> #include <QtCore/QTextStream> -#include <QtCore/QCoreApplication> +#include <QtCore/QTimer> -#include <QtGui/QMenuBar> #include <QtGui/QAction> -#include <QtGui/QToolBar> -#include <QtGui/QStatusBar> +#include <QtGui/QComboBox> +#include <QtGui/QDesktopServices> +#include <QtGui/QDesktopWidget> +#include <QtGui/QDockWidget> +#include <QtGui/QFontDatabase> +#include <QtGui/QFileDialog> #include <QtGui/QLabel> -#include <QtGui/QLineEdit> #include <QtGui/QLayout> -#include <QtGui/QDockWidget> -#include <QtGui/QTreeView> +#include <QtGui/QLineEdit> +#include <QtGui/QMenuBar> #include <QtGui/QMessageBox> -#include <QtGui/QFontDatabase> -#include <QtGui/QComboBox> #include <QtGui/QProgressBar> -#include <QtGui/QDesktopServices> +#include <QtGui/QShortcut> +#include <QtGui/QStatusBar> +#include <QtGui/QToolBar> #include <QtGui/QToolButton> -#include <QtGui/QFileDialog> -#include <QtHelp/QHelpEngineCore> -#include <QtHelp/QHelpSearchEngine> #include <QtHelp/QHelpContentModel> +#include <QtHelp/QHelpEngineCore> #include <QtHelp/QHelpIndexModel> +#include <QtHelp/QHelpSearchEngine> + +#include <cstdlib> QT_BEGIN_NAMESPACE @@ -105,6 +106,7 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) TRACE_OBJ setToolButtonStyle(Qt::ToolButtonFollowStyle); + setDockOptions(dockOptions() | AllowNestedDocks); QString collectionFile; if (usesDefaultCollection()) { @@ -115,6 +117,14 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) } HelpEngineWrapper &helpEngineWrapper = HelpEngineWrapper::instance(collectionFile); + BookmarkManager *bookMarkManager = BookmarkManager::instance(); + + if (!initHelpDB(!cmdLine->collectionFileGiven())) { + qDebug("Fatal error: Help engine initialization failed. " + "Error message was: %s\nAssistant will now exit.", + qPrintable(HelpEngineWrapper::instance().error())); + std::exit(1); + } m_centralWidget = new CentralWidget(this); setCentralWidget(m_centralWidget); @@ -131,132 +141,154 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) contentDock->setWidget(m_contentWindow); addDockWidget(Qt::LeftDockWidgetArea, contentDock); - QDockWidget *bookmarkDock = 0; - if (BookmarkManager *manager = BookmarkManager::instance()) { - bookmarkDock = new QDockWidget(tr("Bookmarks"), this); - bookmarkDock->setObjectName(QLatin1String("BookmarkWindow")); - bookmarkDock->setWidget(m_bookmarkWidget = manager->bookmarkDockWidget()); - addDockWidget(Qt::LeftDockWidgetArea, bookmarkDock); - - connect(manager, SIGNAL(escapePressed()), this, + m_searchWindow = new SearchWidget(helpEngineWrapper.searchEngine()); + m_searchWindow->setFont(!helpEngineWrapper.usesBrowserFont() ? qApp->font() + : helpEngineWrapper.browserFont()); + QDockWidget *searchDock = new QDockWidget(tr("Search"), this); + searchDock->setObjectName(QLatin1String("SearchWindow")); + searchDock->setWidget(m_searchWindow); + addDockWidget(Qt::LeftDockWidgetArea, searchDock); + + QDockWidget *bookmarkDock = new QDockWidget(tr("Bookmarks"), this); + bookmarkDock->setObjectName(QLatin1String("BookmarkWindow")); + bookmarkDock->setWidget(m_bookmarkWidget + = bookMarkManager->bookmarkDockWidget()); + addDockWidget(Qt::LeftDockWidgetArea, bookmarkDock); + + QDockWidget *openPagesDock = new QDockWidget(tr("Open Pages"), this); + openPagesDock->setObjectName(QLatin1String("Open Pages")); + OpenPagesManager *openPagesManager + = OpenPagesManager::createInstance(this, usesDefaultCollection(), m_cmdLine->url()); + openPagesDock->setWidget(openPagesManager->openPagesWidget()); + addDockWidget(Qt::LeftDockWidgetArea, openPagesDock); + + connect(m_centralWidget, SIGNAL(addBookmark(QString, QString)), + bookMarkManager, SLOT(addBookmark(QString, QString))); + connect(bookMarkManager, SIGNAL(escapePressed()), this, SLOT(activateCurrentCentralWidgetTab())); - connect(manager, SIGNAL(setSource(QUrl)), m_centralWidget, + connect(bookMarkManager, SIGNAL(setSource(QUrl)), m_centralWidget, SLOT(setSource(QUrl))); - connect(manager, SIGNAL(setSourceInNewTab(QUrl)), m_centralWidget, - SLOT(setSourceInNewTab(QUrl))); - connect(m_centralWidget, SIGNAL(addBookmark(QString, QString)), manager, - SLOT(addBookmark(QString, QString))); - } + connect(bookMarkManager, SIGNAL(setSourceInNewTab(QUrl)), + openPagesManager, SLOT(createPage(QUrl))); QHelpSearchEngine *searchEngine = helpEngineWrapper.searchEngine(); connect(searchEngine, SIGNAL(indexingStarted()), this, SLOT(indexingStarted())); connect(searchEngine, SIGNAL(indexingFinished()), this, SLOT(indexingFinished())); - m_centralWidget->createSearchWidget(searchEngine); - m_centralWidget->activateSearchWidget(); - QString defWindowTitle = tr("Qt Assistant"); setWindowTitle(defWindowTitle); setupActions(); statusBar()->show(); + m_centralWidget->connectTabBar(); - if (initHelpDB(!cmdLine->collectionFileGiven())) { - setupFilterToolbar(); - setupAddressToolbar(); - - const QString windowTitle = helpEngineWrapper.windowTitle(); - setWindowTitle(windowTitle.isEmpty() ? defWindowTitle : windowTitle); - QByteArray iconArray = helpEngineWrapper.applicationIcon(); - if (iconArray.size() > 0) { - QPixmap pix; - pix.loadFromData(iconArray); - QIcon appIcon(pix); - qApp->setWindowIcon(appIcon); - } else { - QIcon appIcon(QLatin1String(":/trolltech/assistant/images/assistant-128.png")); - qApp->setWindowIcon(appIcon); - } + setupFilterToolbar(); + setupAddressToolbar(); - // Show the widget here, otherwise the restore geometry and state won't work - // on x11. - show(); - QByteArray ba(helpEngineWrapper.mainWindow()); - if (!ba.isEmpty()) - restoreState(ba); - - ba = helpEngineWrapper.mainWindowGeometry(); - if (!ba.isEmpty()) { - restoreGeometry(ba); - } else { - tabifyDockWidget(contentDock, indexDock); - if (bookmarkDock) - tabifyDockWidget(indexDock, bookmarkDock); - contentDock->raise(); - resize(QSize(800, 600)); - } + const QString windowTitle = helpEngineWrapper.windowTitle(); + setWindowTitle(windowTitle.isEmpty() ? defWindowTitle : windowTitle); + QByteArray iconArray = helpEngineWrapper.applicationIcon(); + if (iconArray.size() > 0) { + QPixmap pix; + pix.loadFromData(iconArray); + QIcon appIcon(pix); + qApp->setWindowIcon(appIcon); + } else { + QIcon appIcon(QLatin1String(":/trolltech/assistant/images/assistant-128.png")); + qApp->setWindowIcon(appIcon); + } - if (!helpEngineWrapper.hasFontSettings()) { - helpEngineWrapper.setUseAppFont(false); - helpEngineWrapper.setUseBrowserFont(false); - helpEngineWrapper.setAppFont(qApp->font()); - helpEngineWrapper.setAppWritingSystem(QFontDatabase::Latin); - helpEngineWrapper.setBrowserFont(qApp->font()); - helpEngineWrapper.setBrowserWritingSystem(QFontDatabase::Latin); - } else { - updateApplicationFont(); - } + QToolBar *toolBar = addToolBar(tr("Bookmark Toolbar")); + toolBar->setObjectName(QLatin1String("Bookmark Toolbar")); + bookMarkManager->setBookmarksToolbar(toolBar); - updateAboutMenuText(); - - QTimer::singleShot(0, this, SLOT(insertLastPages())); - if (m_cmdLine->enableRemoteControl()) - (void)new RemoteControl(this); - - if (m_cmdLine->contents() == CmdLineParser::Show) - showContents(); - else if (m_cmdLine->contents() == CmdLineParser::Hide) - hideContents(); - - if (m_cmdLine->index() == CmdLineParser::Show) - showIndex(); - else if (m_cmdLine->index() == CmdLineParser::Hide) - hideIndex(); - - if (m_cmdLine->bookmarks() == CmdLineParser::Show) - showBookmarksDockWidget(); - else if (m_cmdLine->bookmarks() == CmdLineParser::Hide) - hideBookmarksDockWidget(); - - if (m_cmdLine->search() == CmdLineParser::Show) - showSearch(); - else if (m_cmdLine->search() == CmdLineParser::Hide) - hideSearch(); - - if (m_cmdLine->contents() == CmdLineParser::Activate) - showContents(); - else if (m_cmdLine->index() == CmdLineParser::Activate) - showIndex(); - else if (m_cmdLine->bookmarks() == CmdLineParser::Activate) - showBookmarksDockWidget(); - - if (!m_cmdLine->currentFilter().isEmpty()) { - const QString &curFilter = m_cmdLine->currentFilter(); - if (helpEngineWrapper.customFilters().contains(curFilter)) - helpEngineWrapper.setCurrentFilter(curFilter); - } + // Show the widget here, otherwise the restore geometry and state won't work + // on x11. + show(); - if (usesDefaultCollection()) - QTimer::singleShot(0, this, SLOT(lookForNewQtDocumentation())); - else - checkInitState(); + toolBar->hide(); + toolBarMenu()->addAction(toolBar->toggleViewAction()); + + QByteArray ba(helpEngineWrapper.mainWindow()); + if (!ba.isEmpty()) + restoreState(ba); + + ba = helpEngineWrapper.mainWindowGeometry(); + if (!ba.isEmpty()) { + restoreGeometry(ba); + } else { + tabifyDockWidget(contentDock, indexDock); + tabifyDockWidget(indexDock, bookmarkDock); + tabifyDockWidget(bookmarkDock, searchDock); + contentDock->raise(); + const QRect screen = QApplication::desktop()->screenGeometry(); + resize(4*screen.width()/5, 4*screen.height()/5); + } - connect(&helpEngineWrapper, SIGNAL(documentationRemoved(QString)), - this, SLOT(documentationRemoved(QString))); - connect(&helpEngineWrapper, SIGNAL(documentationUpdated(QString)), - this, SLOT(documentationUpdated(QString))); + if (!helpEngineWrapper.hasFontSettings()) { + helpEngineWrapper.setUseAppFont(false); + helpEngineWrapper.setUseBrowserFont(false); + helpEngineWrapper.setAppFont(qApp->font()); + helpEngineWrapper.setAppWritingSystem(QFontDatabase::Latin); + helpEngineWrapper.setBrowserFont(qApp->font()); + helpEngineWrapper.setBrowserWritingSystem(QFontDatabase::Latin); + } else { + updateApplicationFont(); + } + + updateAboutMenuText(); + + QTimer::singleShot(0, this, SLOT(insertLastPages())); + if (m_cmdLine->enableRemoteControl()) + (void)new RemoteControl(this); + + if (m_cmdLine->contents() == CmdLineParser::Show) + showContents(); + else if (m_cmdLine->contents() == CmdLineParser::Hide) + hideContents(); + + if (m_cmdLine->index() == CmdLineParser::Show) + showIndex(); + else if (m_cmdLine->index() == CmdLineParser::Hide) + hideIndex(); + + if (m_cmdLine->bookmarks() == CmdLineParser::Show) + showBookmarksDockWidget(); + else if (m_cmdLine->bookmarks() == CmdLineParser::Hide) + hideBookmarksDockWidget(); + + if (m_cmdLine->search() == CmdLineParser::Show) + showSearch(); + else if (m_cmdLine->search() == CmdLineParser::Hide) + hideSearch(); + + if (m_cmdLine->contents() == CmdLineParser::Activate) + showContents(); + else if (m_cmdLine->index() == CmdLineParser::Activate) + showIndex(); + else if (m_cmdLine->bookmarks() == CmdLineParser::Activate) + showBookmarksDockWidget(); + + if (!m_cmdLine->currentFilter().isEmpty()) { + const QString &curFilter = m_cmdLine->currentFilter(); + if (helpEngineWrapper.customFilters().contains(curFilter)) + helpEngineWrapper.setCurrentFilter(curFilter); } + + if (usesDefaultCollection()) + QTimer::singleShot(0, this, SLOT(lookForNewQtDocumentation())); + else + checkInitState(); + + connect(&helpEngineWrapper, SIGNAL(documentationRemoved(QString)), + this, SLOT(documentationRemoved(QString))); + connect(&helpEngineWrapper, SIGNAL(documentationUpdated(QString)), + this, SLOT(documentationUpdated(QString))); + setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + GlobalActions::instance()->updateActions(); + if (helpEngineWrapper.addressBarEnabled()) + showNewAddress(); } MainWindow::~MainWindow() @@ -392,11 +424,6 @@ void MainWindow::checkInitState() void MainWindow::insertLastPages() { TRACE_OBJ - if (m_cmdLine->url().isValid()) - m_centralWidget->setSource(m_cmdLine->url()); - else - m_centralWidget->setupWidget(); - if (m_cmdLine->search() == CmdLineParser::Activate) showSearch(); } @@ -414,8 +441,13 @@ void MainWindow::setupActions() QMenu *menu = menuBar()->addMenu(tr("&File")); - m_newTabAction = menu->addAction(tr("New &Tab"), m_centralWidget, SLOT(newTab())); + OpenPagesManager * const openPages = OpenPagesManager::instance(); + m_newTabAction + = menu->addAction(tr("New &Tab"), openPages, SLOT(createPage())); m_newTabAction->setShortcut(QKeySequence::AddTab); + m_closeTabAction = menu->addAction(tr("&Close Tab"), + openPages, SLOT(closeCurrentPage())); + m_closeTabAction->setShortcuts(QKeySequence::Close); menu->addSeparator(); @@ -424,40 +456,24 @@ void MainWindow::setupActions() m_printPreviewAction = menu->addAction(tr("Print Preview..."), m_centralWidget, SLOT(printPreview())); - m_printAction = menu->addAction(tr("&Print..."), m_centralWidget, SLOT(print())); - m_printAction->setPriority(QAction::LowPriority); - m_printAction->setIcon(QIcon(resourcePath + QLatin1String("/print.png"))); - m_printAction->setShortcut(QKeySequence::Print); - + GlobalActions *globalActions = GlobalActions::instance(this); + menu->addAction(globalActions->printAction()); menu->addSeparator(); - m_closeTabAction = menu->addAction(tr("&Close Tab"), m_centralWidget, - SLOT(closeTab())); - m_closeTabAction->setShortcuts(QKeySequence::Close); - - QAction *tmp = menu->addAction(QIcon::fromTheme("application-exit"), - tr("&Quit"), this, SLOT(close())); - tmp->setMenuRole(QAction::QuitRole); + QIcon appExitIcon = QIcon::fromTheme("application-exit"); + QAction *tmp; #ifdef Q_OS_WIN + tmp = menu->addAction(appExitIcon, tr("E&xit"), this, SLOT(close())); tmp->setShortcut(QKeySequence(tr("CTRL+Q"))); #else + tmp = menu->addAction(appExitIcon, tr("&Quit"), this, SLOT(close())); tmp->setShortcut(QKeySequence::Quit); #endif + tmp->setMenuRole(QAction::QuitRole); menu = menuBar()->addMenu(tr("&Edit")); - m_copyAction = menu->addAction(tr("&Copy selected Text"), m_centralWidget, - SLOT(copySelection())); - m_copyAction->setPriority(QAction::LowPriority); - m_copyAction->setIconText("&Copy"); - m_copyAction->setIcon(QIcon(resourcePath + QLatin1String("/editcopy.png"))); - m_copyAction->setShortcuts(QKeySequence::Copy); - m_copyAction->setEnabled(false); - - m_findAction = menu->addAction(tr("&Find in Text..."), m_centralWidget, - SLOT(showTextSearch())); - m_findAction->setIconText(tr("&Find")); - m_findAction->setIcon(QIcon(resourcePath + QLatin1String("/find.png"))); - m_findAction->setShortcuts(QKeySequence::Find); + menu->addAction(globalActions->copyAction()); + menu->addAction(globalActions->findAction()); QAction *findNextAction = menu->addAction(tr("Find &Next"), m_centralWidget, SLOT(findNext())); @@ -472,17 +488,8 @@ void MainWindow::setupActions() tmp->setMenuRole(QAction::PreferencesRole); m_viewMenu = menuBar()->addMenu(tr("&View")); - m_zoomInAction = m_viewMenu->addAction(tr("Zoom &in"), m_centralWidget, - SLOT(zoomIn())); - m_zoomInAction->setPriority(QAction::LowPriority); - m_zoomInAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomin.png"))); - m_zoomInAction->setShortcut(QKeySequence::ZoomIn); - - m_zoomOutAction = m_viewMenu->addAction(tr("Zoom &out"), m_centralWidget, - SLOT(zoomOut())); - m_zoomOutAction->setPriority(QAction::LowPriority); - m_zoomOutAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomout.png"))); - m_zoomOutAction->setShortcut(QKeySequence::ZoomOut); + m_viewMenu->addAction(globalActions->zoomInAction()); + m_viewMenu->addAction(globalActions->zoomOutAction()); m_resetZoomAction = m_viewMenu->addAction(tr("Normal &Size"), m_centralWidget, SLOT(resetZoom())); @@ -498,24 +505,15 @@ void MainWindow::setupActions() QKeySequence(tr("ALT+I"))); m_viewMenu->addAction(tr("Bookmarks"), this, SLOT(showBookmarksDockWidget()), QKeySequence(tr("ALT+O"))); - m_viewMenu->addAction(tr("Search"), this, SLOT(showSearchWidget()), + m_viewMenu->addAction(tr("Search"), this, SLOT(showSearch()), QKeySequence(tr("ALT+S"))); + m_viewMenu->addAction(tr("Open Pages"), this, SLOT(showOpenPages()), + QKeySequence(tr("ALT+P"))); menu = menuBar()->addMenu(tr("&Go")); - m_homeAction = menu->addAction(tr("&Home"), m_centralWidget, SLOT(home())); - m_homeAction->setShortcut(tr("ALT+Home")); - m_homeAction->setIcon(QIcon(resourcePath + QLatin1String("/home.png"))); - - m_backAction = menu->addAction(tr("&Back"), m_centralWidget, SLOT(backward())); - m_backAction->setEnabled(false); - m_backAction->setShortcuts(QKeySequence::Back); - m_backAction->setIcon(QIcon(resourcePath + QLatin1String("/previous.png"))); - - m_nextAction = menu->addAction(tr("&Forward"), m_centralWidget, SLOT(forward())); - m_nextAction->setPriority(QAction::LowPriority); - m_nextAction->setEnabled(false); - m_nextAction->setShortcuts(QKeySequence::Forward); - m_nextAction->setIcon(QIcon(resourcePath + QLatin1String("/next.png"))); + menu->addAction(globalActions->homeAction()); + menu->addAction(globalActions->backAction()); + menu->addAction(globalActions->nextAction()); m_syncAction = menu->addAction(tr("Sync with Table of Contents"), this, SLOT(syncContents())); @@ -524,60 +522,52 @@ void MainWindow::setupActions() menu->addSeparator(); - tmp = menu->addAction(tr("Next Page"), m_centralWidget, SLOT(nextPage())); + tmp = menu->addAction(tr("Next Page"), openPages, SLOT(nextPage())); tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Right")) << QKeySequence(Qt::CTRL + Qt::Key_PageDown)); - tmp = menu->addAction(tr("Previous Page"), m_centralWidget, SLOT(previousPage())); + tmp = menu->addAction(tr("Previous Page"), openPages, SLOT(previousPage())); tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Left")) << QKeySequence(Qt::CTRL + Qt::Key_PageUp)); - if (BookmarkManager *manager = BookmarkManager::instance()) - manager->takeBookmarksMenu(menuBar()->addMenu(tr("&Bookmarks"))); +#ifdef Q_WS_MAC + QShortcut *sct = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Tab), this); + connect(sct, SIGNAL(activated()), openPages, SLOT(nextPageWithSwitcher())); + sct = new QShortcut(QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Tab), this); + connect(sct, SIGNAL(activated()), openPages, SLOT(previousPageWithSwitcher())); +#else + QShortcut *sct = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Tab), this); + connect(sct, SIGNAL(activated()), openPages, SLOT(nextPageWithSwitcher())); + sct = new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab), this); + connect(sct, SIGNAL(activated()), openPages, SLOT(previousPageWithSwitcher())); +#endif + + BookmarkManager::instance()->setBookmarksMenu(menuBar()->addMenu(tr("&Bookmarks"))); menu = menuBar()->addMenu(tr("&Help")); m_aboutAction = menu->addAction(tr("About..."), this, SLOT(showAboutDialog())); m_aboutAction->setMenuRole(QAction::AboutRole); #ifdef Q_WS_X11 - m_newTabAction->setIcon(QIcon::fromTheme("tab-new", m_newTabAction->icon())); - m_closeTabAction->setIcon(QIcon::fromTheme("window-close", m_closeTabAction->icon())); - m_backAction->setIcon(QIcon::fromTheme("go-previous" , m_backAction->icon())); - m_nextAction->setIcon(QIcon::fromTheme("go-next" , m_nextAction->icon())); - m_zoomInAction->setIcon(QIcon::fromTheme("zoom-in" , m_zoomInAction->icon())); - m_zoomOutAction->setIcon(QIcon::fromTheme("zoom-out" , m_zoomOutAction->icon())); m_resetZoomAction->setIcon(QIcon::fromTheme("zoom-original" , m_resetZoomAction->icon())); m_syncAction->setIcon(QIcon::fromTheme("view-refresh" , m_syncAction->icon())); - m_copyAction->setIcon(QIcon::fromTheme("edit-copy" , m_copyAction->icon())); - m_findAction->setIcon(QIcon::fromTheme("edit-find" , m_findAction->icon())); - m_homeAction->setIcon(QIcon::fromTheme("go-home" , m_homeAction->icon())); - m_pageSetupAction->setIcon(QIcon::fromTheme("document-page-setup", m_pageSetupAction->icon())); - m_printPreviewAction->setIcon(QIcon::fromTheme("document-print-preview", m_printPreviewAction->icon())); - m_printAction->setIcon(QIcon::fromTheme("document-print" , m_printAction->icon())); - m_aboutAction->setIcon(QIcon::fromTheme("help-about", m_aboutAction->icon())); #endif QToolBar *navigationBar = addToolBar(tr("Navigation Toolbar")); navigationBar->setObjectName(QLatin1String("NavigationToolBar")); - navigationBar->addAction(m_backAction); - navigationBar->addAction(m_nextAction); - navigationBar->addAction(m_homeAction); + navigationBar->addAction(globalActions->backAction()); + navigationBar->addAction(globalActions->nextAction()); + navigationBar->addAction(globalActions->homeAction()); navigationBar->addAction(m_syncAction); - QAction *sep = navigationBar->addSeparator(); - navigationBar->addAction(m_copyAction); - navigationBar->addAction(m_printAction); - navigationBar->addAction(m_findAction); - QAction *sep2 = navigationBar->addSeparator(); - navigationBar->addAction(m_zoomInAction); - navigationBar->addAction(m_zoomOutAction); + navigationBar->addSeparator(); + navigationBar->addAction(globalActions->copyAction()); + navigationBar->addAction(globalActions->printAction()); + navigationBar->addAction(globalActions->findAction()); + navigationBar->addSeparator(); + navigationBar->addAction(globalActions->zoomInAction()); + navigationBar->addAction(globalActions->zoomOutAction()); navigationBar->addAction(m_resetZoomAction); - QList<QAction*> actionList; - actionList << m_backAction << m_nextAction << m_homeAction << sep - << m_zoomInAction << m_zoomOutAction << sep2 << m_copyAction - << m_printAction << m_findAction; - m_centralWidget->setGlobalActions(actionList); - #if defined(Q_WS_MAC) QMenu *windowMenu = new QMenu(tr("&Window"), this); menuBar()->insertMenu(menu->menuAction(), windowMenu); @@ -587,16 +577,14 @@ void MainWindow::setupActions() #endif // content viewer connections - connect(m_centralWidget, SIGNAL(copyAvailable(bool)), this, - SLOT(copyAvailable(bool))); - connect(m_centralWidget, SIGNAL(currentViewerChanged()), this, - SLOT(updateNavigationItems())); - connect(m_centralWidget, SIGNAL(currentViewerChanged()), this, - SLOT(updateTabCloseAction())); - connect(m_centralWidget, SIGNAL(forwardAvailable(bool)), this, - SLOT(updateNavigationItems())); - connect(m_centralWidget, SIGNAL(backwardAvailable(bool)), this, - SLOT(updateNavigationItems())); + connect(m_centralWidget, SIGNAL(copyAvailable(bool)), globalActions, + SLOT(setCopyAvailable(bool))); + connect(m_centralWidget, SIGNAL(currentViewerChanged()), globalActions, + SLOT(updateActions())); + connect(m_centralWidget, SIGNAL(forwardAvailable(bool)), globalActions, + SLOT(updateActions())); + connect(m_centralWidget, SIGNAL(backwardAvailable(bool)), globalActions, + SLOT(updateActions())); connect(m_centralWidget, SIGNAL(highlighted(QString)), statusBar(), SLOT(showMessage(QString))); @@ -614,6 +602,12 @@ void MainWindow::setupActions() connect(m_contentWindow, SIGNAL(escapePressed()), this, SLOT(activateCurrentCentralWidgetTab())); + // search window + connect(m_searchWindow, SIGNAL(requestShowLink(QUrl)), + CentralWidget::instance(), SLOT(setSourceFromSearch(QUrl))); + connect(m_searchWindow, SIGNAL(requestShowLinkInNewTab(QUrl)), + OpenPagesManager::instance(), SLOT(createNewPageFromSearch(QUrl))); + #if defined(QT_NO_PRINTER) m_pageSetupAction->setVisible(false); m_printPreviewAction->setVisible(false); @@ -737,26 +731,6 @@ void MainWindow::gotoAddress() m_centralWidget->setSource(m_addressLineEdit->text()); } -void MainWindow::updateNavigationItems() -{ - TRACE_OBJ - bool hasCurrentViewer = m_centralWidget->isHomeAvailable(); - m_copyAction->setEnabled(m_centralWidget->hasSelection()); - m_homeAction->setEnabled(hasCurrentViewer); - m_syncAction->setEnabled(hasCurrentViewer); - m_printPreviewAction->setEnabled(hasCurrentViewer); - m_printAction->setEnabled(hasCurrentViewer); - m_nextAction->setEnabled(m_centralWidget->isForwardAvailable()); - m_backAction->setEnabled(m_centralWidget->isBackwardAvailable()); - m_newTabAction->setEnabled(hasCurrentViewer); -} - -void MainWindow::updateTabCloseAction() -{ - TRACE_OBJ - m_closeTabAction->setEnabled(m_centralWidget->enableTabCloseAction()); -} - void MainWindow::showTopicChooser(const QMap<QString, QUrl> &links, const QString &keyword) { @@ -775,6 +749,8 @@ void MainWindow::showPreferences() SLOT(updateApplicationFont())); connect(&dia, SIGNAL(updateBrowserFont()), m_centralWidget, SLOT(updateBrowserFont())); + connect(&dia, SIGNAL(updateUserInterface()), m_centralWidget, + SLOT(updateUserInterface())); dia.showDialog(); } @@ -790,12 +766,6 @@ void MainWindow::syncContents() qApp->restoreOverrideCursor(); } -void MainWindow::copyAvailable(bool yes) -{ - TRACE_OBJ - m_copyAction->setEnabled(yes); -} - void MainWindow::showAboutDialog() { TRACE_OBJ @@ -904,15 +874,13 @@ void MainWindow::setBookmarksVisible(bool visible) void MainWindow::showBookmarksDockWidget() { TRACE_OBJ - if (m_bookmarkWidget) - activateDockWidget(m_bookmarkWidget); + activateDockWidget(m_bookmarkWidget); } void MainWindow::hideBookmarksDockWidget() { TRACE_OBJ - if (m_bookmarkWidget) - m_bookmarkWidget->parentWidget()->hide(); + m_bookmarkWidget->parentWidget()->hide(); } void MainWindow::setSearchVisible(bool visible) @@ -927,13 +895,19 @@ void MainWindow::setSearchVisible(bool visible) void MainWindow::showSearch() { TRACE_OBJ - m_centralWidget->activateSearchWidget(); + activateDockWidget(m_searchWindow); +} + +void MainWindow::showOpenPages() +{ + TRACE_OBJ + activateDockWidget(OpenPagesManager::instance()->openPagesWidget()); } void MainWindow::hideSearch() { TRACE_OBJ - m_centralWidget->removeSearchWidget(); + m_searchWindow->parentWidget()->hide(); } void MainWindow::activateDockWidget(QWidget *w) @@ -953,10 +927,7 @@ void MainWindow::setIndexString(const QString &str) void MainWindow::activateCurrentBrowser() { TRACE_OBJ - CentralWidget *cw = CentralWidget::instance(); - if (cw) { - cw->activateTab(true); - } + CentralWidget::instance()->activateTab(); } void MainWindow::activateCurrentCentralWidgetTab() @@ -965,12 +936,6 @@ void MainWindow::activateCurrentCentralWidgetTab() m_centralWidget->activateTab(); } -void MainWindow::showSearchWidget() -{ - TRACE_OBJ - m_centralWidget->activateSearchWidget(true); -} - void MainWindow::updateApplicationFont() { TRACE_OBJ @@ -1092,17 +1057,13 @@ void MainWindow::currentFilterChanged(const QString &filter) void MainWindow::documentationRemoved(const QString &namespaceName) { TRACE_OBJ - CentralWidget* widget = CentralWidget::instance(); - widget->closeOrReloadTabs(widget->currentSourceFileList(). - keys(namespaceName), false); + OpenPagesManager::instance()->closePages(namespaceName); } void MainWindow::documentationUpdated(const QString &namespaceName) { TRACE_OBJ - CentralWidget* widget = CentralWidget::instance(); - widget->closeOrReloadTabs(widget->currentSourceFileList(). - keys(namespaceName), true); + OpenPagesManager::instance()->reloadPages(namespaceName); } void MainWindow::resetQtDocInfo(const QString &component) diff --git a/tools/assistant/tools/assistant/mainwindow.h b/tools/assistant/tools/assistant/mainwindow.h index 255f00c..5d72a7a 100644 --- a/tools/assistant/tools/assistant/mainwindow.h +++ b/tools/assistant/tools/assistant/mainwindow.h @@ -42,24 +42,27 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H +#include <QtCore/QList> #include <QtCore/QUrl> #include <QtGui/QMainWindow> QT_BEGIN_NAMESPACE class QAction; +class QComboBox; class QFileSystemWatcher; class QLineEdit; -class QComboBox; class QMenu; -class IndexWindow; -class QHelpEngineCore; -class QHelpEngine; class CentralWidget; -class ContentWindow; class CmdLineParser; +class ContentWindow; +class IndexWindow; +class OpenPagesWindow; class QtDocInstaller; +class QHelpEngineCore; +class QHelpEngine; +class SearchWidget; class MainWindow : public QMainWindow { @@ -87,7 +90,6 @@ public slots: void setIndexVisible(bool visible); void setBookmarksVisible(bool visible); void setSearchVisible(bool visible); - void showSearchWidget(); void syncContents(); void activateCurrentCentralWidgetTab(); void currentFilterChanged(const QString &filter); @@ -96,14 +98,12 @@ private slots: void showContents(); void showIndex(); void showSearch(); + void showOpenPages(); void insertLastPages(); void gotoAddress(); void showPreferences(); void showNewAddress(); void showAboutDialog(); - void copyAvailable(bool yes); - void updateNavigationItems(); - void updateTabCloseAction(); void showNewAddress(const QUrl &url); void showTopicChooser(const QMap<QString, QUrl> &links, const QString &keyword); void updateApplicationFont(); @@ -144,20 +144,13 @@ private: CentralWidget *m_centralWidget; IndexWindow *m_indexWindow; ContentWindow *m_contentWindow; + SearchWidget *m_searchWindow; QLineEdit *m_addressLineEdit; QComboBox *m_filterCombo; - QAction *m_backAction; - QAction *m_nextAction; - QAction *m_homeAction; QAction *m_syncAction; - QAction *m_copyAction; - QAction *m_findAction; - QAction *m_printAction; QAction *m_printPreviewAction; QAction *m_pageSetupAction; - QAction *m_zoomInAction; - QAction *m_zoomOutAction; QAction *m_resetZoomAction; QAction *m_aboutAction; QAction *m_closeTabAction; diff --git a/tools/assistant/tools/assistant/openpagesmanager.cpp b/tools/assistant/tools/assistant/openpagesmanager.cpp new file mode 100644 index 0000000..c574a09 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesmanager.cpp @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "openpagesmanager.h" + +#include "centralwidget.h" +#include "helpenginewrapper.h" +#include "helpviewer.h" +#include "openpagesmodel.h" +#include "openpagesswitcher.h" +#include "openpageswidget.h" +#include "tracer.h" +#include "../shared/collectionconfiguration.h" + +#include <QtGui/QApplication> +#include <QtGui/QTreeView> + +QT_BEGIN_NAMESPACE + +OpenPagesManager *OpenPagesManager::m_instance = 0; + +OpenPagesManager *OpenPagesManager::createInstance(QObject *parent, + bool defaultCollection, const QUrl &cmdLineUrl) +{ + TRACE_OBJ + Q_ASSERT(!m_instance); + m_instance = new OpenPagesManager(parent, defaultCollection, cmdLineUrl); + return m_instance; +} + +OpenPagesManager *OpenPagesManager::instance() +{ + TRACE_OBJ + Q_ASSERT(m_instance); + return m_instance; +} + +OpenPagesManager::OpenPagesManager(QObject *parent, bool defaultCollection, + const QUrl &cmdLineUrl) + : QObject(parent) + , m_model(new OpenPagesModel(this)) + , m_openPagesWidget(0) + , m_openPagesSwitcher(0) +{ + TRACE_OBJ + m_openPagesWidget = new OpenPagesWidget(m_model); + m_openPagesWidget->setFrameStyle(QFrame::NoFrame); + connect(m_openPagesWidget, SIGNAL(setCurrentPage(QModelIndex)), this, + SLOT(setCurrentPage(QModelIndex))); + connect(m_openPagesWidget, SIGNAL(closePage(QModelIndex)), this, + SLOT(closePage(QModelIndex))); + connect(m_openPagesWidget, SIGNAL(closePagesExcept(QModelIndex)), this, + SLOT(closePagesExcept(QModelIndex))); + + m_openPagesSwitcher = new OpenPagesSwitcher(m_model); + connect(m_openPagesSwitcher, SIGNAL(closePage(QModelIndex)), this, + SLOT(closePage(QModelIndex))); + connect(m_openPagesSwitcher, SIGNAL(setCurrentPage(QModelIndex)), this, + SLOT(setCurrentPage(QModelIndex))); + + setupInitialPages(defaultCollection, cmdLineUrl); +} + +OpenPagesManager ::~OpenPagesManager() +{ + TRACE_OBJ + m_instance = 0; + delete m_openPagesSwitcher; +} + +int OpenPagesManager::pageCount() const +{ + TRACE_OBJ + return m_model->rowCount(); +} + +void OpenPagesManager::setupInitialPages(bool defaultCollection, + const QUrl &cmdLineUrl) +{ + TRACE_OBJ + if (cmdLineUrl.isValid()) { + createPage(cmdLineUrl); + return; + } + + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + int initialPage = 0; + switch (helpEngine.startOption()) { + case ShowHomePage: + m_model->addPage(helpEngine.homePage()); + break; + case ShowBlankPage: + m_model->addPage(QUrl(QLatin1String("about:blank"))); + break; + case ShowLastPages: { + const QStringList &lastShownPageList = helpEngine.lastShownPages(); + const int pageCount = lastShownPageList.count(); + if (pageCount == 0) { + if (defaultCollection) + m_model->addPage(QUrl(QLatin1String("help"))); + else + m_model->addPage(QUrl(QLatin1String("about:blank"))); + } else { + QStringList zoomFactors = helpEngine.lastZoomFactors(); + while (zoomFactors.count() < pageCount) + zoomFactors.append(CollectionConfiguration::DefaultZoomFactor); + initialPage = helpEngine.lastTabPage(); + if (initialPage >= pageCount) { + qWarning("Initial page set to %d, maximum possible value is %d", + initialPage, pageCount - 1); + initialPage = 0; + } + for (int curPage = 0; curPage < pageCount; ++curPage) { + const QString &curFile = lastShownPageList.at(curPage); + if (helpEngine.findFile(curFile).isValid() + || curFile == QLatin1String("about:blank")) { + m_model->addPage(curFile, zoomFactors.at(curPage).toFloat()); + } else if (curPage <= initialPage && initialPage > 0) + --initialPage; + } + } + break; + } + default: + Q_ASSERT(!"Unhandled option"); + } + + if (m_model->rowCount() == 0) + m_model->addPage(helpEngine.homePage()); + for (int i = 0; i < m_model->rowCount(); ++i) + CentralWidget::instance()->addPage(m_model->pageAt(i)); + setCurrentPage((initialPage >= m_model->rowCount()) + ? m_model->rowCount() - 1 : initialPage); + m_openPagesSwitcher->selectCurrentPage(); +} + +HelpViewer *OpenPagesManager::createPage() +{ + TRACE_OBJ + return createPage(QUrl(QLatin1String("about:blank"))); +} + +void OpenPagesManager::closeCurrentPage() +{ + TRACE_OBJ + Q_ASSERT(m_model->rowCount() > 1); + const QModelIndexList selectedIndexes + = m_openPagesWidget->selectionModel()->selectedRows(); + if (selectedIndexes.isEmpty()) + return; + Q_ASSERT(selectedIndexes.count() == 1); + removePage(selectedIndexes.first().row()); +} + +HelpViewer *OpenPagesManager::createPage(const QUrl &url, bool fromSearch) +{ + TRACE_OBJ + if (HelpViewer::launchWithExternalApp(url)) + return 0; + + m_model->addPage(url); + const int index = m_model->rowCount() - 1; + HelpViewer * const page = m_model->pageAt(index); + CentralWidget::instance()->addPage(page, fromSearch); + setCurrentPage(index); + return page; +} + +HelpViewer *OpenPagesManager::createNewPageFromSearch(const QUrl &url) +{ + TRACE_OBJ + return createPage(url, true); +} + +void OpenPagesManager::closePage(HelpViewer *viewer) +{ + TRACE_OBJ + for (int i = 0; i < m_model->rowCount(); ++i) { + if (m_model->pageAt(i) == viewer) { + removePage(i); + break; + } + } +} + +void OpenPagesManager::closePage(const QModelIndex &index) +{ + TRACE_OBJ + if (index.isValid()) + removePage(index.row()); +} + +void OpenPagesManager::closePages(const QString &nameSpace) +{ + TRACE_OBJ + closeOrReloadPages(nameSpace, false); +} + +void OpenPagesManager::reloadPages(const QString &nameSpace) +{ + TRACE_OBJ + closeOrReloadPages(nameSpace, true); + m_openPagesWidget->selectCurrentPage(); +} + +void OpenPagesManager::closeOrReloadPages(const QString &nameSpace, bool tryReload) +{ + TRACE_OBJ + for (int i = m_model->rowCount() - 1; i >= 0; --i) { + HelpViewer *page = m_model->pageAt(i); + if (page->source().host() != nameSpace) + continue; + if (tryReload && HelpEngineWrapper::instance().findFile(page->source()).isValid()) + page->reload(); + else if (m_model->rowCount() == 1) + page->setSource(QUrl(QLatin1String("about:blank"))); + else + removePage(i); + } +} + +bool OpenPagesManager::pagesOpenForNamespace(const QString &nameSpace) const +{ + TRACE_OBJ + for (int i = 0; i < m_model->rowCount(); ++i) + if (m_model->pageAt(i)->source().host() == nameSpace) + return true; + return false; +} + +void OpenPagesManager::setCurrentPage(const QModelIndex &index) +{ + TRACE_OBJ + if (index.isValid()) + setCurrentPage(index.row()); +} + +void OpenPagesManager::setCurrentPage(int index) +{ + TRACE_OBJ + setCurrentPage(m_model->pageAt(index)); +} + +void OpenPagesManager::setCurrentPage(HelpViewer *page) +{ + TRACE_OBJ + CentralWidget::instance()->setCurrentPage(page); + m_openPagesWidget->selectCurrentPage(); +} + +void OpenPagesManager::removePage(int index) +{ + TRACE_OBJ + CentralWidget::instance()->removePage(index); + m_model->removePage(index); + m_openPagesWidget->selectCurrentPage(); +} + + +void OpenPagesManager::closePagesExcept(const QModelIndex &index) +{ + TRACE_OBJ + if (!index.isValid()) + return; + + int i = 0; + HelpViewer *viewer = m_model->pageAt(index.row()); + while (m_model->rowCount() > 1) { + if (m_model->pageAt(i) != viewer) + removePage(i); + else + ++i; + } +} + +QAbstractItemView *OpenPagesManager::openPagesWidget() const +{ + TRACE_OBJ + return m_openPagesWidget; +} + +void OpenPagesManager::nextPage() +{ + TRACE_OBJ + nextOrPreviousPage(1); +} + +void OpenPagesManager::nextPageWithSwitcher() +{ + TRACE_OBJ + if (!m_openPagesSwitcher->isVisible()) { + m_openPagesSwitcher->selectCurrentPage(); + m_openPagesSwitcher->gotoNextPage(); + showSwitcherOrSelectPage(); + } else { + m_openPagesSwitcher->gotoNextPage(); + } +} + +void OpenPagesManager::previousPage() +{ + TRACE_OBJ + nextOrPreviousPage(-1); +} + +void OpenPagesManager::previousPageWithSwitcher() +{ + TRACE_OBJ + if (!m_openPagesSwitcher->isVisible()) { + m_openPagesSwitcher->selectCurrentPage(); + m_openPagesSwitcher->gotoPreviousPage(); + showSwitcherOrSelectPage(); + } else { + m_openPagesSwitcher->gotoPreviousPage(); + } +} + +void OpenPagesManager::nextOrPreviousPage(int offset) +{ + TRACE_OBJ + setCurrentPage((CentralWidget::instance()->currentIndex() + offset + + m_model->rowCount()) % m_model->rowCount()); +} + +void OpenPagesManager::showSwitcherOrSelectPage() const +{ + TRACE_OBJ + if (QApplication::keyboardModifiers() != Qt::NoModifier) { + const int width = CentralWidget::instance()->width(); + const int height = CentralWidget::instance()->height(); + const QPoint p(CentralWidget::instance()->mapToGlobal(QPoint(0, 0))); + m_openPagesSwitcher->move((width - m_openPagesSwitcher->width()) / 2 + p.x(), + (height - m_openPagesSwitcher->height()) / 2 + p.y()); + m_openPagesSwitcher->setVisible(true); + } else { + m_openPagesSwitcher->selectAndHide(); + } +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/openpagesmanager.h b/tools/assistant/tools/assistant/openpagesmanager.h new file mode 100644 index 0000000..6037cd9 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesmanager.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OPENPAGESMANAGER_H +#define OPENPAGESMANAGER_H + +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class QAbstractItemView; +class QModelIndex; +class QUrl; + +class HelpViewer; +class OpenPagesModel; +class OpenPagesSwitcher; +class OpenPagesWidget; + +class OpenPagesManager : public QObject +{ + Q_OBJECT +public: + static OpenPagesManager *createInstance(QObject *parent, + bool defaultCollection, const QUrl &cmdLineUrl); + static OpenPagesManager *instance(); + + bool pagesOpenForNamespace(const QString &nameSpace) const; + void closePages(const QString &nameSpace); + void reloadPages(const QString &nameSpace); + + QAbstractItemView* openPagesWidget() const; + + int pageCount() const; + void setCurrentPage(int index); + +public slots: + HelpViewer *createPage(const QUrl &url, bool fromSearch = false); + HelpViewer *createNewPageFromSearch(const QUrl &url); + HelpViewer *createPage(); + void closeCurrentPage(); + + void nextPage(); + void nextPageWithSwitcher(); + void previousPage(); + void previousPageWithSwitcher(); + + void closePage(HelpViewer *page); + void setCurrentPage(HelpViewer *page); + +private slots: + void setCurrentPage(const QModelIndex &index); + void closePage(const QModelIndex &index); + void closePagesExcept(const QModelIndex &index); + +private: + OpenPagesManager(QObject *parent, bool defaultCollection, + const QUrl &cmdLineUrl); + ~OpenPagesManager(); + + void setupInitialPages(bool defaultCollection, const QUrl &cmdLineUrl); + void closeOrReloadPages(const QString &nameSpace, bool tryReload); + void removePage(int index); + + void nextOrPreviousPage(int offset); + void showSwitcherOrSelectPage() const; + + OpenPagesModel *m_model; + OpenPagesWidget *m_openPagesWidget; + OpenPagesSwitcher *m_openPagesSwitcher; + + static OpenPagesManager *m_instance; +}; + +QT_END_NAMESPACE + +#endif // OPENPAGESMANAGER_H diff --git a/tools/assistant/tools/assistant/openpagesmodel.cpp b/tools/assistant/tools/assistant/openpagesmodel.cpp new file mode 100644 index 0000000..c18dac1 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesmodel.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "openpagesmodel.h" + +#include "helpenginewrapper.h" +#include "helpviewer.h" +#include "tracer.h" + +#include <QtCore/QStringList> +#include <QtCore/QUrl> + +QT_BEGIN_NAMESPACE + +OpenPagesModel::OpenPagesModel(QObject *parent) : QAbstractTableModel(parent) +{ + TRACE_OBJ +} + +int OpenPagesModel::rowCount(const QModelIndex &parent) const +{ + TRACE_OBJ + return parent.isValid() ? 0 : m_pages.count(); +} + +int OpenPagesModel::columnCount(const QModelIndex &/*parent*/) const +{ + TRACE_OBJ + return 2; +} + +QVariant OpenPagesModel::data(const QModelIndex &index, int role) const +{ + TRACE_OBJ + if (!index.isValid() || index.row() >= rowCount() || index.column() > 0 + || role != Qt::DisplayRole) + return QVariant(); + QString title = m_pages.at(index.row())->title(); + title.replace(QLatin1Char('&'), QLatin1String("&&")); + return title.isEmpty() ? QLatin1String("(Untitled)") : title; +} + +void OpenPagesModel::addPage(const QUrl &url, qreal zoom) +{ + TRACE_OBJ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + HelpViewer *page = new HelpViewer(zoom); + connect(page, SIGNAL(titleChanged()), this, SLOT(handleTitleChanged())); + m_pages << page; + endInsertRows(); + page->setSource(url); +} + +void OpenPagesModel::removePage(int index) +{ + TRACE_OBJ + Q_ASSERT(index >= 0 && index < rowCount()); + beginRemoveRows(QModelIndex(), index, index); + HelpViewer *page = m_pages.at(index); + m_pages.removeAt(index); + endRemoveRows(); + page->deleteLater(); +} + +HelpViewer *OpenPagesModel::pageAt(int index) const +{ + TRACE_OBJ + Q_ASSERT(index >= 0 && index < rowCount()); + return m_pages.at(index); +} + +void OpenPagesModel::handleTitleChanged() +{ + TRACE_OBJ + HelpViewer *page = static_cast<HelpViewer *>(sender()); + const int row = m_pages.indexOf(page); + Q_ASSERT(row != -1 ); + const QModelIndex &item = index(row, 0); + emit dataChanged(item, item); +} + +QT_END_NAMESPACE diff --git a/tools/qtconfig/previewwidgetbase.cpp b/tools/assistant/tools/assistant/openpagesmodel.h index e186175..ea75233 100644 --- a/tools/qtconfig/previewwidgetbase.cpp +++ b/tools/assistant/tools/assistant/openpagesmodel.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the tools applications of the Qt Toolkit. +** This file is part of the Assistant module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage @@ -39,50 +39,38 @@ ** ****************************************************************************/ -#include "previewwidgetbase.h" +#ifndef OPENPAGESMODEL_H +#define OPENPAGESMODEL_H -#include <QVariant> +#include <QtCore/QAbstractTableModel> +#include <QtCore/QList> QT_BEGIN_NAMESPACE -/* - * Constructs a PreviewWidgetBase as a child of 'parent', with the - * name 'name' and widget flags set to 'f'. - */ -PreviewWidgetBase::PreviewWidgetBase(QWidget* parent, const char* name, Qt::WindowFlags fl) - : QWidget(parent, name, fl) -{ - setupUi(this); - +class HelpViewer; +class QUrl; - // signals and slots connections - init(); -} - -/* - * Destroys the object and frees any allocated resources - */ -PreviewWidgetBase::~PreviewWidgetBase() +class OpenPagesModel : public QAbstractTableModel { - destroy(); - // no need to delete child widgets, Qt does it all for us -} + Q_OBJECT +public: + OpenPagesModel(QObject *parent); -/* - * Sets the strings of the subwidgets using the current - * language. - */ -void PreviewWidgetBase::languageChange() -{ - retranslateUi(this); -} + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; -void PreviewWidgetBase::init() -{ -} + void addPage(const QUrl &url, qreal zoom = 0); + void removePage(int index); + HelpViewer *pageAt(int index) const; -void PreviewWidgetBase::destroy() -{ -} +private slots: + void handleTitleChanged(); + +private: + QList<HelpViewer *> m_pages; +}; QT_END_NAMESPACE + +#endif // OPENPAGESMODEL_H diff --git a/tools/assistant/tools/assistant/openpagesswitcher.cpp b/tools/assistant/tools/assistant/openpagesswitcher.cpp new file mode 100644 index 0000000..cc6ef23 --- /dev/null +++ b/tools/assistant/tools/assistant/openpagesswitcher.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "openpagesswitcher.h" + +#include "centralwidget.h" +#include "openpagesmodel.h" +#include "openpageswidget.h" +#include "tracer.h" + +#include <QtCore/QEvent> + +#include <QtGui/QKeyEvent> +#include <QtGui/QVBoxLayout> + +QT_BEGIN_NAMESPACE + +const int gWidth = 300; +const int gHeight = 200; + +OpenPagesSwitcher::OpenPagesSwitcher(OpenPagesModel *model) + : QFrame(0, Qt::Popup) + , m_openPagesModel(model) +{ + TRACE_OBJ + resize(gWidth, gHeight); + + m_openPagesWidget = new OpenPagesWidget(m_openPagesModel); + + // We disable the frame on this list view and use a QFrame around it instead. + // This improves the look with QGTKStyle. +#ifndef Q_WS_MAC + setFrameStyle(m_openPagesWidget->frameStyle()); +#endif + m_openPagesWidget->setFrameStyle(QFrame::NoFrame); + + m_openPagesWidget->allowContextMenu(false); + m_openPagesWidget->installEventFilter(this); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->addWidget(m_openPagesWidget); + + connect(m_openPagesWidget, SIGNAL(closePage(QModelIndex)), this, + SIGNAL(closePage(QModelIndex))); + connect(m_openPagesWidget, SIGNAL(setCurrentPage(QModelIndex)), this, + SIGNAL(setCurrentPage(QModelIndex))); +} + +OpenPagesSwitcher::~OpenPagesSwitcher() +{ + TRACE_OBJ +} + +void OpenPagesSwitcher::gotoNextPage() +{ + TRACE_OBJ + selectPageUpDown(1); +} + +void OpenPagesSwitcher::gotoPreviousPage() +{ + TRACE_OBJ + selectPageUpDown(-1); +} + +void OpenPagesSwitcher::selectAndHide() +{ + TRACE_OBJ + setVisible(false); + emit setCurrentPage(m_openPagesWidget->currentIndex()); +} + +void OpenPagesSwitcher::selectCurrentPage() +{ + TRACE_OBJ + m_openPagesWidget->selectCurrentPage(); +} + +void OpenPagesSwitcher::setVisible(bool visible) +{ + TRACE_OBJ + QWidget::setVisible(visible); + if (visible) + setFocus(); +} + +void OpenPagesSwitcher::focusInEvent(QFocusEvent *event) +{ + TRACE_OBJ + Q_UNUSED(event) + m_openPagesWidget->setFocus(); +} + +bool OpenPagesSwitcher::eventFilter(QObject *object, QEvent *event) +{ + TRACE_OBJ + if (object == m_openPagesWidget) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + if (ke->key() == Qt::Key_Escape) { + setVisible(false); + return true; + } + + const int key = ke->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter || key == Qt::Key_Space) { + emit setCurrentPage(m_openPagesWidget->currentIndex()); + return true; + } + + Qt::KeyboardModifier modifier = Qt::ControlModifier; +#ifdef Q_WS_MAC + modifier = Qt::AltModifier; +#endif + if (key == Qt::Key_Backtab + && (ke->modifiers() == (modifier | Qt::ShiftModifier))) + gotoPreviousPage(); + else if (key == Qt::Key_Tab && (ke->modifiers() == modifier)) + gotoNextPage(); + } else if (event->type() == QEvent::KeyRelease) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + if (ke->modifiers() == 0 + /*HACK this is to overcome some event inconsistencies between platforms*/ + || (ke->modifiers() == Qt::AltModifier + && (ke->key() == Qt::Key_Alt || ke->key() == -1))) { + selectAndHide(); + } + } + } + return QWidget::eventFilter(object, event); +} + +void OpenPagesSwitcher::selectPageUpDown(int summand) +{ + TRACE_OBJ + const int pageCount = m_openPagesModel->rowCount(); + if (pageCount < 2) + return; + + const QModelIndexList &list = m_openPagesWidget->selectionModel()->selectedIndexes(); + if (list.isEmpty()) + return; + + QModelIndex index = list.first(); + if (!index.isValid()) + return; + + index = m_openPagesModel->index((index.row() + summand + pageCount) % pageCount, 0); + if (index.isValid()) { + m_openPagesWidget->setCurrentIndex(index); + m_openPagesWidget->scrollTo(index, QAbstractItemView::PositionAtCenter); + } +} + +QT_END_NAMESPACE diff --git a/tools/qtconfig/paletteeditoradvancedbase.h b/tools/assistant/tools/assistant/openpagesswitcher.h index 03aad7a..cfd09ff 100644 --- a/tools/qtconfig/paletteeditoradvancedbase.h +++ b/tools/assistant/tools/assistant/openpagesswitcher.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the tools applications of the Qt Toolkit. +** This file is part of the Assistant module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage @@ -39,40 +39,47 @@ ** ****************************************************************************/ -#ifndef PALETTEEDITORADVANCEDBASE_H -#define PALETTEEDITORADVANCEDBASE_H +#ifndef OPENPAGESSWITCHER_H +#define OPENPAGESSWITCHER_H -#include "ui_paletteeditoradvancedbase.h" -#include <QVariant> +#include <QtGui/QFrame> QT_BEGIN_NAMESPACE -class ColorButton; +class OpenPagesModel; +class OpenPagesWidget; +class QModelIndex; -class PaletteEditorAdvancedBase : public QDialog, public Ui::PaletteEditorAdvancedBase +class OpenPagesSwitcher : public QFrame { Q_OBJECT public: - PaletteEditorAdvancedBase(QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WindowFlags fl = 0); - ~PaletteEditorAdvancedBase(); + OpenPagesSwitcher(OpenPagesModel *model); + ~OpenPagesSwitcher(); -protected slots: - virtual void languageChange(); + void gotoNextPage(); + void gotoPreviousPage(); - virtual void init(); - virtual void destroy(); - virtual void onCentral(int); - virtual void onChooseCentralColor(); - virtual void onChooseEffectColor(); - virtual void onEffect(int); - virtual void onToggleBuildDisabled(bool); - virtual void onToggleBuildEffects(bool); - virtual void onToggleBuildInactive(bool); - virtual void paletteSelected(int); + void selectAndHide(); + void selectCurrentPage(); + void setVisible(bool visible); + void focusInEvent(QFocusEvent *event); + bool eventFilter(QObject *object, QEvent *event); + +signals: + void closePage(const QModelIndex &index); + void setCurrentPage(const QModelIndex &index); + +private: + void selectPageUpDown(int summand); + +private: + OpenPagesModel *m_openPagesModel; + OpenPagesWidget *m_openPagesWidget; }; QT_END_NAMESPACE -#endif // PALETTEEDITORADVANCEDBASE_H +#endif // OPENPAGESSWITCHER_H diff --git a/tools/assistant/tools/assistant/openpageswidget.cpp b/tools/assistant/tools/assistant/openpageswidget.cpp new file mode 100644 index 0000000..59a0832 --- /dev/null +++ b/tools/assistant/tools/assistant/openpageswidget.cpp @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "openpageswidget.h" + +#include "centralwidget.h" +#include "openpagesmodel.h" +#include "tracer.h" + +#include <QtGui/QApplication> +#include <QtGui/QHeaderView> +#include <QtGui/QKeyEvent> +#include <QtGui/QMouseEvent> +#include <QtGui/QMenu> +#include <QtGui/QPainter> + +#ifdef Q_WS_MAC +#include <qmacstyle_mac.h> +#endif + +QT_BEGIN_NAMESPACE + +OpenPagesDelegate::OpenPagesDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ + TRACE_OBJ +} + +void OpenPagesDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + TRACE_OBJ + if (option.state & QStyle::State_MouseOver) { + if ((QApplication::mouseButtons() & Qt::LeftButton) == 0) + pressedIndex = QModelIndex(); + QBrush brush = option.palette.alternateBase(); + if (index == pressedIndex) + brush = option.palette.dark(); + painter->fillRect(option.rect, brush); + } + + QStyledItemDelegate::paint(painter, option, index); + + if (index.column() == 1 && index.model()->rowCount() > 1 + && option.state & QStyle::State_MouseOver) { + QIcon icon((option.state & QStyle::State_Selected) + ? ":/trolltech/assistant/images/closebutton.png" + : ":/trolltech/assistant/images/darkclosebutton.png"); + + const QRect iconRect(option.rect.right() - option.rect.height(), + option.rect.top(), option.rect.height(), option.rect.height()); + icon.paint(painter, iconRect, Qt::AlignRight | Qt::AlignVCenter); + } +} + +// -- OpenPagesWidget + +OpenPagesWidget::OpenPagesWidget(OpenPagesModel *model) + : m_allowContextMenu(true) +{ + TRACE_OBJ + setModel(model); + setIndentation(0); + setItemDelegate((m_delegate = new OpenPagesDelegate(this))); + + setTextElideMode(Qt::ElideMiddle); + setAttribute(Qt::WA_MacShowFocusRect, false); + + viewport()->setAttribute(Qt::WA_Hover); + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::SingleSelection); + + header()->hide(); + header()->setStretchLastSection(false); + header()->setResizeMode(0, QHeaderView::Stretch); + header()->setResizeMode(1, QHeaderView::Fixed); + header()->resizeSection(1, 18); + + installEventFilter(this); + setUniformRowHeights(true); + setContextMenuPolicy(Qt::CustomContextMenu); + + connect(this, SIGNAL(clicked(QModelIndex)), this, + SLOT(handleClicked(QModelIndex))); + connect(this, SIGNAL(pressed(QModelIndex)), this, + SLOT(handlePressed(QModelIndex))); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(contextMenuRequested(QPoint))); +} + +OpenPagesWidget::~OpenPagesWidget() +{ + TRACE_OBJ +} + +void OpenPagesWidget::selectCurrentPage() +{ + TRACE_OBJ + const QModelIndex ¤t = + model()->index(CentralWidget::instance()->currentIndex(), 0); + + QItemSelectionModel * const selModel = selectionModel(); + selModel->select(current, + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + selModel->clearSelection(); + + setCurrentIndex(current); + scrollTo(currentIndex()); +} + +void OpenPagesWidget::allowContextMenu(bool ok) +{ + TRACE_OBJ + m_allowContextMenu = ok; +} + +void OpenPagesWidget::contextMenuRequested(QPoint pos) +{ + TRACE_OBJ + QModelIndex index = indexAt(pos); + if (!index.isValid() || !m_allowContextMenu) + return; + + if (index.column() == 1) + index = index.sibling(index.row(), 0); + QMenu contextMenu; + QAction *closeEditor = contextMenu.addAction(tr("Close %1").arg(index.data() + .toString())); + QAction *closeOtherEditors = contextMenu.addAction(tr("Close All Except %1") + .arg(index.data().toString())); + + if (model()->rowCount() == 1) { + closeEditor->setEnabled(false); + closeOtherEditors->setEnabled(false); + } + + QAction *action = contextMenu.exec(mapToGlobal(pos)); + if (action == closeEditor) + emit closePage(index); + else if (action == closeOtherEditors) + emit closePagesExcept(index); +} + +void OpenPagesWidget::handlePressed(const QModelIndex &index) +{ + TRACE_OBJ + if (index.column() == 0) + emit setCurrentPage(index); + + if (index.column() == 1) + m_delegate->pressedIndex = index; +} + +void OpenPagesWidget::handleClicked(const QModelIndex &index) +{ + TRACE_OBJ + // implemented here to handle the funky close button and to work around a + // bug in item views where the delegate wouldn't get the QStyle::State_MouseOver + if (index.column() == 1) { + if (model()->rowCount() > 1) + emit closePage(index); + + QWidget *vp = viewport(); + const QPoint &cursorPos = QCursor::pos(); + QMouseEvent e(QEvent::MouseMove, vp->mapFromGlobal(cursorPos), cursorPos, + Qt::NoButton, 0, 0); + QCoreApplication::sendEvent(vp, &e); + } +} + +bool OpenPagesWidget::eventFilter(QObject *obj, QEvent *event) +{ + TRACE_OBJ + if (obj != this) + return QWidget::eventFilter(obj, event); + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + if (currentIndex().isValid() && ke->modifiers() == 0) { + const int key = ke->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter + || key == Qt::Key_Space) { + emit setCurrentPage(currentIndex()); + } else if ((key == Qt::Key_Delete || key == Qt::Key_Backspace) + && model()->rowCount() > 1) { + emit closePage(currentIndex()); + } + } + } else if (event->type() == QEvent::KeyRelease) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + if (ke->modifiers() == 0 + && (ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down)) { + emit setCurrentPage(currentIndex()); + } + } + return QWidget::eventFilter(obj, event); +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/openpageswidget.h b/tools/assistant/tools/assistant/openpageswidget.h new file mode 100644 index 0000000..4f66a9f --- /dev/null +++ b/tools/assistant/tools/assistant/openpageswidget.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Assistant module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OPENPAGESWIDGET_H +#define OPENPAGESWIDGET_H + +#include <QtGui/QStyledItemDelegate> +#include <QtGui/QTreeView> + +QT_BEGIN_NAMESPACE + +class OpenPagesModel; + +class OpenPagesDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit OpenPagesDelegate(QObject *parent = 0); + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + mutable QModelIndex pressedIndex; +}; + +class OpenPagesWidget : public QTreeView +{ + Q_OBJECT +public: + OpenPagesWidget(OpenPagesModel *model); + ~OpenPagesWidget(); + + void selectCurrentPage(); + void allowContextMenu(bool ok); + +signals: + void setCurrentPage(const QModelIndex &index); + void closePage(const QModelIndex &index); + void closePagesExcept(const QModelIndex &index); + +private slots: + void contextMenuRequested(QPoint pos); + void handlePressed(const QModelIndex &index); + void handleClicked(const QModelIndex &index); + +private: + bool eventFilter(QObject *obj, QEvent *event); + + bool m_allowContextMenu; + OpenPagesDelegate *m_delegate; +}; + +QT_END_NAMESPACE + +#endif // OPENPAGESWIDGET_H diff --git a/tools/assistant/tools/assistant/preferencesdialog.cpp b/tools/assistant/tools/assistant/preferencesdialog.cpp index d0d8c3d..dd54b79 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.cpp +++ b/tools/assistant/tools/assistant/preferencesdialog.cpp @@ -45,6 +45,7 @@ #include "fontpanel.h" #include "helpenginewrapper.h" #include "installdialog.h" +#include "openpagesmanager.h" #include "tracer.h" #include <QtCore/QtAlgorithms> @@ -302,15 +303,12 @@ void PreferencesDialog::addDocumentationLocal() void PreferencesDialog::removeDocumentation() { TRACE_OBJ - bool foundBefore = false; - CentralWidget* widget = CentralWidget::instance(); - QMap<int, QString> openedDocList = widget->currentSourceFileList(); - QStringList values(openedDocList.values()); + bool foundBefore = false; QList<QListWidgetItem*> l = m_ui.registeredDocsListWidget->selectedItems(); foreach (QListWidgetItem* item, l) { const QString& ns = item->text(); - if (!foundBefore && values.contains(ns)) { + if (!foundBefore && OpenPagesManager::instance()->pagesOpenForNamespace(ns)) { if (0 == QMessageBox::information(this, tr("Remove Documentation"), tr("Some documents currently opened in Assistant reference the " "documentation you are attempting to remove. Removing the " @@ -320,7 +318,6 @@ void PreferencesDialog::removeDocumentation() } m_unregDocs.append(ns); - m_TabsToClose += openedDocList.keys(ns); delete m_ui.registeredDocsListWidget->takeItem( m_ui.registeredDocsListWidget->row(item)); } @@ -374,14 +371,18 @@ void PreferencesDialog::applyChanges() } } - CentralWidget::instance()->closeOrReloadTabs(m_TabsToClose, false); - - foreach (const QString &doc, m_unregDocs) + foreach (const QString &doc, m_unregDocs) { + OpenPagesManager::instance()->closePages(doc); helpEngine.unregisterDocumentation(doc); + } if (filtersWereChanged || !m_regDocs.isEmpty() || !m_unregDocs.isEmpty()) helpEngine.setupData(); + helpEngine.setShowTabs(m_ui.showTabs->isChecked()); + if (m_showTabs != m_ui.showTabs->isChecked()) + emit updateUserInterface(); + accept(); } @@ -424,13 +425,13 @@ void PreferencesDialog::updateFontSettingsPage() connect(m_browserFontPanel, SIGNAL(toggled(bool)), this, SLOT(browserFontSettingToggled(bool))); - QList<QComboBox*> allCombos = qFindChildren<QComboBox*>(m_appFontPanel); + QList<QComboBox*> allCombos = m_appFontPanel->findChildren<QComboBox*>(); foreach (QComboBox* box, allCombos) { connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(appFontSettingChanged(int))); } - allCombos = qFindChildren<QComboBox*>(m_browserFontPanel); + allCombos = m_browserFontPanel->findChildren<QComboBox*>(); foreach (QComboBox* box, allCombos) { connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(browserFontSettingChanged(int))); @@ -473,6 +474,9 @@ void PreferencesDialog::updateOptionsPage() int option = helpEngine.startOption(); m_ui.helpStartComboBox->setCurrentIndex(option); + m_showTabs = helpEngine.showTabs(); + m_ui.showTabs->setChecked(m_showTabs); + connect(m_ui.blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage())); connect(m_ui.currentPageButton, SIGNAL(clicked()), this, SLOT(setCurrentPage())); connect(m_ui.defaultPageButton, SIGNAL(clicked()), this, SLOT(setDefaultPage())); diff --git a/tools/assistant/tools/assistant/preferencesdialog.h b/tools/assistant/tools/assistant/preferencesdialog.h index b79053e..520544c 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.h +++ b/tools/assistant/tools/assistant/preferencesdialog.h @@ -81,6 +81,7 @@ private slots: signals: void updateBrowserFont(); void updateApplicationFont(); + void updateUserInterface(); private: void updateFilterPage(); @@ -96,12 +97,12 @@ private: QStringList m_docsBackup; QStringList m_regDocs; QStringList m_unregDocs; - QList<int> m_TabsToClose; FontPanel *m_appFontPanel; FontPanel *m_browserFontPanel; bool m_appFontChanged; bool m_browserFontChanged; HelpEngineWrapper &helpEngine; + bool m_showTabs; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/preferencesdialog.ui b/tools/assistant/tools/assistant/preferencesdialog.ui index 279084d..1c6833a 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.ui +++ b/tools/assistant/tools/assistant/preferencesdialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>375</width> - <height>266</height> + <height>275</height> </rect> </property> <property name="windowTitle"> @@ -187,7 +187,7 @@ <attribute name="title"> <string>Options</string> </attribute> - <layout class="QVBoxLayout" name="verticalLayout_2"> + <layout class="QVBoxLayout" name="verticalLayout_3"> <item> <widget class="QGroupBox" name="groupBox_2"> <property name="title"> @@ -310,6 +310,22 @@ </widget> </item> <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Appearance</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QCheckBox" name="showTabs"> + <property name="text"> + <string>Show tabs for each individual page</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> <spacer name="verticalSpacer_2"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/tools/assistant/tools/assistant/remotecontrol.cpp b/tools/assistant/tools/assistant/remotecontrol.cpp index e17e04d..752cae7 100644 --- a/tools/assistant/tools/assistant/remotecontrol.cpp +++ b/tools/assistant/tools/assistant/remotecontrol.cpp @@ -38,12 +38,13 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "tracer.h" - #include "remotecontrol.h" -#include "mainwindow.h" + #include "centralwidget.h" #include "helpenginewrapper.h" +#include "mainwindow.h" +#include "openpagesmanager.h" +#include "tracer.h" #include <QtCore/QFile> #include <QtCore/QFileInfo> @@ -57,6 +58,7 @@ #include <QtHelp/QHelpEngine> #include <QtHelp/QHelpIndexWidget> +#include <QtHelp/QHelpSearchQueryWidget> #ifdef Q_OS_WIN # include "remotecontrol_win.h" @@ -259,8 +261,25 @@ void RemoteControl::handleActivateKeywordCommand(const QString &arg) m_activateKeyword = arg; } else { m_mainWindow->setIndexString(arg); - if (!arg.isEmpty()) - helpEngine.indexWidget()->activateCurrentItem(); + if (!arg.isEmpty()) { + if (!helpEngine.indexWidget()->currentIndex().isValid() + && helpEngine.fullTextSearchFallbackEnabled()) { + if (QHelpSearchEngine *se = helpEngine.searchEngine()) { + m_mainWindow->setSearchVisible(true); + if (QHelpSearchQueryWidget *w = se->queryWidget()) { + w->collapseExtendedSearch(); + QList<QHelpSearchQuery> queryList; + queryList << QHelpSearchQuery(QHelpSearchQuery::DEFAULT, + QStringList(arg)); + w->setQuery(queryList); + se->search(queryList); + } + } + } else { + m_mainWindow->setIndexVisible(true); + helpEngine.indexWidget()->activateCurrentItem(); + } + } } } @@ -323,8 +342,7 @@ void RemoteControl::handleUnregisterCommand(const QString &arg) const QString &absFileName = QFileInfo(arg).absoluteFilePath(); const QString &ns = QHelpEngineCore::namespaceName(absFileName); if (helpEngine.registeredDocumentations().contains(ns)) { - CentralWidget* widget = CentralWidget::instance(); - widget->closeOrReloadTabs(widget->currentSourceFileList().keys(ns), false); + OpenPagesManager::instance()->closePages(ns); if (helpEngine.unregisterDocumentation(ns)) helpEngine.setupData(); } diff --git a/tools/assistant/tools/assistant/searchwidget.cpp b/tools/assistant/tools/assistant/searchwidget.cpp index 2a4c253..8b15b75 100644 --- a/tools/assistant/tools/assistant/searchwidget.cpp +++ b/tools/assistant/tools/assistant/searchwidget.cpp @@ -63,7 +63,6 @@ QT_BEGIN_NAMESPACE SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent) : QWidget(parent) , zoomCount(0) - , attached(false) , searchEngine(engine) { TRACE_OBJ @@ -86,7 +85,7 @@ SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent) connect(searchEngine, SIGNAL(searchingFinished(int)), this, SLOT(searchingFinished(int))); - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser) // Will be null if lib was configured not to use CLucene. browser->viewport()->installEventFilter(this); } @@ -100,7 +99,7 @@ SearchWidget::~SearchWidget() void SearchWidget::zoomIn() { TRACE_OBJ - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser && zoomCount != 10) { zoomCount++; browser->zoomIn(); @@ -110,7 +109,7 @@ void SearchWidget::zoomIn() void SearchWidget::zoomOut() { TRACE_OBJ - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser && zoomCount != -5) { zoomCount--; browser->zoomOut(); @@ -123,25 +122,13 @@ void SearchWidget::resetZoom() if (zoomCount == 0) return; - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser) { browser->zoomOut(zoomCount); zoomCount = 0; } } -bool SearchWidget::isAttached() const -{ - TRACE_OBJ - return attached; -} - -void SearchWidget::setAttached(bool state) -{ - TRACE_OBJ - attached = state; -} - void SearchWidget::search() const { TRACE_OBJ @@ -165,7 +152,7 @@ void SearchWidget::searchingFinished(int hits) bool SearchWidget::eventFilter(QObject* o, QEvent *e) { TRACE_OBJ - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (browser && o == browser->viewport() && e->type() == QEvent::MouseButtonRelease){ QMouseEvent *me = static_cast<QMouseEvent*>(e); @@ -196,7 +183,7 @@ void SearchWidget::contextMenuEvent(QContextMenuEvent *contextMenuEvent) QMenu menu; QPoint point = contextMenuEvent->globalPos(); - QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); + QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); if (!browser) return; diff --git a/tools/assistant/tools/assistant/searchwidget.h b/tools/assistant/tools/assistant/searchwidget.h index 7555fbc..f1f9987 100644 --- a/tools/assistant/tools/assistant/searchwidget.h +++ b/tools/assistant/tools/assistant/searchwidget.h @@ -65,9 +65,6 @@ public: void zoomOut(); void resetZoom(); - bool isAttached() const; - void setAttached(bool state); - signals: void requestShowLink(const QUrl &url); void requestShowLinkInNewTab(const QUrl &url); @@ -84,7 +81,6 @@ private: private: int zoomCount; - bool attached; QHelpSearchEngine *searchEngine; QHelpSearchResultWidget *resultWidget; }; diff --git a/tools/assistant/tools/qcollectiongenerator/main.cpp b/tools/assistant/tools/qcollectiongenerator/main.cpp index 04b45f2..9e0d7ed 100644 --- a/tools/assistant/tools/qcollectiongenerator/main.cpp +++ b/tools/assistant/tools/qcollectiongenerator/main.cpp @@ -97,6 +97,10 @@ public: QString cacheDirectory() const { return m_cacheDirectory; } bool cacheDirRelativeToCollection() const { return m_cacheDirRelativeToCollection; } + bool fullTextSearchFallbackEnabled() const { + return m_enableFullTextSearchFallback; + } + private: void raiseErrorWithLine(); void readConfig(); @@ -125,6 +129,7 @@ private: QStringList m_filesToRegister; QString m_cacheDirectory; bool m_cacheDirRelativeToCollection; + bool m_enableFullTextSearchFallback; }; void CollectionConfigReader::raiseErrorWithLine() @@ -139,6 +144,7 @@ void CollectionConfigReader::readData(const QByteArray &contents) m_enableAddressBar = true; m_hideAddressBar = true; m_enableDocumentationManager = true; + m_enableFullTextSearchFallback = false; addData(contents); while (!atEnd()) { @@ -212,6 +218,9 @@ void CollectionConfigReader::readAssistantSettings() attributes().value(QLatin1String("base")) == QLatin1String("collection"); m_cacheDirectory = readElementText(); + } else if (name() == QLatin1String("enableFullTextSearchFallback")) { + if (readElementText() == QLatin1String("true")) + m_enableFullTextSearchFallback = true; } else { raiseErrorWithLine(); } @@ -513,6 +522,8 @@ int main(int argc, char *argv[]) !config.hideAddressBar()); CollectionConfiguration::setCreationTime(helpEngine, QDateTime::currentDateTime().toTime_t()); + CollectionConfiguration::setFullTextSearchFallbackEnabled(helpEngine, + config.fullTextSearchFallbackEnabled()); if (!config.applicationIcon().isEmpty()) { QFile icon(absoluteFileName(basePath, config.applicationIcon())); diff --git a/tools/assistant/tools/shared/collectionconfiguration.cpp b/tools/assistant/tools/shared/collectionconfiguration.cpp index ef31d09..702fada 100644 --- a/tools/assistant/tools/shared/collectionconfiguration.cpp +++ b/tools/assistant/tools/shared/collectionconfiguration.cpp @@ -71,6 +71,7 @@ namespace { #endif )); const QString WindowTitleKey(QLatin1String("WindowTitle")); + const QString FullTextSearchFallbackKey(QLatin1String("FullTextSearchFallback")); } // anonymous namespace const QString CollectionConfiguration::DefaultZoomFactor(QLatin1String("0.0")); @@ -308,6 +309,19 @@ void CollectionConfiguration::copyConfiguration(const QHelpEngineCore &source, setAboutTexts(target, aboutTexts(source)); setAboutImages(target, aboutImages(source)); setDefaultHomePage(target, defaultHomePage(source)); + setFullTextSearchFallbackEnabled(target, fullTextSearchFallbackEnabled(source)); +} + +bool CollectionConfiguration:: fullTextSearchFallbackEnabled( + const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(FullTextSearchFallbackKey, false).toBool(); +} + +void CollectionConfiguration::setFullTextSearchFallbackEnabled( + QHelpEngineCore &helpEngine, bool on) +{ + helpEngine.setCustomValue(FullTextSearchFallbackKey, on); } QT_END_NAMESPACE diff --git a/tools/assistant/tools/shared/collectionconfiguration.h b/tools/assistant/tools/shared/collectionconfiguration.h index 124309e..da2267b 100644 --- a/tools/assistant/tools/shared/collectionconfiguration.h +++ b/tools/assistant/tools/shared/collectionconfiguration.h @@ -136,6 +136,10 @@ public: static const QDateTime lastRegisterTime(const QHelpEngineCore &helpEngine); static void updateLastRegisterTime(QHelpEngineCore &helpEngine); + static bool fullTextSearchFallbackEnabled(const QHelpEngineCore &helpEngine); + static void setFullTextSearchFallbackEnabled(QHelpEngineCore &helpEngine, + bool on); + static const QString DefaultZoomFactor; static const QString ListSeparator; }; diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro index 0a49fbe..c2f1b65 100644 --- a/tools/configure/configure.pro +++ b/tools/configure/configure.pro @@ -48,6 +48,10 @@ HEADERS = configureapp.h environment.h tools.h\ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.h \ $$QT_SOURCE_TREE/src/corelib/io/qfile.h \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystementry_p.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine_p.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemmetadata_p.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemiterator_p.h \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.h \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_p.h \ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.h \ @@ -61,6 +65,7 @@ HEADERS = configureapp.h environment.h tools.h\ $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.h \ $$QT_SOURCE_TREE/src/corelib/tools/qstringmatcher.h \ $$QT_SOURCE_TREE/src/corelib/tools/qunicodetables_p.h \ + $$QT_SOURCE_TREE/src/corelib/kernel/qsystemerror_p.h \ $$QT_SOURCE_TREE/src/corelib/xml/qxmlstream.h \ $$QT_SOURCE_TREE/src/corelib/xml/qxmlutils_p.h \ $$QT_SOURCE_TREE/tools/shared/symbian/epocroot_p.h \ @@ -74,6 +79,8 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qhash.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qlist.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qlocale.cpp \ + $$QT_SOURCE_TREE/src/corelib/tools/qlocale_win.cpp \ + $$QT_SOURCE_TREE/src/corelib/tools/qlocale_tools.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qvector.cpp \ $$QT_SOURCE_TREE/src/corelib/codecs/qutfcodec.cpp \ $$QT_SOURCE_TREE/src/corelib/codecs/qtextcodec.cpp \ @@ -86,9 +93,13 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystementry.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine_win.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemiterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \ @@ -103,6 +114,7 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qunicodetables.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qvsnprintf.cpp \ $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp \ + $$QT_SOURCE_TREE/src/corelib/kernel/qsystemerror.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qurl.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qline.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qsize.cpp \ @@ -115,8 +127,6 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/tools/shared/symbian/epocroot.cpp \ $$QT_SOURCE_TREE/tools/shared/windows/registry.cpp -win32:SOURCES += $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp - DEFINES += COMMERCIAL_VERSION INCLUDEPATH += $$QT_SOURCE_TREE/src/corelib/arch/generic \ diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 69cd70b..e6d8526 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -281,6 +281,7 @@ Configure::Configure(int& argc, char** argv) dictionary[ "DECLARATIVE" ] = "auto"; dictionary[ "DECLARATIVE_DEBUG" ]= "yes"; dictionary[ "PLUGIN_MANIFESTS" ] = "yes"; + dictionary[ "DIRECTWRITE" ] = "no"; QString version; QFile qglobal_h(sourcePath + "/src/corelib/global/qglobal.h"); @@ -437,6 +438,7 @@ void Configure::parseCmdLine() { int argCount = configCmdLine.size(); int i = 0; + const QStringList imageFormats = QStringList() << "gif" << "png" << "mng" << "jpeg" << "tiff"; #if !defined(EVAL) if (argCount < 1) // skip rest if no arguments @@ -590,8 +592,6 @@ void Configure::parseCmdLine() // Image formats -------------------------------------------- else if (configCmdLine.at(i) == "-no-gif") dictionary[ "GIF" ] = "no"; - else if (configCmdLine.at(i) == "-qt-gif") - dictionary[ "GIF" ] = "plugin"; else if (configCmdLine.at(i) == "-no-libtiff") { dictionary[ "TIFF"] = "no"; @@ -831,6 +831,17 @@ void Configure::parseCmdLine() dictionary[ "SQL_IBASE" ] = "plugin"; else if (configCmdLine.at(i) == "-no-sql-ibase") dictionary[ "SQL_IBASE" ] = "no"; + + // Image formats -------------------------------------------- + else if (configCmdLine.at(i).startsWith("-qt-imageformat-") && + imageFormats.contains(configCmdLine.at(i).section('-', 3))) + dictionary[ configCmdLine.at(i).section('-', 3).toUpper() ] = "yes"; + else if (configCmdLine.at(i).startsWith("-plugin-imageformat-") && + imageFormats.contains(configCmdLine.at(i).section('-', 3))) + dictionary[ configCmdLine.at(i).section('-', 3).toUpper() ] = "plugin"; + else if (configCmdLine.at(i).startsWith("-no-imageformat-") && + imageFormats.contains(configCmdLine.at(i).section('-', 3))) + dictionary[ configCmdLine.at(i).section('-', 3).toUpper() ] = "no"; #endif // IDE project generation ----------------------------------- else if (configCmdLine.at(i) == "-no-dsp") @@ -1219,6 +1230,12 @@ void Configure::parseCmdLine() } } + else if (configCmdLine.at(i) == "-directwrite") { + dictionary["DIRECTWRITE"] = "yes"; + } else if (configCmdLine.at(i) == "-no-directwrite") { + dictionary["DIRECTWRITE"] = "no"; + } + else { dictionary[ "HELP" ] = "yes"; cout << "Unknown option " << configCmdLine.at(i) << endl; @@ -1545,10 +1562,8 @@ void Configure::applySpecSpecifics() dictionary[ "QT3SUPPORT" ] = "no"; dictionary[ "OPENGL" ] = "no"; dictionary[ "OPENSSL" ] = "yes"; - // We accidently enabled IPv6 for Qt Symbian in 4.6.x. However the underlying OpenC does not fully support IPV6. - // Therefore for 4.7.1 and following we disable it until OpenC either supports it or we have the native Qt - // symbian socket engine. - dictionary[ "IPV6" ] = "no"; + // On Symbian we now always will have IPv6 with no chance to disable it + dictionary[ "IPV6" ] = "yes"; dictionary[ "STL" ] = "yes"; dictionary[ "EXCEPTIONS" ] = "yes"; dictionary[ "RTTI" ] = "yes"; @@ -1663,7 +1678,7 @@ bool Configure::displayHelp() "[-no-qmake] [-qmake] [-dont-process] [-process]\n" "[-no-style-<style>] [-qt-style-<style>] [-redo]\n" "[-saveconfig <config>] [-loadconfig <config>]\n" - "[-qt-zlib] [-system-zlib] [-no-gif] [-qt-gif] [-no-libpng]\n" + "[-qt-zlib] [-system-zlib] [-no-gif] [-no-libpng]\n" "[-qt-libpng] [-system-libpng] [-no-libtiff] [-qt-libtiff]\n" "[-system-libtiff] [-no-libjpeg] [-qt-libjpeg] [-system-libjpeg]\n" "[-no-libmng] [-qt-libmng] [-system-libmng] [-no-qt3support] [-mmx]\n" @@ -1674,7 +1689,9 @@ bool Configure::displayHelp() "[-phonon] [-no-phonon-backend] [-phonon-backend]\n" "[-no-multimedia] [-multimedia] [-no-audio-backend] [-audio-backend]\n" "[-no-script] [-script] [-no-scripttools] [-scripttools]\n" - "[-no-webkit] [-webkit] [-webkit-debug] [-graphicssystem raster|opengl|openvg]\n\n", 0, 7); + "[-no-webkit] [-webkit] [-webkit-debug]\n" + "[-graphicssystem raster|opengl|openvg]\n" + "[-no-directwrite] [-directwrite]\n\n", 0, 7); desc("Installation options:\n\n"); @@ -1796,7 +1813,6 @@ bool Configure::displayHelp() desc("ZLIB", "system", "-system-zlib", "Use zlib from the operating system.\nSee http://www.gzip.org/zlib\n"); desc("GIF", "no", "-no-gif", "Do not compile GIF reading support."); - desc("GIF", "auto", "-qt-gif", "Compile GIF reading support.\nSee also src/gui/image/qgifhandler_p.h\n"); desc("LIBPNG", "no", "-no-libpng", "Do not compile PNG support."); desc("LIBPNG", "qt", "-qt-libpng", "Use the libpng bundled with Qt."); @@ -1872,6 +1888,8 @@ bool Configure::displayHelp() desc("DECLARATIVE", "yes", "-declarative", "Build the declarative module"); desc("DECLARATIVE_DEBUG", "no", "-no-declarative-debug", "Do not build the declarative debugging support"); desc("DECLARATIVE_DEBUG", "yes", "-declarative-debug", "Build the declarative debugging support"); + desc("DIRECTWRITE", "no", "-no-directwrite", "Do not build support for DirectWrite font rendering"); + desc("DIRECTWRITE", "yes", "-directwrite", "Build support for DirectWrite font rendering (experimental, requires DirectWrite availability on target systems, e.g. Windows Vista with Platform Update, Windows 7, etc.)"); desc( "-arch <arch>", "Specify an architecture.\n" "Available values for <arch>:"); @@ -1961,6 +1979,22 @@ QString Configure::findFileInPaths(const QString &fileName, const QString &paths return QString(); } +static QString mingwPaths(const QString &mingwPath, const QString &pathName) +{ + QString ret; + QDir mingwDir = QFileInfo(mingwPath).dir(); + const QFileInfoList subdirs = mingwDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (int i = 0 ;i < subdirs.length(); ++i) { + const QFileInfo &fi = subdirs.at(i); + const QString name = fi.fileName(); + if (name == pathName) + ret += fi.absoluteFilePath() + ';'; + else if (name.contains("mingw")) + ret += fi.absoluteFilePath() + QDir::separator() + pathName + ';'; + } + return ret; +} + bool Configure::findFile(const QString &fileName) { const QString file = fileName.toLower(); @@ -1971,18 +2005,22 @@ bool Configure::findFile(const QString &fileName) QString paths; if (file.endsWith(".h")) { if (!mingwPath.isNull()) { - if (!findFileInPaths(file, mingwPath + QLatin1String("/../include")).isNull()) + if (!findFileInPaths(file, mingwPaths(mingwPath, "include")).isNull()) return true; //now let's try the additional compiler path - QDir mingwLibDir = mingwPath + QLatin1String("/../lib/gcc/mingw32"); - foreach(const QFileInfo &version, mingwLibDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { - if (!findFileInPaths(file, version.absoluteFilePath() + QLatin1String("/include")).isNull()) - return true; + + const QFileInfoList mingwConfigs = QDir(mingwPath + QLatin1String("/../lib/gcc")).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (int i = 0; i < mingwConfigs.length(); ++i) { + const QDir mingwLibDir = mingwConfigs.at(i).absoluteFilePath(); + foreach(const QFileInfo &version, mingwLibDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { + if (!findFileInPaths(file, version.absoluteFilePath() + QLatin1String("/include")).isNull()) + return true; + } } } paths = QString::fromLocal8Bit(getenv("INCLUDE")); } else if (file.endsWith(".lib") || file.endsWith(".a")) { - if (!mingwPath.isNull() && !findFileInPaths(file, mingwPath + QLatin1String("/../lib")).isNull()) + if (!mingwPath.isNull() && !findFileInPaths(file, mingwPaths(mingwPath, "lib")).isNull()) return true; paths = QString::fromLocal8Bit(getenv("LIB")); } else { @@ -2135,13 +2173,8 @@ bool Configure::checkAvailability(const QString &part) else if (part == "INCREDIBUILD_XGE") available = findFile("BuildConsole.exe") && findFile("xgConsole.exe"); else if (part == "XMLPATTERNS") - { - /* MSVC 6.0 and MSVC 2002/7.0 has too poor C++ support for QtXmlPatterns. */ - return dictionary.value("QMAKESPEC") != "win32-msvc" - && dictionary.value("QMAKESPEC") != "win32-msvc.net" // Leave for now, since we can't be sure if they are using 2002 or 2003 with this spec - && dictionary.value("QMAKESPEC") != "win32-msvc2002" - && dictionary.value("EXCEPTIONS") == "yes"; - } else if (part == "PHONON") { + available = dictionary.value("EXCEPTIONS") == "yes"; + else if (part == "PHONON") { if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith("symbian")) { available = true; } else { @@ -2220,6 +2253,8 @@ bool Configure::checkAvailability(const QString &part) available = false; } } + } else if (part == "DIRECTWRITE") { + available = findFile("dwrite.h") && findFile("d2d1.h") && findFile("dwrite.lib"); } return available; @@ -2375,6 +2410,15 @@ bool Configure::verifyConfiguration() dictionary["SCRIPT"] = "yes"; } + if (dictionary["DIRECTWRITE"] == "yes" && !checkAvailability("DIRECTWRITE")) { + cout << "WARNING: To be able to compile the DirectWrite font engine you will" << endl + << "need the Microsoft DirectWrite and Microsoft Direct2D development" << endl + << "files such as headers and libraries." << endl + << "(Press any key to continue..)"; + if (_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout) + exit(0); // Exit cleanly for Ctrl+C + } + return true; } @@ -2716,7 +2760,7 @@ void Configure::generateOutputVars() QFile::remove(dst); if (dictionary["WEBKIT"] != "no") { // This include takes care of adding "webkit" to QT_CONFIG. - QString src = sourcePath + "/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri"; + QString src = sourcePath + "/src/3rdparty/webkit/Source/WebKit/qt/qt_webkit_version.pri"; QFile::copy(src, dst); if (dictionary["WEBKIT"] == "debug") qtConfig += "webkit-debug"; @@ -2731,6 +2775,9 @@ void Configure::generateOutputVars() qtConfig += "declarative"; } + if (dictionary["DIRECTWRITE"] == "yes") + qtConfig += "directwrite"; + if (dictionary[ "NATIVE_GESTURES" ] == "yes") qtConfig += "native-gestures"; @@ -2962,6 +3009,10 @@ void Configure::generateCachefile() configStream << " def_files_disabled"; } } + + if (dictionary["DIRECTWRITE"] == "yes") + configStream << "directwrite"; + configStream << endl; configStream << "QT_ARCH = " << dictionary[ "ARCHITECTURE" ] << endl; if (dictionary["QT_EDITION"].contains("OPENSOURCE")) @@ -3087,10 +3138,7 @@ void Configure::generateConfigfiles() tmpStream << "/* Machine byte-order */" << endl; tmpStream << "#define Q_BIG_ENDIAN 4321" << endl; tmpStream << "#define Q_LITTLE_ENDIAN 1234" << endl; - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) - tmpStream << "#define Q_BYTE_ORDER Q_BIG_ENDIAN" << endl; - else - tmpStream << "#define Q_BYTE_ORDER Q_LITTLE_ENDIAN" << endl; + tmpStream << "#define Q_BYTE_ORDER Q_LITTLE_ENDIAN" << endl; tmpStream << endl << "// Compile time features" << endl; tmpStream << "#define QT_ARCH_" << dictionary["ARCHITECTURE"].toUpper() << endl; @@ -3168,8 +3216,6 @@ void Configure::generateConfigfiles() if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith("symbian")) { // These features are not ported to Symbian (yet) - qconfigList += "QT_NO_CONCURRENT"; - qconfigList += "QT_NO_QFUTURE"; qconfigList += "QT_NO_CRASHHANDLER"; qconfigList += "QT_NO_PRINTER"; qconfigList += "QT_NO_SYSTEMTRAYICON"; @@ -3433,7 +3479,8 @@ void Configure::displayConfig() cout << "QtScript support............" << dictionary[ "SCRIPT" ] << endl; cout << "QtScriptTools support......." << dictionary[ "SCRIPTTOOLS" ] << endl; cout << "Graphics System............." << dictionary[ "GRAPHICS_SYSTEM" ] << endl; - cout << "Qt3 compatibility..........." << dictionary[ "QT3SUPPORT" ] << endl << endl; + cout << "Qt3 compatibility..........." << dictionary[ "QT3SUPPORT" ] << endl; + cout << "DirectWrite support........." << dictionary[ "DIRECTWRITE" ] << endl << endl; cout << "Third Party Libraries:" << endl; cout << " ZLIB support............" << dictionary[ "ZLIB" ] << endl; @@ -3552,17 +3599,21 @@ void Configure::displayConfig() #if !defined(EVAL) void Configure::generateHeaders() { - if (dictionary["SYNCQT"] == "yes" - && findFile("perl.exe")) { - cout << "Running syncqt..." << endl; - QStringList args; - args += buildPath + "/bin/syncqt.bat"; - QStringList env; - env += QString("QTDIR=" + sourcePath); - env += QString("PATH=" + buildPath + "/bin/;" + qgetenv("PATH")); - int retc = Environment::execute(args, env, QStringList()); - if (retc) { - cout << "syncqt failed, return code " << retc << endl << endl; + if (dictionary["SYNCQT"] == "yes") { + if (findFile("perl.exe")) { + cout << "Running syncqt..." << endl; + QStringList args; + args += buildPath + "/bin/syncqt.bat"; + QStringList env; + env += QString("QTDIR=" + sourcePath); + env += QString("PATH=" + buildPath + "/bin/;" + qgetenv("PATH")); + int retc = Environment::execute(args, env, QStringList()); + if (retc) { + cout << "syncqt failed, return code " << retc << endl << endl; + dictionary["DONE"] = "error"; + } + } else { + cout << "Perl not found in environment - cannot run syncqt." << endl; dictionary["DONE"] = "error"; } } diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp index d9f890e..f9b3e85 100644 --- a/tools/configure/environment.cpp +++ b/tools/configure/environment.cpp @@ -75,8 +75,6 @@ struct CompilerInfo{ {CC_BORLAND, "Borland C++", 0, "bcc32.exe"}, {CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "g++.exe"}, {CC_INTEL, "Intel(R) C++ Compiler for 32-bit applications", 0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe - {CC_MSVC6, "Microsoft (R) 32-bit C/C++ Optimizing Compiler (6.x)", "Software\\Microsoft\\VisualStudio\\6.0\\Setup\\Microsoft Visual C++\\ProductDir", "cl.exe"}, // link.exe, lib.exe - {CC_NET2002, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe {CC_NET2003, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe {CC_NET2005, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2005 (8.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe {CC_NET2008, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2008 (9.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe @@ -118,14 +116,6 @@ QString Environment::detectQMakeSpec() case CC_NET2003: spec = "win32-msvc2003"; break; - case CC_NET2002: - spec = "win32-msvc2002"; - break; - case CC_MSVC4: - case CC_MSVC5: - case CC_MSVC6: - spec = "win32-msvc"; - break; case CC_INTEL: spec = "win32-icc"; break; @@ -152,7 +142,7 @@ QString Environment::detectQMakeSpec() Compiler Environment::detectCompiler() { #ifndef Q_OS_WIN32 - return MSVC6; // Always generate MSVC 6.0 versions on other platforms + return CC_UNKNOWN; // Always generate CC_UNKNOWN on other platforms #else if(detectedCompiler != CC_UNKNOWN) return detectedCompiler; diff --git a/tools/configure/environment.h b/tools/configure/environment.h index d54b3e0..9bbd096 100644 --- a/tools/configure/environment.h +++ b/tools/configure/environment.h @@ -50,10 +50,6 @@ enum Compiler { CC_BORLAND = 0x01, CC_MINGW = 0x02, CC_INTEL = 0x03, - CC_MSVC4 = 0x40, - CC_MSVC5 = 0x50, - CC_MSVC6 = 0x60, - CC_NET2002 = 0x70, CC_NET2003 = 0x71, CC_NET2005 = 0x80, CC_NET2008 = 0x90, diff --git a/tools/designer/data/ui4.xsd b/tools/designer/data/ui4.xsd index de4253c..53bae62 100644 --- a/tools/designer/data/ui4.xsd +++ b/tools/designer/data/ui4.xsd @@ -207,6 +207,7 @@ <xs:attribute name="column" type="xs:integer" /> <xs:attribute name="rowspan" type="xs:integer" /> <xs:attribute name="colspan" type="xs:integer" /> + <xs:attribute name="alignment" type="xs:string" /> </xs:complexType> <!-- item view begin --> @@ -414,7 +415,7 @@ <xs:complexType name="StringList"> <xs:sequence> - <xs:element name="string" type="xs:string" maxOccurs="unbounded" /> + <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> @@ -434,6 +435,7 @@ <xs:element name="selectedoff" type="ResourcePixmap" minOccurs="0" /> <xs:element name="selectedon" type="ResourcePixmap" minOccurs="0" /> </xs:all> + <xs:attribute name="theme" type="xs:string" /> <xs:attribute name="resource" type="xs:string" /> <!-- pre 4.4 legacy support --> </xs:complexType> diff --git a/tools/designer/src/components/buddyeditor/buddyeditor.cpp b/tools/designer/src/components/buddyeditor/buddyeditor.cpp index 9926251..d64d665 100644 --- a/tools/designer/src/components/buddyeditor/buddyeditor.cpp +++ b/tools/designer/src/components/buddyeditor/buddyeditor.cpp @@ -51,6 +51,7 @@ #include <qdesigner_utils_p.h> #include <qlayout_widget_p.h> #include <connectionedit_p.h> +#include <metadatabase_p.h> #include <QtCore/qdebug.h> #include <QtGui/QLabel> @@ -75,7 +76,8 @@ static bool canBeBuddy(QWidget *w, QDesignerFormWindowInterface *form) if (index != -1) { bool ok = false; const Qt::FocusPolicy q = static_cast<Qt::FocusPolicy>(qdesigner_internal::Utils::valueOf(sheet->property(index), &ok)); - return ok && q != Qt::NoFocus; + // Refuse No-focus unless the widget is promoted. + return (ok && q != Qt::NoFocus) || qdesigner_internal::isPromoted(form->core(), w); } } return false; @@ -153,13 +155,13 @@ void BuddyEditor::updateBackground() m_updating = true; QList<Connection *> newList; - const LabelList label_list = qFindChildren<QLabel*>(background()); + const LabelList label_list = background()->findChildren<QLabel*>(); foreach (QLabel *label, label_list) { const QString buddy_name = buddy(label, m_formWindow->core()); if (buddy_name.isEmpty()) continue; - const QList<QWidget *> targets = qFindChildren<QWidget*>(background(), buddy_name); + const QList<QWidget *> targets = background()->findChildren<QWidget*>(buddy_name); if (targets.isEmpty()) continue; @@ -238,12 +240,12 @@ void BuddyEditor::setBackground(QWidget *background) clear(); ConnectionEdit::setBackground(background); - const LabelList label_list = qFindChildren<QLabel*>(background); + const LabelList label_list = background->findChildren<QLabel*>(); foreach (QLabel *label, label_list) { const QString buddy_name = buddy(label, m_formWindow->core()); if (buddy_name.isEmpty()) continue; - QWidget *target = qFindChild<QWidget*>(background, buddy_name); + QWidget *target = background->findChild<QWidget*>(buddy_name); if (target == 0) continue; @@ -297,7 +299,7 @@ void BuddyEditor::endConnection(QWidget *target, const QPoint &pos) void BuddyEditor::widgetRemoved(QWidget *widget) { - QList<QWidget*> child_list = qFindChildren<QWidget*>(widget); + QList<QWidget*> child_list = widget->findChildren<QWidget*>(); child_list.prepend(widget); ConnectionSet remove_set; @@ -354,7 +356,7 @@ void BuddyEditor::deleteSelected() void BuddyEditor::autoBuddy() { // Any labels? - LabelList labelList = qFindChildren<QLabel*>(background()); + LabelList labelList = background()->findChildren<QLabel*>(); if (labelList.empty()) return; // Find already used buddies diff --git a/tools/designer/src/components/formeditor/dpi_chooser.cpp b/tools/designer/src/components/formeditor/dpi_chooser.cpp index 0082a62..8a039d0 100644 --- a/tools/designer/src/components/formeditor/dpi_chooser.cpp +++ b/tools/designer/src/components/formeditor/dpi_chooser.cpp @@ -97,13 +97,13 @@ DPI_Chooser::DPI_Chooser(QWidget *parent) : m_systemEntry->description = 0; const struct DPI_Entry *systemEntry = m_systemEntry; //: System resolution - m_predefinedCombo->addItem(tr("System (%1 x %2)").arg(m_systemEntry->dpiX).arg(m_systemEntry->dpiY), qVariantFromValue(systemEntry)); + m_predefinedCombo->addItem(tr("System (%1 x %2)").arg(m_systemEntry->dpiX).arg(m_systemEntry->dpiY), QVariant::fromValue(systemEntry)); // Devices. Exclude the system values as not to duplicate the entries const int predefinedCount = sizeof(dpiEntries)/sizeof(DPI_Entry); const struct DPI_Entry *ecend = dpiEntries + predefinedCount; for (const struct DPI_Entry *it = dpiEntries; it < ecend; ++it) if (it->dpiX != m_systemEntry->dpiX || it->dpiY != m_systemEntry->dpiY) - m_predefinedCombo->addItem(tr(it->description), qVariantFromValue(it)); + m_predefinedCombo->addItem(tr(it->description), QVariant::fromValue(it)); m_predefinedCombo->addItem(tr("User defined")); setFocusProxy(m_predefinedCombo); diff --git a/tools/designer/src/components/formeditor/formeditor.qrc b/tools/designer/src/components/formeditor/formeditor.qrc index 42724dd..e42cc66 100644 --- a/tools/designer/src/components/formeditor/formeditor.qrc +++ b/tools/designer/src/components/formeditor/formeditor.qrc @@ -152,6 +152,7 @@ <file>images/win/textjustify.png</file> <file>images/win/textsuperscript.png</file> <file>images/win/textsubscript.png</file> + <file>images/win/simplifyrichtext.png</file> <file>images/win/back.png</file> <file>images/win/forward.png</file> <file>images/win/down.png</file> @@ -166,6 +167,7 @@ <file>images/mac/textjustify.png</file> <file>images/mac/textsuperscript.png</file> <file>images/mac/textsubscript.png</file> + <file>images/mac/simplifyrichtext.png</file> </qresource> <qresource prefix="/trolltech/brushes"> <file>defaultbrushes.xml</file> diff --git a/tools/designer/src/components/formeditor/formwindow.cpp b/tools/designer/src/components/formeditor/formwindow.cpp index 6e023de..ec0837f 100644 --- a/tools/designer/src/components/formeditor/formwindow.cpp +++ b/tools/designer/src/components/formeditor/formwindow.cpp @@ -387,7 +387,7 @@ void FormWindow::setCursorToAll(const QCursor &c, QWidget *start) { #ifndef QT_NO_CURSOR start->setCursor(c); - const QWidgetList widgets = qFindChildren<QWidget*>(start); + const QWidgetList widgets = start->findChildren<QWidget*>(); foreach (QWidget *widget, widgets) { if (!qobject_cast<WidgetHandle*>(widget)) { widget->setCursor(c); @@ -945,7 +945,7 @@ bool FormWindow::isMainContainer(const QWidget *w) const void FormWindow::updateChildSelections(QWidget *w) { - const QWidgetList l = qFindChildren<QWidget*>(w); + const QWidgetList l = w->findChildren<QWidget*>(); if (!l.empty()) { const QWidgetList::const_iterator lcend = l.constEnd(); for (QWidgetList::const_iterator it = l.constBegin(); it != lcend; ++it) { @@ -1155,19 +1155,19 @@ bool FormWindow::unify(QObject *w, QString &s, bool changeIt) existingNames.insert(main->objectName()); const QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase(); - const QWidgetList widgetChildren = qFindChildren<QWidget*>(main); + const QWidgetList widgetChildren = main->findChildren<QWidget*>(); if (!widgetChildren.empty()) insertNames(metaDataBase, widgetChildren.constBegin(), widgetChildren.constEnd(), w, existingNames); - const QList<QLayout *> layoutChildren = qFindChildren<QLayout*>(main); + const QList<QLayout *> layoutChildren = main->findChildren<QLayout*>(); if (!layoutChildren.empty()) insertNames(metaDataBase, layoutChildren.constBegin(), layoutChildren.constEnd(), w, existingNames); - const QList<QAction *> actionChildren = qFindChildren<QAction*>(main); + const QList<QAction *> actionChildren = main->findChildren<QAction*>(); if (!actionChildren.empty()) insertNames(metaDataBase, actionChildren.constBegin(), actionChildren.constEnd(), w, existingNames); - const QList<QButtonGroup *> buttonGroupChildren = qFindChildren<QButtonGroup*>(main); + const QList<QButtonGroup *> buttonGroupChildren = main->findChildren<QButtonGroup*>(); if (!buttonGroupChildren.empty()) insertNames(metaDataBase, buttonGroupChildren.constBegin(), buttonGroupChildren.constEnd(), w, existingNames); @@ -1283,7 +1283,7 @@ void FormWindow::resizeWidget(QWidget *widget, const QRect &geometry) void FormWindow::raiseChildSelections(QWidget *w) { - const QWidgetList l = qFindChildren<QWidget*>(w); + const QWidgetList l = w->findChildren<QWidget*>(); if (l.isEmpty()) return; m_selection->raiseList(l); @@ -1344,7 +1344,7 @@ QWidgetList FormWindow::selectedWidgets() const void FormWindow::selectWidgets() { bool selectionChanged = false; - const QWidgetList l = qFindChildren<QWidget*>(mainContainer()); + const QWidgetList l = mainContainer()->findChildren<QWidget*>(); QListIterator <QWidget*> it(l); const QRect selRect(mapToGlobal(m_currRect.topLeft()), m_currRect.size()); while (it.hasNext()) { @@ -1523,7 +1523,7 @@ void ArrowKeyPropertyCommand::init(QWidgetList &l, const ArrowKeyOperation &op) QObjectList ol; foreach(QWidget *w, l) ol.push_back(w); - SetPropertyCommand::init(ol, QLatin1String("geometry"), qVariantFromValue(op)); + SetPropertyCommand::init(ol, QLatin1String("geometry"), QVariant::fromValue(op)); setText(op.resize ? FormWindow::tr("Key Resize") : FormWindow::tr("Key Move")); } @@ -1531,14 +1531,14 @@ void ArrowKeyPropertyCommand::init(QWidgetList &l, const ArrowKeyOperation &op) QVariant ArrowKeyPropertyCommand::mergeValue(const QVariant &newMergeValue) { // Merge move operations of the same arrow key - if (!qVariantCanConvert<ArrowKeyOperation>(newMergeValue)) + if (!newMergeValue.canConvert<ArrowKeyOperation>()) return QVariant(); ArrowKeyOperation mergedOperation = qvariant_cast<ArrowKeyOperation>(newValue()); const ArrowKeyOperation newMergeOperation = qvariant_cast<ArrowKeyOperation>(newMergeValue); if (mergedOperation.resize != newMergeOperation.resize || mergedOperation.arrowKey != newMergeOperation.arrowKey) return QVariant(); mergedOperation.distance += newMergeOperation.distance; - return qVariantFromValue(mergedOperation); + return QVariant::fromValue(mergedOperation); } void FormWindow::handleArrowKeyEvent(int key, Qt::KeyboardModifiers modifiers) @@ -2248,7 +2248,7 @@ QAction *FormWindow::createSelectAncestorSubMenu(QWidget *w) for (int i = 0; i < size; i++) { QWidget *w = parents.at(i); QAction *a = ag->addAction(objectNameOf(w)); - a->setData(qVariantFromValue(w)); + a->setData(QVariant::fromValue(w)); menu->addAction(a); } QAction *ma = new QAction(tr("Select Ancestor"), 0); @@ -2803,7 +2803,7 @@ bool FormWindow::dropDockWidget(QDesignerDnDItemInterface *item, const QPoint &g PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(propertySheet->property(propertySheet->indexOf(dockWidgetAreaName))); e.value = area; QVariant v; - qVariantSetValue(v, e); + v.setValue(e); SetPropertyCommand *cmd = new SetPropertyCommand(this); cmd->init(widget, dockWidgetAreaName, v); m_undoStack.push(cmd); diff --git a/tools/designer/src/components/formeditor/images/mac/simplifyrichtext.png b/tools/designer/src/components/formeditor/images/mac/simplifyrichtext.png Binary files differnew file mode 100644 index 0000000..a48e974 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/simplifyrichtext.png diff --git a/tools/designer/src/components/formeditor/images/win/simplifyrichtext.png b/tools/designer/src/components/formeditor/images/win/simplifyrichtext.png Binary files differnew file mode 100644 index 0000000..e251cf7 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/simplifyrichtext.png diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.cpp b/tools/designer/src/components/formeditor/qdesigner_resource.cpp index 5c0215a..0c26542 100644 --- a/tools/designer/src/components/formeditor/qdesigner_resource.cpp +++ b/tools/designer/src/components/formeditor/qdesigner_resource.cpp @@ -171,7 +171,7 @@ QDesignerResourceBuilder::QDesignerResourceBuilder(QDesignerFormEditorInterface { } -static inline void setIconPixmap(QIcon::Mode m, QIcon::State s, const QDir &workingDirectory, +static inline void setIconPixmap(QIcon::Mode m, QIcon::State s, const QDir &workingDirectory, QString path, PropertySheetIconValue &icon, const QDesignerLanguageExtension *lang = 0) { @@ -197,12 +197,13 @@ QVariant QDesignerResourceBuilder::loadResource(const QDir &workingDirectory, co m_loadedQrcFiles.insert(QFileInfo(workingDirectory, dp->attributeResource()).absoluteFilePath(), false); #endif } - return qVariantFromValue(pixmap); + return QVariant::fromValue(pixmap); } case DomProperty::IconSet: { PropertySheetIconValue icon; DomResourceIcon *di = property->elementIconSet(); + icon.setTheme(di->attributeTheme()); if (const int flags = iconStateFlags(di)) { // new, post 4.4 format if (flags & NormalOff) setIconPixmap(QIcon::Normal, QIcon::Off, workingDirectory, di->elementNormalOff()->text(), icon, m_lang); @@ -227,7 +228,7 @@ QVariant QDesignerResourceBuilder::loadResource(const QDir &workingDirectory, co m_loadedQrcFiles.insert(QFileInfo(workingDirectory, di->attributeResource()).absoluteFilePath(), false); #endif } - return qVariantFromValue(icon); + return QVariant::fromValue(icon); } default: break; @@ -237,12 +238,12 @@ QVariant QDesignerResourceBuilder::loadResource(const QDir &workingDirectory, co QVariant QDesignerResourceBuilder::toNativeValue(const QVariant &value) const { - if (qVariantCanConvert<PropertySheetPixmapValue>(value)) { + if (value.canConvert<PropertySheetPixmapValue>()) { if (m_pixmapCache) - return m_pixmapCache->pixmap(qVariantValue<PropertySheetPixmapValue>(value)); - } else if (qVariantCanConvert<PropertySheetIconValue>(value)) { + return m_pixmapCache->pixmap(qvariant_cast<PropertySheetPixmapValue>(value)); + } else if (value.canConvert<PropertySheetIconValue>()) { if (m_iconCache) - return m_iconCache->icon(qVariantValue<PropertySheetIconValue>(value)); + return m_iconCache->icon(qvariant_cast<PropertySheetIconValue>(value)); } return value; } @@ -250,7 +251,7 @@ QVariant QDesignerResourceBuilder::toNativeValue(const QVariant &value) const DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory, const QVariant &value) const { DomProperty *p = new DomProperty; - if (qVariantCanConvert<PropertySheetPixmapValue>(value)) { + if (value.canConvert<PropertySheetPixmapValue>()) { const PropertySheetPixmapValue pix = qvariant_cast<PropertySheetPixmapValue>(value); DomResourcePixmap *rp = new DomResourcePixmap; const QString pixPath = pix.path(); @@ -275,11 +276,14 @@ DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory } p->setElementPixmap(rp); return p; - } else if (qVariantCanConvert<PropertySheetIconValue>(value)) { + } else if (value.canConvert<PropertySheetIconValue>()) { const PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(value); const QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> pixmaps = icon.paths(); - if (!pixmaps.isEmpty()) { + const QString theme = icon.theme(); + if (!pixmaps.isEmpty() || !theme.isEmpty()) { DomResourceIcon *ri = new DomResourceIcon; + if (!theme.isEmpty()) + ri->setAttributeTheme(theme); QMapIterator<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> itPix(pixmaps); while (itPix.hasNext()) { const QIcon::Mode mode = itPix.next().key().first; @@ -331,7 +335,7 @@ DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory bool QDesignerResourceBuilder::isResourceType(const QVariant &value) const { - if (qVariantCanConvert<PropertySheetPixmapValue>(value) || qVariantCanConvert<PropertySheetIconValue>(value)) + if (value.canConvert<PropertySheetPixmapValue>() || value.canConvert<PropertySheetIconValue>()) return true; return false; } @@ -364,26 +368,26 @@ QVariant QDesignerTextBuilder::loadText(const DomProperty *text) const if (!translatable) strVal.setTranslatable(translatable); } - return qVariantFromValue(strVal); + return QVariant::fromValue(strVal); } QVariant QDesignerTextBuilder::toNativeValue(const QVariant &value) const { - if (qVariantCanConvert<PropertySheetStringValue>(value)) - return qVariantFromValue(qVariantValue<PropertySheetStringValue>(value).value()); + if (value.canConvert<PropertySheetStringValue>()) + return QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(value).value()); return value; } DomProperty *QDesignerTextBuilder::saveText(const QVariant &value) const { - if (!qVariantCanConvert<PropertySheetStringValue>(value) && !qVariantCanConvert<QString>(value)) + if (!value.canConvert<PropertySheetStringValue>() && !value.canConvert<QString>()) return 0; DomProperty *property = new DomProperty(); DomString *domStr = new DomString(); - if (qVariantCanConvert<PropertySheetStringValue>(value)) { - PropertySheetStringValue str = qVariantValue<PropertySheetStringValue>(value); + if (value.canConvert<PropertySheetStringValue>()) { + PropertySheetStringValue str = qvariant_cast<PropertySheetStringValue>(value); domStr->setText(str.value()); @@ -475,7 +479,7 @@ void QDesignerResource::saveDom(DomUI *ui, QWidget *widget) if (classVar.canConvert(QVariant::String)) classStr = classVar.toString(); else - classStr = qVariantValue<PropertySheetStringValue>(classVar).value(); + classStr = qvariant_cast<PropertySheetStringValue>(classVar).value(); ui->setElementClass(classStr); for (int index = 0; index < m_formWindow->toolCount(); ++index) { @@ -737,7 +741,10 @@ QWidget *QDesignerResource::load(QIODevice *dev, QWidget *parentWidget) case LoadPreCheckOk: break; } - return QEditorFormBuilder::load(dev, parentWidget); + QWidget *w = QEditorFormBuilder::load(dev, parentWidget); + if (w) // Store the class name as 'reset' value for the main container's object name. + w->setProperty("_q_classname", w->objectName()); + return w; } bool QDesignerResource::saveRelative() const @@ -946,7 +953,7 @@ QWidget *QDesignerResource::create(DomWidget *ui_widget, QWidget *parentWidget) w->addAction(a); } else if (QActionGroup *g = m_actionGroups.value(name)) { w->addActions(g->actions()); - } else if (QMenu *menu = qFindChild<QMenu*>(w, name)) { + } else if (QMenu *menu = w->findChild<QMenu*>(name)) { w->addAction(menu->menuAction()); addMenuAction(menu->menuAction()); } @@ -1045,7 +1052,7 @@ static bool readDomEnumerationValue(const DomProperty *p, switch (p->kind()) { case DomProperty::Set: { const QVariant sheetValue = sheet->property(index); - if (qVariantCanConvert<PropertySheetFlagValue>(sheetValue)) { + if (sheetValue.canConvert<PropertySheetFlagValue>()) { const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(sheetValue); bool ok = false; v = f.metaFlags.parseFlags(p->elementSet(), &ok); @@ -1057,7 +1064,7 @@ static bool readDomEnumerationValue(const DomProperty *p, break; case DomProperty::Enum: { const QVariant sheetValue = sheet->property(index); - if (qVariantCanConvert<PropertySheetEnumValue>(sheetValue)) { + if (sheetValue.canConvert<PropertySheetEnumValue>()) { const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(sheetValue); bool ok = false; v = e.metaEnum.parseEnum(p->elementEnum(), &ok); @@ -1110,7 +1117,7 @@ void QDesignerResource::applyProperties(QObject *o, const QList<DomProperty*> &p if (!translatable) keyVal.setTranslatable(translatable); } - v = qVariantFromValue(keyVal); + v = QVariant::fromValue(keyVal); } else { const DomString *str = p->elementString(); PropertySheetStringValue strVal(v.toString()); @@ -1124,7 +1131,7 @@ void QDesignerResource::applyProperties(QObject *o, const QList<DomProperty*> &p if (!translatable) strVal.setTranslatable(translatable); } - v = qVariantFromValue(strVal); + v = QVariant::fromValue(strVal); } } @@ -1135,18 +1142,18 @@ void QDesignerResource::applyProperties(QObject *o, const QList<DomProperty*> &p } else if (dynamicPropertiesAllowed) { QVariant defaultValue = QVariant(v.type()); bool isDefault = (v == defaultValue); - if (qVariantCanConvert<PropertySheetIconValue>(v)) { + if (v.canConvert<PropertySheetIconValue>()) { defaultValue = QVariant(QVariant::Icon); - isDefault = (qVariantValue<PropertySheetIconValue>(v) == PropertySheetIconValue()); - } else if (qVariantCanConvert<PropertySheetPixmapValue>(v)) { + isDefault = (qvariant_cast<PropertySheetIconValue>(v) == PropertySheetIconValue()); + } else if (v.canConvert<PropertySheetPixmapValue>()) { defaultValue = QVariant(QVariant::Pixmap); - isDefault = (qVariantValue<PropertySheetPixmapValue>(v) == PropertySheetPixmapValue()); - } else if (qVariantCanConvert<PropertySheetStringValue>(v)) { + isDefault = (qvariant_cast<PropertySheetPixmapValue>(v) == PropertySheetPixmapValue()); + } else if (v.canConvert<PropertySheetStringValue>()) { defaultValue = QVariant(QVariant::String); - isDefault = (qVariantValue<PropertySheetStringValue>(v) == PropertySheetStringValue()); - } else if (qVariantCanConvert<PropertySheetKeySequenceValue>(v)) { + isDefault = (qvariant_cast<PropertySheetStringValue>(v) == PropertySheetStringValue()); + } else if (v.canConvert<PropertySheetKeySequenceValue>()) { defaultValue = QVariant(QVariant::KeySequence); - isDefault = (qVariantValue<PropertySheetKeySequenceValue>(v) == PropertySheetKeySequenceValue()); + isDefault = (qvariant_cast<PropertySheetKeySequenceValue>(v) == PropertySheetKeySequenceValue()); } if (defaultValue.type() != QVariant::UserType) { const int idx = dynamicSheet->addDynamicProperty(p->attributeName(), defaultValue); @@ -1185,12 +1192,12 @@ QWidget *QDesignerResource::createWidget(const QString &widgetName, QWidget *par if (!qobject_cast<QMenu*>(w) && (!parentWidget || !container)) { m_formWindow->manageWidget(w); if (parentWidget) { - QList<QWidget *> list = qVariantValue<QWidgetList>(parentWidget->property("_q_widgetOrder")); + QList<QWidget *> list = qvariant_cast<QWidgetList>(parentWidget->property("_q_widgetOrder")); list.append(w); - parentWidget->setProperty("_q_widgetOrder", qVariantFromValue(list)); - QList<QWidget *> zOrder = qVariantValue<QWidgetList>(parentWidget->property("_q_zOrder")); + parentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(list)); + QList<QWidget *> zOrder = qvariant_cast<QWidgetList>(parentWidget->property("_q_zOrder")); zOrder.append(w); - parentWidget->setProperty("_q_zOrder", qVariantFromValue(zOrder)); + parentWidget->setProperty("_q_zOrder", QVariant::fromValue(zOrder)); } } else { core()->metaDataBase()->add(w); @@ -1320,7 +1327,7 @@ DomLayout *QDesignerResource::createDom(QLayout *layout, DomLayout *ui_parentLay QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(layout); if (item == 0) { - layout = qFindChild<QLayout*>(layout); + layout = layout->findChild<QLayout*>(); // refresh the meta database item item = core()->metaDataBase()->item(layout); } @@ -1377,34 +1384,6 @@ DomLayoutItem *QDesignerResource::createDom(QLayoutItem *item, DomLayout *ui_lay } else { return 0; } - - if (m_chain.size() && item->widget()) { - if (QGridLayout *grid = qobject_cast<QGridLayout*>(m_chain.top())) { - const int index = Utils::indexOfWidget(grid, item->widget()); - - int row, column, rowspan, colspan; - grid->getItemPosition(index, &row, &column, &rowspan, &colspan); - ui_item->setAttributeRow(row); - ui_item->setAttributeColumn(column); - - if (colspan != 1) - ui_item->setAttributeColSpan(colspan); - - if (rowspan != 1) - ui_item->setAttributeRowSpan(rowspan); - } else { - if (QFormLayout *form = qobject_cast<QFormLayout*>(m_chain.top())) { - const int index = Utils::indexOfWidget(form, item->widget()); - int row, column, colspan; - getFormLayoutItemPosition(form, index, &row, &column, 0, &colspan); - ui_item->setAttributeRow(row); - ui_item->setAttributeColumn(column); - if (colspan != 1) - ui_item->setAttributeColSpan(colspan); - } - } - } - return ui_item; } @@ -1440,7 +1419,7 @@ void QDesignerResource::applyTabStops(QWidget *widget, DomTabStops *tabStops) QList<QWidget*> tabOrder; foreach (const QString &widgetName, tabStops->elementTabStop()) { - if (QWidget *w = qFindChild<QWidget*>(widget, widgetName)) { + if (QWidget *w = widget->findChild<QWidget*>(widgetName)) { tabOrder.append(w); } } @@ -1605,8 +1584,8 @@ DomWidget *QDesignerResource::saveWidget(QTabWidget *widget, DomWidget *ui_paren // attribute `icon' widget->setCurrentIndex(i); QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget); - PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentTabIcon")))); - DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), qVariantFromValue(icon)); + PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentTabIcon")))); + DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), QVariant::fromValue(icon)); if (p) { p->setAttributeName(strings.iconAttribute); ui_attribute_list.append(p); @@ -1620,7 +1599,7 @@ DomWidget *QDesignerResource::saveWidget(QTabWidget *widget, DomWidget *ui_paren // attribute `toolTip' QVariant v = sheet->property(sheet->indexOf(QLatin1String("currentTabToolTip"))); - if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + if (!qvariant_cast<PropertySheetStringValue>(v).value().isEmpty()) { p = textBuilder()->saveText(v); if (p) { p->setAttributeName(strings.toolTipAttribute); @@ -1630,7 +1609,7 @@ DomWidget *QDesignerResource::saveWidget(QTabWidget *widget, DomWidget *ui_paren // attribute `whatsThis' v = sheet->property(sheet->indexOf(QLatin1String("currentTabWhatsThis"))); - if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + if (!qvariant_cast<PropertySheetStringValue>(v).value().isEmpty()) { p = textBuilder()->saveText(v); if (p) { p->setAttributeName(strings.whatsThisAttribute); @@ -1676,8 +1655,8 @@ DomWidget *QDesignerResource::saveWidget(QToolBox *widget, DomWidget *ui_parentW // attribute `icon' widget->setCurrentIndex(i); QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget); - PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentItemIcon")))); - DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), qVariantFromValue(icon)); + PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentItemIcon")))); + DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), QVariant::fromValue(icon)); if (p) { p->setAttributeName(strings.iconAttribute); ui_attribute_list.append(p); @@ -1690,7 +1669,7 @@ DomWidget *QDesignerResource::saveWidget(QToolBox *widget, DomWidget *ui_parentW // attribute `toolTip' QVariant v = sheet->property(sheet->indexOf(QLatin1String("currentItemToolTip"))); - if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + if (!qvariant_cast<PropertySheetStringValue>(v).value().isEmpty()) { p = textBuilder()->saveText(v); if (p) { p->setAttributeName(strings.toolTipAttribute); @@ -2209,8 +2188,8 @@ DomProperty *QDesignerResource::createProperty(QObject *object, const QString &p return 0; } - if (qVariantCanConvert<PropertySheetFlagValue>(value)) { - const PropertySheetFlagValue f = qVariantValue<PropertySheetFlagValue>(value); + if (value.canConvert<PropertySheetFlagValue>()) { + const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(value); const QString flagString = f.metaFlags.toString(f.value, DesignerMetaFlags::FullyQualified); if (flagString.isEmpty()) return 0; @@ -2222,8 +2201,8 @@ DomProperty *QDesignerResource::createProperty(QObject *object, const QString &p p->setAttributeName(propertyName); p->setElementSet(flagString); return applyProperStdSetAttribute(object, propertyName, p); - } else if (qVariantCanConvert<PropertySheetEnumValue>(value)) { - const PropertySheetEnumValue e = qVariantValue<PropertySheetEnumValue>(value); + } else if (value.canConvert<PropertySheetEnumValue>()) { + const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(value); bool ok; const QString id = e.metaEnum.toString(e.value, DesignerMetaEnum::FullyQualified, &ok); if (!ok) @@ -2238,8 +2217,8 @@ DomProperty *QDesignerResource::createProperty(QObject *object, const QString &p p->setAttributeName(propertyName); p->setElementEnum(id); return applyProperStdSetAttribute(object, propertyName, p); - } else if (qVariantCanConvert<PropertySheetStringValue>(value)) { - const PropertySheetStringValue strVal = qVariantValue<PropertySheetStringValue>(value); + } else if (value.canConvert<PropertySheetStringValue>()) { + const PropertySheetStringValue strVal = qvariant_cast<PropertySheetStringValue>(value); DomProperty *p = new DomProperty; if (!hasSetter(core(), object, propertyName)) p->setAttributeStdset(0); @@ -2249,8 +2228,8 @@ DomProperty *QDesignerResource::createProperty(QObject *object, const QString &p saveStringProperty(p, strVal); return applyProperStdSetAttribute(object, propertyName, p); - } else if (qVariantCanConvert<PropertySheetKeySequenceValue>(value)) { - const PropertySheetKeySequenceValue keyVal = qVariantValue<PropertySheetKeySequenceValue>(value); + } else if (value.canConvert<PropertySheetKeySequenceValue>()) { + const PropertySheetKeySequenceValue keyVal = qvariant_cast<PropertySheetKeySequenceValue>(value); DomProperty *p = new DomProperty; if (!hasSetter(core(), object, propertyName)) p->setAttributeStdset(0); @@ -2302,6 +2281,7 @@ void QDesignerResource::createResources(DomResources *resources) path = core()->dialogGui()->getOpenFileName(dialogParent, fileDialogTitle, fi.absolutePath(), fileDialogPattern); if (path.isEmpty()) break; + m_formWindow->setProperty("_q_resourcepathchanged", QVariant(true)); } else { break; } diff --git a/tools/designer/src/components/formeditor/qmainwindow_container.cpp b/tools/designer/src/components/formeditor/qmainwindow_container.cpp index 19f2245..64475dd 100644 --- a/tools/designer/src/components/formeditor/qmainwindow_container.cpp +++ b/tools/designer/src/components/formeditor/qmainwindow_container.cpp @@ -104,7 +104,7 @@ Qt::DockWidgetArea dockWidgetArea(QDockWidget *me) QList<QLayout*> candidates; if (mw->layout()) { candidates.append(mw->layout()); - candidates += qFindChildren<QLayout*>(mw->layout()); + candidates += mw->layout()->findChildren<QLayout*>(); } foreach (QLayout *l, candidates) { if (l->indexOf(me) != -1) { diff --git a/tools/designer/src/components/lib/lib.pro b/tools/designer/src/components/lib/lib.pro index 0ada845..50a8b00 100644 --- a/tools/designer/src/components/lib/lib.pro +++ b/tools/designer/src/components/lib/lib.pro @@ -64,7 +64,7 @@ PRECOMPILED_HEADER= lib_pch.h include(../../sharedcomponents.pri) include(../component.pri) -unix { +unix|win32-g++* { QMAKE_PKGCONFIG_REQUIRES = QtCore QtDesigner QtGui QtXml contains(QT_CONFIG, script): QMAKE_PKGCONFIG_REQUIRES += QtScript } diff --git a/tools/designer/src/components/objectinspector/objectinspectormodel.cpp b/tools/designer/src/components/objectinspector/objectinspectormodel.cpp index e95b44c..a1cbc1a 100644 --- a/tools/designer/src/components/objectinspector/objectinspectormodel.cpp +++ b/tools/designer/src/components/objectinspector/objectinspectormodel.cpp @@ -273,7 +273,7 @@ namespace qdesigner_internal { void ObjectData::setItems(const StandardItemList &row, const ObjectInspectorIcons &icons) const { - const QVariant object = qVariantFromValue(m_object); + const QVariant object = QVariant::fromValue(m_object); row[ObjectInspectorModel::ObjectNameColumn]->setData(object, DataRole); row[ObjectInspectorModel::ClassNameColumn]->setData(object, DataRole); setItemsDisplayData(row, icons, ClassNameChanged|ObjectNameChanged|ClassIconChanged|TypeChanged|LayoutTypeChanged); diff --git a/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp index 1430fb9..85d302f 100644 --- a/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp +++ b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp @@ -163,7 +163,7 @@ void BrushPropertyManager::initializeProperty(QtVariantPropertyManager *vm, QtPr for (int i = 0; i < brushStyleCount; i++) styles.push_back(QCoreApplication::translate("BrushPropertyManager", brushStyles[i])); styleSubProperty->setAttribute(QLatin1String("enumNames"), styles); - styleSubProperty->setAttribute(QLatin1String("enumIcons"), qVariantFromValue(brushStyleIcons())); + styleSubProperty->setAttribute(QLatin1String("enumIcons"), QVariant::fromValue(brushStyleIcons())); m_brushPropertyToStyleSubProperty.insert(property, styleSubProperty); m_brushStyleSubPropertyToProperty.insert(styleSubProperty, property); // color diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp index 3bcd83d..1646e5f 100644 --- a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp +++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp @@ -83,6 +83,7 @@ static const char *validationModesAttributeC = "validationMode"; static const char *superPaletteAttributeC = "superPalette"; static const char *defaultResourceAttributeC = "defaultResource"; static const char *fontAttributeC = "font"; +static const char *themeAttributeC = "theme"; class DesignerFlagPropertyType { @@ -113,13 +114,15 @@ public: void setTextPropertyValidationMode(TextPropertyValidationMode vm); void setRichTextDefaultFont(const QFont &font) { m_richTextDefaultFont = font; } - QFont richTextDefaultFont() const { return m_richTextDefaultFont; } + QFont richTextDefaultFont() const { return m_richTextDefaultFont; } void setSpacing(int spacing); TextPropertyEditor::UpdateMode updateMode() const { return m_editor->updateMode(); } void setUpdateMode(TextPropertyEditor::UpdateMode um) { m_editor->setUpdateMode(um); } + void setIconThemeModeEnabled(bool enable); + public slots: void setText(const QString &text); @@ -132,6 +135,8 @@ private slots: void fileActionActivated(); private: TextPropertyEditor *m_editor; + IconThemeEditor *m_themeEditor; + bool m_iconThemeModeEnabled; QFont m_richTextDefaultFont; QToolButton *m_button; QMenu *m_menu; @@ -144,6 +149,8 @@ private: TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) : QWidget(parent), m_editor(new TextPropertyEditor(this)), + m_themeEditor(new IconThemeEditor(this, false)), + m_iconThemeModeEnabled(false), m_richTextDefaultFont(QApplication::font()), m_button(new QToolButton(this)), m_menu(new QMenu(this)), @@ -152,7 +159,11 @@ TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) : m_layout(new QHBoxLayout(this)), m_core(core) { + m_themeEditor->setVisible(false); + m_button->setVisible(false); + m_layout->addWidget(m_editor); + m_layout->addWidget(m_themeEditor); m_button->setText(tr("...")); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); m_button->setFixedWidth(20); @@ -163,9 +174,10 @@ TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) : connect(m_resourceAction, SIGNAL(triggered()), this, SLOT(resourceActionActivated())); connect(m_fileAction, SIGNAL(triggered()), this, SLOT(fileActionActivated())); connect(m_editor, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged(QString))); + connect(m_themeEditor, SIGNAL(edited(QString)), this, SIGNAL(textChanged(QString))); connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); - m_button->setVisible(false); setFocusProxy(m_editor); m_menu->addAction(m_resourceAction); @@ -177,6 +189,22 @@ void TextEditor::setSpacing(int spacing) m_layout->setSpacing(spacing); } +void TextEditor::setIconThemeModeEnabled(bool enable) +{ + if (m_iconThemeModeEnabled == enable) + return; // nothing changes + m_iconThemeModeEnabled = enable; + m_editor->setVisible(!enable); + m_themeEditor->setVisible(enable); + if (enable) { + m_themeEditor->setTheme(m_editor->text()); + setFocusProxy(m_themeEditor); + } else { + m_editor->setText(m_themeEditor->theme()); + setFocusProxy(m_editor); + } +} + TextPropertyValidationMode TextEditor::textPropertyValidationMode() const { return m_editor->textPropertyValidationMode(); @@ -199,7 +227,10 @@ void TextEditor::setTextPropertyValidationMode(TextPropertyValidationMode vm) void TextEditor::setText(const QString &text) { - m_editor->setText(text); + if (m_iconThemeModeEnabled) + m_themeEditor->setTheme(text); + else + m_editor->setText(text); } void TextEditor::buttonClicked() @@ -279,6 +310,49 @@ void TextEditor::fileActionActivated() emit textChanged(newText); } +// ------------ ThemeInputDialog + +class IconThemeDialog : public QDialog +{ + Q_OBJECT +public: + static QString getTheme(QWidget *parent, const QString &theme, bool *ok); +private: + IconThemeDialog(QWidget *parent); + IconThemeEditor *m_editor; +}; + +IconThemeDialog::IconThemeDialog(QWidget *parent) + : QDialog(parent) +{ + setWindowTitle(tr("Set Icon From Theme")); + + QVBoxLayout *layout = new QVBoxLayout(this); + QLabel *label = new QLabel(tr("Input icon name from the current theme:"), this); + m_editor = new IconThemeEditor(this); + QDialogButtonBox *buttons = new QDialogButtonBox(this); + buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + layout->addWidget(label); + layout->addWidget(m_editor); + layout->addWidget(buttons); + + connect(buttons, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); +} + +QString IconThemeDialog::getTheme(QWidget *parent, const QString &theme, bool *ok) +{ + IconThemeDialog dlg(parent); + dlg.m_editor->setTheme(theme); + if (dlg.exec() == QDialog::Accepted) { + *ok = true; + return dlg.m_editor->theme(); + } + *ok = false; + return QString(); +} + // ------------ PixmapEditor class PixmapEditor : public QWidget { @@ -288,12 +362,15 @@ public: void setSpacing(int spacing); void setPixmapCache(DesignerPixmapCache *cache); + void setIconThemeModeEnabled(bool enabled); public slots: void setPath(const QString &path); + void setTheme(const QString &theme); void setDefaultPixmap(const QPixmap &pixmap); signals: void pathChanged(const QString &path); + void themeChanged(const QString &theme); protected: void contextMenuEvent(QContextMenuEvent *event); @@ -302,32 +379,39 @@ private slots: void defaultActionActivated(); void resourceActionActivated(); void fileActionActivated(); + void themeActionActivated(); void copyActionActivated(); void pasteActionActivated(); void clipboardDataChanged(); private: + void updateLabels(); + bool m_iconThemeModeEnabled; QDesignerFormEditorInterface *m_core; QLabel *m_pixmapLabel; QLabel *m_pathLabel; QToolButton *m_button; QAction *m_resourceAction; QAction *m_fileAction; + QAction *m_themeAction; QAction *m_copyAction; QAction *m_pasteAction; QHBoxLayout *m_layout; QPixmap m_defaultPixmap; QString m_path; + QString m_theme; DesignerPixmapCache *m_pixmapCache; }; PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) : QWidget(parent), + m_iconThemeModeEnabled(false), m_core(core), m_pixmapLabel(new QLabel(this)), m_pathLabel(new QLabel(this)), m_button(new QToolButton(this)), m_resourceAction(new QAction(tr("Choose Resource..."), this)), m_fileAction(new QAction(tr("Choose File..."), this)), + m_themeAction(new QAction(tr("Set Icon From Theme..."), this)), m_copyAction(new QAction(createIconSet(QLatin1String("editcopy.png")), tr("Copy Path"), this)), m_pasteAction(new QAction(createIconSet(QLatin1String("editpaste.png")), tr("Paste Path"), this)), m_layout(new QHBoxLayout(this)), @@ -345,10 +429,12 @@ PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) m_pixmapLabel->setFixedWidth(16); m_pixmapLabel->setAlignment(Qt::AlignCenter); m_pathLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); + m_themeAction->setVisible(false); QMenu *menu = new QMenu(this); menu->addAction(m_resourceAction); menu->addAction(m_fileAction); + menu->addAction(m_themeAction); m_button->setMenu(menu); m_button->setText(tr("...")); @@ -356,6 +442,7 @@ PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) connect(m_button, SIGNAL(clicked()), this, SLOT(defaultActionActivated())); connect(m_resourceAction, SIGNAL(triggered()), this, SLOT(resourceActionActivated())); connect(m_fileAction, SIGNAL(triggered()), this, SLOT(fileActionActivated())); + connect(m_themeAction, SIGNAL(triggered()), this, SLOT(themeActionActivated())); connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copyActionActivated())); connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(pasteActionActivated())); setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored)); @@ -370,6 +457,14 @@ void PixmapEditor::setPixmapCache(DesignerPixmapCache *cache) m_pixmapCache = cache; } +void PixmapEditor::setIconThemeModeEnabled(bool enabled) +{ + if (m_iconThemeModeEnabled == enabled) + return; + m_iconThemeModeEnabled = enabled; + m_themeAction->setVisible(enabled); +} + void PixmapEditor::setSpacing(int spacing) { m_layout->setSpacing(spacing); @@ -378,22 +473,40 @@ void PixmapEditor::setSpacing(int spacing) void PixmapEditor::setPath(const QString &path) { m_path = path; - if (m_path.isEmpty()) { - m_pathLabel->setText(path); - m_pixmapLabel->setPixmap(m_defaultPixmap); - m_copyAction->setEnabled(false); - } else { - m_pathLabel->setText(QFileInfo(m_path).fileName()); - if (m_pixmapCache) - m_pixmapLabel->setPixmap(QIcon(m_pixmapCache->pixmap(PropertySheetPixmapValue(path))).pixmap(16, 16)); + updateLabels(); +} + +void PixmapEditor::setTheme(const QString &theme) +{ + m_theme = theme; + updateLabels(); +} + +void PixmapEditor::updateLabels() +{ + if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme)) { + m_pixmapLabel->setPixmap(QIcon::fromTheme(m_theme).pixmap(16, 16)); + m_pathLabel->setText(tr("[Theme] %1").arg(m_theme)); m_copyAction->setEnabled(true); + } else { + if (m_path.isEmpty()) { + m_pathLabel->setText(m_path); + m_pixmapLabel->setPixmap(m_defaultPixmap); + m_copyAction->setEnabled(false); + } else { + m_pathLabel->setText(QFileInfo(m_path).fileName()); + if (m_pixmapCache) + m_pixmapLabel->setPixmap(QIcon(m_pixmapCache->pixmap(PropertySheetPixmapValue(m_path))).pixmap(16, 16)); + m_copyAction->setEnabled(true); + } } } void PixmapEditor::setDefaultPixmap(const QPixmap &pixmap) { m_defaultPixmap = QIcon(pixmap).pixmap(16, 16); - if (m_path.isEmpty()) + const bool hasThemeIcon = m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme); + if (!hasThemeIcon && m_path.isEmpty()) m_pixmapLabel->setPixmap(m_defaultPixmap); } @@ -408,6 +521,10 @@ void PixmapEditor::contextMenuEvent(QContextMenuEvent *event) void PixmapEditor::defaultActionActivated() { + if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme)) { + themeActionActivated(); + return; + } // Default to resource const PropertySheetPixmapValue::PixmapSource ps = m_path.isEmpty() ? PropertySheetPixmapValue::ResourcePixmap : PropertySheetPixmapValue::getPixmapSource(m_core, m_path); switch (ps) { @@ -426,6 +543,7 @@ void PixmapEditor::resourceActionActivated() const QString oldPath = m_path; const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this); if (!newPath.isEmpty() && newPath != oldPath) { + setTheme(QString()); setPath(newPath); emit pathChanged(newPath); } @@ -435,15 +553,30 @@ void PixmapEditor::fileActionActivated() { const QString newPath = IconSelector::choosePixmapFile(m_path, m_core->dialogGui(), this); if (!newPath.isEmpty() && newPath != m_path) { + setTheme(QString()); setPath(newPath); emit pathChanged(newPath); } } +void PixmapEditor::themeActionActivated() +{ + bool ok; + const QString newTheme = IconThemeDialog::getTheme(this, m_theme, &ok); + if (ok && newTheme != m_theme) { + setTheme(newTheme); + setPath(QString()); + emit themeChanged(newTheme); + } +} + void PixmapEditor::copyActionActivated() { QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(m_path); + if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme)) + clipboard->setText(m_theme); + else + clipboard->setText(m_path); } void PixmapEditor::pasteActionActivated() @@ -455,8 +588,15 @@ void PixmapEditor::pasteActionActivated() QStringList list = text.split(QLatin1Char('\n')); if (list.size() > 0) { text = list.at(0); - setPath(text); - emit pathChanged(text); + if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(text)) { + setTheme(text); + setPath(QString()); + emit themeChanged(text); + } else { + setPath(text); + setTheme(QString()); + emit pathChanged(text); + } } } } @@ -740,7 +880,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari m_changingSubValue = false; data.val = newValue; QVariant v; - qVariantSetValue(v, data.val); + v.setValue(data.val); variantProperty(flagProperty)->setValue(v); } else if (QtProperty *alignProperty = m_alignHToProperty.value(property, 0)) { const uint v = m_alignValues.value(alignProperty); @@ -763,7 +903,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(stringProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *stringProperty = m_translatableToString.value(property, 0)) { const PropertySheetStringValue v = m_stringValues.value(stringProperty); PropertySheetStringValue newValue = v; @@ -771,7 +911,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(stringProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *stringProperty = m_disambiguationToString.value(property, 0)) { const PropertySheetStringValue v = m_stringValues.value(stringProperty); PropertySheetStringValue newValue = v; @@ -779,7 +919,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(stringProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *keySequenceProperty = m_commentToKeySequence.value(property, 0)) { const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); PropertySheetKeySequenceValue newValue = v; @@ -787,7 +927,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(keySequenceProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *keySequenceProperty = m_translatableToKeySequence.value(property, 0)) { const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); PropertySheetKeySequenceValue newValue = v; @@ -795,7 +935,7 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(keySequenceProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *keySequenceProperty = m_disambiguationToKeySequence.value(property, 0)) { const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); PropertySheetKeySequenceValue newValue = v; @@ -803,16 +943,21 @@ void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVari if (v == newValue) return; - variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + variantProperty(keySequenceProperty)->setValue(QVariant::fromValue(newValue)); } else if (QtProperty *iProperty = m_iconSubPropertyToProperty.value(property, 0)) { QtVariantProperty *iconProperty = variantProperty(iProperty); - PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(iconProperty->value()); - QPair<QIcon::Mode, QIcon::State> pair = m_iconSubPropertyToState.value(property); - icon.setPixmap(pair.first, pair.second, qVariantValue<PropertySheetPixmapValue>(value)); + PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(iconProperty->value()); + QMap<QtProperty *, QPair<QIcon::Mode, QIcon::State> >::ConstIterator itState = m_iconSubPropertyToState.constFind(property); + if (itState != m_iconSubPropertyToState.constEnd()) { + QPair<QIcon::Mode, QIcon::State> pair = m_iconSubPropertyToState.value(property); + icon.setPixmap(pair.first, pair.second, qvariant_cast<PropertySheetPixmapValue>(value)); + } else { // must be theme property + icon.setTheme(value.toString()); + } QtProperty *origSourceOfChange = m_sourceOfChange; if (!origSourceOfChange) m_sourceOfChange = property; - iconProperty->setValue(qVariantFromValue(icon)); + iconProperty->setValue(QVariant::fromValue(icon)); if (!origSourceOfChange) m_sourceOfChange = origSourceOfChange; } else if (m_iconValues.contains(property)) { @@ -859,12 +1004,16 @@ void DesignerPropertyManager::slotPropertyDestroyed(QtProperty *property) m_keySequenceToDisambiguation.remove(keySequenceDisambiguationProperty); m_disambiguationToKeySequence.remove(property); } else if (QtProperty *iconProperty = m_iconSubPropertyToProperty.value(property, 0)) { - QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> >::iterator it = - m_propertyToIconSubProperties.find(iconProperty); - QPair<QIcon::Mode, QIcon::State> state = m_iconSubPropertyToState.value(property); - QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> &propertyList = it.value(); - propertyList.remove(state); - m_iconSubPropertyToState.remove(property); + if (m_propertyToTheme.value(iconProperty) == property) { + m_propertyToTheme.remove(iconProperty); + } else { + QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> >::iterator it = + m_propertyToIconSubProperties.find(iconProperty); + QPair<QIcon::Mode, QIcon::State> state = m_iconSubPropertyToState.value(property); + QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> &propertyList = it.value(); + propertyList.remove(state); + m_iconSubPropertyToState.remove(property); + } m_iconSubPropertyToProperty.remove(property); } else { m_fontManager.slotPropertyDestroyed(property); @@ -887,6 +1036,7 @@ QStringList DesignerPropertyManager::attributes(int propertyType) const } else if (propertyType == designerStringTypeId() || propertyType == QVariant::String) { list.append(QLatin1String(validationModesAttributeC)); list.append(QLatin1String(fontAttributeC)); + list.append(QLatin1String(themeAttributeC)); } else if (propertyType == QVariant::Palette) { list.append(QLatin1String(superPaletteAttributeC)); } @@ -912,6 +1062,8 @@ int DesignerPropertyManager::attributeType(int propertyType, const QString &attr return QVariant::Int; if (attribute == QLatin1String(fontAttributeC)) return QVariant::Font; + if (attribute == QLatin1String(themeAttributeC)) + return QVariant::Bool; } if (propertyType == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC)) return QVariant::Palette; @@ -933,7 +1085,7 @@ QVariant DesignerPropertyManager::attributeValue(const QtProperty *property, con PropertyFlagDataMap::const_iterator it = m_flagValues.constFind(prop); if (it != m_flagValues.constEnd()) { QVariant v; - qVariantSetValue(v, it.value().flags); + v.setValue(it.value().flags); return v; } } @@ -949,6 +1101,12 @@ QVariant DesignerPropertyManager::attributeValue(const QtProperty *property, con return it.value(); } + if (attribute == QLatin1String(themeAttributeC)) { + const PropertyBoolMap::const_iterator it = m_stringThemeAttributes.constFind(prop); + if (it != m_stringThemeAttributes.constEnd()) + return it.value(); + } + if (attribute == QLatin1String(superPaletteAttributeC)) { PropertyPaletteDataMap::const_iterator it = m_paletteValues.constFind(prop); if (it != m_paletteValues.constEnd()) @@ -985,7 +1143,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, if (value.userType() != designerFlagListTypeId()) return; - const DesignerFlagList flags = qVariantValue<DesignerFlagList>(value); + const DesignerFlagList flags = qvariant_cast<DesignerFlagList>(value); PropertyFlagDataMap::iterator fit = m_flagValues.find(property); FlagData data = fit.value(); if (data.flags == flags) @@ -1022,7 +1180,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, fit.value() = data; QVariant v; - qVariantSetValue(v, flags); + v.setValue(flags); emit attributeChanged(property, attribute, v); emit propertyChanged(property); @@ -1057,11 +1215,26 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, it.value() = newValue; emit attributeChanged(property, attribute, newValue); + } else if (attribute == QLatin1String(themeAttributeC) && m_stringThemeAttributes.contains(property)) { + if (value.userType() != QVariant::Bool) + return; + + const PropertyBoolMap::iterator it = m_stringThemeAttributes.find(property); + const bool oldValue = it.value(); + + const bool newValue = value.toBool(); + + if (oldValue == newValue) + return; + + it.value() = newValue; + + emit attributeChanged(property, attribute, newValue); } else if (attribute == QLatin1String(superPaletteAttributeC) && m_paletteValues.contains(property)) { if (value.userType() != QVariant::Palette) return; - QPalette superPalette = qVariantValue<QPalette>(value); + QPalette superPalette = qvariant_cast<QPalette>(value); const PropertyPaletteDataMap::iterator it = m_paletteValues.find(property); PaletteData data = it.value(); @@ -1077,7 +1250,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, it.value() = data; QVariant v; - qVariantSetValue(v, superPalette); + v.setValue(superPalette); emit attributeChanged(property, attribute, v); emit propertyChanged(property); @@ -1086,7 +1259,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, if (value.userType() != QVariant::Pixmap) return; - QPixmap defaultPixmap = qVariantValue<QPixmap>(value); + QPixmap defaultPixmap = qvariant_cast<QPixmap>(value); const QMap<QtProperty *, QPixmap>::iterator it = m_defaultPixmaps.find(property); QPixmap oldDefaultPixmap = it.value(); @@ -1095,7 +1268,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, it.value() = defaultPixmap; - QVariant v = qVariantFromValue(defaultPixmap); + QVariant v = QVariant::fromValue(defaultPixmap); emit attributeChanged(property, attribute, v); emit propertyChanged(property); @@ -1103,7 +1276,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, if (value.userType() != QVariant::Icon) return; - QIcon defaultIcon = qVariantValue<QIcon>(value); + QIcon defaultIcon = qvariant_cast<QIcon>(value); const QMap<QtProperty *, QIcon>::iterator it = m_defaultIcons.find(property); QIcon oldDefaultIcon = it.value(); @@ -1124,7 +1297,7 @@ void DesignerPropertyManager::setAttribute(QtProperty *property, } } - QVariant v = qVariantFromValue(defaultIcon); + QVariant v = QVariant::fromValue(defaultIcon); emit attributeChanged(property, attribute, v); emit propertyChanged(property); @@ -1234,7 +1407,11 @@ QString DesignerPropertyManager::valueText(const QtProperty *property) const return inherited; } if (m_iconValues.contains(const_cast<QtProperty *>(property))) { - const PropertySheetIconValue::ModeStateToPixmapMap paths = m_iconValues.value(const_cast<QtProperty *>(property)).paths(); + const PropertySheetIconValue icon = m_iconValues.value(const_cast<QtProperty *>(property)); + const QString theme = icon.theme(); + if (!theme.isEmpty() && QIcon::hasThemeIcon(theme)) + return tr("[Theme] %1").arg(theme); + const PropertySheetIconValue::ModeStateToPixmapMap paths = icon.paths(); const PropertySheetIconValue::ModeStateToPixmapMap::const_iterator it = paths.constFind(qMakePair(QIcon::Normal, QIcon::Off)); if (it == paths.constEnd()) return QString(); @@ -1265,12 +1442,12 @@ QString DesignerPropertyManager::valueText(const QtProperty *property) const return m_stringListValues.value(const_cast<QtProperty *>(property)).join(QLatin1String("; ")); } if (QtVariantPropertyManager::valueType(property) == QVariant::String || QtVariantPropertyManager::valueType(property) == designerStringTypeId()) { - const QString str = (QtVariantPropertyManager::valueType(property) == QVariant::String) ? value(property).toString() : qVariantValue<PropertySheetStringValue>(value(property)).value(); + const QString str = (QtVariantPropertyManager::valueType(property) == QVariant::String) ? value(property).toString() : qvariant_cast<PropertySheetStringValue>(value(property)).value(); const int validationMode = attributeValue(property, QLatin1String(validationModesAttributeC)).toInt(); return TextPropertyEditor::stringToEditorString(str, static_cast<TextPropertyValidationMode>(validationMode)); } if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId()) { - return qVariantValue<PropertySheetKeySequenceValue>(value(property)).value(); + return qvariant_cast<PropertySheetKeySequenceValue>(value(property)).value(); } if (QtVariantPropertyManager::valueType(property) == QVariant::Bool) { return QString(); @@ -1313,13 +1490,13 @@ void DesignerPropertyManager::reloadResourceProperties() } emit propertyChanged(property); - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(itIcon.value())); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(itIcon.value())); } QMapIterator<QtProperty *, qdesigner_internal::PropertySheetPixmapValue> itPix(m_pixmapValues); while (itPix.hasNext()) { QtProperty *property = itPix.next().key(); emit propertyChanged(property); - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(itPix.value())); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(itPix.value())); } } @@ -1339,6 +1516,8 @@ QIcon DesignerPropertyManager::valueIcon(const QtProperty *property) const qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow); if (fwb) return fwb->pixmapCache()->pixmap(m_pixmapValues.value(const_cast<QtProperty *>(property))); + } else if (m_stringThemeAttributes.value(const_cast<QtProperty *>(property), false)) { + return QIcon::fromTheme(value(property).toString()); } else { QIcon rc; if (m_brushManager.valueIcon(property, &rc)) @@ -1357,13 +1536,13 @@ QVariant DesignerPropertyManager::value(const QtProperty *property) const if (m_paletteValues.contains(const_cast<QtProperty *>(property))) return m_paletteValues.value(const_cast<QtProperty *>(property)).val; if (m_iconValues.contains(const_cast<QtProperty *>(property))) - return qVariantFromValue(m_iconValues.value(const_cast<QtProperty *>(property))); + return QVariant::fromValue(m_iconValues.value(const_cast<QtProperty *>(property))); if (m_pixmapValues.contains(const_cast<QtProperty *>(property))) - return qVariantFromValue(m_pixmapValues.value(const_cast<QtProperty *>(property))); + return QVariant::fromValue(m_pixmapValues.value(const_cast<QtProperty *>(property))); if (m_stringValues.contains(const_cast<QtProperty *>(property))) - return qVariantFromValue(m_stringValues.value(const_cast<QtProperty *>(property))); + return QVariant::fromValue(m_stringValues.value(const_cast<QtProperty *>(property))); if (m_keySequenceValues.contains(const_cast<QtProperty *>(property))) - return qVariantFromValue(m_keySequenceValues.value(const_cast<QtProperty *>(property))); + return QVariant::fromValue(m_keySequenceValues.value(const_cast<QtProperty *>(property))); if (m_uintValues.contains(const_cast<QtProperty *>(property))) return m_uintValues.value(const_cast<QtProperty *>(property)); if (m_longLongValues.contains(const_cast<QtProperty *>(property))) @@ -1497,7 +1676,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.userType() != designerStringTypeId()) return; - const PropertySheetStringValue v = qVariantValue<PropertySheetStringValue>(value); + const PropertySheetStringValue v = qvariant_cast<PropertySheetStringValue>(value); const PropertySheetStringValue val = m_stringValues.value(property); @@ -1517,7 +1696,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val m_stringValues[property] = v; - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(v)); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(v)); emit propertyChanged(property); return; @@ -1525,7 +1704,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.userType() != designerKeySequenceTypeId()) return; - const PropertySheetKeySequenceValue v = qVariantValue<PropertySheetKeySequenceValue>(value); + const PropertySheetKeySequenceValue v = qvariant_cast<PropertySheetKeySequenceValue>(value); const PropertySheetKeySequenceValue val = m_keySequenceValues.value(property); @@ -1545,7 +1724,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val m_keySequenceValues[property] = v; - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(v)); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(v)); emit propertyChanged(property); return; @@ -1553,7 +1732,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.type() != QVariant::Palette && !value.canConvert(QVariant::Palette)) return; - QPalette p = qVariantValue<QPalette>(value); + QPalette p = qvariant_cast<QPalette>(value); PaletteData data = m_paletteValues.value(property); @@ -1575,7 +1754,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.userType() != designerIconTypeId()) return; - const PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(value); + const PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(value); const PropertySheetIconValue oldIcon = m_iconValues.value(property); if (icon == oldIcon) @@ -1600,12 +1779,18 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val QtVariantProperty *subProperty = variantProperty(itSub.value()); bool hasPath = iconPaths.contains(pair); subProperty->setModified(hasPath); - subProperty->setValue(qVariantFromValue(iconPaths.value(pair))); + subProperty->setValue(QVariant::fromValue(iconPaths.value(pair))); subProperty->setAttribute(QLatin1String(defaultResourceAttributeC), defaultIcon.pixmap(16, 16, pair.first, pair.second)); } + QtVariantProperty *themeSubProperty = variantProperty(m_propertyToTheme.value(property)); + if (themeSubProperty) { + const QString theme = icon.theme(); + themeSubProperty->setModified(!theme.isEmpty()); + themeSubProperty->setValue(theme); + } - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(icon)); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(icon)); emit propertyChanged(property); QString toolTip; @@ -1620,7 +1805,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (value.userType() != designerPixmapTypeId()) return; - const PropertySheetPixmapValue pixmap = qVariantValue<PropertySheetPixmapValue>(value); + const PropertySheetPixmapValue pixmap = qvariant_cast<PropertySheetPixmapValue>(value); const PropertySheetPixmapValue oldPixmap = m_pixmapValues.value(property); if (pixmap == oldPixmap) @@ -1628,7 +1813,7 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val m_pixmapValues[property] = pixmap; - emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(pixmap)); + emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(pixmap)); emit propertyChanged(property); property->setToolTip(pixmap.path()); @@ -1746,9 +1931,9 @@ void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &val if (QtVariantPropertyManager::valueType(property) == QVariant::String) property->setToolTip(DesignerPropertyManager::value(property).toString()); else if (QtVariantPropertyManager::valueType(property) == designerStringTypeId()) - property->setToolTip(qVariantValue<PropertySheetStringValue>(DesignerPropertyManager::value(property)).value()); + property->setToolTip(qvariant_cast<PropertySheetStringValue>(DesignerPropertyManager::value(property)).value()); else if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId()) - property->setToolTip(qVariantValue<PropertySheetKeySequenceValue>(DesignerPropertyManager::value(property)).value()); + property->setToolTip(qvariant_cast<PropertySheetKeySequenceValue>(DesignerPropertyManager::value(property)).value()); else if (QtVariantPropertyManager::valueType(property) == QVariant::Bool) property->setToolTip(QtVariantPropertyManager::valueText(property)); } @@ -1766,6 +1951,7 @@ void DesignerPropertyManager::initializeProperty(QtProperty *property) case QVariant::String: m_stringAttributes[property] = ValidationSingleLine; m_stringFontAttributes[property] = QApplication::font(); + m_stringThemeAttributes[property] = false; break; case QVariant::UInt: m_uintValues[property] = 0; @@ -1820,6 +2006,13 @@ void DesignerPropertyManager::initializeProperty(QtProperty *property) m_iconValues[property] = PropertySheetIconValue(); m_defaultIcons[property] = QIcon(); + QtVariantProperty *themeProp = addProperty(QVariant::String, tr("Theme")); + themeProp->setAttribute(QLatin1String(themeAttributeC), true); + m_iconSubPropertyToProperty[themeProp] = property; + m_propertyToTheme[property] = themeProp; + m_resetMap[themeProp] = true; + property->addSubProperty(themeProp); + createIconSubProperty(property, QIcon::Normal, QIcon::Off, tr("Normal Off")); createIconSubProperty(property, QIcon::Normal, QIcon::On, tr("Normal On")); createIconSubProperty(property, QIcon::Disabled, QIcon::Off, tr("Disabled Off")); @@ -1833,6 +2026,7 @@ void DesignerPropertyManager::initializeProperty(QtProperty *property) m_stringValues[property] = val; m_stringAttributes[property] = ValidationMultiLine; m_stringFontAttributes[property] = QApplication::font(); + m_stringThemeAttributes[property] = false; QtVariantProperty *translatable = addProperty(QVariant::Bool, tr("translatable")); translatable->setValue(val.translatable()); @@ -1921,37 +2115,43 @@ void DesignerPropertyManager::uninitializeProperty(QtProperty *property) QtProperty *stringComment = m_stringToComment.value(property); if (stringComment) { delete stringComment; - m_stringToComment.remove(stringComment); + m_commentToString.remove(stringComment); } QtProperty *stringTranslatable = m_stringToTranslatable.value(property); if (stringTranslatable) { delete stringTranslatable; - m_stringToTranslatable.remove(stringTranslatable); + m_translatableToString.remove(stringTranslatable); } QtProperty *stringDisambiguation = m_stringToDisambiguation.value(property); if (stringDisambiguation) { delete stringDisambiguation; - m_stringToDisambiguation.remove(stringDisambiguation); + m_disambiguationToString.remove(stringDisambiguation); } QtProperty *keySequenceComment = m_keySequenceToComment.value(property); if (keySequenceComment) { delete keySequenceComment; - m_keySequenceToComment.remove(keySequenceComment); + m_commentToKeySequence.remove(keySequenceComment); } QtProperty *keySequenceTranslatable = m_keySequenceToTranslatable.value(property); if (keySequenceTranslatable) { delete keySequenceTranslatable; - m_keySequenceToTranslatable.remove(keySequenceTranslatable); + m_translatableToKeySequence.remove(keySequenceTranslatable); } QtProperty *keySequenceDisambiguation = m_keySequenceToDisambiguation.value(property); if (keySequenceDisambiguation) { delete keySequenceDisambiguation; - m_keySequenceToDisambiguation.remove(keySequenceDisambiguation); + m_disambiguationToKeySequence.remove(keySequenceDisambiguation); + } + + QtProperty *iconTheme = m_propertyToTheme.value(property); + if (iconTheme) { + delete iconTheme; + m_iconSubPropertyToProperty.remove(iconTheme); } m_propertyToAlignH.remove(property); @@ -2010,15 +2210,20 @@ bool DesignerPropertyManager::resetFontSubProperty(QtProperty *property) bool DesignerPropertyManager::resetIconSubProperty(QtProperty *property) { - if (!m_iconSubPropertyToProperty.contains(property)) - return false; - - if (!m_pixmapValues.contains(property)) + QtProperty *iconProperty = m_iconSubPropertyToProperty.value(property); + if (!iconProperty) return false; - QtVariantProperty *pixmapProperty = variantProperty(property); - pixmapProperty->setValue(qVariantFromValue(PropertySheetPixmapValue())); - return true; + if (m_pixmapValues.contains(property)) { + QtVariantProperty *pixmapProperty = variantProperty(property); + pixmapProperty->setValue(QVariant::fromValue(PropertySheetPixmapValue())); + return true; + } else if (m_propertyToTheme.contains(iconProperty)) { + QtVariantProperty *themeProperty = variantProperty(property); + themeProperty->setValue(QString()); + return true; + } + return false; } // -------- DesignerEditorFactory @@ -2116,6 +2321,10 @@ void DesignerEditorFactory::slotAttributeChanged(QtProperty *property, const QSt const QFont font = qvariant_cast<QFont>(value); applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setRichTextDefaultFont, font); } + if (attribute == QLatin1String(themeAttributeC)) { + const bool themeEnabled = value.toBool(); + applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setIconThemeModeEnabled, themeEnabled); + } } else if (type == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC)) { const QPalette palette = qvariant_cast<QPalette>(value); applyToEditors(m_palettePropertyToEditors.value(property), &PaletteEditorButton::setSuperPalette, palette); @@ -2131,7 +2340,7 @@ void DesignerEditorFactory::slotPropertyChanged(QtProperty *property) if (!property->isModified()) defaultPixmap = qvariant_cast<QIcon>(manager->attributeValue(property, QLatin1String(defaultResourceAttributeC))).pixmap(16, 16); else if (m_fwb) - defaultPixmap = m_fwb->iconCache()->icon(qVariantValue<PropertySheetIconValue>(manager->value(property))).pixmap(16, 16); + defaultPixmap = m_fwb->iconCache()->icon(qvariant_cast<PropertySheetIconValue>(manager->value(property))).pixmap(16, 16); QList<PixmapEditor *> editors = m_iconPropertyToEditors.value(property); QListIterator<PixmapEditor *> it(editors); while (it.hasNext()) { @@ -2174,14 +2383,18 @@ void DesignerEditorFactory::slotValueChanged(QtProperty *property, const QVarian applyToEditors(m_stringListPropertyToEditors.value(property), &StringListEditorButton::setStringList, value.toStringList()); break; default: - if (type == DesignerPropertyManager::designerIconTypeId()) - applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setPath, qVariantValue<PropertySheetIconValue>(value).pixmap(QIcon::Normal, QIcon::Off).path()); - else if (type == DesignerPropertyManager::designerPixmapTypeId()) - applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setPath, qVariantValue<PropertySheetPixmapValue>(value).path()); - else if (type == DesignerPropertyManager::designerStringTypeId()) - applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, qVariantValue<PropertySheetStringValue>(value).value()); - else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) - applyToEditors(m_keySequencePropertyToEditors.value(property), &QtKeySequenceEdit::setKeySequence, qVariantValue<PropertySheetKeySequenceValue>(value).value()); + if (type == DesignerPropertyManager::designerIconTypeId()) { + PropertySheetIconValue iconValue = qvariant_cast<PropertySheetIconValue>(value); + const QString theme = iconValue.theme(); + applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setTheme, iconValue.theme()); + applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setPath, iconValue.pixmap(QIcon::Normal, QIcon::Off).path()); + } else if (type == DesignerPropertyManager::designerPixmapTypeId()) { + applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setPath, qvariant_cast<PropertySheetPixmapValue>(value).path()); + } else if (type == DesignerPropertyManager::designerStringTypeId()) { + applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, qvariant_cast<PropertySheetStringValue>(value).value()); + } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) { + applyToEditors(m_keySequencePropertyToEditors.value(property), &QtKeySequenceEdit::setKeySequence, qvariant_cast<PropertySheetKeySequenceValue>(value).value()); + } break; } } @@ -2215,6 +2428,8 @@ QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, const QVariant richTextDefaultFont = manager->attributeValue(property, QLatin1String(fontAttributeC)); if (richTextDefaultFont.type() == QVariant::Font) ed->setRichTextDefaultFont(qvariant_cast<QFont>(richTextDefaultFont)); + const bool themeEnabled = manager->attributeValue(property, QLatin1String(themeAttributeC)).toBool(); + ed->setIconThemeModeEnabled(themeEnabled); m_stringPropertyToEditors[property].append(ed); m_editorToStringProperty[ed] = property; connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); @@ -2308,7 +2523,9 @@ QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, } else if (type == DesignerPropertyManager::designerIconTypeId()) { PixmapEditor *ed = new PixmapEditor(m_core, parent); ed->setPixmapCache(m_fwb->pixmapCache()); + ed->setIconThemeModeEnabled(true); PropertySheetIconValue value = qvariant_cast<PropertySheetIconValue>(manager->value(property)); + ed->setTheme(value.theme()); ed->setPath(value.pixmap(QIcon::Normal, QIcon::Off).path()); QPixmap defaultPixmap; if (!property->isModified()) @@ -2321,10 +2538,11 @@ QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, m_editorToIconProperty[ed] = property; connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); connect(ed, SIGNAL(pathChanged(QString)), this, SLOT(slotIconChanged(QString))); + connect(ed, SIGNAL(themeChanged(QString)), this, SLOT(slotIconThemeChanged(QString))); editor = ed; } else if (type == DesignerPropertyManager::designerStringTypeId()) { const TextPropertyValidationMode tvm = static_cast<TextPropertyValidationMode>(manager->attributeValue(property, QLatin1String(validationModesAttributeC)).toInt()); - TextEditor *ed = createTextEditor(parent, tvm, qVariantValue<PropertySheetStringValue>(manager->value(property)).value()); + TextEditor *ed = createTextEditor(parent, tvm, qvariant_cast<PropertySheetStringValue>(manager->value(property)).value()); const QVariant richTextDefaultFont = manager->attributeValue(property, QLatin1String(fontAttributeC)); if (richTextDefaultFont.type() == QVariant::Font) ed->setRichTextDefaultFont(qvariant_cast<QFont>(richTextDefaultFont)); @@ -2335,7 +2553,7 @@ QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, editor = ed; } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) { QtKeySequenceEdit *ed = new QtKeySequenceEdit(parent); - ed->setKeySequence(qVariantValue<PropertySheetKeySequenceValue>(manager->value(property)).value()); + ed->setKeySequence(qvariant_cast<PropertySheetKeySequenceValue>(manager->value(property)).value()); m_keySequencePropertyToEditors[property].append(ed); m_editorToKeySequenceProperty[ed] = property; connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); @@ -2456,12 +2674,12 @@ void DesignerEditorFactory::slotStringTextChanged(const QString &value) QtVariantProperty *varProp = manager->variantProperty(prop); QVariant val = varProp->value(); if (val.userType() == DesignerPropertyManager::designerStringTypeId()) { - PropertySheetStringValue strVal = qVariantValue<PropertySheetStringValue>(val); + PropertySheetStringValue strVal = qvariant_cast<PropertySheetStringValue>(val); strVal.setValue(value); // Disable translation if no translation subproperties exist. if (varProp->subProperties().empty()) strVal.setTranslatable(false); - val = qVariantFromValue(strVal); + val = QVariant::fromValue(strVal); } else { val = QVariant(value); } @@ -2482,11 +2700,11 @@ void DesignerEditorFactory::slotKeySequenceChanged(const QKeySequence &value) QtVariantProperty *varProp = manager->variantProperty(prop); QVariant val = varProp->value(); if (val.userType() == DesignerPropertyManager::designerKeySequenceTypeId()) { - PropertySheetKeySequenceValue keyVal = qVariantValue<PropertySheetKeySequenceValue>(val); + PropertySheetKeySequenceValue keyVal = qvariant_cast<PropertySheetKeySequenceValue>(val); keyVal.setValue(value); - val = qVariantFromValue(keyVal); + val = QVariant::fromValue(keyVal); } else { - val = qVariantFromValue(value); + val = QVariant::fromValue(value); } m_changingPropertyValue = true; manager->variantProperty(prop)->setValue(val); @@ -2497,24 +2715,32 @@ void DesignerEditorFactory::slotKeySequenceChanged(const QKeySequence &value) void DesignerEditorFactory::slotPaletteChanged(const QPalette &value) { - updateManager(this, &m_changingPropertyValue, m_editorToPaletteProperty, qobject_cast<QWidget *>(sender()), qVariantFromValue(value)); + updateManager(this, &m_changingPropertyValue, m_editorToPaletteProperty, qobject_cast<QWidget *>(sender()), QVariant::fromValue(value)); } void DesignerEditorFactory::slotPixmapChanged(const QString &value) { updateManager(this, &m_changingPropertyValue, m_editorToPixmapProperty, qobject_cast<QWidget *>(sender()), - qVariantFromValue(PropertySheetPixmapValue(value))); + QVariant::fromValue(PropertySheetPixmapValue(value))); } void DesignerEditorFactory::slotIconChanged(const QString &value) { updateManager(this, &m_changingPropertyValue, m_editorToIconProperty, qobject_cast<QWidget *>(sender()), - qVariantFromValue(PropertySheetIconValue(PropertySheetPixmapValue(value)))); + QVariant::fromValue(PropertySheetIconValue(PropertySheetPixmapValue(value)))); +} + +void DesignerEditorFactory::slotIconThemeChanged(const QString &value) +{ + PropertySheetIconValue icon; + icon.setTheme(value); + updateManager(this, &m_changingPropertyValue, m_editorToIconProperty, qobject_cast<QWidget *>(sender()), + QVariant::fromValue(icon)); } void DesignerEditorFactory::slotStringListChanged(const QStringList &value) { - updateManager(this, &m_changingPropertyValue, m_editorToStringListProperty, qobject_cast<QWidget *>(sender()), qVariantFromValue(value)); + updateManager(this, &m_changingPropertyValue, m_editorToStringListProperty, qobject_cast<QWidget *>(sender()), QVariant::fromValue(value)); } ResetDecorator::~ResetDecorator() diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.h b/tools/designer/src/components/propertyeditor/designerpropertymanager.h index 0ad93d7..58085f9 100644 --- a/tools/designer/src/components/propertyeditor/designerpropertymanager.h +++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.h @@ -180,6 +180,7 @@ private: QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> > m_propertyToIconSubProperties; QMap<QtProperty *, QPair<QIcon::Mode, QIcon::State> > m_iconSubPropertyToState; PropertyToPropertyMap m_iconSubPropertyToProperty; + PropertyToPropertyMap m_propertyToTheme; QMap<QtProperty *, qdesigner_internal::PropertySheetStringValue> m_stringValues; QMap<QtProperty *, QtProperty *> m_stringToComment; @@ -221,6 +222,7 @@ private: PropertyIntMap m_stringAttributes; typedef QMap<QtProperty *, QFont> PropertyFontMap; PropertyFontMap m_stringFontAttributes; + PropertyBoolMap m_stringThemeAttributes; BrushPropertyManager m_brushManager; FontPropertyManager m_fontManager; @@ -261,6 +263,7 @@ private slots: void slotPaletteChanged(const QPalette &value); void slotPixmapChanged(const QString &value); void slotIconChanged(const QString &value); + void slotIconThemeChanged(const QString &value); void slotUintChanged(const QString &value); void slotLongLongChanged(const QString &value); void slotULongLongChanged(const QString &value); diff --git a/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp b/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp index f3a3cbd..2e4dc90 100644 --- a/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp +++ b/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp @@ -123,7 +123,7 @@ namespace qdesigner_internal { // This will cause a recursion QtVariantProperty *antialiasing = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "Antialiasing")); - const QFont font = qVariantValue<QFont>(vm->variantProperty(property)->value()); + const QFont font = qvariant_cast<QFont>(vm->variantProperty(property)->value()); antialiasing->setAttribute(QLatin1String("enumNames"), m_aliasingEnumNames); antialiasing->setValue(antialiasingToIndex(font.styleStrategy())); @@ -196,7 +196,7 @@ namespace qdesigner_internal { mask &= ~flag; font.resolve(mask); - qVariantSetValue(v, font); + v.setValue(font); fontProperty->setValue(v); return true; } @@ -250,13 +250,13 @@ namespace qdesigner_internal { QtVariantProperty *fontProperty = vm->variantProperty(antialiasingProperty); const QFont::StyleStrategy newValue = indexToAntialiasing(value.toInt()); - QFont font = qVariantValue<QFont>(fontProperty->value()); + QFont font = qvariant_cast<QFont>(fontProperty->value()); const QFont::StyleStrategy oldValue = font.styleStrategy(); if (newValue == oldValue) return Unchanged; font.setStyleStrategy(newValue); - fontProperty->setValue(qVariantFromValue(font)); + fontProperty->setValue(QVariant::fromValue(font)); return Changed; } @@ -268,7 +268,7 @@ namespace qdesigner_internal { const PropertyList &subProperties = it.value(); - QFont font = qVariantValue<QFont>(value); + QFont font = qvariant_cast<QFont>(value); const unsigned mask = font.resolve(); const int count = subProperties.size(); @@ -285,7 +285,7 @@ namespace qdesigner_internal { if (QtProperty *antialiasingProperty = m_propertyToAntialiasing.value(property, 0)) { QtVariantProperty *antialiasing = vm->variantProperty(antialiasingProperty); if (antialiasing) { - QFont font = qVariantValue<QFont>(value); + QFont font = qvariant_cast<QFont>(value); antialiasing->setValue(antialiasingToIndex(font.styleStrategy())); } } diff --git a/tools/designer/src/components/propertyeditor/paletteeditor.cpp b/tools/designer/src/components/propertyeditor/paletteeditor.cpp index 81fbab5..bf995fd 100644 --- a/tools/designer/src/components/propertyeditor/paletteeditor.cpp +++ b/tools/designer/src/components/propertyeditor/paletteeditor.cpp @@ -294,7 +294,7 @@ bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int return false; if (index.column() != 0 && role == BrushRole) { - const QBrush br = qVariantValue<QBrush>(value); + const QBrush br = qvariant_cast<QBrush>(value); const QPalette::ColorRole r = static_cast<QPalette::ColorRole>(index.row()); const QPalette::ColorGroup g = columnToGroup(index.column()); m_palette.setBrush(g, r, br); @@ -336,7 +336,7 @@ bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int } if (index.column() == 0 && role == Qt::EditRole) { uint mask = m_palette.resolve(); - const bool isMask = qVariantValue<bool>(value); + const bool isMask = qvariant_cast<bool>(value); const int r = index.row(); if (isMask) mask |= (1 << r); @@ -532,13 +532,13 @@ QWidget *ColorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem void ColorDelegate::setEditorData(QWidget *ed, const QModelIndex &index) const { if (index.column() == 0) { - const bool mask = qVariantValue<bool>(index.model()->data(index, Qt::EditRole)); + const bool mask = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole)); RoleEditor *editor = static_cast<RoleEditor *>(ed); editor->setEdited(mask); - const QString colorName = qVariantValue<QString>(index.model()->data(index, Qt::DisplayRole)); + const QString colorName = qvariant_cast<QString>(index.model()->data(index, Qt::DisplayRole)); editor->setLabel(colorName); } else { - const QBrush br = qVariantValue<QBrush>(index.model()->data(index, BrushRole)); + const QBrush br = qvariant_cast<QBrush>(index.model()->data(index, BrushRole)); BrushEditor *editor = static_cast<BrushEditor *>(ed); editor->setBrush(br); } @@ -571,11 +571,11 @@ void ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &index) const { QStyleOptionViewItem option = opt; - const bool mask = qVariantValue<bool>(index.model()->data(index, Qt::EditRole)); + const bool mask = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole)); if (index.column() == 0 && mask) { option.font.setBold(true); } - QBrush br = qVariantValue<QBrush>(index.model()->data(index, BrushRole)); + QBrush br = qvariant_cast<QBrush>(index.model()->data(index, BrushRole)); if (br.style() == Qt::LinearGradientPattern || br.style() == Qt::RadialGradientPattern || br.style() == Qt::ConicalGradientPattern) { diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.cpp b/tools/designer/src/components/propertyeditor/propertyeditor.cpp index 4c36d88..416b680 100644 --- a/tools/designer/src/components/propertyeditor/propertyeditor.cpp +++ b/tools/designer/src/components/propertyeditor/propertyeditor.cpp @@ -91,6 +91,7 @@ static const char *ViewKeyC = "View"; static const char *ColorKeyC = "Colored"; static const char *SortedKeyC = "Sorted"; static const char *ExpansionKeyC = "ExpandedItems"; +static const char *SplitterPositionKeyC = "SplitterPosition"; enum SettingsView { TreeView, ButtonView }; @@ -365,10 +366,12 @@ PropertyEditor::PropertyEditor(QDesignerFormEditorInterface *core, QWidget *pare m_sorting = settings->value(QLatin1String(SortedKeyC), false).toBool(); m_coloring = settings->value(QLatin1String(ColorKeyC), true).toBool(); const QVariantMap expansionState = settings->value(QLatin1String(ExpansionKeyC), QVariantMap()).toMap(); + const int splitterPosition = settings->value(QLatin1String(SplitterPositionKeyC), 150).toInt(); settings->endGroup(); // Apply settings m_sortingAction->setChecked(m_sorting); m_coloringAction->setChecked(m_coloring); + m_treeBrowser->setSplitterPosition(splitterPosition); #if QT_VERSION >= 0x040500 switch (view) { case TreeView: @@ -415,6 +418,7 @@ void PropertyEditor::saveSettings() const expansionState.insert(it.key(), QVariant(it.value())); } settings->setValue(QLatin1String(ExpansionKeyC), expansionState); + settings->setValue(QLatin1String(SplitterPositionKeyC), m_treeBrowser->splitterPosition()); settings->endGroup(); } @@ -872,12 +876,12 @@ void PropertyEditor::updateBrowserValue(QtVariantProperty *property, const QVari int PropertyEditor::toBrowserType(const QVariant &value, const QString &propertyName) const { - if (qVariantCanConvert<PropertySheetFlagValue>(value)) { + if (value.canConvert<PropertySheetFlagValue>()) { if (m_strings.m_alignmentProperties.contains(propertyName)) return DesignerPropertyManager::designerAlignmentTypeId(); return DesignerPropertyManager::designerFlagTypeId(); } - if (qVariantCanConvert<PropertySheetEnumValue>(value)) + if (value.canConvert<PropertySheetEnumValue>()) return DesignerPropertyManager::enumTypeId(); return value.userType(); @@ -1034,7 +1038,7 @@ void PropertyEditor::setObject(QObject *object) } m_updatingBrowser = true; QVariant v; - qVariantSetValue(v, flags); + v.setValue(flags); property->setAttribute(m_strings.m_flagsAttribute, v); m_updatingBrowser = false; } @@ -1223,7 +1227,7 @@ void PropertyEditor::slotValueChanged(QtProperty *property, const QVariant &valu e.value = e.metaEnum.parseEnum(valName, &ok); Q_ASSERT(ok); QVariant v; - qVariantSetValue(v, e); + v.setValue(e); emitPropertyValueChanged(property->propertyName(), v, true); return; } diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.pri b/tools/designer/src/components/propertyeditor/propertyeditor.pri index bb1afdb..60219e1 100644 --- a/tools/designer/src/components/propertyeditor/propertyeditor.pri +++ b/tools/designer/src/components/propertyeditor/propertyeditor.pri @@ -4,15 +4,8 @@ INCLUDEPATH += $$PWD -# --- Property browser is also linked into the designer_shared library. -# Avoid conflict when linking statically -contains(CONFIG, static) { - INCLUDEPATH *= $$QT_SOURCE_TREE/tools/shared/qtpropertybrowser - INCLUDEPATH *= $$QT_SOURCE_TREE/tools/shared/qtgradienteditor -} else { - include(../../../../shared/qtpropertybrowser/qtpropertybrowser.pri) - include(../../../../shared/qtgradienteditor/qtcolorbutton.pri) -} +include(../../../../shared/qtpropertybrowser/qtpropertybrowser.pri) +include(../../../../shared/qtgradienteditor/qtcolorbutton.pri) FORMS += $$PWD/paletteeditor.ui \ $$PWD/stringlisteditor.ui \ diff --git a/tools/designer/src/components/signalsloteditor/connectdialog.cpp b/tools/designer/src/components/signalsloteditor/connectdialog.cpp index d353e09..2d55abd 100644 --- a/tools/designer/src/components/signalsloteditor/connectdialog.cpp +++ b/tools/designer/src/components/signalsloteditor/connectdialog.cpp @@ -231,7 +231,7 @@ void ConnectDialog::populateSlotList(const QString &signal) QFont font = QApplication::font(); font.setItalic(true); - QVariant variantFont = qVariantFromValue(font); + QVariant variantFont = QVariant::fromValue(font); QListWidgetItem *curr = 0; QMap<QString, QString>::ConstIterator itMember = memberToClassName.constBegin(); @@ -271,7 +271,7 @@ void ConnectDialog::populateSignalList() QFont font = QApplication::font(); font.setItalic(true); - QVariant variantFont = qVariantFromValue(font); + QVariant variantFont = QVariant::fromValue(font); QListWidgetItem *curr = 0; QMap<QString, QString>::ConstIterator itMember = memberToClassName.constBegin(); diff --git a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp index 2152102..6edd107 100644 --- a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp +++ b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp @@ -248,7 +248,7 @@ namespace qdesigner_internal { if (obj_name == form->mainContainer()->objectName()) { object = form->mainContainer(); } else { - object = qFindChild<QObject*>(form->mainContainer(), obj_name); + object = form->mainContainer()->findChild<QObject*>(obj_name); } if (!object) return ClassesMemberFunctions(); diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp index 91a49c4..8efe092 100644 --- a/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp +++ b/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp @@ -372,7 +372,7 @@ QObject *SignalSlotEditor::objectByName(QWidget *topLevel, const QString &name) if (topLevel->objectName() == name) object = topLevel; else - object = qFindChild<QObject*>(topLevel, name); + object = topLevel->findChild<QObject*>(name); const QDesignerMetaDataBaseInterface *mdb = formWindow()->core()->metaDataBase(); if (mdb->item(object)) return object; diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp index 7b38a42..6155db3 100644 --- a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp +++ b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp @@ -117,7 +117,7 @@ static QStringList objectNameList(QDesignerFormWindowInterface *form) const QDesignerMetaDataBaseInterface *mdb = form->core()->metaDataBase(); // Add managed actions and actions with managed menus - const ActionList actions = qFindChildren<QAction*>(mainContainer); + const ActionList actions = mainContainer->findChildren<QAction*>(); if (!actions.empty()) { const ActionList::const_iterator cend = actions.constEnd(); for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it) { @@ -135,7 +135,7 @@ static QStringList objectNameList(QDesignerFormWindowInterface *form) } // Add managed buttons groups - const ButtonGroupList buttonGroups = qFindChildren<QButtonGroup *>(mainContainer); + const ButtonGroupList buttonGroups = mainContainer->findChildren<QButtonGroup *>(); if (!buttonGroups.empty()) { const ButtonGroupList::const_iterator cend = buttonGroups.constEnd(); for (ButtonGroupList::const_iterator it = buttonGroups.constBegin(); it != cend; ++it) @@ -473,7 +473,7 @@ void InlineEditorModel::addTextList(const QMap<QString, bool> &text_list) insertRows(cnt, text_list.size()); QFont font = QApplication::font(); font.setItalic(true); - QVariant fontVariant = qVariantFromValue(font); + QVariant fontVariant = QVariant::fromValue(font); QMap<QString, bool>::ConstIterator it = text_list.constBegin(); const QMap<QString, bool>::ConstIterator itEnd = text_list.constEnd(); while (it != itEnd) { @@ -662,7 +662,7 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, if (obj_name == m_form->mainContainer()->objectName()) { object = m_form->mainContainer(); } else { - object = qFindChild<QObject*>(m_form->mainContainer(), obj_name); + object = m_form->mainContainer()->findChild<QObject*>(obj_name); } inline_editor->addText(type == qdesigner_internal::SignalMember ? tr("<signal>") : tr("<slot>")); foreach (const qdesigner_internal::ClassMemberFunctions &class_info, class_list) { @@ -771,7 +771,7 @@ void SignalSlotEditorWindow::setActiveFormWindow(QDesignerFormWindowInterface *f } } - m_editor = qFindChild<SignalSlotEditor*>(form); + m_editor = form->findChild<SignalSlotEditor*>(); m_model->setEditor(m_editor); if (!m_editor.isNull()) { ConnectionDelegate *delegate diff --git a/tools/designer/src/components/tabordereditor/tabordereditor.cpp b/tools/designer/src/components/tabordereditor/tabordereditor.cpp index 3009f9d..a32ffe4 100644 --- a/tools/designer/src/components/tabordereditor/tabordereditor.cpp +++ b/tools/designer/src/components/tabordereditor/tabordereditor.cpp @@ -208,7 +208,7 @@ bool TabOrderEditor::skipWidget(QWidget *w) const if (index != -1) { bool ok = false; Qt::FocusPolicy q = (Qt::FocusPolicy) Utils::valueOf(sheet->property(index), &ok); - return !ok || q == Qt::NoFocus; + return !ok || !(q & Qt::TabFocus); } } @@ -239,7 +239,7 @@ void TabOrderEditor::initTabOrder() childQueue.append(formWindow()->mainContainer()); while (!childQueue.isEmpty()) { QWidget *child = childQueue.takeFirst(); - childQueue += qVariantValue<QWidgetList>(child->property("_q_widgetOrder")); + childQueue += qvariant_cast<QWidgetList>(child->property("_q_widgetOrder")); if (skipWidget(child)) continue; diff --git a/tools/designer/src/components/taskmenu/button_taskmenu.cpp b/tools/designer/src/components/taskmenu/button_taskmenu.cpp index f7a441e..282abe6 100644 --- a/tools/designer/src/components/taskmenu/button_taskmenu.cpp +++ b/tools/designer/src/components/taskmenu/button_taskmenu.cpp @@ -508,7 +508,7 @@ bool ButtonTaskMenu::refreshAssignMenu(const QDesignerFormWindowInterface *fw, i QButtonGroup *bg = *it; if (*it != currentGroup) { QAction *a = new QAction(bg->objectName(), m_assignGroupSubMenu); - a->setData(qVariantFromValue(bg)); + a->setData(QVariant::fromValue(bg)); m_assignActionGroup->addAction(a); m_assignGroupSubMenu->addAction(a); } @@ -528,7 +528,7 @@ bool ButtonTaskMenu::refreshAssignMenu(const QDesignerFormWindowInterface *fw, i QList<QAction*> ButtonTaskMenu::taskActions() const { ButtonTaskMenu *ncThis = const_cast<ButtonTaskMenu*>(this); - QButtonGroup *buttonGroup; + QButtonGroup *buttonGroup = 0; QDesignerFormWindowInterface *fw = formWindow(); const SelectionType st = selectionType(fw->cursor(), &buttonGroup); diff --git a/tools/designer/src/components/taskmenu/inplace_editor.cpp b/tools/designer/src/components/taskmenu/inplace_editor.cpp index 07f1c3c..6bc7af3 100644 --- a/tools/designer/src/components/taskmenu/inplace_editor.cpp +++ b/tools/designer/src/components/taskmenu/inplace_editor.cpp @@ -106,7 +106,7 @@ void TaskMenuInlineEditor::editText() const int index = sheet->indexOf(m_property); if (index == -1) return; - m_value = qVariantValue<PropertySheetStringValue>(sheet->property(index)); + m_value = qvariant_cast<PropertySheetStringValue>(sheet->property(index)); const QString oldValue = m_value.value(); m_editor = new InPlaceEditor(m_widget, m_vm, m_formWindow, oldValue, editRectangle()); @@ -119,9 +119,9 @@ void TaskMenuInlineEditor::updateText(const QString &text) // do not use the cursor selection m_value.setValue(text); if (m_managed) { - m_formWindow->cursor()->setProperty(m_property, qVariantFromValue(m_value)); + m_formWindow->cursor()->setProperty(m_property, QVariant::fromValue(m_value)); } else { - m_formWindow->cursor()->setWidgetProperty(m_widget, m_property, qVariantFromValue(m_value)); + m_formWindow->cursor()->setWidgetProperty(m_widget, m_property, QVariant::fromValue(m_value)); } } diff --git a/tools/designer/src/components/taskmenu/itemlisteditor.cpp b/tools/designer/src/components/taskmenu/itemlisteditor.cpp index 8a3282f..d682aff 100644 --- a/tools/designer/src/components/taskmenu/itemlisteditor.cpp +++ b/tools/designer/src/components/taskmenu/itemlisteditor.cpp @@ -80,7 +80,7 @@ private: ////////////////// Item editor /////////////// AbstractItemEditor::AbstractItemEditor(QDesignerFormWindowInterface *form, QWidget *parent) - : QDialog(parent), + : QWidget(parent), m_iconCache(qobject_cast<FormWindowBase *>(form)->iconCache()), m_updatingBrowser(false) { @@ -104,15 +104,6 @@ AbstractItemEditor::~AbstractItemEditor() m_propertyBrowser->unsetFactoryForManager(m_propertyManager); } -void AbstractItemEditor::keyPressEvent(QKeyEvent *e) -{ - // Avoid that embedded dialogs react to enter and escape keys. - if (this == window()) - QDialog::keyPressEvent(e); - else - QWidget::keyPressEvent(e); -} - static const char * const itemFlagNames[] = { QT_TRANSLATE_NOOP("AbstractItemEditor", "Selectable"), QT_TRANSLATE_NOOP("AbstractItemEditor", "Editable"), @@ -191,8 +182,8 @@ void AbstractItemEditor::propertyChanged(QtProperty *property) return; if ((role == ItemFlagsShadowRole && prop->value().toInt() == (int)QListWidgetItem().flags()) - || (role == Qt::DecorationPropertyRole && !qVariantValue<PropertySheetIconValue>(prop->value()).mask()) - || (role == Qt::FontRole && !qVariantValue<QFont>(prop->value()).resolve())) { + || (role == Qt::DecorationPropertyRole && !qvariant_cast<PropertySheetIconValue>(prop->value()).mask()) + || (role == Qt::FontRole && !qvariant_cast<QFont>(prop->value()).resolve())) { prop->setModified(false); setItemData(role, QVariant()); } else { @@ -202,19 +193,19 @@ void AbstractItemEditor::propertyChanged(QtProperty *property) switch (role) { case Qt::DecorationPropertyRole: - setItemData(Qt::DecorationRole, qVariantFromValue(iconCache()->icon(qVariantValue<PropertySheetIconValue>(prop->value())))); + setItemData(Qt::DecorationRole, QVariant::fromValue(iconCache()->icon(qvariant_cast<PropertySheetIconValue>(prop->value())))); break; case Qt::DisplayPropertyRole: - setItemData(Qt::EditRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value())); + setItemData(Qt::EditRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value())); break; case Qt::ToolTipPropertyRole: - setItemData(Qt::ToolTipRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value())); + setItemData(Qt::ToolTipRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value())); break; case Qt::StatusTipPropertyRole: - setItemData(Qt::StatusTipRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value())); + setItemData(Qt::StatusTipRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value())); break; case Qt::WhatsThisPropertyRole: - setItemData(Qt::WhatsThisRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value())); + setItemData(Qt::WhatsThisRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value())); break; default: break; @@ -236,22 +227,22 @@ void AbstractItemEditor::resetProperty(QtProperty *property) QtVariantProperty *prop = m_propertyManager->variantProperty(property); int role = m_propertyToRole.value(prop); if (role == ItemFlagsShadowRole) - prop->setValue(qVariantFromValue((int)QListWidgetItem().flags())); + prop->setValue(QVariant::fromValue((int)QListWidgetItem().flags())); else prop->setValue(QVariant(prop->valueType(), (void *)0)); prop->setModified(false); setItemData(role, QVariant()); if (role == Qt::DecorationPropertyRole) - setItemData(Qt::DecorationRole, qVariantFromValue(QIcon())); + setItemData(Qt::DecorationRole, QVariant::fromValue(QIcon())); if (role == Qt::DisplayPropertyRole) - setItemData(Qt::EditRole, qVariantFromValue(QString())); + setItemData(Qt::EditRole, QVariant::fromValue(QString())); if (role == Qt::ToolTipPropertyRole) - setItemData(Qt::ToolTipRole, qVariantFromValue(QString())); + setItemData(Qt::ToolTipRole, QVariant::fromValue(QString())); if (role == Qt::StatusTipPropertyRole) - setItemData(Qt::StatusTipRole, qVariantFromValue(QString())); + setItemData(Qt::StatusTipRole, QVariant::fromValue(QString())); if (role == Qt::WhatsThisPropertyRole) - setItemData(Qt::WhatsThisRole, qVariantFromValue(QString())); + setItemData(Qt::WhatsThisRole, QVariant::fromValue(QString())); } void AbstractItemEditor::cacheReloaded() @@ -268,7 +259,7 @@ void AbstractItemEditor::updateBrowser() QVariant val = getItemData(role); if (!val.isValid()) { if (role == ItemFlagsShadowRole) - val = qVariantFromValue((int)QListWidgetItem().flags()); + val = QVariant::fromValue((int)QListWidgetItem().flags()); else val = QVariant((int)prop->value().userType(), (void *)0); prop->setModified(false); @@ -304,7 +295,7 @@ ItemListEditor::ItemListEditor(QDesignerFormWindowInterface *form, QWidget *pare injectPropertyBrowser(this, ui.widget); connect(ui.showPropertiesButton, SIGNAL(clicked()), this, SLOT(togglePropertyBrowser())); - togglePropertyBrowser(); + setPropertyBrowserVisible(false); QIcon upIcon = createIconSet(QString::fromUtf8("up.png")); QIcon downIcon = createIconSet(QString::fromUtf8("down.png")); @@ -340,7 +331,7 @@ void ItemListEditor::on_newListItemButton_clicked() int row = ui.listWidget->currentRow() + 1; QListWidgetItem *item = new QListWidgetItem(m_newItemText); - item->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_newItemText))); + item->setData(Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(m_newItemText))); item->setFlags(item->flags() | Qt::ItemIsEditable); if (row < ui.listWidget->count()) ui.listWidget->insertItem(row, item); @@ -403,29 +394,27 @@ void ItemListEditor::on_listWidget_itemChanged(QListWidgetItem *item) if (m_updatingBrowser) return; - PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)); + PropertySheetStringValue val = qvariant_cast<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)); val.setValue(item->text()); BoolBlocker block(m_updatingBrowser); - item->setData(Qt::DisplayPropertyRole, qVariantFromValue(val)); + item->setData(Qt::DisplayPropertyRole, QVariant::fromValue(val)); // The checkState could change, too, but if this signal is connected, // checkState is not in the list anyway, as we are editing a header item. emit itemChanged(ui.listWidget->currentRow(), Qt::DisplayPropertyRole, - qVariantFromValue(val)); + QVariant::fromValue(val)); updateBrowser(); } void ItemListEditor::togglePropertyBrowser() { - // Always hide in case parent widget is not visible -> on startup - const bool isVisible = - !this->isVisible() ? true : m_propertyBrowser->isVisible(); - if (isVisible) - ui.showPropertiesButton->setText(tr("Properties &<<")); - else - ui.showPropertiesButton->setText(tr("Properties &>>")); + setPropertyBrowserVisible(!m_propertyBrowser->isVisible()); +} - m_propertyBrowser->setVisible(!isVisible); +void ItemListEditor::setPropertyBrowserVisible(bool v) +{ + ui.showPropertiesButton->setText(v ? tr("Properties &>>") : tr("Properties &<<")); + m_propertyBrowser->setVisible(v); } void ItemListEditor::setItemData(int role, const QVariant &v) @@ -438,8 +427,8 @@ void ItemListEditor::setItemData(int role, const QVariant &v) QVariant newValue = v; if (role == Qt::FontRole && newValue.type() == QVariant::Font) { QFont oldFont = ui.listWidget->font(); - QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont); - newValue = qVariantFromValue(newFont); + QFont newFont = qvariant_cast<QFont>(newValue).resolve(oldFont); + newValue = QVariant::fromValue(newFont); item->setData(role, QVariant()); // force the right font with the current resolve mask is set (item view bug) } item->setData(role, newValue); @@ -484,6 +473,6 @@ void ItemListEditor::updateEditor() else m_propertyBrowser->clear(); } -} +} // namespace qdesigner_internal QT_END_NAMESPACE diff --git a/tools/designer/src/components/taskmenu/itemlisteditor.h b/tools/designer/src/components/taskmenu/itemlisteditor.h index 03560c5..57bbeef 100644 --- a/tools/designer/src/components/taskmenu/itemlisteditor.h +++ b/tools/designer/src/components/taskmenu/itemlisteditor.h @@ -53,6 +53,7 @@ class QtProperty; class QtVariantProperty; class QtTreePropertyBrowser; class QSplitter; +class QVBoxLayout; namespace qdesigner_internal { @@ -72,12 +73,12 @@ private: bool reset; }; -class AbstractItemEditor: public QDialog +class AbstractItemEditor: public QWidget { Q_OBJECT public: - AbstractItemEditor(QDesignerFormWindowInterface *form, QWidget *parent); + explicit AbstractItemEditor(QDesignerFormWindowInterface *form, QWidget *parent); ~AbstractItemEditor(); DesignerIconCache *iconCache() const { return m_iconCache; } @@ -95,7 +96,6 @@ private slots: void cacheReloaded(); protected: - void keyPressEvent(QKeyEvent *e); void setupProperties(PropertyDefinition *propDefs); void setupObject(QWidget *object); void setupEditor(QWidget *object, PropertyDefinition *propDefs); @@ -120,7 +120,7 @@ class ItemListEditor: public AbstractItemEditor Q_OBJECT public: - ItemListEditor(QDesignerFormWindowInterface *form, QWidget *parent); + explicit ItemListEditor(QDesignerFormWindowInterface *form, QWidget *parent); void setupEditor(QWidget *object, PropertyDefinition *propDefs); QListWidget *listWidget() const { return ui.listWidget; } @@ -150,6 +150,8 @@ protected: virtual void setItemData(int role, const QVariant &v); virtual QVariant getItemData(int role) const; +private: + void setPropertyBrowserVisible(bool v); void updateEditor(); Ui::ItemListEditor ui; bool m_updating; diff --git a/tools/designer/src/components/taskmenu/listwidgeteditor.h b/tools/designer/src/components/taskmenu/listwidgeteditor.h index a8290d4..30b851b 100644 --- a/tools/designer/src/components/taskmenu/listwidgeteditor.h +++ b/tools/designer/src/components/taskmenu/listwidgeteditor.h @@ -45,7 +45,7 @@ #include "itemlisteditor.h" #include <qdesigner_command_p.h> -#include <QtGui/QDialog> +#include <QtGui/QWidget> QT_BEGIN_NAMESPACE diff --git a/tools/designer/src/components/taskmenu/tablewidget_taskmenu.cpp b/tools/designer/src/components/taskmenu/tablewidget_taskmenu.cpp index 9c25669..b77a090 100644 --- a/tools/designer/src/components/taskmenu/tablewidget_taskmenu.cpp +++ b/tools/designer/src/components/taskmenu/tablewidget_taskmenu.cpp @@ -94,7 +94,7 @@ void TableWidgetTaskMenu::editItems() Q_ASSERT(m_tableWidget != 0); - TableWidgetEditor dlg(m_formWindow, m_tableWidget->window()); + TableWidgetEditorDialog dlg(m_formWindow, m_tableWidget->window()); TableWidgetContents oldCont = dlg.fillContentsFromTableWidget(m_tableWidget); if (dlg.exec() == QDialog::Accepted) { TableWidgetContents newCont = dlg.contents(); diff --git a/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp b/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp index b67b854..b5da43c 100644 --- a/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp +++ b/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp @@ -57,10 +57,10 @@ QT_BEGIN_NAMESPACE -using namespace qdesigner_internal; +namespace qdesigner_internal { -TableWidgetEditor::TableWidgetEditor(QDesignerFormWindowInterface *form, QWidget *parent) - : AbstractItemEditor(form, parent), m_updatingBrowser(false) +TableWidgetEditor::TableWidgetEditor(QDesignerFormWindowInterface *form, QDialog *dialog) + : AbstractItemEditor(form, 0), m_updatingBrowser(false) { m_columnEditor = new ItemListEditor(form, this); m_columnEditor->setObjectName(QLatin1String("columnEditor")); @@ -68,12 +68,12 @@ TableWidgetEditor::TableWidgetEditor(QDesignerFormWindowInterface *form, QWidget m_rowEditor = new ItemListEditor(form, this); m_rowEditor->setObjectName(QLatin1String("rowEditor")); m_rowEditor->setNewItemText(tr("New Row")); - ui.setupUi(this); + ui.setupUi(dialog); injectPropertyBrowser(ui.itemsTab, ui.widget); connect(ui.showPropertiesButton, SIGNAL(clicked()), this, SLOT(togglePropertyBrowser())); - togglePropertyBrowser(); + setPropertyBrowserVisible(false); ui.tabWidget->insertTab(0, m_columnEditor, tr("&Columns")); ui.tabWidget->insertTab(1, m_rowEditor, tr("&Rows")); @@ -83,6 +83,36 @@ TableWidgetEditor::TableWidgetEditor(QDesignerFormWindowInterface *form, QWidget ui.tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); connect(iconCache(), SIGNAL(reloaded()), this, SLOT(cacheReloaded())); + + connect(ui.tableWidget, SIGNAL(currentCellChanged(int,int,int,int)), + this, SLOT(on_tableWidget_currentCellChanged(int,int,int,int))); + connect(ui.tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), + this, SLOT(on_tableWidget_itemChanged(QTableWidgetItem*))); + connect(m_columnEditor, SIGNAL(indexChanged(int)), + this, SLOT(on_columnEditor_indexChanged(int))); + connect(m_columnEditor, SIGNAL(itemChanged(int,int,QVariant)), + this, SLOT(on_columnEditor_itemChanged(int,int,QVariant))); + connect(m_columnEditor, SIGNAL(itemInserted(int)), + this, SLOT(on_columnEditor_itemInserted(int))); + connect(m_columnEditor, SIGNAL(itemDeleted(int)), + this, SLOT(on_columnEditor_itemDeleted(int))); + connect(m_columnEditor, SIGNAL(itemMovedUp(int)), + this, SLOT(on_columnEditor_itemMovedUp(int))); + connect(m_columnEditor, SIGNAL(itemMovedDown(int)), + this, SLOT(on_columnEditor_itemMovedDown(int))); + + connect(m_rowEditor, SIGNAL(indexChanged(int)), + this, SLOT(on_rowEditor_indexChanged(int))); + connect(m_rowEditor, SIGNAL(itemChanged(int,int,QVariant)), + this, SLOT(on_rowEditor_itemChanged(int,int,QVariant))); + connect(m_rowEditor, SIGNAL(itemInserted(int)), + this, SLOT(on_rowEditor_itemInserted(int))); + connect(m_rowEditor, SIGNAL(itemDeleted(int)), + this, SLOT(on_rowEditor_itemDeleted(int))); + connect(m_rowEditor, SIGNAL(itemMovedUp(int)), + this, SLOT(on_rowEditor_itemMovedUp(int))); + connect(m_rowEditor, SIGNAL(itemMovedDown(int)), + this, SLOT(on_rowEditor_itemMovedDown(int))); } static AbstractItemEditor::PropertyDefinition tableHeaderPropList[] = { @@ -152,8 +182,8 @@ void TableWidgetEditor::setItemData(int role, const QVariant &v) QVariant newValue = v; if (role == Qt::FontRole && newValue.type() == QVariant::Font) { QFont oldFont = ui.tableWidget->font(); - QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont); - newValue = qVariantFromValue(newFont); + QFont newFont = qvariant_cast<QFont>(newValue).resolve(oldFont); + newValue = QVariant::fromValue(newFont); item->setData(role, QVariant()); // force the right font with the current resolve mask is set (item view bug) } item->setData(role, newValue); @@ -179,10 +209,10 @@ void TableWidgetEditor::on_tableWidget_itemChanged(QTableWidgetItem *item) if (m_updatingBrowser) return; - PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)); + PropertySheetStringValue val = qvariant_cast<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)); val.setValue(item->text()); BoolBlocker block(m_updatingBrowser); - item->setData(Qt::DisplayPropertyRole, qVariantFromValue(val)); + item->setData(Qt::DisplayPropertyRole, QVariant::fromValue(val)); updateBrowser(); } @@ -207,16 +237,15 @@ void TableWidgetEditor::on_rowEditor_itemChanged(int idx, int role, const QVaria ui.tableWidget->verticalHeaderItem(idx)->setData(role, v); } +void TableWidgetEditor::setPropertyBrowserVisible(bool v) +{ + ui.showPropertiesButton->setText(v ? tr("Properties &>>") : tr("Properties &<<")); + m_propertyBrowser->setVisible(v); +} + void TableWidgetEditor::togglePropertyBrowser() { - // Always hide in case parent widget is not visible -> on startup - const bool isVisible = - !this->isVisible() ? true : m_propertyBrowser->isVisible(); - if (isVisible) - ui.showPropertiesButton->setText(tr("Properties &<<")); - else - ui.showPropertiesButton->setText(tr("Properties &>>")); - m_propertyBrowser->setVisible(!isVisible); + setPropertyBrowserVisible(!m_propertyBrowser->isVisible()); } void TableWidgetEditor::updateEditor() @@ -317,7 +346,7 @@ void TableWidgetEditor::on_columnEditor_itemInserted(int idx) ui.tableWidget->setColumnCount(columnCount + 1); QTableWidgetItem *newItem = new QTableWidgetItem(m_columnEditor->newItemText()); - newItem->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_columnEditor->newItemText()))); + newItem->setData(Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(m_columnEditor->newItemText()))); ui.tableWidget->setHorizontalHeaderItem(columnCount, newItem); moveColumnsLeft(idx, columnCount); @@ -359,7 +388,7 @@ void TableWidgetEditor::on_rowEditor_itemInserted(int idx) ui.tableWidget->setRowCount(rowCount + 1); QTableWidgetItem *newItem = new QTableWidgetItem(m_rowEditor->newItemText()); - newItem->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_rowEditor->newItemText()))); + newItem->setData(Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(m_rowEditor->newItemText()))); ui.tableWidget->setVerticalHeaderItem(rowCount, newItem); moveRowsDown(idx, rowCount); @@ -400,4 +429,22 @@ void TableWidgetEditor::cacheReloaded() reloadIconResources(iconCache(), ui.tableWidget); } +TableWidgetEditorDialog::TableWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent) : + QDialog(parent), m_editor(form, this) +{ + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); +} + +TableWidgetContents TableWidgetEditorDialog::fillContentsFromTableWidget(QTableWidget *tableWidget) +{ + return m_editor.fillContentsFromTableWidget(tableWidget); +} + +TableWidgetContents TableWidgetEditorDialog::contents() const +{ + return m_editor.contents(); +} + +} // namespace qdesigner_internal + QT_END_NAMESPACE diff --git a/tools/designer/src/components/taskmenu/tablewidgeteditor.h b/tools/designer/src/components/taskmenu/tablewidgeteditor.h index b64909c..f99bdc5 100644 --- a/tools/designer/src/components/taskmenu/tablewidgeteditor.h +++ b/tools/designer/src/components/taskmenu/tablewidgeteditor.h @@ -46,6 +46,8 @@ #include "listwidgeteditor.h" +#include <QtGui/QDialog> + QT_BEGIN_NAMESPACE class QTableWidget; @@ -60,7 +62,7 @@ class TableWidgetEditor: public AbstractItemEditor { Q_OBJECT public: - TableWidgetEditor(QDesignerFormWindowInterface *form, QWidget *parent); + explicit TableWidgetEditor(QDesignerFormWindowInterface *form, QDialog *dialog); TableWidgetContents fillContentsFromTableWidget(QTableWidget *tableWidget); TableWidgetContents contents() const; @@ -95,6 +97,7 @@ protected: virtual QVariant getItemData(int role) const; private: + void setPropertyBrowserVisible(bool v); void updateEditor(); void moveColumnsLeft(int fromColumn, int toColumn); void moveColumnsRight(int fromColumn, int toColumn); @@ -107,6 +110,19 @@ private: bool m_updatingBrowser; }; +class TableWidgetEditorDialog : public QDialog +{ + Q_OBJECT +public: + explicit TableWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent); + + TableWidgetContents fillContentsFromTableWidget(QTableWidget *tableWidget); + TableWidgetContents contents() const; + +private: + TableWidgetEditor m_editor; +}; + } // namespace qdesigner_internal QT_END_NAMESPACE diff --git a/tools/designer/src/components/taskmenu/treewidget_taskmenu.cpp b/tools/designer/src/components/taskmenu/treewidget_taskmenu.cpp index 1b8677a..1395e31 100644 --- a/tools/designer/src/components/taskmenu/treewidget_taskmenu.cpp +++ b/tools/designer/src/components/taskmenu/treewidget_taskmenu.cpp @@ -93,7 +93,7 @@ void TreeWidgetTaskMenu::editItems() Q_ASSERT(m_treeWidget != 0); - TreeWidgetEditor dlg(m_formWindow, m_treeWidget->window()); + TreeWidgetEditorDialog dlg(m_formWindow, m_treeWidget->window()); TreeWidgetContents oldCont = dlg.fillContentsFromTreeWidget(m_treeWidget); if (dlg.exec() == QDialog::Accepted) { TreeWidgetContents newCont = dlg.contents(); diff --git a/tools/designer/src/components/taskmenu/treewidgeteditor.cpp b/tools/designer/src/components/taskmenu/treewidgeteditor.cpp index 0746b64..1e8f894 100644 --- a/tools/designer/src/components/taskmenu/treewidgeteditor.cpp +++ b/tools/designer/src/components/taskmenu/treewidgeteditor.cpp @@ -60,18 +60,18 @@ QT_BEGIN_NAMESPACE namespace qdesigner_internal { -TreeWidgetEditor::TreeWidgetEditor(QDesignerFormWindowInterface *form, QWidget *parent) - : AbstractItemEditor(form, parent), m_updatingBrowser(false) +TreeWidgetEditor::TreeWidgetEditor(QDesignerFormWindowInterface *form, QDialog *dialog) + : AbstractItemEditor(form, 0), m_updatingBrowser(false) { m_columnEditor = new ItemListEditor(form, this); m_columnEditor->setObjectName(QLatin1String("columnEditor")); m_columnEditor->setNewItemText(tr("New Column")); - ui.setupUi(this); + ui.setupUi(dialog); injectPropertyBrowser(ui.itemsTab, ui.widget); connect(ui.showPropertiesButton, SIGNAL(clicked()), this, SLOT(togglePropertyBrowser())); - togglePropertyBrowser(); + setPropertyBrowserVisible(false); ui.tabWidget->insertTab(0, m_columnEditor, tr("&Columns")); ui.tabWidget->setCurrentIndex(0); @@ -87,6 +87,30 @@ TreeWidgetEditor::TreeWidgetEditor(QDesignerFormWindowInterface *form, QWidget * ui.treeWidget->header()->setMovable(false); + connect(ui.newItemButton, SIGNAL(clicked()), this, SLOT(on_newItemButton_clicked())); + connect(ui.newSubItemButton, SIGNAL(clicked()), this, SLOT(on_newSubItemButton_clicked())); + connect(ui.moveItemUpButton, SIGNAL(clicked()), this, SLOT(on_moveItemUpButton_clicked())); + connect(ui.moveItemDownButton, SIGNAL(clicked()), this, SLOT(on_moveItemDownButton_clicked())); + connect(ui.moveItemRightButton, SIGNAL(clicked()), this, SLOT(on_moveItemRightButton_clicked())); + connect(ui.moveItemLeftButton, SIGNAL(clicked()), this, SLOT(on_moveItemLeftButton_clicked())); + connect(ui.treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), + this, SLOT(on_treeWidget_currentItemChanged())); + connect(ui.treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), + this, SLOT(on_treeWidget_itemChanged(QTreeWidgetItem*,int))); + + connect(m_columnEditor, SIGNAL(indexChanged(int)), + this, SLOT(on_columnEditor_indexChanged(int))); + connect(m_columnEditor, SIGNAL(itemChanged(int,int,QVariant)), + this, SLOT(on_columnEditor_itemChanged(int,int,QVariant))); + connect(m_columnEditor, SIGNAL(itemInserted(int)), + this, SLOT(on_columnEditor_itemInserted(int))); + connect(m_columnEditor, SIGNAL(itemDeleted(int)), + this, SLOT(on_columnEditor_itemDeleted(int))); + connect(m_columnEditor, SIGNAL(itemMovedUp(int)), + this, SLOT(on_columnEditor_itemMovedUp(int))); + connect(m_columnEditor, SIGNAL(itemMovedDown(int)), + this, SLOT(on_columnEditor_itemMovedDown(int))); + connect(iconCache(), SIGNAL(reloaded()), this, SLOT(cacheReloaded())); } @@ -171,8 +195,8 @@ void TreeWidgetEditor::setItemData(int role, const QVariant &v) BoolBlocker block(m_updatingBrowser); if (role == Qt::FontRole && newValue.type() == QVariant::Font) { QFont oldFont = ui.treeWidget->font(); - QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont); - newValue = qVariantFromValue(newFont); + QFont newFont = qvariant_cast<QFont>(newValue).resolve(oldFont); + newValue = QVariant::fromValue(newFont); ui.treeWidget->currentItem()->setData(col, role, QVariant()); // force the right font with the current resolve mask is set (item view bug) } ui.treeWidget->currentItem()->setData(col, role, newValue); @@ -198,7 +222,7 @@ void TreeWidgetEditor::on_newItemButton_clicked() newItem = new QTreeWidgetItem(ui.treeWidget); const QString newItemText = tr("New Item"); newItem->setText(0, newItemText); - newItem->setData(0, Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(newItemText))); + newItem->setData(0, Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(newItemText))); newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); ui.treeWidget->blockSignals(false); @@ -217,7 +241,7 @@ void TreeWidgetEditor::on_newSubItemButton_clicked() QTreeWidgetItem *newItem = new QTreeWidgetItem(curItem); const QString newItemText = tr("New Subitem"); newItem->setText(0, newItemText); - newItem->setData(0, Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(newItemText))); + newItem->setData(0, Qt::DisplayPropertyRole, QVariant::fromValue(PropertySheetStringValue(newItemText))); newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); ui.treeWidget->blockSignals(false); @@ -386,15 +410,13 @@ void TreeWidgetEditor::on_moveItemRightButton_clicked() void TreeWidgetEditor::togglePropertyBrowser() { - // Always hide in case parent widget is not visible -> on startup - const bool isVisible = - !this->isVisible() ? true : m_propertyBrowser->isVisible(); - if (isVisible) - ui.showPropertiesButton->setText(tr("Properties &<<")); - else - ui.showPropertiesButton->setText(tr("Properties &>>")); + setPropertyBrowserVisible(!m_propertyBrowser->isVisible()); +} - m_propertyBrowser->setVisible(!isVisible); +void TreeWidgetEditor::setPropertyBrowserVisible(bool v) +{ + ui.showPropertiesButton->setText(v ? tr("Properties &>>") : tr("Properties &<<")); + m_propertyBrowser->setVisible(v); } void TreeWidgetEditor::on_treeWidget_currentItemChanged() @@ -408,10 +430,10 @@ void TreeWidgetEditor::on_treeWidget_itemChanged(QTreeWidgetItem *item, int colu if (m_updatingBrowser) return; - PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(column, Qt::DisplayPropertyRole)); + PropertySheetStringValue val = qvariant_cast<PropertySheetStringValue>(item->data(column, Qt::DisplayPropertyRole)); val.setValue(item->text(column)); BoolBlocker block(m_updatingBrowser); - item->setData(column, Qt::DisplayPropertyRole, qVariantFromValue(val)); + item->setData(column, Qt::DisplayPropertyRole, QVariant::fromValue(val)); updateBrowser(); } @@ -425,7 +447,7 @@ void TreeWidgetEditor::on_columnEditor_indexChanged(int idx) void TreeWidgetEditor::on_columnEditor_itemChanged(int idx, int role, const QVariant &v) { if (role == Qt::DisplayPropertyRole) - ui.treeWidget->headerItem()->setData(idx, Qt::EditRole, qVariantValue<PropertySheetStringValue>(v).value()); + ui.treeWidget->headerItem()->setData(idx, Qt::EditRole, qvariant_cast<PropertySheetStringValue>(v).value()); ui.treeWidget->headerItem()->setData(idx, role, v); } @@ -599,5 +621,22 @@ void TreeWidgetEditor::cacheReloaded() reloadIconResources(iconCache(), ui.treeWidget); } +TreeWidgetEditorDialog::TreeWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent) : + QDialog(parent), m_editor(form, this) +{ + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); +} + +TreeWidgetContents TreeWidgetEditorDialog::fillContentsFromTreeWidget(QTreeWidget *treeWidget) +{ + return m_editor.fillContentsFromTreeWidget(treeWidget); } + +TreeWidgetContents TreeWidgetEditorDialog::contents() const +{ + return m_editor.contents(); +} + +} // namespace qdesigner_internal + QT_END_NAMESPACE diff --git a/tools/designer/src/components/taskmenu/treewidgeteditor.h b/tools/designer/src/components/taskmenu/treewidgeteditor.h index 30fef55..63a9da9 100644 --- a/tools/designer/src/components/taskmenu/treewidgeteditor.h +++ b/tools/designer/src/components/taskmenu/treewidgeteditor.h @@ -46,6 +46,8 @@ #include "listwidgeteditor.h" +#include <QtGui/QDialog> + QT_BEGIN_NAMESPACE class QTreeWidget; @@ -60,7 +62,7 @@ class TreeWidgetEditor: public AbstractItemEditor { Q_OBJECT public: - TreeWidgetEditor(QDesignerFormWindowInterface *form, QWidget *parent); + explicit TreeWidgetEditor(QDesignerFormWindowInterface *form, QDialog *dialog); TreeWidgetContents fillContentsFromTreeWidget(QTreeWidget *treeWidget); TreeWidgetContents contents() const; @@ -93,6 +95,7 @@ protected: virtual QVariant getItemData(int role) const; private: + void setPropertyBrowserVisible(bool v); QtVariantProperty *setupPropertyGroup(const QString &title, PropertyDefinition *propDefs); void updateEditor(); void moveColumnItems(const PropertyDefinition *propList, QTreeWidgetItem *item, int fromColumn, int toColumn, int step); @@ -106,6 +109,19 @@ private: bool m_updatingBrowser; }; +class TreeWidgetEditorDialog : public QDialog +{ + Q_OBJECT +public: + explicit TreeWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent); + + TreeWidgetContents fillContentsFromTreeWidget(QTreeWidget *treeWidget); + TreeWidgetContents contents() const; + +private: + TreeWidgetEditor m_editor; +}; + } // namespace qdesigner_internal QT_END_NAMESPACE diff --git a/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp b/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp index 6019c7a..cb13424 100644 --- a/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp +++ b/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp @@ -185,7 +185,7 @@ static QWidget *decorationFromDomWidget(DomUI *dom_ui, QDesignerFormEditorInterf fakeTopLevel->setParent(0, Qt::ToolTip); // Container // Actual widget const DomWidget *domW = dom_ui->elementWidget()->elementWidget().front(); - QWidget *w = qFindChildren<QWidget*>(fakeTopLevel).front(); + QWidget *w = fakeTopLevel->findChildren<QWidget*>().front(); Q_ASSERT(w); // hack begin; // We set _q_dockDrag dynamic property which will be detected in drag enter event of form window. diff --git a/tools/designer/src/designer/qdesigner_formwindow.cpp b/tools/designer/src/designer/qdesigner_formwindow.cpp index 440a8d6..5163cb6 100644 --- a/tools/designer/src/designer/qdesigner_formwindow.cpp +++ b/tools/designer/src/designer/qdesigner_formwindow.cpp @@ -159,6 +159,7 @@ void QDesignerFormWindow::firstShow() if (m_editor) { connect(m_editor, SIGNAL(fileNameChanged(QString)), this, SLOT(updateWindowTitle(QString))); updateWindowTitle(m_editor->fileName()); + updateChanged(); } } show(); diff --git a/tools/designer/src/designer/qdesigner_settings.cpp b/tools/designer/src/designer/qdesigner_settings.cpp index 8654acf..15e2813 100644 --- a/tools/designer/src/designer/qdesigner_settings.cpp +++ b/tools/designer/src/designer/qdesigner_settings.cpp @@ -241,7 +241,7 @@ ToolWindowFontSettings QDesignerSettings::toolWindowFont() const fontSettings.m_writingSystem = static_cast<QFontDatabase::WritingSystem>(value(QLatin1String("UI/writingSystem"), QFontDatabase::Any).toInt()); - fontSettings.m_font = qVariantValue<QFont>(value(QLatin1String("UI/font"))); + fontSettings.m_font = qvariant_cast<QFont>(value(QLatin1String("UI/font"))); fontSettings.m_useFont = settings()->value(QLatin1String("UI/useFont"), QVariant(false)).toBool(); return fontSettings; diff --git a/tools/designer/src/designer/qdesigner_workbench.cpp b/tools/designer/src/designer/qdesigner_workbench.cpp index 7b832c3..090629f 100644 --- a/tools/designer/src/designer/qdesigner_workbench.cpp +++ b/tools/designer/src/designer/qdesigner_workbench.cpp @@ -198,7 +198,7 @@ QDesignerWorkbench::QDesignerWorkbench() : // Build main menu bar addMenu(m_globalMenuBar, tr("&File"), m_actionManager->fileActions()->actions()); - QMenu *editMenu = addMenu(m_globalMenuBar, tr("Edit"), m_actionManager->editActions()->actions()); + QMenu *editMenu = addMenu(m_globalMenuBar, tr("&Edit"), m_actionManager->editActions()->actions()); editMenu->addSeparator(); addActionsToMenu(editMenu, m_actionManager->toolActions()->actions()); @@ -410,6 +410,9 @@ void QDesignerWorkbench::switchToDockedMode() switchToNeutralMode(); +#ifdef Q_WS_X11 + QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false); +#endif #ifndef Q_WS_MAC QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow(); widgetBoxWrapper->action()->setVisible(true); @@ -477,6 +480,14 @@ void QDesignerWorkbench::switchToTopLevelMode() // The widget box is special, it gets the menubar and gets to be the main widget. m_core->setTopLevel(widgetBoxWrapper); +#ifdef Q_WS_X11 + // For now the appmenu protocol does not make it possible to associate a + // menubar with all application windows. This means in top level mode you + // can only reach the menubar when the widgetbox window is active. Since + // this is quite inconvenient, better not use the native menubar in this + // configuration and keep the menubar in the widgetbox window. + QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true); +#endif #ifndef Q_WS_MAC widgetBoxWrapper->setMenuBar(m_globalMenuBar); widgetBoxWrapper->action()->setVisible(false); @@ -966,7 +977,9 @@ QDesignerFormWindow * QDesignerWorkbench::loadForm(const QString &fileName, return 0; } *uic3Converted = editor->fileName().isEmpty(); - editor->setDirty(false); + // Did user specify another (missing) resource path -> set dirty. + const bool dirty = editor->property("_q_resourcepathchanged").toBool(); + editor->setDirty(dirty); resizeForm(formWindow, editor->mainContainer()); formWindowManager->setActiveFormWindow(editor); return formWindow; diff --git a/tools/designer/src/lib/lib.pro b/tools/designer/src/lib/lib.pro index 495976d..3ba6f52 100644 --- a/tools/designer/src/lib/lib.pro +++ b/tools/designer/src/lib/lib.pro @@ -13,7 +13,7 @@ isEmpty(QT_MAJOR_VERSION) { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } -unix:QMAKE_PKGCONFIG_REQUIRES += QtXml +unix|win32-g++*:QMAKE_PKGCONFIG_REQUIRES += QtXml include(../../../../src/qt_targets.pri) QMAKE_TARGET_PRODUCT = Designer diff --git a/tools/designer/src/lib/sdk/abstractintegration.cpp b/tools/designer/src/lib/sdk/abstractintegration.cpp index e46a78f..4358b0b 100644 --- a/tools/designer/src/lib/sdk/abstractintegration.cpp +++ b/tools/designer/src/lib/sdk/abstractintegration.cpp @@ -42,13 +42,64 @@ #include "abstractintegration.h" #include "abstractformeditor.h" +#include <QtCore/QVariant> +#include <QtCore/QSharedPointer> + +QT_BEGIN_NAMESPACE + +// Add 'private' struct as a dynamic property. + +static const char privatePropertyC[] = "_q_integrationprivate"; + +struct QDesignerIntegrationInterfacePrivate { + QDesignerIntegrationInterfacePrivate() : + headerSuffix(QLatin1String(".h")), + headerLowercase(true) {} + + QString headerSuffix; + bool headerLowercase; +}; + +typedef QSharedPointer<QDesignerIntegrationInterfacePrivate> QDesignerIntegrationInterfacePrivatePtr; + +QT_END_NAMESPACE +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QDesignerIntegrationInterfacePrivatePtr)) QT_BEGIN_NAMESPACE +static QDesignerIntegrationInterfacePrivatePtr integrationD(const QObject *o) +{ + const QVariant property = o->property(privatePropertyC); + Q_ASSERT(qVariantCanConvert<QDesignerIntegrationInterfacePrivatePtr>(property)); + return qvariant_cast<QDesignerIntegrationInterfacePrivatePtr>(property); +} + QDesignerIntegrationInterface::QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent) : QObject(parent), m_core(core) { core->setIntegration(this); + const QDesignerIntegrationInterfacePrivatePtr d(new QDesignerIntegrationInterfacePrivate); + setProperty(privatePropertyC, qVariantFromValue<QDesignerIntegrationInterfacePrivatePtr>(d)); +} + +QString QDesignerIntegrationInterface::headerSuffix() const +{ + return integrationD(this)->headerSuffix; +} + +void QDesignerIntegrationInterface::setHeaderSuffix(const QString &headerSuffix) +{ + integrationD(this)->headerSuffix = headerSuffix; +} + +bool QDesignerIntegrationInterface::isHeaderLowercase() const +{ + return integrationD(this)->headerLowercase; +} + +void QDesignerIntegrationInterface::setHeaderLowercase(bool headerLowercase) +{ + integrationD(this)->headerLowercase = headerLowercase; } QT_END_NAMESPACE diff --git a/tools/designer/src/lib/sdk/abstractintegration.h b/tools/designer/src/lib/sdk/abstractintegration.h index 88ff051..df75707 100644 --- a/tools/designer/src/lib/sdk/abstractintegration.h +++ b/tools/designer/src/lib/sdk/abstractintegration.h @@ -45,6 +45,7 @@ #include <QtDesigner/sdk_global.h> #include <QtCore/QObject> +#include <QtCore/QString> QT_BEGIN_HEADER @@ -55,6 +56,9 @@ class QDesignerFormEditorInterface; class QDESIGNER_SDK_EXPORT QDesignerIntegrationInterface: public QObject { Q_OBJECT + Q_PROPERTY(QString headerSuffix READ headerSuffix WRITE setHeaderSuffix) + Q_PROPERTY(bool headerLowercase READ isHeaderLowercase WRITE setHeaderLowercase) + public: QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent = 0); @@ -62,6 +66,12 @@ public: virtual QWidget *containerWindow(QWidget *widget) const = 0; + QString headerSuffix() const; + void setHeaderSuffix(const QString &headerSuffix); + + bool isHeaderLowercase() const; + void setHeaderLowercase(bool headerLowerCase); + private: QDesignerFormEditorInterface *m_core; }; diff --git a/tools/designer/src/lib/shared/actioneditor.cpp b/tools/designer/src/lib/shared/actioneditor.cpp index 88e31f4..73b6dc1 100644 --- a/tools/designer/src/lib/shared/actioneditor.cpp +++ b/tools/designer/src/lib/shared/actioneditor.cpp @@ -288,7 +288,7 @@ void ActionEditor::setFormWindow(QDesignerFormWindowInterface *formWindow) return; if (m_formWindow != 0) { - const ActionList actionList = qFindChildren<QAction*>(m_formWindow->mainContainer()); + const ActionList actionList = m_formWindow->mainContainer()->findChildren<QAction*>(); foreach (QAction *action, actionList) disconnect(action, SIGNAL(changed()), this, SLOT(slotActionChanged())); } @@ -311,7 +311,7 @@ void ActionEditor::setFormWindow(QDesignerFormWindowInterface *formWindow) m_actionNew->setEnabled(true); m_filterWidget->setEnabled(true); - const ActionList actionList = qFindChildren<QAction*>(formWindow->mainContainer()); + const ActionList actionList = formWindow->mainContainer()->findChildren<QAction*>(); foreach (QAction *action, actionList) if (!action->isSeparator() && core()->metaDataBase()->item(action) != 0) { // Show unless it has a menu. However, listen for change on menu actions also as it might be removed @@ -445,7 +445,6 @@ void ActionEditor::slotNewAction() if (dlg.exec() == QDialog::Accepted) { const ActionData actionData = dlg.actionData(); m_actionView->clearSelection(); - QAction *action = new QAction(formWindow()); action->setObjectName(actionData.name); formWindow()->ensureUniqueObjectName(action); @@ -459,9 +458,9 @@ void ActionEditor::slotNewAction() setInitialProperty(sheet, QLatin1String(checkablePropertyC), QVariant(true)); if (!actionData.keysequence.value().isEmpty()) - setInitialProperty(sheet, QLatin1String(shortcutPropertyC), qVariantFromValue(actionData.keysequence)); + setInitialProperty(sheet, QLatin1String(shortcutPropertyC), QVariant::fromValue(actionData.keysequence)); - sheet->setProperty(sheet->indexOf(QLatin1String(iconPropertyC)), qVariantFromValue(actionData.icon)); + sheet->setProperty(sheet->indexOf(QLatin1String(iconPropertyC)), QVariant::fromValue(actionData.icon)); AddActionCommand *cmd = new AddActionCommand(formWindow()); cmd->init(action); @@ -480,13 +479,13 @@ static inline bool isSameIcon(const QIcon &i1, const QIcon &i2) static QDesignerFormWindowCommand *setIconPropertyCommand(const PropertySheetIconValue &newIcon, QAction *action, QDesignerFormWindowInterface *fw) { const QString iconProperty = QLatin1String(iconPropertyC); - if (newIcon.paths().isEmpty()) { + if (newIcon.isEmpty()) { ResetPropertyCommand *cmd = new ResetPropertyCommand(fw); cmd->init(action, iconProperty); return cmd; } SetPropertyCommand *cmd = new SetPropertyCommand(fw); - cmd->init(action, iconProperty, qVariantFromValue(newIcon)); + cmd->init(action, iconProperty, QVariant::fromValue(newIcon)); return cmd; } @@ -502,7 +501,7 @@ static QDesignerFormWindowCommand *setKeySequencePropertyCommand(const PropertyS return cmd; } SetPropertyCommand *cmd = new SetPropertyCommand(fw); - cmd->init(action, shortcutProperty, qVariantFromValue(ks)); + cmd->init(action, shortcutProperty, QVariant::fromValue(ks)); return cmd; } @@ -528,7 +527,7 @@ static inline QString textPropertyValue(const QDesignerPropertySheetExtension *s { const int index = sheet->indexOf(name); Q_ASSERT(index != -1); - const PropertySheetStringValue ps = qVariantValue<PropertySheetStringValue>(sheet->property(index)); + const PropertySheetStringValue ps = qvariant_cast<PropertySheetStringValue>(sheet->property(index)); return ps.value(); } @@ -545,7 +544,7 @@ void ActionEditor::editAction(QAction *action) oldActionData.name = action->objectName(); oldActionData.text = action->text(); oldActionData.toolTip = textPropertyValue(sheet, QLatin1String(toolTipPropertyC)); - oldActionData.icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC)))); + oldActionData.icon = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC)))); oldActionData.keysequence = ActionModel::actionShortCut(sheet); oldActionData.checkable = action->isCheckable(); dlg.setActionData(oldActionData); @@ -677,7 +676,7 @@ void ActionEditor::resourceImageDropped(const QString &path, QAction *action) QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), action); const PropertySheetIconValue oldIcon = - qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC)))); + qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC)))); PropertySheetIconValue newIcon; newIcon.setPixmap(QIcon::Normal, QIcon::Off, PropertySheetPixmapValue(path)); if (newIcon.paths().isEmpty() || newIcon.paths() == oldIcon.paths()) diff --git a/tools/designer/src/lib/shared/actionrepository.cpp b/tools/designer/src/lib/shared/actionrepository.cpp index f650f80..0f62a43 100644 --- a/tools/designer/src/lib/shared/actionrepository.cpp +++ b/tools/designer/src/lib/shared/actionrepository.cpp @@ -136,7 +136,7 @@ QModelIndex ActionModel::addAction(QAction *action) const Qt::ItemFlags flags = Qt::ItemIsSelectable|Qt::ItemIsDropEnabled|Qt::ItemIsDragEnabled|Qt::ItemIsEnabled; QVariant itemData; - qVariantSetValue(itemData, action); + itemData.setValue(action); for (int i = 0; i < NumColumns; i++) { QStandardItem *item = new QStandardItem; diff --git a/tools/designer/src/lib/shared/connectionedit.cpp b/tools/designer/src/lib/shared/connectionedit.cpp index 30f9117..f4065dc 100644 --- a/tools/designer/src/lib/shared/connectionedit.cpp +++ b/tools/designer/src/lib/shared/connectionedit.cpp @@ -1395,7 +1395,7 @@ void ConnectionEdit::widgetRemoved(QWidget *widget) if (m_con_list.empty()) return; - QWidgetList child_list = qFindChildren<QWidget*>(widget); + QWidgetList child_list = widget->findChildren<QWidget*>(); child_list.prepend(widget); const ConnectionSet remove_set = findConnectionsOf(m_con_list, child_list.constBegin(), child_list.constEnd()); @@ -1545,7 +1545,7 @@ void ConnectionEdit::setSource(Connection *con, const QString &obj_name) { QObject *object = 0; if (!obj_name.isEmpty()) { - object = qFindChild<QObject*>(m_bg_widget, obj_name); + object = m_bg_widget->findChild<QObject*>(obj_name); if (object == 0 && m_bg_widget->objectName() == obj_name) object = m_bg_widget; @@ -1559,7 +1559,7 @@ void ConnectionEdit::setTarget(Connection *con, const QString &obj_name) { QObject *object = 0; if (!obj_name.isEmpty()) { - object = qFindChild<QObject*>(m_bg_widget, obj_name); + object = m_bg_widget->findChild<QObject*>(obj_name); if (object == 0 && m_bg_widget->objectName() == obj_name) object = m_bg_widget; diff --git a/tools/designer/src/lib/shared/formlayoutmenu.cpp b/tools/designer/src/lib/shared/formlayoutmenu.cpp index 4443d55..ce1db8f 100644 --- a/tools/designer/src/lib/shared/formlayoutmenu.cpp +++ b/tools/designer/src/lib/shared/formlayoutmenu.cpp @@ -432,16 +432,16 @@ static QPair<QWidget *,QWidget *> const QString objectNameProperty = QLatin1String("objectName"); QDesignerPropertySheetExtension *labelSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), rc.first); int nameIndex = labelSheet->indexOf(objectNameProperty); - labelSheet->setProperty(nameIndex, qVariantFromValue(PropertySheetStringValue(row.labelName))); + labelSheet->setProperty(nameIndex, QVariant::fromValue(PropertySheetStringValue(row.labelName))); labelSheet->setChanged(nameIndex, true); formWindow->ensureUniqueObjectName(rc.first); const int textIndex = labelSheet->indexOf(QLatin1String("text")); - labelSheet->setProperty(textIndex, qVariantFromValue(PropertySheetStringValue(row.labelText))); + labelSheet->setProperty(textIndex, QVariant::fromValue(PropertySheetStringValue(row.labelText))); labelSheet->setChanged(textIndex, true); // Set up properties of the control QDesignerPropertySheetExtension *controlSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), rc.second); nameIndex = controlSheet->indexOf(objectNameProperty); - controlSheet->setProperty(nameIndex, qVariantFromValue(PropertySheetStringValue(row.fieldName))); + controlSheet->setProperty(nameIndex, QVariant::fromValue(PropertySheetStringValue(row.fieldName))); controlSheet->setChanged(nameIndex, true); formWindow->ensureUniqueObjectName(rc.second); return rc; diff --git a/tools/designer/src/lib/shared/formwindowbase.cpp b/tools/designer/src/lib/shared/formwindowbase.cpp index b049f85..1832c39 100644 --- a/tools/designer/src/lib/shared/formwindowbase.cpp +++ b/tools/designer/src/lib/shared/formwindowbase.cpp @@ -184,11 +184,11 @@ void FormWindowBase::reloadProperties() const int index = itIndex.next().key(); const QVariant newValue = sheet->property(index); if (qobject_cast<QLabel *>(sheet->object()) && sheet->propertyName(index) == QLatin1String("text")) { - const PropertySheetStringValue newString = qVariantValue<PropertySheetStringValue>(newValue); + const PropertySheetStringValue newString = qvariant_cast<PropertySheetStringValue>(newValue); // optimize a bit, reset only if the text value might contain a reference to qt resources // (however reloading of icons other than taken from resources might not work here) if (newString.value().contains(QLatin1String(":/"))) { - const QVariant resetValue = qVariantFromValue(PropertySheetStringValue()); + const QVariant resetValue = QVariant::fromValue(PropertySheetStringValue()); sheet->setProperty(index, resetValue); } } diff --git a/tools/designer/src/lib/shared/grid.cpp b/tools/designer/src/lib/shared/grid.cpp index ab75217..1813acf 100644 --- a/tools/designer/src/lib/shared/grid.cpp +++ b/tools/designer/src/lib/shared/grid.cpp @@ -71,7 +71,7 @@ template <class T> const QVariantMap::const_iterator it = v.constFind(key); const bool found = it != v.constEnd(); if (found) - value = qVariantValue<T>(it.value()); + value = qvariant_cast<T>(it.value()); return found; } @@ -89,12 +89,20 @@ Grid::Grid() : bool Grid::fromVariantMap(const QVariantMap& vm) { - *this = Grid(); - valueFromVariantMap(vm, QLatin1String(KEY_VISIBLE), m_visible); - valueFromVariantMap(vm, QLatin1String(KEY_SNAPX), m_snapX); - valueFromVariantMap(vm, QLatin1String(KEY_SNAPY), m_snapY); - valueFromVariantMap(vm, QLatin1String(KEY_DELTAX), m_deltaX); - return valueFromVariantMap(vm, QLatin1String(KEY_DELTAY), m_deltaY); + Grid grid; + bool anyData = valueFromVariantMap(vm, QLatin1String(KEY_VISIBLE), grid.m_visible); + anyData |= valueFromVariantMap(vm, QLatin1String(KEY_SNAPX), grid.m_snapX); + anyData |= valueFromVariantMap(vm, QLatin1String(KEY_SNAPY), grid.m_snapY); + anyData |= valueFromVariantMap(vm, QLatin1String(KEY_DELTAX), grid.m_deltaX); + anyData |= valueFromVariantMap(vm, QLatin1String(KEY_DELTAY), grid.m_deltaY); + if (!anyData) + return false; + if (grid.m_deltaX == 0 || grid.m_deltaY == 0) { + qWarning("Attempt to set invalid grid with a spacing of 0."); + return false; + } + *this = grid; + return true; } QVariantMap Grid::toVariantMap(bool forceKeys) const diff --git a/tools/designer/src/lib/shared/iconselector.cpp b/tools/designer/src/lib/shared/iconselector.cpp index b4d29e5..80668e9 100644 --- a/tools/designer/src/lib/shared/iconselector.cpp +++ b/tools/designer/src/lib/shared/iconselector.cpp @@ -67,8 +67,12 @@ #include <QtGui/QImageReader> #include <QtGui/QDialogButtonBox> #include <QtGui/QVBoxLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QLabel> +#include <QtGui/QValidator> #include <QtCore/QDebug> + QT_BEGIN_NAMESPACE namespace qdesigner_internal { @@ -181,6 +185,14 @@ LanguageResourceDialog* LanguageResourceDialog::create(QDesignerFormEditorInterf } // ------------ IconSelectorPrivate + +static inline QPixmap emptyPixmap() +{ + QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); + img.fill(0); + return QPixmap::fromImage(img); +} + class IconSelectorPrivate { IconSelector *q_ptr; @@ -201,7 +213,7 @@ public: QMap<QPair<QIcon::Mode, QIcon::State>, int> m_stateToIndex; QMap<int, QPair<QIcon::Mode, QIcon::State> > m_indexToState; - QIcon m_emptyIcon; + const QIcon m_emptyIcon; QComboBox *m_stateComboBox; QToolButton *m_iconButton; QAction *m_resetAction; @@ -215,6 +227,7 @@ public: IconSelectorPrivate::IconSelectorPrivate() : q_ptr(0), + m_emptyIcon(emptyPixmap()), m_stateComboBox(0), m_iconButton(0), m_resetAction(0), @@ -449,10 +462,6 @@ IconSelector::IconSelector(QWidget *parent) : d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::Off), tr("Selected Off") ); d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::On), tr("Selected On") ); - QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); - img.fill(0); - d_ptr->m_emptyIcon = QIcon(QPixmap::fromImage(img)); - QMenu *setMenu = new QMenu(this); QAction *setResourceAction = new QAction(tr("Choose Resource..."), this); @@ -535,9 +544,112 @@ void IconSelector::setPixmapCache(DesignerPixmapCache *pixmapCache) d_ptr->slotUpdate(); } +// --- IconThemeEditor + +// Validator for theme line edit, accepts empty or non-blank strings. +class BlankSuppressingValidator : public QValidator { +public: + explicit BlankSuppressingValidator(QObject * parent = 0) : QValidator(parent) {} + + virtual State validate(QString &input, int &pos) const { + const int blankPos = input.indexOf(QLatin1Char(' ')); + if (blankPos != -1) { + pos = blankPos; + return Invalid; + } + return Acceptable; + } +}; + +struct IconThemeEditorPrivate { + IconThemeEditorPrivate(); + + const QPixmap m_emptyPixmap; + QLineEdit *m_themeLineEdit; + QLabel *m_themeLabel; +}; + +IconThemeEditorPrivate::IconThemeEditorPrivate() : + m_emptyPixmap(emptyPixmap()), + m_themeLineEdit(new QLineEdit), + m_themeLabel(new QLabel) +{ +} + +IconThemeEditor::IconThemeEditor(QWidget *parent, bool wantResetButton) : + QWidget (parent), d(new IconThemeEditorPrivate) +{ + QHBoxLayout *mainHLayout = new QHBoxLayout; + mainHLayout->setMargin(0); + + // Vertically center theme preview label + d->m_themeLabel->setPixmap(d->m_emptyPixmap); + + QVBoxLayout *themeLabelVLayout = new QVBoxLayout; + d->m_themeLabel->setMargin(1); + themeLabelVLayout->setMargin(0); + themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); + themeLabelVLayout->addWidget(d->m_themeLabel); + themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); + mainHLayout->addLayout(themeLabelVLayout); + + d->m_themeLineEdit = new QLineEdit; + d->m_themeLineEdit->setValidator(new BlankSuppressingValidator(d->m_themeLineEdit)); + connect(d->m_themeLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged(QString))); + connect(d->m_themeLineEdit, SIGNAL(textEdited(QString)), this, SIGNAL(edited(QString))); + mainHLayout->addWidget(d->m_themeLineEdit); + + if (wantResetButton) { + QToolButton *themeResetButton = new QToolButton; + themeResetButton->setIcon(createIconSet(QLatin1String("resetproperty.png"))); + connect(themeResetButton, SIGNAL(clicked()), this, SLOT(reset())); + mainHLayout->addWidget(themeResetButton); + } + + setLayout(mainHLayout); + setFocusProxy(d->m_themeLineEdit); +} + +IconThemeEditor::~IconThemeEditor() +{ +} + +void IconThemeEditor::reset() +{ + d->m_themeLineEdit->clear(); + emit edited(QString()); +} + +void IconThemeEditor::slotChanged(const QString &theme) +{ + updatePreview(theme); +} + +void IconThemeEditor::updatePreview(const QString &t) +{ + // Update preview label with icon. + if (t.isEmpty() || !QIcon::hasThemeIcon(t)) { // Empty + const QPixmap *currentPixmap = d->m_themeLabel->pixmap(); + if (currentPixmap == 0 || currentPixmap->serialNumber() != d->m_emptyPixmap.serialNumber()) + d->m_themeLabel->setPixmap(d->m_emptyPixmap); + } else { + const QIcon icon = QIcon::fromTheme(t); + d->m_themeLabel->setPixmap(icon.pixmap(d->m_emptyPixmap.size())); + } +} + +QString IconThemeEditor::theme() const +{ + return d->m_themeLineEdit->text(); +} + +void IconThemeEditor::setTheme(const QString &t) +{ + d->m_themeLineEdit->setText(t); +} + } // qdesigner_internal QT_END_NAMESPACE #include "moc_iconselector_p.cpp" - diff --git a/tools/designer/src/lib/shared/iconselector_p.h b/tools/designer/src/lib/shared/iconselector_p.h index b84f8bc..b62cf05 100644 --- a/tools/designer/src/lib/shared/iconselector_p.h +++ b/tools/designer/src/lib/shared/iconselector_p.h @@ -55,9 +55,12 @@ #define ICONSELECTOR_H #include "shared_global_p.h" + #include <QtGui/QWidget> #include <QtGui/QDialog> +#include <QtCore/QScopedPointer> + QT_BEGIN_NAMESPACE class QtResourceModel; @@ -70,6 +73,7 @@ namespace qdesigner_internal { class DesignerIconCache; class DesignerPixmapCache; class PropertySheetIconValue; +struct IconThemeEditorPrivate; // Resource Dialog that embeds the language-dependent resource widget as returned by the language extension class QDESIGNER_SHARED_EXPORT LanguageResourceDialog : public QDialog @@ -133,6 +137,32 @@ private: Q_PRIVATE_SLOT(d_func(), void slotUpdate()) }; +// IconThemeEditor: Let's the user input theme icon names and shows a preview label. +class QDESIGNER_SHARED_EXPORT IconThemeEditor : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QString theme READ theme WRITE setTheme DESIGNABLE true) +public: + explicit IconThemeEditor(QWidget *parent = 0, bool wantResetButton = true); + virtual ~IconThemeEditor(); + + QString theme() const; + void setTheme(const QString &theme); + +signals: + void edited(const QString &); + +public slots: + void reset(); + +private slots: + void slotChanged(const QString &); + +private: + void updatePreview(const QString &); + + QScopedPointer<IconThemeEditorPrivate> d; +}; } // namespace qdesigner_internal diff --git a/tools/designer/src/lib/shared/layoutinfo.cpp b/tools/designer/src/lib/shared/layoutinfo.cpp index 6580cf6..c7e131ea7 100644 --- a/tools/designer/src/lib/shared/layoutinfo.cpp +++ b/tools/designer/src/lib/shared/layoutinfo.cpp @@ -190,7 +190,7 @@ LayoutInfo::Type LayoutInfo::laidoutWidgetType(const QDesignerFormEditorInterfac } // 3) Some child layout (see below comment about Q3GroupBox) - const QList<QLayout*> childLayouts = qFindChildren<QLayout*>(parentLayout); + const QList<QLayout*> childLayouts = parentLayout->findChildren<QLayout*>(); if (childLayouts.empty()) return NoLayout; const QList<QLayout*>::const_iterator lcend = childLayouts.constEnd(); @@ -244,7 +244,7 @@ QLayout *LayoutInfo::managedLayout(const QDesignerFormEditorInterface *core, QLa * widget->layout() returns an internal VBoxLayout. */ const QDesignerMetaDataBaseItemInterface *item = metaDataBase->item(layout); if (item == 0) { - layout = qFindChild<QLayout*>(layout); + layout = layout->findChild<QLayout*>(); item = metaDataBase->item(layout); } if (!item) diff --git a/tools/designer/src/lib/shared/morphmenu.cpp b/tools/designer/src/lib/shared/morphmenu.cpp index 61c378e..667cae4 100644 --- a/tools/designer/src/lib/shared/morphmenu.cpp +++ b/tools/designer/src/lib/shared/morphmenu.cpp @@ -193,7 +193,7 @@ static QStringList classesOfCategory(MorphCategory cat) << QLatin1String("QSpinBox") << QLatin1String("QDoubleSpinBox"); break; case MorphTextEdit: - l << QLatin1String("QTextEdit") << QLatin1String("QPlainTextEdit"); + l << QLatin1String("QTextEdit") << QLatin1String("QPlainTextEdit") << QLatin1String("QTextBrowser"); break; } } @@ -240,7 +240,7 @@ static QString suggestObjectName(const QString &oldClassName, const QString &new QLabel *buddyLabelOf(QDesignerFormWindowInterface *fw, QWidget *w) { typedef QList<QLabel*> LabelList; - const LabelList labelList = qFindChildren<QLabel*>(fw); + const LabelList labelList = fw->findChildren<QLabel*>(); if (labelList.empty()) return 0; const LabelList::const_iterator cend = labelList.constEnd(); @@ -256,11 +256,11 @@ static void replaceWidgetListDynamicProperty(QWidget *parentWidget, QWidget *oldWidget, QWidget *newWidget, const char *name) { - QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name)); + QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name)); const int index = list.indexOf(oldWidget); if (index != -1) { list.replace(index, newWidget); - parentWidget->setProperty(name, qVariantFromValue(list)); + parentWidget->setProperty(name, QVariant::fromValue(list)); } } diff --git a/tools/designer/src/lib/shared/newactiondialog.cpp b/tools/designer/src/lib/shared/newactiondialog.cpp index bfb31e1..4effaed 100644 --- a/tools/designer/src/lib/shared/newactiondialog.cpp +++ b/tools/designer/src/lib/shared/newactiondialog.cpp @@ -133,6 +133,7 @@ ActionData NewActionDialog::actionData() const rc.name = actionName(); rc.toolTip = m_ui->tooltipEditor->text(); rc.icon = m_ui->iconSelector->icon(); + rc.icon.setTheme(m_ui->iconThemeEditor->theme()); rc.checkable = m_ui->checkableCheckBox->checkState() == Qt::Checked; rc.keysequence = PropertySheetKeySequenceValue(m_ui->keySequenceEdit->keySequence()); return rc; @@ -142,7 +143,8 @@ void NewActionDialog::setActionData(const ActionData &d) { m_ui->editActionText->setText(d.text); m_ui->editObjectName->setText(d.name); - m_ui->iconSelector->setIcon(d.icon); + m_ui->iconSelector->setIcon(d.icon.unthemed()); + m_ui->iconThemeEditor->setTheme(d.icon.theme()); m_ui->tooltipEditor->setText(d.toolTip); m_ui->keySequenceEdit->setKeySequence(d.keysequence.value()); m_ui->checkableCheckBox->setCheckState(d.checkable ? Qt::Checked : Qt::Unchecked); diff --git a/tools/designer/src/lib/shared/newactiondialog.ui b/tools/designer/src/lib/shared/newactiondialog.ui index 1fa6abc..844b1a2 100644 --- a/tools/designer/src/lib/shared/newactiondialog.ui +++ b/tools/designer/src/lib/shared/newactiondialog.ui @@ -42,6 +42,14 @@ *********************************************************************</comment> <class>qdesigner_internal::NewActionDialog</class> <widget class="QDialog" name="qdesigner_internal::NewActionDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>366</width> + <height>270</height> + </rect> + </property> <property name="windowTitle"> <string>New Action...</string> </property> @@ -81,7 +89,51 @@ <item row="1" column="1"> <widget class="QLineEdit" name="editObjectName"/> </item> + <item row="2" column="0"> + <widget class="QLabel" name="toolTipLabel"> + <property name="text"> + <string>T&oolTip:</string> + </property> + <property name="buddy"> + <cstring>tooltipEditor</cstring> + </property> + </widget> + </item> + <item row="2" column="1"> + <layout class="QHBoxLayout" name="toolTipLayout"> + <item> + <widget class="TextPropertyEditor" name="tooltipEditor" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="toolTipToolButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> <item row="3" column="0"> + <widget class="QLabel" name="iconThemeLabel"> + <property name="text"> + <string>Icon th&eme:</string> + </property> + <property name="buddy"> + <cstring>iconThemeEditor</cstring> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="qdesigner_internal::IconThemeEditor" name="iconThemeEditor" native="true"/> + </item> + <item row="4" column="0"> <widget class="QLabel" name="iconLabel"> <property name="text"> <string>&Icon:</string> @@ -91,7 +143,7 @@ </property> </widget> </item> - <item row="3" column="1"> + <item row="4" column="1"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="qdesigner_internal::IconSelector" name="iconSelector" native="true"/> @@ -111,56 +163,34 @@ </item> </layout> </item> - <item row="5" column="0"> - <widget class="QLabel" name="shortcutLabel"> - <property name="text"> - <string>Shortcut:</string> - </property> - </widget> - </item> - <item row="4" column="1"> + <item row="5" column="1"> <widget class="QCheckBox" name="checkableCheckBox"> <property name="text"> <string/> </property> </widget> </item> - <item row="4" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="checkableLabel"> <property name="text"> - <string>Checkable:</string> + <string>&Checkable:</string> + </property> + <property name="buddy"> + <cstring>checkableCheckBox</cstring> </property> </widget> </item> - <item row="2" column="0"> - <widget class="QLabel" name="toolTipLabel"> + <item row="6" column="0"> + <widget class="QLabel" name="shortcutLabel"> <property name="text"> - <string>ToolTip:</string> + <string>&Shortcut:</string> + </property> + <property name="buddy"> + <cstring>keySequenceEdit</cstring> </property> </widget> </item> - <item row="2" column="1"> - <layout class="QHBoxLayout" name="toolTipLayout"> - <item> - <widget class="TextPropertyEditor" name="tooltipEditor" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="toolTipToolButton"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="5" column="1"> + <item row="6" column="1"> <layout class="QHBoxLayout" name="keysequenceLayout"> <item> <widget class="QtKeySequenceEdit" name="keySequenceEdit" native="true"> @@ -234,6 +264,12 @@ <header>textpropertyeditor_p.h</header> <container>1</container> </customwidget> + <customwidget> + <class>qdesigner_internal::IconThemeEditor</class> + <extends>QWidget</extends> + <header>iconselector_p.h</header> + <container>1</container> + </customwidget> </customwidgets> <tabstops> <tabstop>editActionText</tabstop> diff --git a/tools/designer/src/lib/shared/qdesigner_command.cpp b/tools/designer/src/lib/shared/qdesigner_command.cpp index ac607ac..637bb1d 100644 --- a/tools/designer/src/lib/shared/qdesigner_command.cpp +++ b/tools/designer/src/lib/shared/qdesigner_command.cpp @@ -107,23 +107,23 @@ static const char *zOrderPropertyC = "_q_zOrder"; static void addToWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name, int index = -1) { - QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name)); + QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name)); list.removeAll(widget); if (index >= 0 && index < list.size()) { list.insert(index, widget); } else { list.append(widget); } - parentWidget->setProperty(name, qVariantFromValue(list)); + parentWidget->setProperty(name, QVariant::fromValue(list)); } static int removeFromWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name) { - QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name)); + QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name)); const int firstIndex = list.indexOf(widget); if (firstIndex != -1) { list.removeAll(widget); - parentWidget->setProperty(name, qVariantFromValue(list)); + parentWidget->setProperty(name, QVariant::fromValue(list)); } return firstIndex; } @@ -247,7 +247,7 @@ void InsertWidgetCommand::refreshBuddyLabels() { typedef QList<QLabel*> LabelList; - const LabelList label_list = qFindChildren<QLabel*>(formWindow()); + const LabelList label_list = formWindow()->findChildren<QLabel*>(); if (label_list.empty()) return; @@ -281,7 +281,7 @@ void ChangeZOrderCommand::init(QWidget *widget) setText(QApplication::translate("Command", "Change Z-order of '%1'").arg(widget->objectName())); - m_oldParentZOrder = qVariantValue<QWidgetList>(widget->parentWidget()->property("_q_zOrder")); + m_oldParentZOrder = qvariant_cast<QWidgetList>(widget->parentWidget()->property("_q_zOrder")); const int index = m_oldParentZOrder.indexOf(m_widget); if (index != -1 && index + 1 < m_oldParentZOrder.count()) m_oldPreceding = m_oldParentZOrder.at(index + 1); @@ -289,14 +289,14 @@ void ChangeZOrderCommand::init(QWidget *widget) void ChangeZOrderCommand::redo() { - m_widget->parentWidget()->setProperty("_q_zOrder", qVariantFromValue(reorderWidget(m_oldParentZOrder, m_widget))); + m_widget->parentWidget()->setProperty("_q_zOrder", QVariant::fromValue(reorderWidget(m_oldParentZOrder, m_widget))); reorder(m_widget); } void ChangeZOrderCommand::undo() { - m_widget->parentWidget()->setProperty("_q_zOrder", qVariantFromValue(m_oldParentZOrder)); + m_widget->parentWidget()->setProperty("_q_zOrder", QVariant::fromValue(m_oldParentZOrder)); if (m_oldPreceding) m_widget->stackUnder(m_oldPreceding); @@ -365,7 +365,7 @@ void ManageWidgetCommandHelper::init(const QDesignerFormWindowInterface *fw, QWi m_widget = widget; m_managedChildren.clear(); - const QWidgetList children = qFindChildren<QWidget *>(m_widget); + const QWidgetList children = m_widget->findChildren<QWidget *>(); if (children.empty()) return; @@ -580,8 +580,8 @@ void ReparentWidgetCommand::init(QWidget *widget, QWidget *parentWidget) setText(QApplication::translate("Command", "Reparent '%1'").arg(widget->objectName())); - m_oldParentList = qVariantValue<QWidgetList>(m_oldParentWidget->property("_q_widgetOrder")); - m_oldParentZOrder = qVariantValue<QWidgetList>(m_oldParentWidget->property("_q_zOrder")); + m_oldParentList = qvariant_cast<QWidgetList>(m_oldParentWidget->property("_q_widgetOrder")); + m_oldParentZOrder = qvariant_cast<QWidgetList>(m_oldParentWidget->property("_q_zOrder")); } void ReparentWidgetCommand::redo() @@ -591,19 +591,19 @@ void ReparentWidgetCommand::redo() QWidgetList oldList = m_oldParentList; oldList.removeAll(m_widget); - m_oldParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(oldList)); + m_oldParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(oldList)); - QWidgetList newList = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_widgetOrder")); + QWidgetList newList = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_widgetOrder")); newList.append(m_widget); - m_newParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(newList)); + m_newParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(newList)); QWidgetList oldZOrder = m_oldParentZOrder; oldZOrder.removeAll(m_widget); - m_oldParentWidget->setProperty("_q_zOrder", qVariantFromValue(oldZOrder)); + m_oldParentWidget->setProperty("_q_zOrder", QVariant::fromValue(oldZOrder)); - QWidgetList newZOrder = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_zOrder")); + QWidgetList newZOrder = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_zOrder")); newZOrder.append(m_widget); - m_newParentWidget->setProperty("_q_zOrder", qVariantFromValue(newZOrder)); + m_newParentWidget->setProperty("_q_zOrder", QVariant::fromValue(newZOrder)); m_widget->show(); core()->objectInspector()->setFormWindow(formWindow()); @@ -614,16 +614,16 @@ void ReparentWidgetCommand::undo() m_widget->setParent(m_oldParentWidget); m_widget->move(m_oldPos); - m_oldParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(m_oldParentList)); + m_oldParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(m_oldParentList)); - QWidgetList newList = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_widgetOrder")); + QWidgetList newList = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_widgetOrder")); newList.removeAll(m_widget); - m_newParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(newList)); + m_newParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(newList)); - m_oldParentWidget->setProperty("_q_zOrder", qVariantFromValue(m_oldParentZOrder)); + m_oldParentWidget->setProperty("_q_zOrder", QVariant::fromValue(m_oldParentZOrder)); - QWidgetList newZOrder = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_zOrder")); - m_newParentWidget->setProperty("_q_zOrder", qVariantFromValue(newZOrder)); + QWidgetList newZOrder = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_zOrder")); + m_newParentWidget->setProperty("_q_zOrder", QVariant::fromValue(newZOrder)); m_widget->show(); core()->objectInspector()->setFormWindow(formWindow()); @@ -1016,7 +1016,7 @@ void ToolBoxCommand::addPage() QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(formWindow()->core()->extensionManager(), m_toolBox); if (sheet) { qdesigner_internal::PropertySheetStringValue itemText(m_itemText); - sheet->setProperty(sheet->indexOf(QLatin1String("currentItemText")), qVariantFromValue(itemText)); + sheet->setProperty(sheet->indexOf(QLatin1String("currentItemText")), QVariant::fromValue(itemText)); } m_widget->show(); @@ -1176,7 +1176,7 @@ void TabWidgetCommand::addPage() QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(formWindow()->core()->extensionManager(), m_tabWidget); if (sheet) { qdesigner_internal::PropertySheetStringValue itemText(m_itemText); - sheet->setProperty(sheet->indexOf(QLatin1String("currentTabText")), qVariantFromValue(itemText)); + sheet->setProperty(sheet->indexOf(QLatin1String("currentTabText")), QVariant::fromValue(itemText)); } formWindow()->clearSelection(); @@ -2094,12 +2094,12 @@ void AddContainerWidgetPageCommand::init(QWidget *containerWidget, ContainerType case PageContainer: setText(QApplication::translate("Command", "Insert Page")); m_widget = new QDesignerWidget(formWindow(), m_containerWidget); - m_widget->setObjectName(QApplication::translate("Command", "page")); + m_widget->setObjectName(QLatin1String("page")); break; case MdiContainer: setText(QApplication::translate("Command", "Insert Subwindow")); m_widget = new QDesignerWidget(formWindow(), m_containerWidget); - m_widget->setObjectName(QApplication::translate("Command", "subwindow")); + m_widget->setObjectName(QLatin1String("subwindow")); setPropertySheetWindowTitle(core, m_widget, QApplication::translate("Command", "Subwindow")); break; case WizardContainer: // Apply style, don't manage @@ -2193,7 +2193,7 @@ static void copyRolesFromItem(ItemData *id, const T *item, bool editor) if (editor) copyRoleFromItem<T>(id, ItemFlagsShadowRole, item); else if (item->flags() != defaultFlags) - id->m_properties.insert(ItemFlagsShadowRole, qVariantFromValue((int)item->flags())); + id->m_properties.insert(ItemFlagsShadowRole, QVariant::fromValue((int)item->flags())); } template<class T> @@ -2210,19 +2210,19 @@ static void copyRolesToItem(const ItemData *id, T *item, DesignerIconCache *icon switch (it.key()) { case Qt::DecorationPropertyRole: if (iconCache) - item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(it.value()))); + item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(it.value()))); break; case Qt::DisplayPropertyRole: - item->setText(qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setText(qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::ToolTipPropertyRole: - item->setToolTip(qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setToolTip(qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::StatusTipPropertyRole: - item->setStatusTip(qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setStatusTip(qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::WhatsThisPropertyRole: - item->setWhatsThis(qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setWhatsThis(qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; } } @@ -2267,7 +2267,7 @@ ItemData::ItemData(const QTreeWidgetItem *item, int column) { copyRoleFromItem(this, Qt::EditRole, item, column); PropertySheetStringValue str(item->text(column)); - m_properties.insert(Qt::DisplayPropertyRole, qVariantFromValue(str)); + m_properties.insert(Qt::DisplayPropertyRole, QVariant::fromValue(str)); for (int i = 0; itemRoles[i] != -1; i++) copyRoleFromItem(this, itemRoles[i], item, column); @@ -2282,19 +2282,19 @@ void ItemData::fillTreeItemColumn(QTreeWidgetItem *item, int column, DesignerIco switch (it.key()) { case Qt::DecorationPropertyRole: if (iconCache) - item->setIcon(column, iconCache->icon(qVariantValue<PropertySheetIconValue>(it.value()))); + item->setIcon(column, iconCache->icon(qvariant_cast<PropertySheetIconValue>(it.value()))); break; case Qt::DisplayPropertyRole: - item->setText(column, qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setText(column, qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::ToolTipPropertyRole: - item->setToolTip(column, qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setToolTip(column, qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::StatusTipPropertyRole: - item->setStatusTip(column, qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setStatusTip(column, qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; case Qt::WhatsThisPropertyRole: - item->setWhatsThis(column, qVariantValue<PropertySheetStringValue>(it.value()).value()); + item->setWhatsThis(column, qvariant_cast<PropertySheetStringValue>(it.value()).value()); break; } } @@ -2364,10 +2364,10 @@ void ListContents::applyToComboBox(QComboBox *comboBox, DesignerIconCache *iconC foreach (const ItemData &hash, m_items) { QIcon icon; if (iconCache) - icon = iconCache->icon(qVariantValue<PropertySheetIconValue>( + icon = iconCache->icon(qvariant_cast<PropertySheetIconValue>( hash.m_properties[Qt::DecorationPropertyRole])); QVariant var = hash.m_properties[Qt::DisplayPropertyRole]; - PropertySheetStringValue str = qVariantValue<PropertySheetStringValue>(var); + PropertySheetStringValue str = qvariant_cast<PropertySheetStringValue>(var); comboBox->addItem(icon, str.value()); comboBox->setItemData(comboBox->count() - 1, var, @@ -2407,7 +2407,7 @@ bool TableWidgetContents::nonEmpty(const QTableWidgetItem *item, int headerColum if (item->flags() != defaultFlags) return true; - QString text = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)).value(); + QString text = qvariant_cast<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)).value(); if (!text.isEmpty()) { if (headerColumn < 0 || text != defaultHeaderText(headerColumn)) return true; @@ -2545,7 +2545,7 @@ QTreeWidgetItem *TreeWidgetContents::ItemContents::createTreeItem(DesignerIconCa if (m_itemFlags != -1) { if (editor) - item->setData(0, ItemFlagsShadowRole, qVariantFromValue(m_itemFlags)); + item->setData(0, ItemFlagsShadowRole, QVariant::fromValue(m_itemFlags)); else item->setFlags((Qt::ItemFlags)m_itemFlags); } diff --git a/tools/designer/src/lib/shared/qdesigner_command2.cpp b/tools/designer/src/lib/shared/qdesigner_command2.cpp index 37b0d06..6253049 100644 --- a/tools/designer/src/lib/shared/qdesigner_command2.cpp +++ b/tools/designer/src/lib/shared/qdesigner_command2.cpp @@ -154,6 +154,68 @@ QString MorphLayoutCommand::formatDescription(QDesignerFormEditorInterface * /* return QApplication::translate("Command", "Change layout of '%1' from %2 to %3").arg(widgetName, oldName, newName); } +LayoutAlignmentCommand::LayoutAlignmentCommand(QDesignerFormWindowInterface *formWindow) : + QDesignerFormWindowCommand(QApplication::translate("Command", "Change layout alignment"), formWindow), + m_newAlignment(0), m_oldAlignment(0), m_widget(0) +{ +} + +bool LayoutAlignmentCommand::init(QWidget *w, Qt::Alignment alignment) +{ + bool enabled; + m_newAlignment = alignment; + m_oldAlignment = LayoutAlignmentCommand::alignmentOf(core(), w, &enabled); + m_widget = w; + return enabled; +} + +void LayoutAlignmentCommand::redo() +{ + LayoutAlignmentCommand::applyAlignment(core(), m_widget, m_newAlignment); +} + +void LayoutAlignmentCommand::undo() +{ + LayoutAlignmentCommand::applyAlignment(core(), m_widget, m_oldAlignment); +} + +// Find out alignment and return whether command is enabled. +Qt::Alignment LayoutAlignmentCommand::alignmentOf(const QDesignerFormEditorInterface *core, QWidget *w, bool *enabledIn) +{ + bool managed; + QLayout *layout; + + if (enabledIn) + *enabledIn = false; + // Can only work on a managed layout + const LayoutInfo::Type type = LayoutInfo::laidoutWidgetType(core, w, &managed, &layout); + const bool enabled = layout && managed && + (type == LayoutInfo::HBox || type == LayoutInfo::VBox + || type == LayoutInfo::Grid); + if (!enabled) + return Qt::Alignment(0); + // Get alignment + const int index = layout->indexOf(w); + Q_ASSERT(index >= 0); + if (enabledIn) + *enabledIn = true; + return layout->itemAt(index)->alignment(); +} + +void LayoutAlignmentCommand::applyAlignment(const QDesignerFormEditorInterface *core, QWidget *w, Qt::Alignment a) +{ + // Find layout and apply to item + QLayout *layout; + LayoutInfo::laidoutWidgetType(core, w, 0, &layout); + if (layout) { + const int index = layout->indexOf(w); + if (index >= 0) { + layout->itemAt(index)->setAlignment(a); + layout->update(); + } + } +} + } // namespace qdesigner_internal QT_END_NAMESPACE diff --git a/tools/designer/src/lib/shared/qdesigner_command2_p.h b/tools/designer/src/lib/shared/qdesigner_command2_p.h index e11b24c..5c53290 100644 --- a/tools/designer/src/lib/shared/qdesigner_command2_p.h +++ b/tools/designer/src/lib/shared/qdesigner_command2_p.h @@ -94,6 +94,28 @@ private: QWidget *m_layoutBase; }; +// Change the alignment of a widget in a managed grid/box layout cell. +class LayoutAlignmentCommand : public QDesignerFormWindowCommand { + Q_DISABLE_COPY(LayoutAlignmentCommand) +public: + explicit LayoutAlignmentCommand(QDesignerFormWindowInterface *formWindow); + + bool init(QWidget *w, Qt::Alignment alignment); + + virtual void redo(); + virtual void undo(); + + // Find out alignment and return whether command is enabled. + static Qt::Alignment alignmentOf(const QDesignerFormEditorInterface *core, QWidget *w, bool *enabled = 0); + +private: + static void applyAlignment(const QDesignerFormEditorInterface *core, QWidget *w, Qt::Alignment a); + + Qt::Alignment m_newAlignment; + Qt::Alignment m_oldAlignment; + QWidget *m_widget; +}; + } // namespace qdesigner_internal QT_END_NAMESPACE diff --git a/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp b/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp index 220c14c..0828222 100644 --- a/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp +++ b/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp @@ -243,7 +243,7 @@ static bool readDomEnumerationValue(const DomProperty *p, if (index == -1) return false; const QVariant sheetValue = sheet->property(index); - if (qVariantCanConvert<PropertySheetFlagValue>(sheetValue)) { + if (sheetValue.canConvert<PropertySheetFlagValue>()) { const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(sheetValue); bool ok = false; v = f.metaFlags.parseFlags(p->elementSet(), &ok); @@ -258,7 +258,7 @@ static bool readDomEnumerationValue(const DomProperty *p, if (index == -1) return false; const QVariant sheetValue = sheet->property(index); - if (qVariantCanConvert<PropertySheetEnumValue>(sheetValue)) { + if (sheetValue.canConvert<PropertySheetEnumValue>()) { const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(sheetValue); bool ok = false; v = e.metaEnum.parseEnum(p->elementEnum(), &ok); diff --git a/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp b/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp index 6725cab..50baa55 100644 --- a/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp +++ b/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp @@ -115,7 +115,7 @@ void QDesignerFormWindowCommand::updateBuddies(QDesignerFormWindowInterface *for typedef QList<QLabel*> LabelList; - const LabelList label_list = qFindChildren<QLabel*>(form); + const LabelList label_list = form->findChildren<QLabel*>(); if (label_list.empty()) return; diff --git a/tools/designer/src/lib/shared/qdesigner_menu.cpp b/tools/designer/src/lib/shared/qdesigner_menu.cpp index e046f7f..61a3fd6 100644 --- a/tools/designer/src/lib/shared/qdesigner_menu.cpp +++ b/tools/designer/src/lib/shared/qdesigner_menu.cpp @@ -477,7 +477,7 @@ bool QDesignerMenu::handleContextMenuEvent(QWidget *, QContextMenuEvent *event) QMenu menu; QVariant itemData; - qVariantSetValue(itemData, action); + itemData.setValue(action); QAction *addSeparatorAction = menu.addAction(tr("Insert separator")); addSeparatorAction->setData(itemData); @@ -630,7 +630,7 @@ QDesignerMenu *QDesignerMenu::findActivatedMenu() const { QList<QDesignerMenu*> candidates; candidates.append(const_cast<QDesignerMenu*>(this)); - candidates += qFindChildren<QDesignerMenu*>(this); + candidates += findChildren<QDesignerMenu*>(); foreach (QDesignerMenu *m, candidates) { if (m == qApp->activeWindow()) @@ -867,7 +867,7 @@ void QDesignerMenu::closeMenuChain() w = w->parentWidget(); if (w) { - foreach (QMenu *subMenu, qFindChildren<QMenu*>(w)) { + foreach (QMenu *subMenu, w->findChildren<QMenu*>()) { subMenu->hide(); } } @@ -1323,7 +1323,7 @@ QAction *QDesignerMenu::safeActionAt(int index) const void QDesignerMenu::hideSubMenu() { m_lastSubMenuIndex = -1; - foreach (QMenu *subMenu, qFindChildren<QMenu*>(this)) { + foreach (QMenu *subMenu, findChildren<QMenu*>()) { subMenu->hide(); } } diff --git a/tools/designer/src/lib/shared/qdesigner_menubar.cpp b/tools/designer/src/lib/shared/qdesigner_menubar.cpp index f0b341f..ea17dcc 100644 --- a/tools/designer/src/lib/shared/qdesigner_menubar.cpp +++ b/tools/designer/src/lib/shared/qdesigner_menubar.cpp @@ -403,7 +403,7 @@ ActionList QDesignerMenuBar::contextMenuActions() if (QAction *action = safeActionAt(m_currentIndex)) { if (!qobject_cast<SpecialMenuAction*>(action)) { QVariant itemData; - qVariantSetValue(itemData, action); + itemData.setValue(action); QAction *remove_action = new QAction(tr("Remove Menu '%1'").arg(action->menu()->objectName()), 0); remove_action->setData(itemData); diff --git a/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp b/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp index 4f8b726..716f649 100644 --- a/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp +++ b/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp @@ -49,6 +49,7 @@ #include <QtDesigner/QDesignerFormWindowInterface> #include <QtDesigner/QDesignerPromotionInterface> #include <QtDesigner/QDesignerWidgetDataBaseItemInterface> +#include <QtDesigner/QDesignerIntegrationInterface> #include <abstractdialoggui_p.h> #include <QtCore/QTimer> @@ -152,8 +153,13 @@ namespace qdesigner_internal { void NewPromotedClassPanel::slotNameChanged(const QString &className) { // Suggest a name if (!className.isEmpty()) { - QString suggestedHeader = className.toLower().replace(QLatin1String("::"), QString(QLatin1Char('_'))); - suggestedHeader += QLatin1String(".h"); + const QChar dot(QLatin1Char('.')); + QString suggestedHeader = m_promotedHeaderLowerCase ? + className.toLower() : className; + suggestedHeader.replace(QLatin1String("::"), QString(QLatin1Char('_'))); + if (!m_promotedHeaderSuffix.startsWith(dot)) + suggestedHeader += dot; + suggestedHeader += m_promotedHeaderSuffix; const bool blocked = m_includeFileEdit->blockSignals(true); m_includeFileEdit->setText(suggestedHeader); @@ -248,6 +254,8 @@ namespace qdesigner_internal { preselectedBaseClass = baseClassNameList.indexOf(QLatin1String("QFrame")); NewPromotedClassPanel *newPromotedClassPanel = new NewPromotedClassPanel(baseClassNameList, preselectedBaseClass); + newPromotedClassPanel->setPromotedHeaderSuffix(core->integration()->headerSuffix()); + newPromotedClassPanel->setPromotedHeaderLowerCase(core->integration()->isHeaderLowercase()); connect(newPromotedClassPanel, SIGNAL(newPromotedClass(PromotionParameters,bool*)), this, SLOT(slotNewPromotedClass(PromotionParameters,bool*))); connect(this, SIGNAL(selectedBaseClassChanged(QString)), newPromotedClassPanel, SLOT(chooseBaseClass(QString))); diff --git a/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h b/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h index 167f992..530494d 100644 --- a/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h +++ b/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h @@ -84,7 +84,13 @@ namespace qdesigner_internal { int selectedBaseClass = -1, QWidget *parent = 0); - signals: + QString promotedHeaderSuffix() const { return m_promotedHeaderSuffix; } + void setPromotedHeaderSuffix(const QString &s) { m_promotedHeaderSuffix = s; } + + bool isPromotedHeaderLowerCase() const { return m_promotedHeaderLowerCase; } + void setPromotedHeaderLowerCase(bool l) { m_promotedHeaderLowerCase = l; } + + signals: void newPromotedClass(const PromotionParameters &, bool *ok); public slots: @@ -100,6 +106,9 @@ namespace qdesigner_internal { PromotionParameters promotionParameters() const; void enableButtons(); + QString m_promotedHeaderSuffix; + bool m_promotedHeaderLowerCase; + QComboBox *m_baseClassCombo; QLineEdit *m_classNameEdit; QLineEdit *m_includeFileEdit; diff --git a/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp b/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp index 70ba0a5..5a55d57 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp +++ b/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp @@ -505,7 +505,7 @@ PropertyHelper::Value applySubProperty(const QVariant &oldValue, const QVariant case QVariant::Size: return PropertyHelper::Value(applySizeSubProperty(oldValue.toSize(), newValue.toSize(), mask), changed); case QVariant::SizePolicy: - return PropertyHelper::Value(qVariantFromValue(applySizePolicySubProperty(qvariant_cast<QSizePolicy>(oldValue), qvariant_cast<QSizePolicy>(newValue), mask)), changed); + return PropertyHelper::Value(QVariant::fromValue(applySizePolicySubProperty(qvariant_cast<QSizePolicy>(oldValue), qvariant_cast<QSizePolicy>(newValue), mask)), changed); case QVariant::Font: { // Changed flag in case of font and palette depends on resolve mask only, not on the passed "changed" value. @@ -524,27 +524,27 @@ PropertyHelper::Value applySubProperty(const QVariant &oldValue, const QVariant // He press reset button for the whole font property. In result whole font properties for both // widgets should be marked as unchanged. QFont font = applyFontSubProperty(qvariant_cast<QFont>(oldValue), qvariant_cast<QFont>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(font), font.resolve()); + return PropertyHelper::Value(QVariant::fromValue(font), font.resolve()); } case QVariant::Palette: { QPalette palette = applyPaletteSubProperty(qvariant_cast<QPalette>(oldValue), qvariant_cast<QPalette>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(palette), palette.resolve()); + return PropertyHelper::Value(QVariant::fromValue(palette), palette.resolve()); } default: if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetIconValue>()) { PropertySheetIconValue icon = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(oldValue); icon.assign(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(icon), icon.mask()); + return PropertyHelper::Value(QVariant::fromValue(icon), icon.mask()); } else if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetStringValue>()) { qdesigner_internal::PropertySheetStringValue str = applyStringSubProperty( qvariant_cast<qdesigner_internal::PropertySheetStringValue>(oldValue), qvariant_cast<qdesigner_internal::PropertySheetStringValue>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(str), changed); + return PropertyHelper::Value(QVariant::fromValue(str), changed); } else if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetKeySequenceValue>()) { qdesigner_internal::PropertySheetKeySequenceValue key = applyKeySequenceSubProperty( qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(oldValue), qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(newValue), mask); - return PropertyHelper::Value(qVariantFromValue(key), changed); + return PropertyHelper::Value(QVariant::fromValue(key), changed); } // Enumerations, flags switch (specialProperty) { @@ -552,7 +552,7 @@ PropertyHelper::Value applySubProperty(const QVariant &oldValue, const QVariant qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(oldValue); f.value = applyAlignmentSubProperty(variantToAlignment(oldValue), variantToAlignment(newValue), mask); QVariant v; - qVariantSetValue(v, f); + v.setValue(f); return PropertyHelper::Value(v, changed); } default: @@ -651,7 +651,7 @@ void PropertyHelper::checkApplyWidgetValue(QDesignerFormWindowInterface *fw, QWi switch (specialProperty) { case SP_MinimumSize: { const QSize size = checkSize(value.toSize()); - qVariantSetValue(value, size); + value.setValue(size); } break; @@ -660,7 +660,7 @@ void PropertyHelper::checkApplyWidgetValue(QDesignerFormWindowInterface *fw, QWi checkSizes(fw, value.toSize(), &fs, &cs); container->setMaximumSize(cs); fw->mainContainer()->setMaximumSize(fs); - qVariantSetValue(value, fs); + value.setValue(fs); } break; @@ -670,7 +670,7 @@ void PropertyHelper::checkApplyWidgetValue(QDesignerFormWindowInterface *fw, QWi checkSizes(fw, r.size(), &fs, &cs); container->resize(cs); r.setSize(fs); - qVariantSetValue(value, r); + value.setValue(r); } break; default: @@ -727,8 +727,8 @@ void PropertyHelper::updateObject(QDesignerFormWindowInterface *fw, const QVaria case OT_Widget: { switch (m_specialProperty) { case SP_ObjectName: { - const QString oldName = qVariantValue<PropertySheetStringValue>(oldValue).value(); - const QString newName = qVariantValue<PropertySheetStringValue>(newValue).value(); + const QString oldName = qvariant_cast<PropertySheetStringValue>(oldValue).value(); + const QString newName = qvariant_cast<PropertySheetStringValue>(newValue).value(); QDesignerFormWindowCommand::updateBuddies(fw, oldName, newName); } break; @@ -751,8 +751,8 @@ void PropertyHelper::updateObject(QDesignerFormWindowInterface *fw, const QVaria case SP_LayoutName: case SP_SpacerName: if (QDesignerIntegration *integr = integration(fw)) { - const QString oldName = qVariantValue<PropertySheetStringValue>(oldValue).value(); - const QString newName = qVariantValue<PropertySheetStringValue>(newValue).value(); + const QString oldName = qvariant_cast<PropertySheetStringValue>(oldValue).value(); + const QString newName = qvariant_cast<PropertySheetStringValue>(newValue).value(); integr->emitObjectNameChanged(fw, m_object, newName, oldName); } break; diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp index da17e79..cffc130 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp +++ b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp @@ -290,18 +290,18 @@ bool QDesignerPropertySheetPrivate::isResourceProperty(int index) const void QDesignerPropertySheetPrivate::addResourceProperty(int index, QVariant::Type type) { if (type == QVariant::Pixmap) - m_resourceProperties.insert(index, qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue())); + m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue())); else if (type == QVariant::Icon) - m_resourceProperties.insert(index, qVariantFromValue(qdesigner_internal::PropertySheetIconValue())); + m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetIconValue())); } QVariant QDesignerPropertySheetPrivate::emptyResourceProperty(int index) const { QVariant v = m_resourceProperties.value(index); - if (qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(v)) - return qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue()); - if (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(v)) - return qVariantFromValue(qdesigner_internal::PropertySheetIconValue()); + if (v.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) + return QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue()); + if (v.canConvert<qdesigner_internal::PropertySheetIconValue>()) + return QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()); return v; } @@ -320,8 +320,8 @@ void QDesignerPropertySheetPrivate::setResourceProperty(int index, const QVarian Q_ASSERT(isResourceProperty(index)); QVariant &v = m_resourceProperties[index]; - if ((qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(value) && qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(v)) - || (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(value) && qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(v))) + if ((value.canConvert<qdesigner_internal::PropertySheetPixmapValue>() && v.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) + || (value.canConvert<qdesigner_internal::PropertySheetIconValue>() && v.canConvert<qdesigner_internal::PropertySheetIconValue>())) v = value; } @@ -722,14 +722,14 @@ int QDesignerPropertySheet::addDynamicProperty(const QString &propName, const QV QVariant v = value; if (value.type() == QVariant::Icon) - v = qVariantFromValue(qdesigner_internal::PropertySheetIconValue()); + v = QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()); else if (value.type() == QVariant::Pixmap) - v = qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue()); + v = QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue()); else if (value.type() == QVariant::String) - v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue(value.toString())); + v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(value.toString())); else if (value.type() == QVariant::KeySequence) { - const QKeySequence keySequence = qVariantValue<QKeySequence>(value); - v = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence)); + const QKeySequence keySequence = qvariant_cast<QKeySequence>(value); + v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence)); } if (d->m_addIndex.contains(propName)) { @@ -873,9 +873,9 @@ int QDesignerPropertySheet::createFakeProperty(const QString &propertyName, cons info.kind = QDesignerPropertySheetPrivate::FakeProperty; QVariant v = value.isValid() ? value : metaProperty(index); if (v.type() == QVariant::String) - v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); if (v.type() == QVariant::KeySequence) - v = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue()); + v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue()); d->m_fakeProperties.insert(index, v); return index; } @@ -1002,17 +1002,17 @@ QVariant QDesignerPropertySheet::property(int index) const value.setValue(strValue); d->setStringProperty(index, value); // cache it } - return qVariantFromValue(value); + return QVariant::fromValue(value); } if (d->isKeySequenceProperty(index)) { - QKeySequence keyValue = qVariantValue<QKeySequence>(metaProperty(index)); + QKeySequence keyValue = qvariant_cast<QKeySequence>(metaProperty(index)); qdesigner_internal::PropertySheetKeySequenceValue value = d->keySequenceProperty(index); if (keyValue != value.value()) { value.setValue(keyValue); d->setKeySequenceProperty(index, value); // cache it } - return qVariantFromValue(value); + return QVariant::fromValue(value); } return metaProperty(index); @@ -1027,12 +1027,12 @@ QVariant QDesignerPropertySheet::metaProperty(int index) const switch (p->kind()) { case QDesignerMetaPropertyInterface::FlagKind: { qdesigner_internal::PropertySheetFlagValue psflags = qdesigner_internal::PropertySheetFlagValue(v.toInt(), designerMetaFlagsFor(p->enumerator())); - qVariantSetValue(v, psflags); + v.setValue(psflags); } break; case QDesignerMetaPropertyInterface::EnumKind: { qdesigner_internal::PropertySheetEnumValue pse = qdesigner_internal::PropertySheetEnumValue(v.toInt(), designerMetaEnumFor(p->enumerator())); - qVariantSetValue(v, pse); + v.setValue(pse); } break; case QDesignerMetaPropertyInterface::OtherKind: @@ -1043,20 +1043,20 @@ QVariant QDesignerPropertySheet::metaProperty(int index) const QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant &value) const { - if (qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(value)) + if (value.canConvert<qdesigner_internal::PropertySheetEnumValue>()) return qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(value).value; - if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(value)) + if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>()) return qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(value).value; - if (qVariantCanConvert<qdesigner_internal::PropertySheetStringValue>(value)) - return qVariantValue<qdesigner_internal::PropertySheetStringValue>(value).value(); + if (value.canConvert<qdesigner_internal::PropertySheetStringValue>()) + return qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value).value(); - if (qVariantCanConvert<qdesigner_internal::PropertySheetKeySequenceValue>(value)) - return qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value).value(); + if (value.canConvert<qdesigner_internal::PropertySheetKeySequenceValue>()) + return qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value).value(); - if (qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(value)) { - const QString path = qVariantValue<qdesigner_internal::PropertySheetPixmapValue>(value).path(); + if (value.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) { + const QString path = qvariant_cast<qdesigner_internal::PropertySheetPixmapValue>(value).path(); if (path.isEmpty()) return defaultResourceProperty(index); if (d->m_pixmapCache) { @@ -1064,9 +1064,9 @@ QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant } } - if (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(value)) { - const int pathCount = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value).paths().count(); - if (pathCount == 0) + if (value.canConvert<qdesigner_internal::PropertySheetIconValue>()) { + const unsigned mask = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value).mask(); + if (mask == 0) return defaultResourceProperty(index); if (d->m_iconCache) return d->m_iconCache->icon(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value)); @@ -1082,17 +1082,17 @@ void QDesignerPropertySheet::setFakeProperty(int index, const QVariant &value) QVariant &v = d->m_fakeProperties[index]; // set resource properties also (if we are going to have fake resource properties) - if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(value) || qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(value)) { + if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>() || value.canConvert<qdesigner_internal::PropertySheetEnumValue>()) { v = value; - } else if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(v)) { + } else if (v.canConvert<qdesigner_internal::PropertySheetFlagValue>()) { qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(v); f.value = value.toInt(); - qVariantSetValue(v, f); + v.setValue(f); Q_ASSERT(value.type() == QVariant::Int); - } else if (qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(v)) { + } else if (v.canConvert<qdesigner_internal::PropertySheetEnumValue>()) { qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(v); e.value = value.toInt(); - qVariantSetValue(v, e); + v.setValue(e); Q_ASSERT(value.type() == QVariant::Int); } else { v = value; @@ -1139,9 +1139,9 @@ void QDesignerPropertySheet::setProperty(int index, const QVariant &value) if (d->isResourceProperty(index)) d->setResourceProperty(index, value); if (d->isStringProperty(index)) - d->setStringProperty(index, qVariantValue<qdesigner_internal::PropertySheetStringValue>(value)); + d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value)); if (d->isKeySequenceProperty(index)) - d->setKeySequenceProperty(index, qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value)); + d->setKeySequenceProperty(index, qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value)); d->m_object->setProperty(propertyName(index).toUtf8(), resolvePropertyValue(index, value)); if (d->m_object->isWidgetType()) { QWidget *w = qobject_cast<QWidget *>(d->m_object); @@ -1155,26 +1155,26 @@ void QDesignerPropertySheet::setProperty(int index, const QVariant &value) if (d->isResourceProperty(index)) d->setResourceProperty(index, value); if (d->isStringProperty(index)) - d->setStringProperty(index, qVariantValue<qdesigner_internal::PropertySheetStringValue>(value)); + d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value)); if (d->isKeySequenceProperty(index)) - d->setKeySequenceProperty(index, qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value)); + d->setKeySequenceProperty(index, qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value)); const QDesignerMetaPropertyInterface *p = d->m_meta->property(index); p->write(d->m_object, resolvePropertyValue(index, value)); if (qobject_cast<QGroupBox *>(d->m_object) && propertyType(index) == PropertyCheckable) { const int idx = indexOf(QLatin1String("focusPolicy")); if (!isChanged(idx)) { - qdesigner_internal::PropertySheetEnumValue e = qVariantValue<qdesigner_internal::PropertySheetEnumValue>(property(idx)); + qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(property(idx)); if (value.toBool()) { const QDesignerMetaPropertyInterface *p = d->m_meta->property(idx); p->write(d->m_object, Qt::NoFocus); e.value = Qt::StrongFocus; QVariant v; - qVariantSetValue(v, e); + v.setValue(e); setFakeProperty(idx, v); } else { e.value = Qt::NoFocus; QVariant v; - qVariantSetValue(v, e); + v.setValue(e); setFakeProperty(idx, v); } } @@ -1195,10 +1195,19 @@ bool QDesignerPropertySheet::reset(int index) { if (d->invalidIndex(Q_FUNC_INFO, index)) return false; - if (d->isStringProperty(index)) - setProperty(index, qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + if (d->isStringProperty(index)) { + qdesigner_internal::PropertySheetStringValue value; + // Main container: Reset to stored class name as not to change the file names generated by uic. + if (propertyName(index) == QLatin1String("objectName")) { + const QVariant classNameDefaultV = d->m_object->property("_q_classname"); + if (classNameDefaultV.isValid()) + value.setValue(classNameDefaultV.toString()); + } + setProperty(index, QVariant::fromValue(value)); + return true; + } if (d->isKeySequenceProperty(index)) - setProperty(index, qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue())); + setProperty(index, QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue())); if (d->isResourceProperty(index)) { setProperty(index, d->emptyResourceProperty(index)); return true; @@ -1208,10 +1217,10 @@ bool QDesignerPropertySheet::reset(int index) const QVariant defaultValue = d->m_info.value(index).defaultValue; QVariant newValue = defaultValue; if (d->isStringProperty(index)) { - newValue = qVariantFromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString())); + newValue = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString())); } else if (d->isKeySequenceProperty(index)) { - const QKeySequence keySequence = qVariantValue<QKeySequence>(newValue); - newValue = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence)); + const QKeySequence keySequence = qvariant_cast<QKeySequence>(newValue); + newValue = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence)); } if (oldValue == newValue) return true; diff --git a/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp b/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp index f062ba4..d1625a2 100644 --- a/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp +++ b/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp @@ -134,7 +134,7 @@ QTabBar *QTabWidgetEventFilter::tabBar() const { // QTabWidget::tabBar() accessor is protected, grmbl... if (!m_cachedTabBar) { - const QList<QTabBar *> tabBars = qFindChildren<QTabBar *>(m_tabWidget); + const QList<QTabBar *> tabBars = m_tabWidget->findChildren<QTabBar *>(); Q_ASSERT(tabBars.size() == 1); m_cachedTabBar = tabBars.front(); } @@ -405,13 +405,13 @@ QTabWidgetPropertySheet::QTabWidgetPropertySheet(QTabWidget *object, QObject *pa QDesignerPropertySheet(object, parent), m_tabWidget(object) { - createFakeProperty(QLatin1String(currentTabTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentTabTextKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); createFakeProperty(QLatin1String(currentTabNameKey), QString()); - createFakeProperty(QLatin1String(currentTabIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue())); + createFakeProperty(QLatin1String(currentTabIconKey), QVariant::fromValue(qdesigner_internal::PropertySheetIconValue())); if (formWindowBase()) formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentTabIconKey))); - createFakeProperty(QLatin1String(currentTabToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); - createFakeProperty(QLatin1String(currentTabWhatsThisKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentTabToolTipKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentTabWhatsThisKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); // Prevent the tab widget's drag and drop handling from interfering with Designer's createFakeProperty(QLatin1String(tabMovableKey), QVariant(false)); } @@ -447,22 +447,22 @@ void QTabWidgetPropertySheet::setProperty(int index, const QVariant &value) switch (tabWidgetProperty) { case PropertyCurrentTabText: m_tabWidget->setTabText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].text = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyCurrentTabName: currentWidget->setObjectName(value.toString()); break; case PropertyCurrentTabIcon: m_tabWidget->setTabIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value); + m_pageToData[currentWidget].icon = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value); break; case PropertyCurrentTabToolTip: m_tabWidget->setTabToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].tooltip = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyCurrentTabWhatsThis: m_tabWidget->setTabWhatsThis(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].whatsthis = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].whatsthis = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyTabWidgetNone: break; @@ -486,28 +486,28 @@ QVariant QTabWidgetPropertySheet::property(int index) const QWidget *currentWidget = m_tabWidget->currentWidget(); if (!currentWidget) { if (tabWidgetProperty == PropertyCurrentTabIcon) - return qVariantFromValue(qdesigner_internal::PropertySheetIconValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()); if (tabWidgetProperty == PropertyCurrentTabText) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); if (tabWidgetProperty == PropertyCurrentTabToolTip) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); if (tabWidgetProperty == PropertyCurrentTabWhatsThis) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); return QVariant(QString()); } // index-dependent switch (tabWidgetProperty) { case PropertyCurrentTabText: - return qVariantFromValue(m_pageToData.value(currentWidget).text); + return QVariant::fromValue(m_pageToData.value(currentWidget).text); case PropertyCurrentTabName: return currentWidget->objectName(); case PropertyCurrentTabIcon: - return qVariantFromValue(m_pageToData.value(currentWidget).icon); + return QVariant::fromValue(m_pageToData.value(currentWidget).icon); case PropertyCurrentTabToolTip: - return qVariantFromValue(m_pageToData.value(currentWidget).tooltip); + return QVariant::fromValue(m_pageToData.value(currentWidget).tooltip); case PropertyCurrentTabWhatsThis: - return qVariantFromValue(m_pageToData.value(currentWidget).whatsthis); + return QVariant::fromValue(m_pageToData.value(currentWidget).whatsthis); case PropertyTabWidgetNone: break; } diff --git a/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp b/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp index 1e7515f..0c2cb6f 100644 --- a/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp +++ b/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp @@ -41,6 +41,7 @@ #include "qdesigner_taskmenu_p.h" #include "qdesigner_command_p.h" +#include "qdesigner_command2_p.h" #include "richtexteditor_p.h" #include "plaintexteditor_p.h" #include "stylesheeteditor_p.h" @@ -132,7 +133,7 @@ static QString objName(const QDesignerFormEditorInterface *core, QObject *object const QString objectNameProperty = QLatin1String("objectName"); const int index = sheet->indexOf(objectNameProperty); const qdesigner_internal::PropertySheetStringValue objectNameValue - = qVariantValue<qdesigner_internal::PropertySheetStringValue>(sheet->property(index)); + = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(sheet->property(index)); return objectNameValue.value(); } @@ -180,10 +181,128 @@ QString ObjectNameDialog::newObjectName() const { return m_editor->text(); } +} // namespace +namespace qdesigner_internal { + +// Sub menu displaying the alignment options of a widget in a managed +// grid/box layout cell. +class LayoutAlignmentMenu { +public: + explicit LayoutAlignmentMenu(QObject *parent); + + QAction *subMenuAction() const { return m_subMenuAction; } + + void connect(QObject *receiver, const char *aSlot); + + // Set up enabled state and checked actions according to widget (managed box/grid) + bool setAlignment(const QDesignerFormEditorInterface *core, QWidget *w); + + // Return the currently checked alignment + Qt::Alignment alignment() const; + +private: + enum Actions { HorizNone, Left, HorizCenter, Right, VerticalNone, Top, VerticalCenter, Bottom }; + static QAction *createAction(const QString &text, int data, QMenu *menu, QActionGroup *ag); + + QAction *m_subMenuAction; + QActionGroup *m_horizGroup; + QActionGroup *m_verticalGroup; + QAction *m_actions[Bottom + 1]; +}; + +QAction *LayoutAlignmentMenu::createAction(const QString &text, int data, QMenu *menu, QActionGroup *ag) +{ + QAction * a = new QAction(text, 0); + a->setCheckable(true); + a->setData(QVariant(data)); + menu->addAction(a); + ag->addAction(a); + return a; +} + +LayoutAlignmentMenu::LayoutAlignmentMenu(QObject *parent) : + m_subMenuAction(new QAction(QDesignerTaskMenu::tr("Layout Alignment"), parent)), + m_horizGroup(new QActionGroup(parent)), + m_verticalGroup(new QActionGroup(parent)) +{ + m_horizGroup->setExclusive(true); + m_verticalGroup->setExclusive(true); + + QMenu *menu = new QMenu; + m_subMenuAction->setMenu(menu); + + m_actions[HorizNone] = createAction(QDesignerTaskMenu::tr("No Horizontal Alignment"), 0, menu, m_horizGroup); + m_actions[Left] = createAction(QDesignerTaskMenu::tr("Left"), Qt::AlignLeft, menu, m_horizGroup); + m_actions[HorizCenter] = createAction(QDesignerTaskMenu::tr("Center Horizontally"), Qt::AlignHCenter, menu, m_horizGroup); + m_actions[Right] = createAction(QDesignerTaskMenu::tr("Right"), Qt::AlignRight, menu, m_horizGroup); + menu->addSeparator(); + m_actions[VerticalNone] = createAction(QDesignerTaskMenu::tr("No Vertical Alignment"), 0, menu, m_verticalGroup); + m_actions[Top] = createAction(QDesignerTaskMenu::tr("Top"), Qt::AlignTop, menu, m_verticalGroup); + m_actions[VerticalCenter] = createAction(QDesignerTaskMenu::tr("Center Vertically"), Qt::AlignVCenter, menu, m_verticalGroup); + m_actions[Bottom] = createAction(QDesignerTaskMenu::tr("Bottom"), Qt::AlignBottom, menu, m_verticalGroup); +} + +void LayoutAlignmentMenu::connect(QObject *receiver, const char *aSlot) +{ + QObject::connect(m_horizGroup, SIGNAL(triggered(QAction*)), receiver, aSlot); + QObject::connect(m_verticalGroup, SIGNAL(triggered(QAction*)), receiver, aSlot); +} + +bool LayoutAlignmentMenu::setAlignment(const QDesignerFormEditorInterface *core, QWidget *w) +{ + bool enabled; + const Qt::Alignment alignment = LayoutAlignmentCommand::alignmentOf(core, w, &enabled); + if (!enabled) { + m_subMenuAction->setEnabled(false); + m_actions[HorizNone]->setChecked(true); + m_actions[VerticalNone]->setChecked(true); + return false; + } + // Get alignment + switch (alignment & Qt::AlignHorizontal_Mask) { + case Qt::AlignLeft: + m_actions[Left]->setChecked(true); + break; + case Qt::AlignHCenter: + m_actions[HorizCenter]->setChecked(true); + break; + case Qt::AlignRight: + m_actions[Right]->setChecked(true); + break; + default: + m_actions[HorizNone]->setChecked(true); + break; + } + switch (alignment & Qt::AlignVertical_Mask) { + case Qt::AlignTop: + m_actions[Top]->setChecked(true); + break; + case Qt::AlignVCenter: + m_actions[VerticalCenter]->setChecked(true); + break; + case Qt::AlignBottom: + m_actions[Bottom]->setChecked(true); + break; + default: + m_actions[VerticalNone]->setChecked(true); + break; + } + return true; +} + +Qt::Alignment LayoutAlignmentMenu::alignment() const +{ + Qt::Alignment alignment = 0; + if (const QAction *horizAction = m_horizGroup->checkedAction()) + if (const int horizAlign = horizAction->data().toInt()) + alignment |= static_cast<Qt::Alignment>(horizAlign); + if (const QAction *vertAction = m_verticalGroup->checkedAction()) + if (const int vertAlign = vertAction->data().toInt()) + alignment |= static_cast<Qt::Alignment>(vertAlign); + return alignment; } -namespace qdesigner_internal { // -------------- QDesignerTaskMenuPrivate class QDesignerTaskMenuPrivate { public: @@ -214,6 +333,7 @@ public: QAction *m_navigateToSlot; PromotionTaskMenu* m_promotionTaskMenu; QActionGroup *m_sizeActionGroup; + LayoutAlignmentMenu m_layoutAlignmentMenu; QAction *m_sizeActionsSubMenu; }; @@ -242,6 +362,7 @@ QDesignerTaskMenuPrivate::QDesignerTaskMenuPrivate(QWidget *widget, QObject *par m_navigateToSlot(new QAction(QDesignerTaskMenu::tr("Go to slot..."), parent)), m_promotionTaskMenu(new PromotionTaskMenu(widget, PromotionTaskMenu::ModeManagedMultiSelection, parent)), m_sizeActionGroup(new QActionGroup(parent)), + m_layoutAlignmentMenu(parent), m_sizeActionsSubMenu(new QAction(QDesignerTaskMenu::tr("Size Constraints"), parent)) { QMenu *sizeMenu = new QMenu; @@ -293,6 +414,7 @@ QDesignerTaskMenu::QDesignerTaskMenu(QWidget *widget, QObject *parent) : connect(d->m_containerFakeMethods, SIGNAL(triggered()), this, SLOT(containerFakeMethods())); connect(d->m_navigateToSlot, SIGNAL(triggered()), this, SLOT(slotNavigateToSlot())); connect(d->m_sizeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(applySize(QAction*))); + d->m_layoutAlignmentMenu.connect(this, SLOT(slotLayoutAlignment())); } QDesignerTaskMenu::~QDesignerTaskMenu() @@ -410,6 +532,9 @@ QList<QAction*> QDesignerTaskMenu::taskActions() const actions.append(d->m_changeStyleSheet); actions.append(d->m_separator6); actions.append(d->m_sizeActionsSubMenu); + if (d->m_layoutAlignmentMenu.setAlignment(formWindow->core(), d->m_widget)) + actions.append(d->m_layoutAlignmentMenu.subMenuAction()); + d->m_promotionTaskMenu->setMode(formWindow->isManaged(d->m_widget) ? PromotionTaskMenu::ModeManagedMultiSelection : PromotionTaskMenu::ModeUnmanagedMultiSelection); d->m_promotionTaskMenu->addActions(formWindow, PromotionTaskMenu::LeadingSeparator, actions); @@ -447,7 +572,7 @@ void QDesignerTaskMenu::changeObjectName() const QString objectNameProperty = QLatin1String("objectName"); PropertySheetStringValue objectNameValue; objectNameValue.setValue(newObjectName); - setProperty(fw, CurrentWidgetMode, objectNameProperty, qVariantFromValue(objectNameValue)); + setProperty(fw, CurrentWidgetMode, objectNameProperty, QVariant::fromValue(objectNameValue)); } } } @@ -465,7 +590,7 @@ void QDesignerTaskMenu::changeTextProperty(const QString &propertyName, const QS qDebug() << "** WARNING Invalid property" << propertyName << " passed to changeTextProperty!"; return; } - PropertySheetStringValue textValue = qVariantValue<PropertySheetStringValue>(sheet->property(index)); + PropertySheetStringValue textValue = qvariant_cast<PropertySheetStringValue>(sheet->property(index)); const QString oldText = textValue.value(); // Pop up respective dialog bool accepted = false; @@ -498,7 +623,7 @@ void QDesignerTaskMenu::changeTextProperty(const QString &propertyName, const QS textValue.setValue(newText); - setProperty(fw, pm, propertyName, qVariantFromValue(textValue)); + setProperty(fw, pm, propertyName, QVariant::fromValue(textValue)); } void QDesignerTaskMenu::changeToolTip() @@ -673,7 +798,7 @@ void QDesignerTaskMenu::navigateToSlot(QDesignerFormEditorInterface *core, if (selectSignalDialog.exec() == QDialog::Accepted) { QTreeWidgetItem *selectedItem = dialogUi.signalList->selectedItems().first(); const QString signalSignature = selectedItem->text(0); - const QStringList parameterNames = qVariantValue<QStringList>(selectedItem->data(0, Qt::UserRole)); + const QStringList parameterNames = qvariant_cast<QStringList>(selectedItem->data(0, Qt::UserRole)); // TODO: Check whether signal is connected to slot integr->emitNavigateToSlot(objectName, signalSignature, parameterNames); @@ -771,7 +896,17 @@ void QDesignerTaskMenu::setProperty(QDesignerFormWindowInterface *fw, PropertyM } } - +void QDesignerTaskMenu::slotLayoutAlignment() +{ + QDesignerFormWindowInterface *fw = formWindow(); + const Qt::Alignment newAlignment = d->m_layoutAlignmentMenu.alignment(); + LayoutAlignmentCommand *cmd = new LayoutAlignmentCommand(fw); + if (cmd->init(d->m_widget, newAlignment)) { + fw->commandHistory()->push(cmd); + } else { + delete cmd; + } +} } // namespace qdesigner_internal QT_END_NAMESPACE diff --git a/tools/designer/src/lib/shared/qdesigner_taskmenu_p.h b/tools/designer/src/lib/shared/qdesigner_taskmenu_p.h index d5ee3a5..2faffbc 100644 --- a/tools/designer/src/lib/shared/qdesigner_taskmenu_p.h +++ b/tools/designer/src/lib/shared/qdesigner_taskmenu_p.h @@ -118,6 +118,7 @@ private slots: void containerFakeMethods(); void slotNavigateToSlot(); void applySize(QAction *a); + void slotLayoutAlignment(); private: QDesignerTaskMenuPrivate *d; diff --git a/tools/designer/src/lib/shared/qdesigner_toolbar.cpp b/tools/designer/src/lib/shared/qdesigner_toolbar.cpp index 0eab0f7..49ebdd9 100644 --- a/tools/designer/src/lib/shared/qdesigner_toolbar.cpp +++ b/tools/designer/src/lib/shared/qdesigner_toolbar.cpp @@ -146,7 +146,7 @@ ActionList ToolBarEventFilter::contextMenuActions(const QPoint &globalPos) // Insert before if (action && index != 0 && !action->isSeparator()) { QAction *newSeperatorAct = new QAction(tr("Insert Separator before '%1'").arg(action->objectName()), 0); - qVariantSetValue(itemData, action); + itemData.setValue(action); newSeperatorAct->setData(itemData); connect(newSeperatorAct, SIGNAL(triggered()), this, SLOT(slotInsertSeparator())); rc.push_back(newSeperatorAct); @@ -155,7 +155,7 @@ ActionList ToolBarEventFilter::contextMenuActions(const QPoint &globalPos) // Append separator if (actions.empty() || !actions.back()->isSeparator()) { QAction *newSeperatorAct = new QAction(tr("Append Separator"), 0); - qVariantSetValue(itemData, static_cast<QAction*>(0)); + itemData.setValue(static_cast<QAction*>(0)); newSeperatorAct->setData(itemData); connect(newSeperatorAct, SIGNAL(triggered()), this, SLOT(slotInsertSeparator())); rc.push_back(newSeperatorAct); @@ -167,7 +167,7 @@ ActionList ToolBarEventFilter::contextMenuActions(const QPoint &globalPos) // Remove if (action) { QAction *a = new QAction(tr("Remove action '%1'").arg(action->objectName()), 0); - qVariantSetValue(itemData, action); + itemData.setValue(action); a->setData(itemData); connect(a, SIGNAL(triggered()), this, SLOT(slotRemoveSelectedAction())); rc.push_back(a); diff --git a/tools/designer/src/lib/shared/qdesigner_toolbox.cpp b/tools/designer/src/lib/shared/qdesigner_toolbox.cpp index 45f65fd..59168b1 100644 --- a/tools/designer/src/lib/shared/qdesigner_toolbox.cpp +++ b/tools/designer/src/lib/shared/qdesigner_toolbox.cpp @@ -260,12 +260,12 @@ QToolBoxWidgetPropertySheet::QToolBoxWidgetPropertySheet(QToolBox *object, QObje QDesignerPropertySheet(object, parent), m_toolBox(object) { - createFakeProperty(QLatin1String(currentItemTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentItemTextKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); createFakeProperty(QLatin1String(currentItemNameKey), QString()); - createFakeProperty(QLatin1String(currentItemIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue())); + createFakeProperty(QLatin1String(currentItemIconKey), QVariant::fromValue(qdesigner_internal::PropertySheetIconValue())); if (formWindowBase()) formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentItemIconKey))); - createFakeProperty(QLatin1String(currentItemToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue())); + createFakeProperty(QLatin1String(currentItemToolTipKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue())); createFakeProperty(QLatin1String(tabSpacingKey), QVariant(tabSpacingDefault)); } @@ -306,18 +306,18 @@ void QToolBoxWidgetPropertySheet::setProperty(int index, const QVariant &value) switch (toolBoxProperty) { case PropertyCurrentItemText: m_toolBox->setItemText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].text = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyCurrentItemName: currentWidget->setObjectName(value.toString()); break; case PropertyCurrentItemIcon: m_toolBox->setItemIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value); + m_pageToData[currentWidget].icon = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value); break; case PropertyCurrentItemToolTip: m_toolBox->setItemToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value))); - m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value); + m_pageToData[currentWidget].tooltip = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value); break; case PropertyTabSpacing: case PropertyToolBoxNone: @@ -353,24 +353,24 @@ QVariant QToolBoxWidgetPropertySheet::property(int index) const QWidget *currentWidget = m_toolBox->currentWidget(); if (!currentWidget) { if (toolBoxProperty == PropertyCurrentItemIcon) - return qVariantFromValue(qdesigner_internal::PropertySheetIconValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()); if (toolBoxProperty == PropertyCurrentItemText) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); if (toolBoxProperty == PropertyCurrentItemToolTip) - return qVariantFromValue(qdesigner_internal::PropertySheetStringValue()); + return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()); return QVariant(QString()); } // index-dependent switch (toolBoxProperty) { case PropertyCurrentItemText: - return qVariantFromValue(m_pageToData.value(currentWidget).text); + return QVariant::fromValue(m_pageToData.value(currentWidget).text); case PropertyCurrentItemName: return currentWidget->objectName(); case PropertyCurrentItemIcon: - return qVariantFromValue(m_pageToData.value(currentWidget).icon); + return QVariant::fromValue(m_pageToData.value(currentWidget).icon); case PropertyCurrentItemToolTip: - return qVariantFromValue(m_pageToData.value(currentWidget).tooltip); + return QVariant::fromValue(m_pageToData.value(currentWidget).tooltip); case PropertyTabSpacing: case PropertyToolBoxNone: break; diff --git a/tools/designer/src/lib/shared/qdesigner_utils.cpp b/tools/designer/src/lib/shared/qdesigner_utils.cpp index 3c77065..d3a14d2 100644 --- a/tools/designer/src/lib/shared/qdesigner_utils.cpp +++ b/tools/designer/src/lib/shared/qdesigner_utils.cpp @@ -52,15 +52,16 @@ #include <QtDesigner/QDesignerTaskMenuExtension> #include <QtDesigner/QExtensionManager> -#include <QtGui/QIcon> -#include <QtGui/QPixmap> #include <QtCore/QDir> - -#include <QtGui/QApplication> #include <QtCore/QProcess> #include <QtCore/QLibraryInfo> #include <QtCore/QDebug> #include <QtCore/QQueue> +#include <QtCore/QSharedData> + +#include <QtGui/QApplication> +#include <QtGui/QIcon> +#include <QtGui/QPixmap> #include <QtGui/QListWidget> #include <QtGui/QTreeWidget> #include <QtGui/QTableWidget> @@ -82,8 +83,8 @@ namespace qdesigner_internal for (int c = 0; c < item->columnCount(); c++) { const QVariant v = item->data(c, Qt::DecorationPropertyRole); - if (qVariantCanConvert<PropertySheetIconValue>(v)) - item->setIcon(c, iconCache->icon(qVariantValue<PropertySheetIconValue>(v))); + if (v.canConvert<PropertySheetIconValue>()) + item->setIcon(c, iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); } } @@ -93,8 +94,8 @@ namespace qdesigner_internal return; const QVariant v = item->data(Qt::DecorationPropertyRole); - if (qVariantCanConvert<PropertySheetIconValue>(v)) - item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(v))); + if (v.canConvert<PropertySheetIconValue>()) + item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); } void reloadTableItem(DesignerIconCache *iconCache, QTableWidgetItem *item) @@ -103,8 +104,8 @@ namespace qdesigner_internal return; const QVariant v = item->data(Qt::DecorationPropertyRole); - if (qVariantCanConvert<PropertySheetIconValue>(v)) - item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(v))); + if (v.canConvert<PropertySheetIconValue>()) + item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); } void reloadIconResources(DesignerIconCache *iconCache, QObject *object) @@ -115,8 +116,8 @@ namespace qdesigner_internal } else if (QComboBox *comboBox = qobject_cast<QComboBox *>(object)) { for (int i = 0; i < comboBox->count(); i++) { const QVariant v = comboBox->itemData(i, Qt::DecorationPropertyRole); - if (qVariantCanConvert<PropertySheetIconValue>(v)) { - QIcon icon = iconCache->icon(qVariantValue<PropertySheetIconValue>(v)); + if (v.canConvert<PropertySheetIconValue>()) { + QIcon icon = iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)); comboBox->setItemIcon(i, icon); comboBox->setItemData(i, icon); } @@ -314,24 +315,51 @@ namespace qdesigner_internal } // ---------- PropertySheetIconValue - PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) + + class PropertySheetIconValueData : public QSharedData { + public: + PropertySheetIconValue::ModeStateToPixmapMap m_paths; + QString m_theme; + }; + + PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) : + m_data(new PropertySheetIconValueData) { setPixmap(QIcon::Normal, QIcon::Off, pixmap); } - PropertySheetIconValue::PropertySheetIconValue() + PropertySheetIconValue::PropertySheetIconValue() : + m_data(new PropertySheetIconValueData) + { + } + + PropertySheetIconValue::~PropertySheetIconValue() { } + PropertySheetIconValue::PropertySheetIconValue(const PropertySheetIconValue &rhs) : + m_data(rhs.m_data) + { + } + + PropertySheetIconValue &PropertySheetIconValue::operator=(const PropertySheetIconValue &rhs) + { + if (this != &rhs) + m_data.operator=(rhs.m_data); + return *this; + } + bool PropertySheetIconValue::equals(const PropertySheetIconValue &rhs) const { - return m_paths == rhs.m_paths; + return m_data->m_theme == rhs.m_data->m_theme && m_data->m_paths == rhs.m_data->m_paths; } bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const { - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_paths); - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_paths); + if (const int themeCmp = m_data->m_theme.compare(other.m_data->m_theme)) + return themeCmp < 0; + QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_data->m_paths); + QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_data->m_paths); while (itThis.hasNext() && itOther.hasNext()) { const ModeStateKey thisPair = itThis.next().key(); const ModeStateKey otherPair = itOther.next().key(); @@ -350,19 +378,34 @@ namespace qdesigner_internal return false; } + bool PropertySheetIconValue::isEmpty() const + { + return m_data->m_theme.isEmpty() && m_data->m_paths.isEmpty(); + } + + QString PropertySheetIconValue::theme() const + { + return m_data->m_theme; + } + + void PropertySheetIconValue::setTheme(const QString &t) + { + m_data->m_theme = t; + } + PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const { const ModeStateKey pair = qMakePair(mode, state); - return m_paths.value(pair); + return m_data->m_paths.value(pair); } void PropertySheetIconValue::setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &pixmap) { const ModeStateKey pair = qMakePair(mode, state); if (pixmap.path().isEmpty()) - m_paths.remove(pair); + m_data->m_paths.remove(pair); else - m_paths.insert(pair, pixmap); + m_data->m_paths.insert(pair, pixmap); } QPixmap DesignerPixmapCache::pixmap(const PropertySheetPixmapValue &value) const @@ -388,16 +431,28 @@ namespace qdesigner_internal QIcon DesignerIconCache::icon(const PropertySheetIconValue &value) const { + typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + QMap<PropertySheetIconValue, QIcon>::const_iterator it = m_cache.constFind(value); if (it != m_cache.constEnd()) return it.value(); + // Match on the theme first if it is available. + if (!value.theme().isEmpty()) { + const QString theme = value.theme(); + if (QIcon::hasThemeIcon(theme)) { + const QIcon themeIcon = QIcon::fromTheme(theme); + m_cache.insert(value, themeIcon); + return themeIcon; + } + } + QIcon icon; - QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> paths = value.paths(); - QMapIterator<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> itPath(paths); - while (itPath.hasNext()) { - QPair<QIcon::Mode, QIcon::State> pair = itPath.next().key(); - icon.addFile(itPath.value().path(), QSize(), pair.first, pair.second); + const PropertySheetIconValue::ModeStateToPixmapMap &paths = value.paths(); + const ModeStateToPixmapMapConstIt cend = paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) { + const QPair<QIcon::Mode, QIcon::State> pair = it.key(); + icon.addFile(it.value().path(), QSize(), pair.first, pair.second); } m_cache.insert(value, icon); return icon; @@ -547,50 +602,75 @@ namespace qdesigner_internal && (m_translatable == rhs.m_translatable) && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment); } - class StateMap + + /* IconSubPropertyMask: Assign each icon sub-property (pixmaps for the + * various states/modes and the theme) a flag bit (see QFont) so that they + * can be handled individually when assigning property values to + * multiselections in the set-property-commands (that is, do not clobber + * other subproperties when assigning just one). + * Provide back-and-forth mapping functions for the icon states. */ + + enum IconSubPropertyMask { + NormalOffIconMask = 0x01, + NormalOnIconMask = 0x02, + DisabledOffIconMask = 0x04, + DisabledOnIconMask = 0x08, + ActiveOffIconMask = 0x10, + ActiveOnIconMask = 0x20, + SelectedOffIconMask = 0x40, + SelectedOnIconMask = 0x80, + ThemeIconMask = 0x10000 + }; + + static inline uint iconStateToSubPropertyFlag(QIcon::Mode mode, QIcon::State state) { - public: - StateMap() - { - m_stateToFlag.insert(qMakePair(QIcon::Normal, QIcon::Off), 0x01); - m_stateToFlag.insert(qMakePair(QIcon::Normal, QIcon::On), 0x02); - m_stateToFlag.insert(qMakePair(QIcon::Disabled, QIcon::Off), 0x04); - m_stateToFlag.insert(qMakePair(QIcon::Disabled, QIcon::On), 0x08); - m_stateToFlag.insert(qMakePair(QIcon::Active, QIcon::Off), 0x10); - m_stateToFlag.insert(qMakePair(QIcon::Active, QIcon::On), 0x20); - m_stateToFlag.insert(qMakePair(QIcon::Selected, QIcon::Off), 0x40); - m_stateToFlag.insert(qMakePair(QIcon::Selected, QIcon::On), 0x80); - - m_flagToState.insert(0x01, qMakePair(QIcon::Normal, QIcon::Off)); - m_flagToState.insert(0x02, qMakePair(QIcon::Normal, QIcon::On)); - m_flagToState.insert(0x04, qMakePair(QIcon::Disabled, QIcon::Off)); - m_flagToState.insert(0x08, qMakePair(QIcon::Disabled, QIcon::On)); - m_flagToState.insert(0x10, qMakePair(QIcon::Active, QIcon::Off)); - m_flagToState.insert(0x20, qMakePair(QIcon::Active, QIcon::On)); - m_flagToState.insert(0x40, qMakePair(QIcon::Selected, QIcon::Off)); - m_flagToState.insert(0x80, qMakePair(QIcon::Selected, QIcon::On)); - } - uint flag(const QPair<QIcon::Mode, QIcon::State> &pair) const - { - return m_stateToFlag.value(pair); + switch (mode) { + case QIcon::Disabled: + return state == QIcon::On ? DisabledOnIconMask : DisabledOffIconMask; + case QIcon::Active: + return state == QIcon::On ? ActiveOnIconMask : ActiveOffIconMask; + case QIcon::Selected: + return state == QIcon::On ? SelectedOnIconMask : SelectedOffIconMask; + case QIcon::Normal: + break; } - QPair<QIcon::Mode, QIcon::State> state(uint flag) const - { - return m_flagToState.value(flag); + return state == QIcon::On ? NormalOnIconMask : NormalOffIconMask; + } + + static inline QPair<QIcon::Mode, QIcon::State> subPropertyFlagToIconModeState(unsigned flag) + { + switch (flag) { + case NormalOnIconMask: + return qMakePair(QIcon::Normal, QIcon::On); + case DisabledOffIconMask: + return qMakePair(QIcon::Disabled, QIcon::Off); + case DisabledOnIconMask: + return qMakePair(QIcon::Disabled, QIcon::On); + case ActiveOffIconMask: + return qMakePair(QIcon::Active, QIcon::Off); + case ActiveOnIconMask: + return qMakePair(QIcon::Active, QIcon::On); + case SelectedOffIconMask: + return qMakePair(QIcon::Selected, QIcon::Off); + case SelectedOnIconMask: + return qMakePair(QIcon::Selected, QIcon::On); + case NormalOffIconMask: + default: + break; } - private: - QMap<QPair<QIcon::Mode, QIcon::State>, uint > m_stateToFlag; - QMap<uint, QPair<QIcon::Mode, QIcon::State> > m_flagToState; - }; - - Q_GLOBAL_STATIC(StateMap, stateMap) + return qMakePair(QIcon::Normal, QIcon::Off); + } uint PropertySheetIconValue::mask() const { + typedef ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + uint flags = 0; - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itPath(m_paths); - while (itPath.hasNext()) - flags |= stateMap()->flag(itPath.next().key()); + const ModeStateToPixmapMapConstIt cend = m_data->m_paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = m_data->m_paths.constBegin(); it != cend; ++it) + flags |= iconStateToSubPropertyFlag(it.key().first, it.key().second); + if (!m_data->m_theme.isEmpty()) + flags |= ThemeIconMask; return flags; } @@ -598,30 +678,64 @@ namespace qdesigner_internal { uint diffMask = mask() | other.mask(); for (int i = 0; i < 8; i++) { - uint flag = 1 << i; + const uint flag = 1 << i; if (diffMask & flag) { // if state is set in both icons, compare the values - const ModeStateKey state = stateMap()->state(flag); + const QPair<QIcon::Mode, QIcon::State> state = subPropertyFlagToIconModeState(flag); if (pixmap(state.first, state.second) == other.pixmap(state.first, state.second)) diffMask &= ~flag; } } + if ((diffMask & ThemeIconMask) && theme() == other.theme()) + diffMask &= ~ThemeIconMask; return diffMask; } + PropertySheetIconValue PropertySheetIconValue::themed() const + { + PropertySheetIconValue rc(*this); + rc.m_data->m_paths.clear(); + return rc; + } + + PropertySheetIconValue PropertySheetIconValue::unthemed() const + { + PropertySheetIconValue rc(*this); + rc.m_data->m_theme.clear(); + return rc; + } + void PropertySheetIconValue::assign(const PropertySheetIconValue &other, uint mask) { for (int i = 0; i < 8; i++) { uint flag = 1 << i; if (mask & flag) { - const ModeStateKey state = stateMap()->state(flag); + const ModeStateKey state = subPropertyFlagToIconModeState(flag); setPixmap(state.first, state.second, other.pixmap(state.first, state.second)); } } + if (mask & ThemeIconMask) + setTheme(other.theme()); } - PropertySheetIconValue::ModeStateToPixmapMap PropertySheetIconValue::paths() const + const PropertySheetIconValue::ModeStateToPixmapMap &PropertySheetIconValue::paths() const { - return m_paths; + return m_data->m_paths; + } + + QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug d, const PropertySheetIconValue &p) + { + typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + + QDebug nospace = d.nospace(); + nospace << "PropertySheetIconValue theme='" << p.theme() << "' "; + + const PropertySheetIconValue::ModeStateToPixmapMap &paths = p.paths(); + const ModeStateToPixmapMapConstIt cend = paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) + nospace << " mode=" << it.key().first << ",state=" << it.key().second + << ",'" << it.value().path() << '\''; + nospace << " mask=0x" << QString::number(p.mask(), 16); + return d; } QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw) diff --git a/tools/designer/src/lib/shared/qdesigner_utils_p.h b/tools/designer/src/lib/shared/qdesigner_utils_p.h index fc5607f..4803f44 100644 --- a/tools/designer/src/lib/shared/qdesigner_utils_p.h +++ b/tools/designer/src/lib/shared/qdesigner_utils_p.h @@ -58,6 +58,7 @@ #include <QtDesigner/QDesignerFormWindowInterface> #include <QtCore/QVariant> +#include <QtCore/QSharedDataPointer> #include <QtCore/QMap> #include <QtGui/QMainWindow> #include <QtGui/QIcon> @@ -65,6 +66,8 @@ QT_BEGIN_NAMESPACE +class QDebug; + namespace qdesigner_internal { class QDesignerFormWindowCommand; class DesignerIconCache; @@ -252,16 +255,26 @@ private: // -------------- IconValue: Returned by the property sheet for icons +class PropertySheetIconValueData; + class QDESIGNER_SHARED_EXPORT PropertySheetIconValue { public: PropertySheetIconValue(const PropertySheetPixmapValue &pixmap); PropertySheetIconValue(); + ~PropertySheetIconValue(); + PropertySheetIconValue(const PropertySheetIconValue &); + PropertySheetIconValue &operator=(const PropertySheetIconValue &); bool operator==(const PropertySheetIconValue &other) const { return equals(other); } bool operator!=(const PropertySheetIconValue &other) const { return !equals(other); } bool operator<(const PropertySheetIconValue &other) const; + bool isEmpty() const; + + QString theme() const; + void setTheme(const QString &); + PropertySheetPixmapValue pixmap(QIcon::Mode mode, QIcon::State state) const; void setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &path); // passing the empty path resets the pixmap @@ -269,17 +282,22 @@ class QDESIGNER_SHARED_EXPORT PropertySheetIconValue uint compare(const PropertySheetIconValue &other) const; void assign(const PropertySheetIconValue &other, uint mask); + // Convenience accessors to get themed/unthemed icons. + PropertySheetIconValue themed() const; + PropertySheetIconValue unthemed() const; + typedef QPair<QIcon::Mode, QIcon::State> ModeStateKey; typedef QMap<ModeStateKey, PropertySheetPixmapValue> ModeStateToPixmapMap; - ModeStateToPixmapMap paths() const; + const ModeStateToPixmapMap &paths() const; private: bool equals(const PropertySheetIconValue &rhs) const; - - ModeStateToPixmapMap m_paths; + QSharedDataPointer<PropertySheetIconValueData> m_data; }; +QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug, const PropertySheetIconValue &); + class QDESIGNER_SHARED_EXPORT DesignerPixmapCache : public QObject { Q_OBJECT @@ -432,15 +450,15 @@ namespace Utils { inline int valueOf(const QVariant &value, bool *ok = 0) { - if (qVariantCanConvert<PropertySheetEnumValue>(value)) { + if (value.canConvert<PropertySheetEnumValue>()) { if (ok) *ok = true; - return qVariantValue<PropertySheetEnumValue>(value).value; + return qvariant_cast<PropertySheetEnumValue>(value).value; } - else if (qVariantCanConvert<PropertySheetFlagValue>(value)) { + else if (value.canConvert<PropertySheetFlagValue>()) { if (ok) *ok = true; - return qVariantValue<PropertySheetFlagValue>(value).value; + return qvariant_cast<PropertySheetFlagValue>(value).value; } return value.toInt(ok); } diff --git a/tools/designer/src/lib/shared/qlayout_widget.cpp b/tools/designer/src/lib/shared/qlayout_widget.cpp index 997a945..f9f5213 100644 --- a/tools/designer/src/lib/shared/qlayout_widget.cpp +++ b/tools/designer/src/lib/shared/qlayout_widget.cpp @@ -601,7 +601,7 @@ QRect LayoutHelper::itemInfo(QLayout *lt, const QWidget *widget) const } } - // Grid Layout state. Datatypically store the state of a GridLayout as a map of + // Grid Layout state. Datatype storing the state of a GridLayout as a map of // widgets to QRect(columns, rows) and size. Used to store the state for undo operations // that do not change the widgets within the layout; also provides some manipulation // functions and ability to apply the state to a layout provided its widgets haven't changed. @@ -634,7 +634,11 @@ QRect LayoutHelper::itemInfo(QLayout *lt, const QWidget *widget) const static CellStates cellStates(const QList<QRect> &rects, int numRows, int numColumns); typedef QMap<QWidget *, QRect> WidgetItemMap; + typedef QMap<QWidget *, Qt::Alignment> WidgetAlignmentMap; + WidgetItemMap widgetItemMap; + WidgetAlignmentMap widgetAlignmentMap; + int rowCount; int colCount; }; @@ -706,8 +710,11 @@ QRect LayoutHelper::itemInfo(QLayout *lt, const QWidget *widget) const const int count = l->count(); for (int i = 0; i < count; i++) { QLayoutItem *item = l->itemAt(i); - if (!LayoutInfo::isEmptyItem(item)) + if (!LayoutInfo::isEmptyItem(item)) { widgetItemMap.insert(item->widget(), gridItemInfo(l, i)); + if (item->alignment()) + widgetAlignmentMap.insert(item->widget(), item->alignment()); + } } } @@ -743,7 +750,8 @@ QRect LayoutHelper::itemInfo(QLayout *lt, const QWidget *widget) const const LayoutItemRectMap::const_iterator icend = itemMap.constEnd(); for (LayoutItemRectMap::const_iterator it = itemMap.constBegin(); it != icend; ++it) { const QRect info = it.value(); - grid->addItem(it.key(), info.y(), info.x(), info.height(), info.width()); + const Qt::Alignment alignment = widgetAlignmentMap.value(it.key()->widget(), Qt::Alignment(0)); + grid->addItem(it.key(), info.y(), info.x(), info.height(), info.width(), alignment); } // create spacers const CellStates cs = cellStates(itemMap.values(), rowCount, colCount); diff --git a/tools/designer/src/lib/shared/qtresourcemodel.cpp b/tools/designer/src/lib/shared/qtresourcemodel.cpp index 2fa39ed..599223b 100644 --- a/tools/designer/src/lib/shared/qtresourcemodel.cpp +++ b/tools/designer/src/lib/shared/qtresourcemodel.cpp @@ -184,15 +184,15 @@ const QByteArray *QtResourceModelPrivate::createResource(const QString &path, QS break; // return code cannot be fully trusted, might still be empty const ResourceDataFileMap resMap = library.resourceDataFileMap(); - if (resMap.empty()) - break; - if (!library.output(buffer, errorDevice)) break; *errorCount = library.failedResources().size(); *contents = resMap.keys(); + if (resMap.empty()) + break; + buffer.close(); rc = new QByteArray(buffer.data()); } while (false); @@ -225,15 +225,18 @@ void QtResourceModelPrivate::registerResourceSet(QtResourceSet *resourceSet) qDebug() << "registerResourceSet " << path; const PathDataMap::const_iterator itRcc = m_pathToData.constFind(path); if (itRcc != m_pathToData.constEnd()) { // otherwise data was not created yet - if (!QResource::registerResource(reinterpret_cast<const uchar *>(itRcc.value()->constData()))) { - qDebug() << "** WARNING: Failed to register " << path << " (QResource failure)."; - } else { - QStringList contents = m_pathToContents.value(path); - QStringListIterator itContents(contents); - while (itContents.hasNext()) { - const QString filePath = itContents.next(); - if (!m_fileToQrc.contains(filePath)) // the first loaded resource has higher priority in qt resource system - m_fileToQrc.insert(filePath, path); + const QByteArray *data = itRcc.value(); + if (data) { + if (!QResource::registerResource(reinterpret_cast<const uchar *>(data->constData()))) { + qWarning() << "** WARNING: Failed to register " << path << " (QResource failure)."; + } else { + QStringList contents = m_pathToContents.value(path); + QStringListIterator itContents(contents); + while (itContents.hasNext()) { + const QString filePath = itContents.next(); + if (!m_fileToQrc.contains(filePath)) // the first loaded resource has higher priority in qt resource system + m_fileToQrc.insert(filePath, path); + } } } } @@ -254,8 +257,11 @@ void QtResourceModelPrivate::unregisterResourceSet(QtResourceSet *resourceSet) qDebug() << "unregisterResourceSet " << path; const PathDataMap::const_iterator itRcc = m_pathToData.constFind(path); if (itRcc != m_pathToData.constEnd()) { // otherwise data was not created yet - if (!QResource::unregisterResource(reinterpret_cast<const uchar *>(itRcc.value()->constData()))) - qDebug() << "** WARNING: Failed to unregister " << path << " (QResource failure)."; + const QByteArray *data = itRcc.value(); + if (data) { + if (!QResource::unregisterResource(reinterpret_cast<const uchar *>(itRcc.value()->constData()))) + qWarning() << "** WARNING: Failed to unregister " << path << " (QResource failure)."; + } } } m_fileToQrc.clear(); @@ -292,15 +298,13 @@ void QtResourceModelPrivate::activate(QtResourceSet *resourceSet, const QStringL QStringList contents; int qrcErrorCount; generatedCount++; - if (const QByteArray *data = createResource(path, &contents, &qrcErrorCount, errorStream)) { - newPathToData.insert(path, data); - if (qrcErrorCount) // Count single failed files as sort of 1/2 error - errorCount++; - addWatcher(path); - } else { - newPathToData.remove(path); + const QByteArray *data = createResource(path, &contents, &qrcErrorCount, errorStream); + + newPathToData.insert(path, data); + if (qrcErrorCount) // Count single failed files as sort of 1/2 error errorCount++; - } + addWatcher(path); + m_pathToModified.insert(path, false); m_pathToContents.insert(path, contents); newResourceSetChanged = true; @@ -326,7 +330,7 @@ void QtResourceModelPrivate::activate(QtResourceSet *resourceSet, const QStringL QListIterator<const QByteArray *> itOld(oldData); if (itOld.hasNext()) { const QByteArray *array = itOld.next(); - if (!newData.contains(array)) + if (array && !newData.contains(array)) toDelete.append(array); } diff --git a/tools/designer/src/lib/shared/richtexteditor.cpp b/tools/designer/src/lib/shared/richtexteditor.cpp index 6fc9a5a..2f73535 100644 --- a/tools/designer/src/lib/shared/richtexteditor.cpp +++ b/tools/designer/src/lib/shared/richtexteditor.cpp @@ -52,6 +52,9 @@ #include <QtCore/QList> #include <QtCore/QMap> #include <QtCore/QPointer> +#include <QtCore/QXmlStreamReader> +#include <QtCore/QXmlStreamWriter> +#include <QtCore/QXmlStreamAttributes> #include <QtGui/QAction> #include <QtGui/QColorDialog> @@ -74,28 +77,129 @@ QT_BEGIN_NAMESPACE -static const char *RichTextDialogC = "RichTextDialog"; -static const char *Geometry = "Geometry"; +static const char RichTextDialogGroupC[] = "RichTextDialog"; +static const char GeometryKeyC[] = "Geometry"; +static const char TabKeyC[] = "Tab"; + +const bool simplifyRichTextDefault = true; namespace qdesigner_internal { +// Richtext simplification filter helpers: Elements to be discarded +static inline bool filterElement(const QStringRef &name) +{ + return name != QLatin1String("meta") && name != QLatin1String("style"); +} + +// Richtext simplification filter helpers: Filter attributes of elements +static inline void filterAttributes(const QStringRef &name, + QXmlStreamAttributes *atts, + bool *paragraphAlignmentFound) +{ + typedef QXmlStreamAttributes::iterator AttributeIt; + + if (atts->isEmpty()) + return; + + // No style attributes for <body> + if (name == QLatin1String("body")) { + atts->clear(); + return; + } + + // Clean out everything except 'align' for 'p' + if (name == QLatin1String("p")) { + for (AttributeIt it = atts->begin(); it != atts->end(); ) { + if (it->name() == QLatin1String("align")) { + ++it; + *paragraphAlignmentFound = true; + } else { + it = atts->erase(it); + } + } + return; + } +} + +// Richtext simplification filter helpers: Check for blank QStringRef. +static inline bool isWhiteSpace(const QStringRef &in) +{ + const int count = in.size(); + for (int i = 0; i < count; i++) + if (!in.at(i).isSpace()) + return false; + return true; +} + +// Richtext simplification filter: Remove hard-coded font settings, +// <style> elements, <p> attributes other than 'align' and +// and unnecessary meta-information. +QString simplifyRichTextFilter(const QString &in, bool *isPlainTextPtr = 0) +{ + unsigned elementCount = 0; + bool paragraphAlignmentFound = false; + QString out; + QXmlStreamReader reader(in); + QXmlStreamWriter writer(&out); + writer.setAutoFormatting(false); + writer.setAutoFormattingIndent(0); + + while (!reader.atEnd()) { + switch (reader.readNext()) { + case QXmlStreamReader::StartElement: + elementCount++; + if (filterElement(reader.name())) { + const QStringRef name = reader.name(); + QXmlStreamAttributes attributes = reader.attributes(); + filterAttributes(name, &attributes, ¶graphAlignmentFound); + writer.writeStartElement(name.toString()); + if (!attributes.isEmpty()) + writer.writeAttributes(attributes); + } else { + reader.readElementText(); // Skip away all nested elements and characters. + } + break; + case QXmlStreamReader::Characters: + if (!isWhiteSpace(reader.text())) + writer.writeCharacters(reader.text().toString()); + break; + case QXmlStreamReader::EndElement: + writer.writeEndElement(); + break; + default: + break; + } + } + // Check for plain text (no spans, just <html><head><body><p>) + if (isPlainTextPtr) + *isPlainTextPtr = !paragraphAlignmentFound && elementCount == 4u; // + return out; +} + class RichTextEditor : public QTextEdit { Q_OBJECT public: - RichTextEditor(QWidget *parent = 0); - void setDefaultFont(const QFont &font); + explicit RichTextEditor(QWidget *parent = 0); + void setDefaultFont(QFont font); QToolBar *createToolBar(QDesignerFormEditorInterface *core, QWidget *parent = 0); + bool simplifyRichText() const { return m_simplifyRichText; } + public slots: void setFontBold(bool b); void setFontPointSize(double); void setText(const QString &text); + void setSimplifyRichText(bool v); QString text(Qt::TextFormat format) const; signals: void stateChanged(); + void simplifyRichTextChanged(bool); + +private: + bool m_simplifyRichText; }; class AddLinkDialog : public QDialog @@ -303,6 +407,7 @@ private: QAction *m_align_justify_action; QAction *m_link_action; QAction *m_image_action; + QAction *m_simplify_richtext_action; ColorAction *m_color_action; QComboBox *m_font_size_input; @@ -432,6 +537,17 @@ RichTextEditorToolBar::RichTextEditorToolBar(QDesignerFormEditorInterface *core, this, SLOT(colorChanged(QColor))); addAction(m_color_action); + addSeparator(); + + // Simplify rich text + m_simplify_richtext_action + = createCheckableAction(createIconSet(QLatin1String("simplifyrichtext.png")), + tr("Simplify Rich Text"), m_editor, SLOT(setSimplifyRichText(bool))); + m_simplify_richtext_action->setChecked(m_editor->simplifyRichText()); + connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)), + m_simplify_richtext_action, SLOT(setChecked(bool))); + addAction(m_simplify_richtext_action); + connect(editor, SIGNAL(textChanged()), this, SLOT(updateActions())); connect(editor, SIGNAL(stateChanged()), this, SLOT(updateActions())); @@ -551,7 +667,7 @@ void RichTextEditorToolBar::updateActions() } RichTextEditor::RichTextEditor(QWidget *parent) - : QTextEdit(parent) + : QTextEdit(parent), m_simplifyRichText(simplifyRichTextDefault) { connect(this, SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, SIGNAL(stateChanged())); @@ -579,14 +695,31 @@ void RichTextEditor::setFontPointSize(double d) void RichTextEditor::setText(const QString &text) { + if (Qt::mightBeRichText(text)) setHtml(text); else setPlainText(text); } -void RichTextEditor::setDefaultFont(const QFont &font) +void RichTextEditor::setSimplifyRichText(bool v) { + if (v != m_simplifyRichText) { + m_simplifyRichText = v; + emit simplifyRichTextChanged(v); + } +} + +void RichTextEditor::setDefaultFont(QFont font) +{ + // Some default fonts on Windows have a default size of 7.8, + // which results in complicated rich text generated by toHtml(). + // Use an integer value. + const int pointSize = qRound(font.pointSizeF()); + if (pointSize > 0 && !qFuzzyCompare(qreal(pointSize), font.pointSizeF())) { + font.setPointSize(pointSize); + } + document()->setDefaultFont(font); if (font.pointSize() > 0) setFontPointSize(font.pointSize()); @@ -602,15 +735,16 @@ QString RichTextEditor::text(Qt::TextFormat format) const case Qt::PlainText: return toPlainText(); case Qt::RichText: - return toHtml(); + return m_simplifyRichText ? simplifyRichTextFilter(toHtml()) : toHtml(); case Qt::AutoText: break; } const QString html = toHtml(); - const QString plain = toPlainText(); - QTextEdit tester; - tester.setPlainText(plain); - return tester.toHtml() == html ? plain : html; + bool isPlainText; + const QString simplifiedHtml = simplifyRichTextFilter(html, &isPlainText); + if (isPlainText) + return toPlainText(); + return m_simplifyRichText ? simplifiedHtml : html; } RichTextEditorDialog::RichTextEditorDialog(QDesignerFormEditorInterface *core, QWidget *parent) : @@ -619,15 +753,25 @@ RichTextEditorDialog::RichTextEditorDialog(QDesignerFormEditorInterface *core, Q m_text_edit(new HtmlTextEdit), m_tab_widget(new QTabWidget), m_state(Clean), - m_core(core) + m_core(core), + m_initialTab(RichTextIndex) { setWindowTitle(tr("Edit text")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + // Read settings + const QDesignerSettingsInterface *settings = core->settingsManager(); + const QString rootKey = QLatin1String(RichTextDialogGroupC) + QLatin1Char('/'); + const QByteArray lastGeometry = settings->value(rootKey + QLatin1String(GeometryKeyC)).toByteArray(); + const int initialTab = settings->value(rootKey + QLatin1String(TabKeyC), QVariant(m_initialTab)).toInt(); + if (initialTab == RichTextIndex || initialTab == SourceIndex) + m_initialTab = initialTab; + m_text_edit->setAcceptRichText(false); new HtmlHighlighter(m_text_edit); connect(m_editor, SIGNAL(textChanged()), this, SLOT(richTextChanged())); + connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)), this, SLOT(richTextChanged())); connect(m_text_edit, SIGNAL(textChanged()), this, SLOT(sourceChanged())); // The toolbar needs to be created after the RichTextEditor @@ -661,32 +805,33 @@ RichTextEditorDialog::RichTextEditorDialog(QDesignerFormEditorInterface *core, Q layout->addWidget(m_tab_widget); layout->addWidget(buttonBox); - m_editor->setFocus(); - - QDesignerSettingsInterface *settings = core->settingsManager(); - settings->beginGroup(QLatin1String(RichTextDialogC)); - - if (settings->contains(QLatin1String(Geometry))) - restoreGeometry(settings->value(QLatin1String(Geometry)).toByteArray()); - - settings->endGroup(); + if (!lastGeometry.isEmpty()) + restoreGeometry(lastGeometry); } RichTextEditorDialog::~RichTextEditorDialog() { QDesignerSettingsInterface *settings = m_core->settingsManager(); - settings->beginGroup(QLatin1String(RichTextDialogC)); + settings->beginGroup(QLatin1String(RichTextDialogGroupC)); - settings->setValue(QLatin1String(Geometry), saveGeometry()); + settings->setValue(QLatin1String(GeometryKeyC), saveGeometry()); + settings->setValue(QLatin1String(TabKeyC), m_tab_widget->currentIndex()); settings->endGroup(); } int RichTextEditorDialog::showDialog() { - m_tab_widget->setCurrentIndex(0); - m_editor->selectAll(); - m_editor->setFocus(); - + m_tab_widget->setCurrentIndex(m_initialTab); + switch (m_initialTab) { + case RichTextIndex: + m_editor->selectAll(); + m_editor->setFocus(); + break; + case SourceIndex: + m_text_edit->selectAll(); + m_text_edit->setFocus(); + break; + } return exec(); } @@ -697,6 +842,9 @@ void RichTextEditorDialog::setDefaultFont(const QFont &font) void RichTextEditorDialog::setText(const QString &text) { + // Generally simplify rich text unless verbose text is found. + const bool isSimplifiedRichText = !text.startsWith("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">"); + m_editor->setSimplifyRichText(isSimplifiedRichText); m_editor->setText(text); m_text_edit->setPlainText(text); m_state = Clean; diff --git a/tools/designer/src/lib/shared/richtexteditor_p.h b/tools/designer/src/lib/shared/richtexteditor_p.h index cf995fa..b6343eb 100644 --- a/tools/designer/src/lib/shared/richtexteditor_p.h +++ b/tools/designer/src/lib/shared/richtexteditor_p.h @@ -93,6 +93,7 @@ private: QTabWidget *m_tab_widget; State m_state; QDesignerFormEditorInterface *m_core; + int m_initialTab; }; } // namespace qdesigner_internal diff --git a/tools/designer/src/lib/shared/shared.pri b/tools/designer/src/lib/shared/shared.pri index 8286360..9d50911 100644 --- a/tools/designer/src/lib/shared/shared.pri +++ b/tools/designer/src/lib/shared/shared.pri @@ -2,7 +2,7 @@ INCLUDEPATH += $$PWD contains(QT_CONFIG, script): QT += script -include(../../../../shared/qtpropertybrowser/qtpropertybrowser.pri) +include(../../../../shared/qtpropertybrowser/qtpropertybrowserutils.pri) include(../../../../shared/deviceskin/deviceskin.pri) include(../../../../../src/tools/rcc/rcc.pri) include(../../../../shared/findwidget/findwidget.pri) diff --git a/tools/designer/src/lib/shared/stylesheeteditor.cpp b/tools/designer/src/lib/shared/stylesheeteditor.cpp index 83456b7..826f5cc 100644 --- a/tools/designer/src/lib/shared/stylesheeteditor.cpp +++ b/tools/designer/src/lib/shared/stylesheeteditor.cpp @@ -394,14 +394,14 @@ StyleSheetPropertyEditorDialog::StyleSheetPropertyEditorDialog(QWidget *parent, qt_extension<QDesignerPropertySheetExtension*>(m_fw->core()->extensionManager(), m_widget); Q_ASSERT(sheet != 0); const int index = sheet->indexOf(QLatin1String(styleSheetProperty)); - const PropertySheetStringValue value = qVariantValue<PropertySheetStringValue>(sheet->property(index)); + const PropertySheetStringValue value = qvariant_cast<PropertySheetStringValue>(sheet->property(index)); setText(value.value()); } void StyleSheetPropertyEditorDialog::applyStyleSheet() { const PropertySheetStringValue value(text(), false); - m_fw->cursor()->setWidgetProperty(m_widget, QLatin1String(styleSheetProperty), qVariantFromValue(value)); + m_fw->cursor()->setWidgetProperty(m_widget, QLatin1String(styleSheetProperty), QVariant::fromValue(value)); } } // namespace qdesigner_internal diff --git a/tools/designer/src/lib/shared/widgetdatabase.cpp b/tools/designer/src/lib/shared/widgetdatabase.cpp index 4d73256..4679743 100644 --- a/tools/designer/src/lib/shared/widgetdatabase.cpp +++ b/tools/designer/src/lib/shared/widgetdatabase.cpp @@ -54,7 +54,8 @@ #include <QtDesigner/QDesignerFormEditorInterface> #include <QtXml/QXmlStreamWriter> -#include <QtCore/QtAlgorithms> + +#include <QtCore/QScopedPointer> #include <QtCore/qdebug.h> #include <QtCore/QMetaProperty> #include <QtCore/QTextStream> @@ -565,10 +566,10 @@ static QString xmlFromWidgetBox(const QDesignerFormEditorInterface *core, const const bool found = QDesignerWidgetBox::findWidget(core->widgetBox(), className, QString(), &widget); if (!found) return QString(); - DomUI *domUI = QDesignerWidgetBox::xmlToUi(className, widget.domXml(), false); - domUI->setAttributeVersion(QLatin1String("4.0")); - if (!domUI) + QScopedPointer<DomUI> domUI(QDesignerWidgetBox::xmlToUi(className, widget.domXml(), false)); + if (domUI.isNull()) return QString(); + domUI->setAttributeVersion(QLatin1String("4.0")); DomWidget *domWidget = domUI->elementWidget(); if (!domWidget) return QString(); @@ -615,7 +616,6 @@ static QString xmlFromWidgetBox(const QDesignerFormEditorInterface *core, const domUI->write(writer); writer.writeEndDocument(); } - delete domUI; return rc; } diff --git a/tools/designer/src/lib/shared/widgetfactory.cpp b/tools/designer/src/lib/shared/widgetfactory.cpp index 51c7c7a..2d8471e 100644 --- a/tools/designer/src/lib/shared/widgetfactory.cpp +++ b/tools/designer/src/lib/shared/widgetfactory.cpp @@ -784,7 +784,7 @@ void WidgetFactory::applyStyleToTopLevel(QStyle *style, QWidget *widget) widget->setStyle(style); widget->setPalette(standardPalette); - const QWidgetList lst = qFindChildren<QWidget*>(widget); + const QWidgetList lst = widget->findChildren<QWidget*>(); const QWidgetList::const_iterator cend = lst.constEnd(); for (QWidgetList::const_iterator it = lst.constBegin(); it != cend; ++it) (*it)->setStyle(style); diff --git a/tools/designer/src/lib/shared/zoomwidget.cpp b/tools/designer/src/lib/shared/zoomwidget.cpp index 78825d8..13e1e68 100644 --- a/tools/designer/src/lib/shared/zoomwidget.cpp +++ b/tools/designer/src/lib/shared/zoomwidget.cpp @@ -328,7 +328,7 @@ void ZoomWidget::setWidget(QWidget *w, Qt::WindowFlags wFlags) scene().removeItem(m_proxy); if (QWidget *w = m_proxy->widget()) { // remove the event filter - if (QObject *evf = qFindChild<QObject*>(w, QLatin1String(zoomedEventFilterRedirectorNameC))) + if (QObject *evf = w->findChild<QObject*>(QLatin1String(zoomedEventFilterRedirectorNameC))) w->removeEventFilter(evf); } m_proxy->deleteLater(); diff --git a/tools/designer/src/lib/uilib/abstractformbuilder.cpp b/tools/designer/src/lib/uilib/abstractformbuilder.cpp index 1abe4f2..81f1a3b 100644 --- a/tools/designer/src/lib/uilib/abstractformbuilder.cpp +++ b/tools/designer/src/lib/uilib/abstractformbuilder.cpp @@ -341,7 +341,7 @@ QWidget *QAbstractFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidge w->addAction(a); } else if (QActionGroup *g = m_actionGroups.value(name)) { w->addActions(g->actions()); - } else if (QMenu *menu = qFindChild<QMenu*>(w, name)) { + } else if (QMenu *menu = w->findChild<QMenu*>(name)) { w->addAction(menu->menuAction()); addMenuAction(menu->menuAction()); } @@ -363,9 +363,9 @@ QWidget *QAbstractFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidge const QStringList zOrderNames = ui_widget->elementZOrder(); if (!zOrderNames.isEmpty()) { - QList<QWidget *> zOrder = qVariantValue<QWidgetList>(w->property("_q_zOrder")); + QList<QWidget *> zOrder = qvariant_cast<QWidgetList>(w->property("_q_zOrder")); foreach (const QString &widgetName, zOrderNames) { - if (QWidget *child = qFindChild<QWidget*>(w, widgetName)) { + if (QWidget *child = w->findChild<QWidget*>(widgetName)) { if (child->parentWidget() == w) { zOrder.removeAll(child); zOrder.append(child); @@ -373,7 +373,7 @@ QWidget *QAbstractFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidge } } } - w->setProperty("_q_zOrder", qVariantFromValue(zOrder)); + w->setProperty("_q_zOrder", QVariant::fromValue(zOrder)); } return w; @@ -794,6 +794,69 @@ static inline QFormLayout::ItemRole formLayoutRole(int column, int colspan) } #endif +static inline QString alignmentValue(Qt::Alignment a) +{ + QString h,v; + switch (a & Qt::AlignHorizontal_Mask) { + case Qt::AlignLeft: + h = QLatin1String("Qt::AlignLeft"); + break; + case Qt::AlignRight: + h = QLatin1String("Qt::AlignRight"); + break; + case Qt::AlignHCenter: + h = QLatin1String("Qt::AlignHCenter"); + break; + case Qt::AlignJustify: + h = QLatin1String("Qt::AlignJustify"); + break; + } + switch (a & Qt::AlignVertical_Mask) { + case Qt::AlignTop: + v = QLatin1String("Qt::AlignTop"); + break; + case Qt::AlignBottom: + v = QLatin1String("Qt::AlignBottom"); + break; + case Qt::AlignVCenter: + v = QLatin1String("Qt::AlignVCenter"); + break; + } + if (h.isEmpty() && v.isEmpty()) + return QString(); + if (!v.isEmpty()) { + if (!h.isEmpty()) + h += QLatin1Char('|'); + h += v; + } + return h; +} + +static inline Qt::Alignment alignmentFromDom(const QString &in) +{ + Qt::Alignment rc = 0; + if (!in.isEmpty()) { + foreach (const QString &f, in.split(QLatin1Char('|'))) { + if (f == QLatin1String("Qt::AlignLeft")) { + rc |= Qt::AlignLeft; + } else if (f == QLatin1String("Qt::AlignRight")) { + rc |= Qt::AlignRight; + } else if (f == QLatin1String("Qt::AlignHCenter")) { + rc |= Qt::AlignHCenter; + } else if (f == QLatin1String("Qt::AlignJustify")) { + rc |= Qt::AlignJustify; + } else if (f == QLatin1String("Qt::AlignTop")) { + rc |= Qt::AlignTop; + } else if (f == QLatin1String("Qt::AlignBottom")) { + rc |= Qt::AlignBottom; + } else if (f == QLatin1String("Qt::AlignVCenter")) { + rc |= Qt::AlignVCenter; + } + } + } + return rc; +} + /*! \internal */ @@ -838,12 +901,15 @@ QLayoutItem *QAbstractFormBuilder::create(DomLayoutItem *ui_layoutItem, QLayout { switch (ui_layoutItem->kind()) { case DomLayoutItem::Widget: { - if (QWidget *w = create(ui_layoutItem->elementWidget(), parentWidget)) + if (QWidget *w = create(ui_layoutItem->elementWidget(), parentWidget)) { #ifdef QFORMINTERNAL_NAMESPACE // uilib - return new QWidgetItemV2(w); + QWidgetItem *item = new QWidgetItemV2(w); #else // Within Designer: Use factory method that returns special items that refuse to shrink to 0,0 - return QLayoutPrivate::createWidgetItem(layout, w); + QWidgetItem *item = QLayoutPrivate::createWidgetItem(layout, w); #endif + item->setAlignment(alignmentFromDom(ui_layoutItem->attributeAlignment())); + return item; + } qWarning() << QCoreApplication::translate("QAbstractFormBuilder", "Empty widget item in %1 '%2'.").arg(QString::fromUtf8(layout->metaObject()->className()), layout->objectName()); return 0; } @@ -1287,7 +1353,7 @@ DomWidget *QAbstractFormBuilder::createDom(QWidget *widget, DomWidget *ui_parent { QList<QObject *> childObjects = widget->children(); - const QList<QWidget *> list = qVariantValue<QWidgetList>(widget->property("_q_widgetOrder")); + const QList<QWidget *> list = qvariant_cast<QWidgetList>(widget->property("_q_widgetOrder")); foreach (QWidget *w, list) { if (childObjects.contains(w)) { children.append(w); @@ -1296,7 +1362,7 @@ DomWidget *QAbstractFormBuilder::createDom(QWidget *widget, DomWidget *ui_parent } children += childObjects; - const QList<QWidget *> zOrder = qVariantValue<QWidgetList>(widget->property("_q_zOrder")); + const QList<QWidget *> zOrder = qvariant_cast<QWidgetList>(widget->property("_q_zOrder")); if (list != zOrder) { QStringList zOrderList; QListIterator<QWidget* > itZOrder(zOrder); @@ -1381,9 +1447,87 @@ DomActionRef *QAbstractFormBuilder::createActionRefDom(QAction *action) return ui_action_ref; } +// Struct to store layout item parameters for saving layout items +struct FormBuilderSaveLayoutEntry { + explicit FormBuilderSaveLayoutEntry(QLayoutItem *li = 0) : + item(li), row(-1), column(-1), rowSpan(0), columnSpan(0), alignment(0) {} + + QLayoutItem *item; + int row; + int column; + int rowSpan; + int columnSpan; + Qt::Alignment alignment; +}; + +// Create list from standard box layout +static QList<FormBuilderSaveLayoutEntry> saveLayoutEntries(const QLayout *layout) +{ + QList<FormBuilderSaveLayoutEntry> rc; + if (const int count = layout->count()) { + rc.reserve(count); + for (int idx = 0; idx < count; ++idx) { + QLayoutItem *item = layout->itemAt(idx); + FormBuilderSaveLayoutEntry entry(item); + entry.alignment = item->alignment(); + rc.append(entry); + } + } + return rc; +} + +// Create list from grid layout +static QList<FormBuilderSaveLayoutEntry> saveGridLayoutEntries(QGridLayout *gridLayout) +{ + QList<FormBuilderSaveLayoutEntry> rc; + if (const int count = gridLayout->count()) { + rc.reserve(count); + for (int idx = 0; idx < count; ++idx) { + QLayoutItem *item = gridLayout->itemAt(idx); + FormBuilderSaveLayoutEntry entry(item); + gridLayout->getItemPosition(idx, &entry.row, &entry.column, &entry.rowSpan,&entry.columnSpan); + entry.alignment = item->alignment(); + rc.append(entry); + } + } + return rc; +} + +#ifndef QT_NO_FORMLAYOUT +// Create list from form layout +static QList<FormBuilderSaveLayoutEntry> saveFormLayoutEntries(const QFormLayout *formLayout) +{ + QList<FormBuilderSaveLayoutEntry> rc; + if (const int count = formLayout->count()) { + rc.reserve(count); + for (int idx = 0; idx < count; ++idx) { + QLayoutItem *item = formLayout->itemAt(idx); + QFormLayout::ItemRole role = QFormLayout::LabelRole; + FormBuilderSaveLayoutEntry entry(item); + formLayout->getItemPosition(idx, &entry.row, &role); + switch (role ) { + case QFormLayout::LabelRole: + entry.column = 0; + break; + case QFormLayout::FieldRole: + entry.column = 1; + break; + case QFormLayout::SpanningRole: + entry.column = 0; + entry.columnSpan = 2; + break; + } + rc.push_back(entry); + } + } + return rc; +} +#endif + /*! \internal */ + DomLayout *QAbstractFormBuilder::createDom(QLayout *layout, DomLayout *ui_layout, DomWidget *ui_parentWidget) { Q_UNUSED(ui_layout) @@ -1394,37 +1538,32 @@ DomLayout *QAbstractFormBuilder::createDom(QLayout *layout, DomLayout *ui_layout lay->setAttributeName(objectName); lay->setElementProperty(computeProperties(layout)); - QList<DomLayoutItem*> ui_items; - - QMap<QObject *, QLayoutItem *> objectToItem; - QList<QLayoutItem *> spacerItems; - QList<QLayoutItem *> newList; - - for (int idx=0; layout->itemAt(idx); ++idx) { - QLayoutItem *item = layout->itemAt(idx); - if (item->widget()) - objectToItem[item->widget()] = item; - else if (item->layout()) - objectToItem[item->layout()] = item; - else if (item->spacerItem()) - spacerItems.append(item); - newList.append(item); - } - - if (qobject_cast<QGridLayout *>(layout)) { - newList.clear(); - QList<QObject *> childrenList = layout->parentWidget()->children(); - foreach (QObject *o, childrenList) { - if (objectToItem.contains(o)) - newList.append(objectToItem[o]); - } - newList += spacerItems; + QList<FormBuilderSaveLayoutEntry> newList; + if (QGridLayout *gridLayout = qobject_cast<QGridLayout *>(layout)) { + newList = saveGridLayoutEntries(gridLayout); +#ifndef QT_NO_FORMLAYOUT + } else if (const QFormLayout *formLayout = qobject_cast<const QFormLayout *>(layout)) { + newList = saveFormLayoutEntries(formLayout); +#endif + } else { + newList = saveLayoutEntries(layout); } - foreach (QLayoutItem *item, newList) { - DomLayoutItem *ui_item = createDom(item, lay, ui_parentWidget); - if (ui_item) + QList<DomLayoutItem*> ui_items; + foreach (const FormBuilderSaveLayoutEntry &item, newList) { + if (DomLayoutItem *ui_item = createDom(item.item, lay, ui_parentWidget)) { + if (item.row >= 0) + ui_item->setAttributeRow(item.row); + if (item.column >= 0) + ui_item->setAttributeColumn(item.column); + if (item.rowSpan > 1) + ui_item->setAttributeRowSpan(item.rowSpan); + if (item.columnSpan > 1) + ui_item->setAttributeColSpan(item.columnSpan); + if (item.alignment) + ui_item->setAttributeAlignment(alignmentValue(item.alignment)); ui_items.append(ui_item); + } } lay->setElementItem(ui_items); @@ -1603,14 +1742,14 @@ void QAbstractFormBuilder::applyTabStops(QWidget *widget, DomTabStops *tabStops) for (int i=0; i<l.size(); ++i) { const QString name = l.at(i); - QWidget *child = qFindChild<QWidget*>(widget, name); + QWidget *child = widget->findChild<QWidget*>(name); if (!child) { uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "While applying tab stops: The widget '%1' could not be found.").arg(name)); continue; } if (i == 0) { - lastWidget = qFindChild<QWidget*>(widget, name); + lastWidget = widget->findChild<QWidget*>(name); continue; } else if (!child || !lastWidget) { continue; @@ -1618,7 +1757,7 @@ void QAbstractFormBuilder::applyTabStops(QWidget *widget, DomTabStops *tabStops) QWidget::setTabOrder(lastWidget, child); - lastWidget = qFindChild<QWidget*>(widget, name); + lastWidget = widget->findChild<QWidget*>(name); } } @@ -1747,7 +1886,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, T *item, if ((p = properties.value(it.second))) { v = formBuilder->textBuilder()->loadText(p); QVariant nativeValue = formBuilder->textBuilder()->toNativeValue(v); - item->setData(it.first.first, qVariantValue<QString>(nativeValue)); + item->setData(it.first.first, qvariant_cast<QString>(nativeValue)); item->setData(it.first.second, v); } @@ -1759,7 +1898,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, T *item, if ((p = properties.value(strings.iconAttribute))) { v = formBuilder->resourceBuilder()->loadResource(formBuilder->workingDirectory(), p); QVariant nativeValue = formBuilder->resourceBuilder()->toNativeValue(v); - item->setIcon(qVariantValue<QIcon>(nativeValue)); + item->setIcon(qvariant_cast<QIcon>(nativeValue)); item->setData(Qt::DecorationPropertyRole, v); } } @@ -1855,7 +1994,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, QTableWidge if ((p = properties.value(it.second))) { v = formBuilder->textBuilder()->loadText(p); QVariant nativeValue = formBuilder->textBuilder()->toNativeValue(v); - item->setData(it.first.first, qVariantValue<QString>(nativeValue)); + item->setData(it.first.first, qvariant_cast<QString>(nativeValue)); item->setData(it.first.second, v); } @@ -1867,7 +2006,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, QTableWidge if ((p = properties.value(strings.iconAttribute))) { v = formBuilder->resourceBuilder()->loadResource(formBuilder->workingDirectory(), p); QVariant nativeValue = formBuilder->resourceBuilder()->toNativeValue(v); - item->setIcon(qVariantValue<QIcon>(nativeValue)); + item->setIcon(qvariant_cast<QIcon>(nativeValue)); item->setData(Qt::DecorationPropertyRole, v); } } @@ -1885,7 +2024,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, QListWidget if ((p = properties.value(it.second))) { v = formBuilder->textBuilder()->loadText(p); QVariant nativeValue = formBuilder->textBuilder()->toNativeValue(v); - item->setData(it.first.first, qVariantValue<QString>(nativeValue)); + item->setData(it.first.first, qvariant_cast<QString>(nativeValue)); item->setData(it.first.second, v); } @@ -1897,7 +2036,7 @@ static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, QListWidget if ((p = properties.value(strings.iconAttribute))) { v = formBuilder->resourceBuilder()->loadResource(formBuilder->workingDirectory(), p); QVariant nativeValue = formBuilder->resourceBuilder()->toNativeValue(v); - item->setIcon(qVariantValue<QIcon>(nativeValue)); + item->setIcon(qvariant_cast<QIcon>(nativeValue)); item->setData(Qt::DecorationPropertyRole, v); } } @@ -2152,6 +2291,7 @@ void QAbstractFormBuilder::saveButtonExtraInfo(const QAbstractButton *widget, Do DomPropertyList attributes = ui_widget->elementAttribute(); DomString *domString = new DomString(); domString->setText(buttonGroup->objectName()); + domString->setAttributeNotr(QLatin1String("true")); DomProperty *domProperty = new DomProperty(); domProperty->setAttributeName(QLatin1String(buttonGroupPropertyC)); domProperty->setElementString(domString); @@ -2337,14 +2477,14 @@ void QAbstractFormBuilder::loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWi if ((p = properties.value(it.second))) { v = textBuilder()->loadText(p); QVariant nativeValue = textBuilder()->toNativeValue(v); - treeWidget->headerItem()->setData(i, it.first.first, qVariantValue<QString>(nativeValue)); + treeWidget->headerItem()->setData(i, it.first.first, qvariant_cast<QString>(nativeValue)); treeWidget->headerItem()->setData(i, it.first.second, v); } if ((p = properties.value(strings.iconAttribute))) { v = resourceBuilder()->loadResource(workingDirectory(), p); QVariant nativeValue = resourceBuilder()->toNativeValue(v); - treeWidget->headerItem()->setIcon(i, qVariantValue<QIcon>(nativeValue)); + treeWidget->headerItem()->setIcon(i, qvariant_cast<QIcon>(nativeValue)); treeWidget->headerItem()->setData(i, Qt::DecorationPropertyRole, v); } } @@ -2374,14 +2514,14 @@ void QAbstractFormBuilder::loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWi col++; QVariant textV = textBuilder()->loadText(property); QVariant nativeValue = textBuilder()->toNativeValue(textV); - currentItem->setText(col, qVariantValue<QString>(nativeValue)); + currentItem->setText(col, qvariant_cast<QString>(nativeValue)); currentItem->setData(col, Qt::DisplayPropertyRole, textV); } else if (col >= 0) { if (property->attributeName() == strings.iconAttribute) { QVariant v = resourceBuilder()->loadResource(workingDirectory(), property); if (v.isValid()) { QVariant nativeValue = resourceBuilder()->toNativeValue(v); - currentItem->setIcon(col, qVariantValue<QIcon>(nativeValue)); + currentItem->setIcon(col, qvariant_cast<QIcon>(nativeValue)); currentItem->setData(col, Qt::DecorationPropertyRole, v); } } else { @@ -2397,7 +2537,7 @@ void QAbstractFormBuilder::loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWi if (rolePair.first >= 0) { QVariant textV = textBuilder()->loadText(property); QVariant nativeValue = textBuilder()->toNativeValue(textV); - currentItem->setData(col, rolePair.first, qVariantValue<QString>(nativeValue)); + currentItem->setData(col, rolePair.first, qvariant_cast<QString>(nativeValue)); currentItem->setData(col, rolePair.second, textV); } } @@ -2475,13 +2615,13 @@ void QAbstractFormBuilder::loadComboBoxExtraInfo(DomWidget *ui_widget, QComboBox p = properties.value(strings.textAttribute); if (p && p->elementString()) { textData = textBuilder()->loadText(p); - text = qVariantValue<QString>(textBuilder()->toNativeValue(textData)); + text = qvariant_cast<QString>(textBuilder()->toNativeValue(textData)); } p = properties.value(strings.iconAttribute); if (p) { iconData = resourceBuilder()->loadResource(workingDirectory(), p); - icon = qVariantValue<QIcon>(resourceBuilder()->toNativeValue(iconData)); + icon = qvariant_cast<QIcon>(resourceBuilder()->toNativeValue(iconData)); } comboBox->addItem(icon, text); diff --git a/tools/designer/src/lib/uilib/formbuilder.cpp b/tools/designer/src/lib/uilib/formbuilder.cpp index de4f5bd..6622bbf 100644 --- a/tools/designer/src/lib/uilib/formbuilder.cpp +++ b/tools/designer/src/lib/uilib/formbuilder.cpp @@ -319,7 +319,7 @@ QWidget *QFormBuilder::widgetByName(QWidget *topLevel, const QString &name) if (topLevel->objectName() == name) return topLevel; - return qFindChild<QWidget*>(topLevel, name); + return topLevel->findChild<QWidget*>(name); } static QObject *objectByName(QWidget *topLevel, const QString &name) @@ -328,7 +328,7 @@ static QObject *objectByName(QWidget *topLevel, const QString &name) if (topLevel->objectName() == name) return topLevel; - return qFindChild<QObject*>(topLevel, name); + return topLevel->findChild<QObject*>(name); } /*! diff --git a/tools/designer/src/lib/uilib/formbuilderextra.cpp b/tools/designer/src/lib/uilib/formbuilderextra.cpp index 54df6a4..b36cecc 100644 --- a/tools/designer/src/lib/uilib/formbuilderextra.cpp +++ b/tools/designer/src/lib/uilib/formbuilderextra.cpp @@ -136,7 +136,7 @@ bool QFormBuilderExtra::applyBuddy(const QString &buddyName, BuddyMode applyMode return false; } - const QWidgetList widgets = qFindChildren<QWidget*>(label->topLevelWidget(), buddyName); + const QWidgetList widgets = label->topLevelWidget()->findChildren<QWidget*>(buddyName); if (widgets.empty()) { label->setBuddy(0); return false; diff --git a/tools/designer/src/lib/uilib/properties.cpp b/tools/designer/src/lib/uilib/properties.cpp index 4c1d369..ebec222 100644 --- a/tools/designer/src/lib/uilib/properties.cpp +++ b/tools/designer/src/lib/uilib/properties.cpp @@ -78,7 +78,7 @@ QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta, case DomProperty::String: { const int index = meta->indexOfProperty(p->attributeName().toUtf8()); if (index != -1 && meta->property(index).type() == QVariant::KeySequence) - return qVariantFromValue(QKeySequence(p->elementString()->text())); + return QVariant::fromValue(QKeySequence(p->elementString()->text())); } break; @@ -96,7 +96,7 @@ QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta, afb->setupColorGroup(palette, QPalette::Disabled, dom->elementDisabled()); palette.setCurrentColorGroup(QPalette::Active); - return qVariantFromValue(palette); + return QVariant::fromValue(palette); } case DomProperty::Set: { @@ -135,7 +135,7 @@ QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta, return QVariant(e.keyToValue(enumValue.toUtf8())); } case DomProperty::Brush: - return qVariantFromValue(afb->setupBrush(p->elementBrush())); + return QVariant::fromValue(afb->setupBrush(p->elementBrush())); default: if (afb->resourceBuilder()->isResourceProperty(p)) { return afb->resourceBuilder()->loadResource(afb->workingDirectory(), p); @@ -212,7 +212,7 @@ QVariant domPropertyToVariant(const DomProperty *p) case DomProperty::Char: { const DomChar *character = p->elementChar(); const QChar c(character->elementUnicode()); - return qVariantFromValue(c); + return QVariant::fromValue(c); } case DomProperty::Color: { @@ -220,7 +220,7 @@ QVariant domPropertyToVariant(const DomProperty *p) QColor c(color->elementRed(), color->elementGreen(), color->elementBlue()); if (color->hasAttributeAlpha()) c.setAlpha(color->attributeAlpha()); - return qVariantFromValue(c); + return QVariant::fromValue(c); } case DomProperty::Font: { @@ -248,7 +248,7 @@ QVariant domPropertyToVariant(const DomProperty *p) if (font->hasElementStyleStrategy()) { f.setStyleStrategy(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QFont::StyleStrategy>("styleStrategy", font->elementStyleStrategy().toLatin1())); } - return qVariantFromValue(f); + return QVariant::fromValue(f); } case DomProperty::Date: { @@ -275,15 +275,15 @@ QVariant domPropertyToVariant(const DomProperty *p) #ifndef QT_NO_CURSOR case DomProperty::Cursor: - return qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(p->elementCursor()))); + return QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(p->elementCursor()))); case DomProperty::CursorShape: - return qVariantFromValue(QCursor(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::CursorShape>("cursorShape", p->elementCursorShape().toLatin1()))); + return QVariant::fromValue(QCursor(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::CursorShape>("cursorShape", p->elementCursorShape().toLatin1()))); #endif case DomProperty::Locale: { const DomLocale *locale = p->elementLocale(); - return qVariantFromValue(QLocale(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Language>("language", locale->attributeLanguage().toLatin1()), + return QVariant::fromValue(QLocale(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Language>("language", locale->attributeLanguage().toLatin1()), enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Country>("country", locale->attributeCountry().toLatin1()))); } case DomProperty::SizePolicy: { @@ -309,7 +309,7 @@ QVariant domPropertyToVariant(const DomProperty *p) sizePolicy.setVerticalPolicy(sp); } - return qVariantFromValue(sizePolicy); + return QVariant::fromValue(sizePolicy); } case DomProperty::StringList: diff --git a/tools/designer/src/lib/uilib/resourcebuilder.cpp b/tools/designer/src/lib/uilib/resourcebuilder.cpp index 868c765..b24266e 100644 --- a/tools/designer/src/lib/uilib/resourcebuilder.cpp +++ b/tools/designer/src/lib/uilib/resourcebuilder.cpp @@ -44,6 +44,7 @@ #include <QtCore/QVariant> #include <QtCore/QFileInfo> #include <QtCore/QDir> +#include <QtCore/QDebug> #include <QtGui/QPixmap> #include <QtGui/QIcon> @@ -53,6 +54,8 @@ QT_BEGIN_NAMESPACE namespace QFormInternal { #endif +enum { themeDebug = 0 }; + QResourceBuilder::QResourceBuilder() { @@ -91,10 +94,18 @@ QVariant QResourceBuilder::loadResource(const QDir &workingDirectory, const DomP case DomProperty::Pixmap: { const DomResourcePixmap *dpx = property->elementPixmap(); QPixmap pixmap(QFileInfo(workingDirectory, dpx->text()).absoluteFilePath()); - return qVariantFromValue(pixmap); + return QVariant::fromValue(pixmap); } case DomProperty::IconSet: { const DomResourceIcon *dpi = property->elementIconSet(); + if (!dpi->attributeTheme().isEmpty()) { + const QString theme = dpi->attributeTheme(); + const bool known = QIcon::hasThemeIcon(theme); + if (themeDebug) + qDebug("Theme %s known %d", qPrintable(theme), known); + if (known) + return qVariantFromValue(QIcon::fromTheme(dpi->attributeTheme())); + } // non-empty theme if (const int flags = iconStateFlags(dpi)) { // new, post 4.4 format QIcon icon; if (flags & NormalOff) @@ -113,10 +124,10 @@ QVariant QResourceBuilder::loadResource(const QDir &workingDirectory, const DomP icon.addFile(QFileInfo(workingDirectory, dpi->elementSelectedOff()->text()).absoluteFilePath(), QSize(), QIcon::Selected, QIcon::Off); if (flags & SelectedOn) icon.addFile(QFileInfo(workingDirectory, dpi->elementSelectedOn()->text()).absoluteFilePath(), QSize(), QIcon::Selected, QIcon::On); - return qVariantFromValue(icon); + return QVariant::fromValue(icon); } else { // 4.3 legacy const QIcon icon(QFileInfo(workingDirectory, dpi->text()).absoluteFilePath()); - return qVariantFromValue(icon); + return QVariant::fromValue(icon); } } break; diff --git a/tools/designer/src/lib/uilib/ui4.cpp b/tools/designer/src/lib/uilib/ui4.cpp index b40b151..f34df3c 100644 --- a/tools/designer/src/lib/uilib/ui4.cpp +++ b/tools/designer/src/lib/uilib/ui4.cpp @@ -3673,6 +3673,7 @@ void DomLayoutItem::clear(bool clear_all) m_attr_rowSpan = 0; m_has_attr_colSpan = false; m_attr_colSpan = 0; + m_has_attr_alignment = false; } m_kind = Unknown; @@ -3694,6 +3695,7 @@ DomLayoutItem::DomLayoutItem() m_attr_rowSpan = 0; m_has_attr_colSpan = false; m_attr_colSpan = 0; + m_has_attr_alignment = false; m_widget = 0; m_layout = 0; m_spacer = 0; @@ -3727,6 +3729,10 @@ void DomLayoutItem::read(QXmlStreamReader &reader) setAttributeColSpan(attribute.value().toString().toInt()); continue; } + if (name == QLatin1String("alignment")) { + setAttributeAlignment(attribute.value().toString()); + continue; + } reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString()); } @@ -3779,6 +3785,8 @@ void DomLayoutItem::read(const QDomElement &node) setAttributeRowSpan(node.attribute(QLatin1String("rowspan")).toInt()); if (node.hasAttribute(QLatin1String("colspan"))) setAttributeColSpan(node.attribute(QLatin1String("colspan")).toInt()); + if (node.hasAttribute(QLatin1String("alignment"))) + setAttributeAlignment(node.attribute(QLatin1String("alignment"))); for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) { if (!n.isElement()) @@ -3828,6 +3836,9 @@ void DomLayoutItem::write(QXmlStreamWriter &writer, const QString &tagName) cons if (hasAttributeColSpan()) writer.writeAttribute(QLatin1String("colspan"), QString::number(attributeColSpan())); + if (hasAttributeAlignment()) + writer.writeAttribute(QLatin1String("alignment"), attributeAlignment()); + switch (kind()) { case Widget: { DomWidget* v = elementWidget(); @@ -7745,6 +7756,7 @@ void DomResourceIcon::clear(bool clear_all) if (clear_all) { m_text = QLatin1String(""); + m_has_attr_theme = false; m_has_attr_resource = false; } @@ -7762,6 +7774,7 @@ void DomResourceIcon::clear(bool clear_all) DomResourceIcon::DomResourceIcon() { m_children = 0; + m_has_attr_theme = false; m_has_attr_resource = false; m_text = QLatin1String(""); m_normalOff = 0; @@ -7791,6 +7804,10 @@ void DomResourceIcon::read(QXmlStreamReader &reader) foreach (const QXmlStreamAttribute &attribute, reader.attributes()) { QStringRef name = attribute.name(); + if (name == QLatin1String("theme")) { + setAttributeTheme(attribute.value().toString()); + continue; + } if (name == QLatin1String("resource")) { setAttributeResource(attribute.value().toString()); continue; @@ -7869,6 +7886,8 @@ void DomResourceIcon::read(QXmlStreamReader &reader) #ifdef QUILOADER_QDOM_READ void DomResourceIcon::read(const QDomElement &node) { + if (node.hasAttribute(QLatin1String("theme"))) + setAttributeTheme(node.attribute(QLatin1String("theme"))); if (node.hasAttribute(QLatin1String("resource"))) setAttributeResource(node.attribute(QLatin1String("resource"))); @@ -7938,6 +7957,9 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co { writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourceicon") : tagName.toLower()); + if (hasAttributeTheme()) + writer.writeAttribute(QLatin1String("theme"), attributeTheme()); + if (hasAttributeResource()) writer.writeAttribute(QLatin1String("resource"), attributeResource()); diff --git a/tools/designer/src/lib/uilib/ui4_p.h b/tools/designer/src/lib/uilib/ui4_p.h index db797cc..8d7f108 100644 --- a/tools/designer/src/lib/uilib/ui4_p.h +++ b/tools/designer/src/lib/uilib/ui4_p.h @@ -1427,6 +1427,11 @@ public: inline void setAttributeColSpan(int a) { m_attr_colSpan = a; m_has_attr_colSpan = true; } inline void clearAttributeColSpan() { m_has_attr_colSpan = false; } + inline bool hasAttributeAlignment() const { return m_has_attr_alignment; } + inline QString attributeAlignment() const { return m_attr_alignment; } + inline void setAttributeAlignment(const QString& a) { m_attr_alignment = a; m_has_attr_alignment = true; } + inline void clearAttributeAlignment() { m_has_attr_alignment = false; } + // child element accessors enum Kind { Unknown = 0, Widget, Layout, Spacer }; inline Kind kind() const { return m_kind; } @@ -1460,6 +1465,9 @@ private: int m_attr_colSpan; bool m_has_attr_colSpan; + QString m_attr_alignment; + bool m_has_attr_alignment; + // child element data Kind m_kind; DomWidget* m_widget; @@ -2809,6 +2817,11 @@ public: inline void setText(const QString &s) { m_text = s; } // attribute accessors + inline bool hasAttributeTheme() const { return m_has_attr_theme; } + inline QString attributeTheme() const { return m_attr_theme; } + inline void setAttributeTheme(const QString& a) { m_attr_theme = a; m_has_attr_theme = true; } + inline void clearAttributeTheme() { m_has_attr_theme = false; } + inline bool hasAttributeResource() const { return m_has_attr_resource; } inline QString attributeResource() const { return m_attr_resource; } inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; } @@ -2868,6 +2881,9 @@ private: void clear(bool clear_all = true); // attribute data + QString m_attr_theme; + bool m_has_attr_theme; + QString m_attr_resource; bool m_has_attr_resource; diff --git a/tools/designer/src/plugins/plugins.pro b/tools/designer/src/plugins/plugins.pro index bcebb82..64763a9 100644 --- a/tools/designer/src/plugins/plugins.pro +++ b/tools/designer/src/plugins/plugins.pro @@ -3,7 +3,7 @@ CONFIG += ordered REQUIRES = !CONFIG(static,shared|static) contains(QT_CONFIG, qt3support): SUBDIRS += widgets -win32: SUBDIRS += activeqt +win32:!win32-g++*: SUBDIRS += activeqt # contains(QT_CONFIG, opengl): SUBDIRS += tools/view3d contains(QT_CONFIG, webkit): SUBDIRS += qwebview contains(QT_CONFIG, phonon): SUBDIRS += phononwidgets diff --git a/tools/designer/src/uitools/quiloader.cpp b/tools/designer/src/uitools/quiloader.cpp index 650cbbe..4b38beb 100644 --- a/tools/designer/src/uitools/quiloader.cpp +++ b/tools/designer/src/uitools/quiloader.cpp @@ -102,27 +102,27 @@ QVariant TranslatingTextBuilder::loadText(const DomProperty *text) const if (str->hasAttributeNotr()) { const QString notr = str->attributeNotr(); if (notr == QLatin1String("true") || notr == QLatin1String("yes")) - return qVariantFromValue(str->text()); + return QVariant::fromValue(str->text()); } QUiTranslatableStringValue strVal; strVal.setValue(str->text().toUtf8()); if (str->hasAttributeComment()) strVal.setComment(str->attributeComment().toUtf8()); - return qVariantFromValue(strVal); + return QVariant::fromValue(strVal); } QVariant TranslatingTextBuilder::toNativeValue(const QVariant &value) const { - if (qVariantCanConvert<QUiTranslatableStringValue>(value)) { - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(value); + if (value.canConvert<QUiTranslatableStringValue>()) { + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(value); if (!m_trEnabled) return QString::fromUtf8(tsv.value().data()); - return qVariantFromValue( + return QVariant::fromValue( QApplication::translate(m_className, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8)); } - if (qVariantCanConvert<QString>(value)) - return qVariantFromValue(qVariantValue<QString>(value)); + if (value.canConvert<QString>()) + return QVariant::fromValue(qvariant_cast<QString>(value)); return value; } @@ -150,7 +150,7 @@ static void recursiveReTranslate(QTreeWidgetItem *item, const QByteArray &class_ for (unsigned j = 0; irs[j].shadowRole >= 0; j++) { QVariant v = item->data(i, irs[j].shadowRole); if (v.isValid()) { - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(v); const QString text = QApplication::translate(class_name, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8); @@ -172,7 +172,7 @@ static void reTranslateWidgetItem(T *item, const QByteArray &class_name) for (unsigned j = 0; irs[j].shadowRole >= 0; j++) { QVariant v = item->data(irs[j].shadowRole); if (v.isValid()) { - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(v); const QString text = QApplication::translate(class_name, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8); @@ -191,7 +191,7 @@ static void reTranslateTableItem(QTableWidgetItem *item, const QByteArray &class do { \ QVariant v = mainWidget->widget(i)->property(propName); \ if (v.isValid()) { \ - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); \ + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(v); \ const QString text = QApplication::translate(m_className, \ tsv.value(), tsv.comment(), \ QCoreApplication::UnicodeUTF8); \ @@ -217,7 +217,7 @@ public: if (prop.startsWith(PROP_GENERIC_PREFIX)) { const QByteArray propName = prop.mid(sizeof(PROP_GENERIC_PREFIX) - 1); const QUiTranslatableStringValue tsv = - qVariantValue<QUiTranslatableStringValue>(o->property(prop)); + qvariant_cast<QUiTranslatableStringValue>(o->property(prop)); const QString text = QApplication::translate(m_className, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8); @@ -273,7 +273,7 @@ public: for (int i = 0; i < cnt; ++i) { const QVariant v = combow->itemData(i, Qt::DisplayPropertyRole); if (v.isValid()) { - QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); + QUiTranslatableStringValue tsv = qvariant_cast<QUiTranslatableStringValue>(v); const QString text = QApplication::translate(m_className, tsv.value(), tsv.comment(), QCoreApplication::UnicodeUTF8); @@ -430,7 +430,7 @@ void FormBuilderPrivate::applyProperties(QObject *o, const QList<DomProperty*> & continue; const QByteArray name = p->attributeName().toUtf8(); if (dynamicTr) { - o->setProperty(PROP_GENERIC_PREFIX + name, qVariantFromValue(strVal)); + o->setProperty(PROP_GENERIC_PREFIX + name, QVariant::fromValue(strVal)); anyTrs = trEnabled; } o->setProperty(name, text); @@ -489,7 +489,7 @@ QWidget *FormBuilderPrivate::create(DomWidget *ui_widget, QWidget *parentWidget) const QString text = convertTranslatable(p##attribute, m_class, &strVal); \ if (!text.isEmpty()) { \ if (dynamicTr) \ - mainWidget->widget(i)->setProperty(propName, qVariantFromValue(strVal)); \ + mainWidget->widget(i)->setProperty(propName, QVariant::fromValue(strVal)); \ mainWidget->setter(i, text); \ } \ } \ diff --git a/tools/designer/src/uitools/uitools.pro b/tools/designer/src/uitools/uitools.pro index 7b94587..be46afc 100644 --- a/tools/designer/src/uitools/uitools.pro +++ b/tools/designer/src/uitools/uitools.pro @@ -1,5 +1,5 @@ TEMPLATE = lib -TARGET = $$qtLibraryTarget(QtUiTools) +TARGET = QtUiTools QT += xml CONFIG += qt staticlib DESTDIR = ../../../../lib @@ -35,7 +35,7 @@ INSTALLS += quitools_headers target.path=$$[QT_INSTALL_LIBS] INSTALLS += target -unix { +unix|win32-g++* { CONFIG += create_pc QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS] QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/$$TARGET @@ -43,3 +43,5 @@ unix { QMAKE_PKGCONFIG_DESTDIR = pkgconfig QMAKE_PKGCONFIG_REQUIRES += QtXml } + +TARGET = $$qtLibraryTarget($$TARGET$$QT_LIBINFIX) #do this towards the end diff --git a/tools/doxygen/config/footer.html b/tools/doxygen/config/footer.html index 8e99c72..d7e968d 100644 --- a/tools/doxygen/config/footer.html +++ b/tools/doxygen/config/footer.html @@ -1,6 +1,6 @@ <p /><address><hr /><div align="center"> <table width="100%" cellspacing="0" border="0"><tr class="address"> -<td width="30%">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).</td> +<td width="30%">Copyright © 2011 Nokia Corporation and/or its subsidiary(-ies).</td> <td width="40%" align="center"><a href="trademarks.html">Trademarks</a></td> <td width="30%" align="right"><div align="right">Qt $projectnumber</div></td> </tr></table></div></address> diff --git a/tools/linguist/linguist/Info_mac.plist b/tools/linguist/linguist/Info_mac.plist index b11f493..b37a43b 100644 --- a/tools/linguist/linguist/Info_mac.plist +++ b/tools/linguist/linguist/Info_mac.plist @@ -14,5 +14,65 @@ <string>????</string> <key>CFBundleExecutable</key> <string>Linguist</string> + + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>CFBundleTypeIconFile</key> + <string>linguist.icns</string> + <key>CFBundleTypeExtensions</key> + <array> + <string>qph</string> + </array> + <key>CFBundleTypeName</key> + <string>Qt Linguist 'Phrase Book'</string> + <key>LSHandlerRank</key> + <string>Default</string> + </dict> + <dict> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>CFBundleTypeIconFile</key> + <string>linguist.icns</string> + <key>CFBundleTypeExtensions</key> + <array> + <string>ts</string> + </array> + <key>CFBundleTypeName</key> + <string>Qt Translation Source</string> + <key>LSHandlerRank</key> + <string>Default</string> + </dict> + <dict> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>CFBundleTypeIconFile</key> + <string>linguist.icns</string> + <key>CFBundleTypeExtensions</key> + <array> + <string>po</string> + </array> + <key>CFBundleTypeName</key> + <string>GNU Gettext Localization File</string> + <key>LSHandlerRank</key> + <string>Default</string> + </dict> + <dict> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>CFBundleTypeIconFile</key> + <string>linguist.icns</string> + <key>CFBundleTypeExtensions</key> + <array> + <string>xlf</string> + </array> + <key>CFBundleTypeName</key> + <string>XLIFF Localization File</string> + <key>LSHandlerRank</key> + <string>Default</string> + </dict> + </array> </dict> </plist> diff --git a/tools/linguist/linguist/formpreviewview.cpp b/tools/linguist/linguist/formpreviewview.cpp index 19db344..09d242a 100644 --- a/tools/linguist/linguist/formpreviewview.cpp +++ b/tools/linguist/linguist/formpreviewview.cpp @@ -83,7 +83,7 @@ static bool operator==(const QUiTranslatableStringValue &tsv1, const QUiTranslat target.type = _type; \ target.target._target; \ target.prop._prop; \ - (*targets)[qVariantValue<QUiTranslatableStringValue>(_tsv)].append(target); \ + (*targets)[qvariant_cast<QUiTranslatableStringValue>(_tsv)].append(target); \ } while (0) static void registerTreeItem(QTreeWidgetItem *item, TargetsHash *targets) @@ -350,14 +350,14 @@ static void highlightAction(QAction *a, bool on) if (on) { if (!bak.isValid()) { QFont fnt = qApp->font(); - a->setProperty(FONT_BACKUP_PROP, qVariantFromValue(a->font().resolve(fnt))); + a->setProperty(FONT_BACKUP_PROP, QVariant::fromValue(a->font().resolve(fnt))); fnt.setBold(true); fnt.setItalic(true); a->setFont(fnt); } } else { if (bak.isValid()) { - a->setFont(qVariantValue<QFont>(bak)); + a->setFont(qvariant_cast<QFont>(bak)); a->setProperty(FONT_BACKUP_PROP, QVariant()); } } @@ -374,8 +374,8 @@ static void highlightWidget(QWidget *w, bool on) foreach (QObject *co, w->children()) if (QWidget *cw = qobject_cast<QWidget *>(co)) cw->setPalette(cw->palette().resolve(pal)); - w->setProperty(PALETTE_BACKUP_PROP, qVariantFromValue(w->palette().resolve(pal))); - w->setProperty(AUTOFILL_BACKUP_PROP, qVariantFromValue(w->autoFillBackground())); + w->setProperty(PALETTE_BACKUP_PROP, QVariant::fromValue(w->palette().resolve(pal))); + w->setProperty(AUTOFILL_BACKUP_PROP, QVariant::fromValue(w->autoFillBackground())); QColor col1 = pal.color(QPalette::Dark); QColor col2 = pal.color(QPalette::Light); pal.setColor(QPalette::Base, col1); @@ -390,8 +390,8 @@ static void highlightWidget(QWidget *w, bool on) } } else { if (bak.isValid()) { - w->setPalette(qVariantValue<QPalette>(bak)); - w->setAutoFillBackground(qVariantValue<bool>(w->property(AUTOFILL_BACKUP_PROP))); + w->setPalette(qvariant_cast<QPalette>(bak)); + w->setAutoFillBackground(qvariant_cast<bool>(w->property(AUTOFILL_BACKUP_PROP))); w->setProperty(PALETTE_BACKUP_PROP, QVariant()); w->setProperty(AUTOFILL_BACKUP_PROP, QVariant()); } @@ -463,6 +463,8 @@ FormPreviewView::FormPreviewView(QWidget *parent, MultiDataModel *dataModel) m_mdiArea = new QMdiArea(this); m_mdiArea->addSubWindow(m_mdiSubWindow); setCentralWidget(m_mdiArea); + m_mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); } void FormPreviewView::setSourceContext(int model, MessageItem *messageItem) diff --git a/tools/linguist/linguist/main.cpp b/tools/linguist/linguist/main.cpp index a137f36..ba45613 100644 --- a/tools/linguist/linguist/main.cpp +++ b/tools/linguist/linguist/main.cpp @@ -54,8 +54,54 @@ #include <QtGui/QPixmap> #include <QtGui/QSplashScreen> +#ifdef Q_WS_MAC +#include <QtCore/QUrl> +#include <QtGui/QFileOpenEvent> +#endif // Q_WS_MAC + QT_USE_NAMESPACE +#ifdef Q_WS_MAC +class ApplicationEventFilter : public QObject +{ + Q_OBJECT + +public: + ApplicationEventFilter() + : m_mainWindow(0) + { + } + + void setMainWindow(MainWindow *mw) + { + m_mainWindow = mw; + if (!m_filesToOpen.isEmpty() && m_mainWindow) { + m_mainWindow->openFiles(m_filesToOpen); + m_filesToOpen.clear(); + } + } + +protected: + bool eventFilter(QObject *object, QEvent *event) + { + if (object == qApp && event->type() == QEvent::FileOpen) { + QFileOpenEvent *e = static_cast<QFileOpenEvent*>(event); + QString file = e->url().toLocalFile(); + if (!m_mainWindow) + m_filesToOpen << file; + else + m_mainWindow->openFiles(QStringList() << file); + return true; + } + return QObject::eventFilter(object, event); + } + +private: + MainWindow *m_mainWindow; + QStringList m_filesToOpen; +}; +#endif // Q_WS_MAC + int main(int argc, char **argv) { Q_INIT_RESOURCE(linguist); @@ -63,6 +109,11 @@ int main(int argc, char **argv) QApplication app(argc, argv); QApplication::setOverrideCursor(Qt::WaitCursor); +#ifdef Q_WS_MAC + ApplicationEventFilter eventFilter; + app.installEventFilter(&eventFilter); +#endif // Q_WS_MAC + QStringList files; QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath); QStringList args = app.arguments(); @@ -111,6 +162,9 @@ int main(int argc, char **argv) splash->show(); MainWindow mw; +#ifdef Q_WS_MAC + eventFilter.setMainWindow(&mw); +#endif // Q_WS_MAC mw.show(); splash->finish(&mw); QApplication::restoreOverrideCursor(); @@ -119,3 +173,7 @@ int main(int argc, char **argv) return app.exec(); } + +#ifdef Q_WS_MAC +#include "main.moc" +#endif // Q_WS_MAC diff --git a/tools/linguist/linguist/mainwindow.cpp b/tools/linguist/linguist/mainwindow.cpp index 1a8e60e..ddefa9a 100644 --- a/tools/linguist/linguist/mainwindow.cpp +++ b/tools/linguist/linguist/mainwindow.cpp @@ -187,7 +187,7 @@ private: static const QVariant &pxObsolete() { static const QVariant v = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png"))); return v; } @@ -1388,7 +1388,7 @@ void MainWindow::setupPhrase() void MainWindow::closeEvent(QCloseEvent *e) { - if (maybeSaveAll() && closePhraseBooks()) + if (maybeSaveAll() && maybeSavePhraseBooks()) e->accept(); else e->ignore(); @@ -2302,7 +2302,7 @@ bool MainWindow::maybeSavePhraseBook(PhraseBook *pb) return true; } -bool MainWindow::closePhraseBooks() +bool MainWindow::maybeSavePhraseBooks() { foreach(PhraseBook *phraseBook, m_phraseBooks) if (!maybeSavePhraseBook(phraseBook)) diff --git a/tools/linguist/linguist/mainwindow.h b/tools/linguist/linguist/mainwindow.h index c589945..7a81ff6 100644 --- a/tools/linguist/linguist/mainwindow.h +++ b/tools/linguist/linguist/mainwindow.h @@ -192,7 +192,7 @@ private: bool isPhraseBookOpen(const QString &name); bool savePhraseBook(QString *name, PhraseBook &pb); bool maybeSavePhraseBook(PhraseBook *phraseBook); - bool closePhraseBooks(); + bool maybeSavePhraseBooks(); QStringList pickTranslationFiles(); void showTranslationSettings(int model); void updateLatestModel(int model); diff --git a/tools/linguist/linguist/messagemodel.cpp b/tools/linguist/linguist/messagemodel.cpp index 625569b..5cbc5e8 100644 --- a/tools/linguist/linguist/messagemodel.cpp +++ b/tools/linguist/linguist/messagemodel.cpp @@ -375,7 +375,7 @@ bool DataModel::release(const QString &fileName, bool verbose, bool ignoreUnfini cd.m_verbose = verbose; cd.m_ignoreUnfinished = ignoreUnfinished; cd.m_saveMode = mode; - bool ok = tor.release(&file, cd); + bool ok = saveQM(tor, file, cd); if (!ok) QMessageBox::warning(parent, QObject::tr("Qt Linguist"), cd.error()); return ok; @@ -1238,17 +1238,17 @@ int MessageModel::columnCount(const QModelIndex &) const QVariant MessageModel::data(const QModelIndex &index, int role) const { static QVariant pxOn = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_on.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_on.png"))); static QVariant pxOff = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_off.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_off.png"))); static QVariant pxObsolete = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png"))); static QVariant pxDanger = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_danger.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_danger.png"))); static QVariant pxWarning = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_warning.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_warning.png"))); static QVariant pxEmpty = - qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_empty.png"))); + QVariant::fromValue(QPixmap(QLatin1String(":/images/s_check_empty.png"))); int row = index.row(); int column = index.column() - 1; diff --git a/tools/linguist/lrelease/lrelease.pro b/tools/linguist/lrelease/lrelease.pro index 89694be..28a741d 100644 --- a/tools/linguist/lrelease/lrelease.pro +++ b/tools/linguist/lrelease/lrelease.pro @@ -5,19 +5,9 @@ DESTDIR = ../../../bin DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII SOURCES += main.cpp -INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global # qlibraryinfo.cpp includes qconfig.cpp -SOURCES += \ - $$QT_SOURCE_TREE/src/corelib/global/qlibraryinfo.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qsettings.cpp -win32:SOURCES += $$QT_SOURCE_TREE/src/corelib/io/qsettings_win.cpp -macx:SOURCES += $$QT_SOURCE_TREE/src/corelib/io/qsettings_mac.cpp - include(../../../src/tools/bootstrap/bootstrap.pri) include(../shared/formats.pri) include(../shared/proparser.pri) -include(../../shared/symbian/epocroot.pri) - -win32:LIBS += -ladvapi32 # for qsettings_win.cpp target.path=$$[QT_INSTALL_BINS] INSTALLS += target diff --git a/tools/linguist/lrelease/main.cpp b/tools/linguist/lrelease/main.cpp index 72d5d48..1fa1474 100644 --- a/tools/linguist/lrelease/main.cpp +++ b/tools/linguist/lrelease/main.cpp @@ -40,7 +40,9 @@ ****************************************************************************/ #include "translator.h" -#include "profileevaluator.h" + +#include <profileparser.h> +#include <profileevaluator.h> #ifndef QT_BOOTSTRAPPED #include <QtCore/QCoreApplication> @@ -55,11 +57,11 @@ #include <QtCore/QStringList> #include <QtCore/QTextStream> -#include <iostream> - QT_USE_NAMESPACE #ifdef QT_BOOTSTRAPPED +static QString binDir; + static void initBinaryDir( #ifndef Q_OS_WIN const char *argv0 @@ -84,6 +86,12 @@ static void printOut(const QString & out) stream << out; } +static void printErr(const QString & out) +{ + QTextStream stream(stderr); + stream << out; +} + static void printUsage() { printOut(LR::tr( @@ -119,7 +127,7 @@ static bool loadTsFile(Translator &tor, const QString &tsFileName, bool /* verbo ConversionData cd; bool ok = tor.load(tsFileName, cd, QLatin1String("auto")); if (!ok) { - std::cerr << qPrintable(LR::tr("lrelease error: %1").arg(cd.error())); + printErr(LR::tr("lrelease error: %1").arg(cd.error())); } else { if (!cd.errors().isEmpty()) printOut(cd.error()); @@ -143,17 +151,17 @@ static bool releaseTranslator(Translator &tor, const QString &qmFileName, QFile file(qmFileName); if (!file.open(QIODevice::WriteOnly)) { - std::cerr << qPrintable(LR::tr("lrelease error: cannot create '%1': %2\n") + printErr(LR::tr("lrelease error: cannot create '%1': %2\n") .arg(qmFileName, file.errorString())); return false; } tor.normalizeTranslations(cd); - bool ok = tor.release(&file, cd); + bool ok = saveQM(tor, file, cd); file.close(); if (!ok) { - std::cerr << qPrintable(LR::tr("lrelease error: cannot save '%1': %2") + printErr(LR::tr("lrelease error: cannot save '%1': %2") .arg(qmFileName, cd.error())); } else if (!cd.errors().isEmpty()) { printOut(cd.error()); @@ -181,6 +189,40 @@ static bool releaseTsFile(const QString& tsFileName, return releaseTranslator(tor, qmFileName, cd, removeIdentical); } +static void print(const QString &fileName, int lineNo, const QString &msg) +{ + if (lineNo) + printErr(QString::fromLatin1("%2(%1): %3").arg(lineNo).arg(fileName, msg)); + else + printErr(msg); +} + +class ParseHandler : public ProFileParserHandler { +public: + virtual void parseError(const QString &fileName, int lineNo, const QString &msg) + { if (verbose) print(fileName, lineNo, msg); } + + bool verbose; +}; + +class EvalHandler : public ProFileEvaluatorHandler { +public: + virtual void configError(const QString &msg) + { printErr(msg); } + virtual void evalError(const QString &fileName, int lineNo, const QString &msg) + { if (verbose) print(fileName, lineNo, msg); } + virtual void fileMessage(const QString &msg) + { printErr(msg); } + + virtual void aboutToEval(ProFile *, ProFile *, EvalFileType) {} + virtual void doneWithEval(ProFile *) {} + + bool verbose; +}; + +static ParseHandler parseHandler; +static EvalHandler evalHandler; + int main(int argc, char **argv) { #ifdef QT_BOOTSTRAPPED @@ -268,27 +310,36 @@ int main(int argc, char **argv) if (inputFile.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive) || inputFile.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) { QFileInfo fi(inputFile); - ProFile pro(fi.absoluteFilePath()); - ProFileEvaluator visitor; - visitor.setVerbose(cd.isVerbose()); + parseHandler.verbose = evalHandler.verbose = cd.isVerbose(); + ProFileOption option; +#ifdef QT_BOOTSTRAPPED + option.initProperties(binDir + QLatin1String("/qmake")); +#else + option.initProperties(app.applicationDirPath() + QLatin1String("/qmake")); +#endif + ProFileParser parser(0, &parseHandler); + ProFileEvaluator visitor(&option, &parser, &evalHandler); - if (!visitor.queryProFile(&pro)) { - std::cerr << qPrintable(LR::tr( + ProFile *pro; + if (!(pro = parser.parsedProFile(QDir::cleanPath(fi.absoluteFilePath())))) { + printErr(LR::tr( "lrelease error: cannot read project file '%1'.\n") .arg(inputFile)); continue; } - if (!visitor.accept(&pro)) { - std::cerr << qPrintable(LR::tr( + if (!visitor.accept(pro)) { + printErr(LR::tr( "lrelease error: cannot process project file '%1'.\n") .arg(inputFile)); + pro->deref(); continue; } + pro->deref(); QStringList translations = visitor.values(QLatin1String("TRANSLATIONS")); if (translations.isEmpty()) { - std::cerr << qPrintable(LR::tr( + printErr(LR::tr( "lrelease warning: Met no 'TRANSLATIONS' entry in project file '%1'\n") .arg(inputFile)); } else { @@ -320,8 +371,6 @@ int main(int argc, char **argv) # include <windows.h> #endif -static QString binDir; - static void initBinaryDir( #ifndef Q_OS_WIN const char *_argv0 @@ -376,16 +425,4 @@ static void initBinaryDir( #endif } -QT_BEGIN_NAMESPACE - -// The name is hard-coded in QLibraryInfo -QString qmake_libraryInfoFile() -{ - if (binDir.isEmpty()) - return QString(); - return QDir(binDir).filePath(QString::fromLatin1("qt.conf")); -} - -QT_END_NAMESPACE - #endif // QT_BOOTSTRAPPED diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp index 727fad9..ab88083 100644 --- a/tools/linguist/lupdate/main.cpp +++ b/tools/linguist/lupdate/main.cpp @@ -42,6 +42,7 @@ #include "lupdate.h" #include <translator.h> +#include <profileparser.h> #include <profileevaluator.h> #include <QtCore/QCoreApplication> @@ -229,6 +230,40 @@ static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFil } } +static void print(const QString &fileName, int lineNo, const QString &msg) +{ + if (lineNo) + printErr(QString::fromLatin1("%2(%1): %3").arg(lineNo).arg(fileName, msg)); + else + printErr(msg); +} + +class ParseHandler : public ProFileParserHandler { +public: + virtual void parseError(const QString &fileName, int lineNo, const QString &msg) + { if (verbose) print(fileName, lineNo, msg); } + + bool verbose; +}; + +class EvalHandler : public ProFileEvaluatorHandler { +public: + virtual void configError(const QString &msg) + { printErr(msg); } + virtual void evalError(const QString &fileName, int lineNo, const QString &msg) + { if (verbose) print(fileName, lineNo, msg); } + virtual void fileMessage(const QString &msg) + { printErr(msg); } + + virtual void aboutToEval(ProFile *, ProFile *, EvalFileType) {} + virtual void doneWithEval(ProFile *) {} + + bool verbose; +}; + +static ParseHandler parseHandler; +static EvalHandler evalHandler; + static QStringList getSources(const char *var, const char *vvar, const QStringList &baseVPaths, const QString &projectDir, const ProFileEvaluator &visitor) { @@ -290,12 +325,14 @@ static void processSources(Translator &fetchedTor, static void processProjects( bool topLevel, bool nestComplain, const QStringList &proFiles, + ProFileOption *option, ProFileParser *parser, UpdateOptions options, const QByteArray &codecForSource, const QString &targetLanguage, const QString &sourceLanguage, Translator *parentTor, bool *fail); static void processProject( - bool nestComplain, const QFileInfo &pfi, ProFileEvaluator &visitor, + bool nestComplain, const QFileInfo &pfi, + ProFileOption *option, ProFileParser *parser, ProFileEvaluator &visitor, UpdateOptions options, const QByteArray &_codecForSource, const QString &targetLanguage, const QString &sourceLanguage, Translator *fetchedTor, bool *fail) @@ -323,7 +360,7 @@ static void processProject( else subProFiles << subPro; } - processProjects(false, nestComplain, subProFiles, options, codecForSource, + processProjects(false, nestComplain, subProFiles, option, parser, options, codecForSource, targetLanguage, sourceLanguage, fetchedTor, fail); } else { ConversionData cd; @@ -349,23 +386,25 @@ static void processProject( static void processProjects( bool topLevel, bool nestComplain, const QStringList &proFiles, + ProFileOption *option, ProFileParser *parser, UpdateOptions options, const QByteArray &codecForSource, const QString &targetLanguage, const QString &sourceLanguage, Translator *parentTor, bool *fail) { foreach (const QString &proFile, proFiles) { - ProFileEvaluator visitor; - visitor.setVerbose(options & Verbose); - - QHash<QString, QStringList> lupdateConfig; - lupdateConfig.insert(QLatin1String("CONFIG"), QStringList(QLatin1String("lupdate_run"))); - visitor.addVariables(lupdateConfig); - QFileInfo pfi(proFile); - ProFile pro(pfi.absoluteFilePath()); - if (!visitor.queryProFile(&pro) || !visitor.accept(&pro)) { + + ProFileEvaluator visitor(option, parser, &evalHandler); + ProFile *pro; + if (!(pro = parser->parsedProFile(QDir::cleanPath(pfi.absoluteFilePath())))) { + if (topLevel) + *fail = true; + continue; + } + if (!visitor.accept(pro)) { if (topLevel) *fail = true; + pro->deref(); continue; } @@ -378,6 +417,7 @@ static void processProjects( } else if (nestComplain) { printErr(LU::tr("lupdate warning: TS files from command line " "prevent recursing into %1.\n").arg(proFile)); + pro->deref(); continue; } } @@ -389,6 +429,7 @@ static void processProjects( // This might mean either a buggy PRO file or an intentional detach - // we can't know without seeing the actual RHS of the assignment ... // Just assume correctness and be silent. + pro->deref(); continue; } Translator tor; @@ -400,9 +441,10 @@ static void processProjects( tor.setCodecName(tmp.last().toLatin1()); setCodec = true; } - processProject(false, pfi, visitor, options, codecForSource, + processProject(false, pfi, option, parser, visitor, options, codecForSource, targetLanguage, sourceLanguage, &tor, fail); updateTsFiles(tor, tsFiles, setCodec, sourceLanguage, targetLanguage, options, fail); + pro->deref(); continue; } noTrans: @@ -411,12 +453,13 @@ static void processProjects( printErr(LU::tr("lupdate warning: no TS files specified. Only diagnostics " "will be produced for '%1'.\n").arg(proFile)); Translator tor; - processProject(nestComplain, pfi, visitor, options, codecForSource, + processProject(nestComplain, pfi, option, parser, visitor, options, codecForSource, targetLanguage, sourceLanguage, &tor, fail); } else { - processProject(nestComplain, pfi, visitor, options, codecForSource, + processProject(nestComplain, pfi, option, parser, visitor, options, codecForSource, targetLanguage, sourceLanguage, parentTor, fail); } + pro->deref(); } } @@ -716,15 +759,22 @@ int main(int argc, char **argv) " Both project and source files / include paths specified.\n")); return 1; } + + parseHandler.verbose = evalHandler.verbose = !!(options & Verbose); + ProFileOption option; + option.initProperties(app.applicationDirPath() + QLatin1String("/qmake")); + option.setCommandLineArguments(QStringList() << QLatin1String("CONFIG+=lupdate_run")); + ProFileParser parser(0, &parseHandler); + if (!tsFileNames.isEmpty()) { Translator fetchedTor; fetchedTor.setCodecName(codecForTr); - processProjects(true, true, proFiles, options, QByteArray(), + processProjects(true, true, proFiles, &option, &parser, options, QByteArray(), targetLanguage, sourceLanguage, &fetchedTor, &fail); updateTsFiles(fetchedTor, tsFileNames, !codecForTr.isEmpty(), sourceLanguage, targetLanguage, options, &fail); } else { - processProjects(true, false, proFiles, options, QByteArray(), + processProjects(true, false, proFiles, &option, &parser, options, QByteArray(), targetLanguage, sourceLanguage, 0, &fail); } } diff --git a/tools/linguist/lupdate/merge.cpp b/tools/linguist/lupdate/merge.cpp index 2d5230b..8b6624d 100644 --- a/tools/linguist/lupdate/merge.cpp +++ b/tools/linguist/lupdate/merge.cpp @@ -348,11 +348,11 @@ Translator merge(const Translator &tor, const Translator &virginTor, if (m.sourceText().isEmpty() && m.id().isEmpty()) { // context/file comment - TranslatorMessage mv = virginTor.find(m.context()); - if (!mv.isNull()) - m.setComment(mv.comment()); + int mvi = virginTor.find(m.context()); + if (mvi >= 0) + m.setComment(virginTor.constMessage(mvi).comment()); } else { - TranslatorMessage mv; + const TranslatorMessage *mv; int mvi = virginTor.find(m); if (mvi < 0) { if (!(options & HeuristicSimilarText)) { @@ -362,16 +362,17 @@ Translator merge(const Translator &tor, const Translator &virginTor, obsoleted++; m.clearReferences(); } else { - mv = virginTor.find(m.context(), m.comment(), m.allReferences()); - if (mv.isNull()) { + mvi = virginTor.find(m.context(), m.comment(), m.allReferences()); + if (mvi < 0) { // did not find it in the virgin, mark it as obsolete goto makeObsolete; } else { + mv = &virginTor.constMessage(mvi); // Do not just accept it if its on the same line number, // but different source text. // Also check if the texts are more or less similar before // we consider them to represent the same message... - if (getSimilarityScore(m.sourceText(), mv.sourceText()) >= textSimilarityThreshold) { + if (getSimilarityScore(m.sourceText(), mv->sourceText()) >= textSimilarityThreshold) { // It is just slightly modified, assume that it is the same string // Mark it as unfinished. (Since the source text @@ -382,7 +383,7 @@ Translator merge(const Translator &tor, const Translator &virginTor, outdateSource: m.setOldSourceText(m.sourceText()); - m.setSourceText(mv.sourceText()); + m.setSourceText(mv->sourceText()); const QString &oldpluralsource = m.extra(QLatin1String("po-msgid_plural")); if (!oldpluralsource.isEmpty()) { m.setExtra(QLatin1String("po-old_msgid_plural"), oldpluralsource); @@ -397,22 +398,22 @@ Translator merge(const Translator &tor, const Translator &virginTor, } } } else { - mv = virginTor.message(mvi); - if (!mv.id().isEmpty() - && (mv.context() != m.context() - || mv.sourceText() != m.sourceText() - || mv.comment() != m.comment())) { + mv = &virginTor.message(mvi); + if (!mv->id().isEmpty() + && (mv->context() != m.context() + || mv->sourceText() != m.sourceText() + || mv->comment() != m.comment())) { known++; newType = TranslatorMessage::Unfinished; - m.setContext(mv.context()); - m.setComment(mv.comment()); - if (mv.sourceText() != m.sourceText()) + m.setContext(mv->context()); + m.setComment(mv->comment()); + if (mv->sourceText() != m.sourceText()) goto outdateSource; } else { switch (m.type()) { case TranslatorMessage::Finished: default: - if (m.isPlural() == mv.isPlural()) { + if (m.isPlural() == mv->isPlural()) { newType = TranslatorMessage::Finished; } else { newType = TranslatorMessage::Unfinished; @@ -435,11 +436,11 @@ Translator merge(const Translator &tor, const Translator &virginTor, // have the <location> element. // why not use operator=()? Because it overwrites e.g. userData. copyAttribs: - m.setReferences(mv.allReferences()); - m.setPlural(mv.isPlural()); - m.setUtf8(mv.isUtf8()); - m.setExtraComment(mv.extraComment()); - m.setId(mv.id()); + m.setReferences(mv->allReferences()); + m.setPlural(mv->isPlural()); + m.setUtf8(mv->isUtf8()); + m.setExtraComment(mv->extraComment()); + m.setId(mv->id()); } } @@ -453,15 +454,16 @@ Translator merge(const Translator &tor, const Translator &virginTor, */ foreach (const TranslatorMessage &mv, virginTor.messages()) { if (mv.sourceText().isEmpty() && mv.id().isEmpty()) { - if (tor.contains(mv.context())) + if (tor.find(mv.context()) >= 0) continue; } else { if (tor.find(mv) >= 0) continue; if (options & HeuristicSimilarText) { - TranslatorMessage m = tor.find(mv.context(), mv.comment(), mv.allReferences()); - if (!m.isNull()) { - if (getSimilarityScore(m.sourceText(), mv.sourceText()) >= textSimilarityThreshold) + int mi = tor.find(mv.context(), mv.comment(), mv.allReferences()); + if (mi >= 0) { + if (getSimilarityScore(tor.constMessage(mi).sourceText(), mv.sourceText()) + >= textSimilarityThreshold) continue; } } diff --git a/tools/linguist/lupdate/qdeclarative.cpp b/tools/linguist/lupdate/qdeclarative.cpp index a5ac0a5..c539821 100644 --- a/tools/linguist/lupdate/qdeclarative.cpp +++ b/tools/linguist/lupdate/qdeclarative.cpp @@ -62,6 +62,7 @@ #include <iostream> #include <cstdlib> +#include <cctype> QT_BEGIN_NAMESPACE diff --git a/tools/linguist/lupdate/qscript.cpp b/tools/linguist/lupdate/qscript.cpp index eb9869f..db1a4d7 100644 --- a/tools/linguist/lupdate/qscript.cpp +++ b/tools/linguist/lupdate/qscript.cpp @@ -67,6 +67,8 @@ class LU { Q_DECLARE_TR_FUNCTIONS(LUpdate) }; +static QString MagicComment(QLatin1String("TRANSLATOR")); + class QScriptGrammar { public: @@ -2092,8 +2094,9 @@ public: ~QScriptParser(); void setLexer(QScript::Lexer *); + void setTranslator(Translator *); - bool parse(Translator *translator); + bool parse(); QString fileName() const { return lexer->fileName(); } @@ -2129,6 +2132,8 @@ protected: private: QScript::Lexer *lexer; + Translator *translator; + QString trcontext; QString extracomment; QString msgid; QString sourcetext; @@ -2160,7 +2165,8 @@ QScriptParser::QScriptParser(): sym_stack(0), state_stack(0), location_stack(0), - lexer(0) + lexer(0), + translator(0) { } @@ -2187,9 +2193,17 @@ void QScriptParser::setLexer(QScript::Lexer *lex) lexer = lex; } -bool QScriptParser::parse(Translator *translator) +void QScriptParser::setTranslator(Translator *tor) +{ + translator = tor; +} + +bool QScriptParser::parse() { Q_ASSERT(lexer != 0); + Q_ASSERT(translator != 0); + trcontext = QFileInfo(fileName()).baseName(); + const int INITIAL_STATE = 0; int yytoken = -1; @@ -2303,11 +2317,10 @@ case 66: { if (args.at(0).type() != QVariant::String) { yyMsg(identLineNo) << qPrintable(LU::tr("%1(): text to translate must be a literal string.\n").arg(name)); } else { - QString context = QFileInfo(fileName()).baseName(); QString text = args.at(0).toString(); QString comment = args.value(1).toString(); bool plural = (args.size() > 2); - recordMessage(translator, context, text, comment, extracomment, + recordMessage(translator, trcontext, text, comment, extracomment, msgid, extra, plural, fileName(), identLineNo); } } @@ -2533,6 +2546,32 @@ void QScriptParser::processComment(const QChar *chars, int length) } } sourcetext.resize(ptr - (ushort *)sourcetext.data()); + } else { + int idx = 0; + ushort c; + while ((c = chars[idx].unicode()) == ' ' || c == '\t' || c == '\n') + ++idx; + if (!memcmp(chars + idx, MagicComment.unicode(), MagicComment.length() * 2)) { + idx += MagicComment.length(); + QString comment = QString(chars + idx, length - idx).simplified(); + int k = comment.indexOf(QLatin1Char(' ')); + if (k == -1) { + trcontext = comment; + } else { + trcontext = comment.left(k); + comment.remove(0, k + 1); + TranslatorMessage msg( + trcontext, QString(), + comment, QString(), + fileName(), lexer->startLineNo(), QStringList(), + TranslatorMessage::Finished, /*plural=*/false); + msg.setExtraComment(extracomment.simplified()); + extracomment.clear(); + translator->append(msg); + translator->setExtras(extra); + extra.clear(); + } + } } } @@ -2558,7 +2597,8 @@ bool loadQScript(Translator &translator, const QString &filename, ConversionData QScript::Lexer lexer(&parser); lexer.setCode(code, filename, /*lineNumber=*/1); parser.setLexer(&lexer); - if (!parser.parse(&translator)) { + parser.setTranslator(&translator); + if (!parser.parse()) { std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": " << qPrintable(parser.errorMessage()) << std::endl; return false; diff --git a/tools/linguist/lupdate/qscript.g b/tools/linguist/lupdate/qscript.g index f6e71c0..3d5cb26 100644 --- a/tools/linguist/lupdate/qscript.g +++ b/tools/linguist/lupdate/qscript.g @@ -104,6 +104,8 @@ class LU { Q_DECLARE_TR_FUNCTIONS(LUpdate) }; +static QString MagicComment(QLatin1String("TRANSLATOR")); + static void recordMessage( Translator *tor, const QString &context, const QString &text, const QString &comment, const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, @@ -1423,8 +1425,9 @@ public: ~QScriptParser(); void setLexer(QScript::Lexer *); + void setTranslator(Translator *); - bool parse(Translator *translator); + bool parse(); QString fileName() const { return lexer->fileName(); } @@ -1460,6 +1463,8 @@ protected: private: QScript::Lexer *lexer; + Translator *translator; + QString trcontext; QString extracomment; QString msgid; QString sourcetext; @@ -1491,7 +1496,8 @@ QScriptParser::QScriptParser(): sym_stack(0), state_stack(0), location_stack(0), - lexer(0) + lexer(0), + translator(0) { } @@ -1518,9 +1524,17 @@ void QScriptParser::setLexer(QScript::Lexer *lex) lexer = lex; } -bool QScriptParser::parse(Translator *translator) +void QScriptParser::setTranslator(Translator *tor) +{ + translator = tor; +} + +bool QScriptParser::parse() { Q_ASSERT(lexer != 0); + Q_ASSERT(translator != 0); + trcontext = QFileInfo(fileName()).baseName(); + const int INITIAL_STATE = 0; int yytoken = -1; @@ -1719,11 +1733,10 @@ case $rule_number: { if (args.at(0).type() != QVariant::String) { yyMsg(identLineNo) << qPrintable(LU::tr("%1(): text to translate must be a literal string.\n").arg(name)); } else { - QString context = QFileInfo(fileName()).baseName(); QString text = args.at(0).toString(); QString comment = args.value(1).toString(); bool plural = (args.size() > 2); - recordMessage(translator, context, text, comment, extracomment, + recordMessage(translator, trcontext, text, comment, extracomment, msgid, extra, plural, fileName(), identLineNo); } } @@ -2181,6 +2194,32 @@ void QScriptParser::processComment(const QChar *chars, int length) } } sourcetext.resize(ptr - (ushort *)sourcetext.data()); + } else { + int idx = 0; + ushort c; + while ((c = chars[idx].unicode()) == ' ' || c == '\t' || c == '\n') + ++idx; + if (!memcmp(chars + idx, MagicComment.unicode(), MagicComment.length() * 2)) { + idx += MagicComment.length(); + QString comment = QString(chars + idx, length - idx).simplified(); + int k = comment.indexOf(QLatin1Char(' ')); + if (k == -1) { + trcontext = comment; + } else { + trcontext = comment.left(k); + comment.remove(0, k + 1); + TranslatorMessage msg( + trcontext, QString(), + comment, QString(), + fileName(), lexer->startLineNo(), QStringList(), + TranslatorMessage::Finished, /*plural=*/false); + msg.setExtraComment(extracomment.simplified()); + extracomment.clear(); + translator->append(msg); + translator->setExtras(extra); + extra.clear(); + } + } } } @@ -2206,7 +2245,8 @@ bool loadQScript(Translator &translator, const QString &filename, ConversionData QScript::Lexer lexer(&parser); lexer.setCode(code, filename, /*lineNumber=*/1); parser.setLexer(&lexer); - if (!parser.parse(&translator)) { + parser.setTranslator(&translator); + if (!parser.parse()) { std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": " << qPrintable(parser.errorMessage()) << std::endl; return false; diff --git a/tools/linguist/shared/ioutils.cpp b/tools/linguist/shared/ioutils.cpp new file mode 100644 index 0000000..9658cf6 --- /dev/null +++ b/tools/linguist/shared/ioutils.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Linguist of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ioutils.h" + +#include <QtCore/QDir> +#include <QtCore/QFile> + +#ifdef Q_OS_WIN +# include <windows.h> +#else +# include <sys/types.h> +# include <sys/stat.h> +# include <unistd.h> +#endif + +using namespace ProFileEvaluatorInternal; + +IoUtils::FileType IoUtils::fileType(const QString &fileName) +{ + Q_ASSERT(fileName.isEmpty() || isAbsolutePath(fileName)); +#ifdef Q_OS_WIN + DWORD attr = GetFileAttributesW((WCHAR*)fileName.utf16()); + if (attr == INVALID_FILE_ATTRIBUTES) + return FileNotFound; + return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FileIsDir : FileIsRegular; +#else + struct ::stat st; + if (::stat(fileName.toLocal8Bit().constData(), &st)) + return FileNotFound; + return S_ISDIR(st.st_mode) ? FileIsDir : FileIsRegular; +#endif +} + +bool IoUtils::isRelativePath(const QString &path) +{ + if (path.startsWith(QLatin1Char('/'))) + return false; +#ifdef Q_OS_WIN + if (path.startsWith(QLatin1Char('\\'))) + return false; + // Unlike QFileInfo, this won't accept a relative path with a drive letter. + // Such paths result in a royal mess anyway ... + if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter() + && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) + return false; +#endif + return true; +} + +QStringRef IoUtils::fileName(const QString &fileName) +{ + return fileName.midRef(fileName.lastIndexOf(QLatin1Char('/')) + 1); +} + +QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName) +{ + if (fileName.isEmpty()) + return QString(); + if (isAbsolutePath(fileName)) + return QDir::cleanPath(fileName); + return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName); +} + +#ifdef QT_BOOTSTRAPPED +inline static bool isSpecialChar(ushort c) +{ + // Chars that should be quoted (TM). This includes: +#ifdef Q_OS_WIN + // - control chars & space + // - the shell meta chars "&()<>^| + // - the potential separators ,;= + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 + }; +#else + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8, + 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78 + }; // 0-32 \'"$`<>|;&(){}*?#!~[] +#endif + + return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); +} + +inline static bool hasSpecialChars(const QString &arg) +{ + for (int x = arg.length() - 1; x >= 0; --x) + if (isSpecialChar(arg.unicode()[x].unicode())) + return true; + return false; +} + +QString IoUtils::shellQuote(const QString &arg) +{ + if (!arg.length()) + return QString::fromLatin1("\"\""); + + QString ret(arg); + if (hasSpecialChars(ret)) { +#ifdef Q_OS_WIN + // Quotes are escaped and their preceding backslashes are doubled. + // It's impossible to escape anything inside a quoted string on cmd + // level, so the outer quoting must be "suspended". + ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\"")); + // The argument must not end with a \ since this would be interpreted + // as escaping the quote -- rather put the \ behind the quote: e.g. + // rather use "foo"\ than "foo\" + int i = ret.length(); + while (i > 0 && ret.at(i - 1) == QLatin1Char('\\')) + --i; + ret.insert(i, QLatin1Char('"')); + ret.prepend(QLatin1Char('"')); +#else // Q_OS_WIN + ret.replace(QLatin1Char('\''), QLatin1String("'\\''")); + ret.prepend(QLatin1Char('\'')); + ret.append(QLatin1Char('\'')); +#endif // Q_OS_WIN + } + return ret; +} +#endif diff --git a/tools/linguist/shared/abstractproitemvisitor.h b/tools/linguist/shared/ioutils.h index 73614c5..e013aef 100644 --- a/tools/linguist/shared/abstractproitemvisitor.h +++ b/tools/linguist/shared/ioutils.h @@ -39,36 +39,36 @@ ** ****************************************************************************/ -#ifndef ABSTRACTPROITEMVISITOR -#define ABSTRACTPROITEMVISITOR +#ifndef IOUTILS_H +#define IOUTILS_H -#include "proitems.h" +#include <QtCore/QString> -QT_BEGIN_NAMESPACE +namespace ProFileEvaluatorInternal { -struct AbstractProItemVisitor -{ - virtual ~AbstractProItemVisitor() {} +/*! + This class provides replacement functionality for QFileInfo, QFile & QDir, + as these are abysmally slow. +*/ +class IoUtils { +public: + enum FileType { + FileNotFound = 0, + FileIsRegular = 1, + FileIsDir = 2 + }; - virtual ProItem::ProItemReturn visitBeginProBlock(ProBlock *block) = 0; - virtual void visitEndProBlock(ProBlock *block) = 0; - - virtual ProItem::ProItemReturn visitProLoopIteration() = 0; - virtual void visitProLoopCleanup() = 0; - - virtual void visitBeginProVariable(ProVariable *variable) = 0; - virtual void visitEndProVariable(ProVariable *variable) = 0; - - virtual ProItem::ProItemReturn visitBeginProFile(ProFile *value) = 0; - virtual ProItem::ProItemReturn visitEndProFile(ProFile *value) = 0; - - virtual void visitProValue(ProValue *value) = 0; - virtual ProItem::ProItemReturn visitProFunction(ProFunction *function) = 0; - virtual void visitProOperator(ProOperator *function) = 0; - virtual void visitProCondition(ProCondition *function) = 0; + static FileType fileType(const QString &fileName); + static bool exists(const QString &fileName) { return fileType(fileName) != FileNotFound; } + static bool isRelativePath(const QString &fileName); + static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); } + static QStringRef fileName(const QString &fileName); // Requires normalized path + static QString resolvePath(const QString &baseDir, const QString &fileName); +#ifdef QT_BOOTSTRAPPED + static QString shellQuote(const QString &arg); +#endif }; -QT_END_NAMESPACE - -#endif // ABSTRACTPROITEMVISITOR +} +#endif // IOUTILS_H diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index 0393768..0539efa 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -40,8 +40,9 @@ ****************************************************************************/ #include "profileevaluator.h" -#include "proparserutils.h" -#include "proitems.h" + +#include "profileparser.h" +#include "ioutils.h" #include <QtCore/QByteArray> #include <QtCore/QDateTime> @@ -56,6 +57,9 @@ #include <QtCore/QString> #include <QtCore/QStringList> #include <QtCore/QTextStream> +#ifdef PROEVALUATOR_THREAD_SAFE +# include <QtCore/QThreadPool> +#endif #ifdef Q_OS_UNIX #include <unistd.h> @@ -74,966 +78,1482 @@ #define QT_PCLOSE pclose #endif +using namespace ProFileEvaluatorInternal; + QT_BEGIN_NAMESPACE +using namespace ProStringConstants; + + +#define fL1S(s) QString::fromLatin1(s) + /////////////////////////////////////////////////////////////////////// // -// Option +// ProFileOption // /////////////////////////////////////////////////////////////////////// -QString -Option::fixString(QString string, uchar flags) +ProFileOption::ProFileOption() { - // XXX Ripped out caching, so this will be slow. Should not matter for current uses. +#ifdef Q_OS_WIN + dirlist_sep = QLatin1Char(';'); + dir_sep = QLatin1Char('\\'); +#else + dirlist_sep = QLatin1Char(':'); + dir_sep = QLatin1Char('/'); +#endif + qmakespec = getEnv(QLatin1String("QMAKESPEC")); - //fix the environment variables - if (flags & Option::FixEnvVars) { - int rep; - QRegExp reg_variableName(QLatin1String("\\$\\(.*\\)")); - reg_variableName.setMinimal(true); - while ((rep = reg_variableName.indexIn(string)) != -1) - string.replace(rep, reg_variableName.matchedLength(), - QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_variableName.matchedLength() - 3).toLatin1().constData()).constData())); - } + host_mode = HOST_UNKNOWN_MODE; + target_mode = TARG_UNKNOWN_MODE; - //canonicalize it (and treat as a path) - if (flags & Option::FixPathCanonicalize) { -#if 0 - string = QFileInfo(string).canonicalFilePath(); +#ifdef PROEVALUATOR_THREAD_SAFE + base_inProgress = false; #endif - string = QDir::cleanPath(string); - } +} - if (string.length() > 2 && string[0].isLetter() && string[1] == QLatin1Char(':')) - string[0] = string[0].toLower(); +ProFileOption::~ProFileOption() +{ +} - //fix separators - Q_ASSERT(!((flags & Option::FixPathToLocalSeparators) && (flags & Option::FixPathToTargetSeparators))); - if (flags & Option::FixPathToLocalSeparators) { -#if defined(Q_OS_WIN32) - string = string.replace(QLatin1Char('/'), QLatin1Char('\\')); -#else - string = string.replace(QLatin1Char('\\'), QLatin1Char('/')); -#endif - } else if (flags & Option::FixPathToTargetSeparators) { - string = string.replace(QLatin1Char('/'), Option::dir_sep) - .replace(QLatin1Char('\\'), Option::dir_sep); +void ProFileOption::setCommandLineArguments(const QStringList &args) +{ + QStringList _precmds, _preconfigs, _postcmds, _postconfigs; + bool after = false; + + bool isConf = false; + foreach (const QString &arg, args) { + if (isConf) { + isConf = false; + if (after) + _postconfigs << arg; + else + _preconfigs << arg; + } else if (arg.startsWith(QLatin1Char('-'))) { + if (arg == QLatin1String("-after")) { + after = true; + } else if (arg == QLatin1String("-config")) { + isConf = true; + } else if (arg == QLatin1String("-win32")) { + host_mode = HOST_WIN_MODE; + target_mode = TARG_WIN_MODE; + } else if (arg == QLatin1String("-unix")) { + host_mode = HOST_UNIX_MODE; + target_mode = TARG_UNIX_MODE; + } else if (arg == QLatin1String("-macx")) { + host_mode = HOST_MACX_MODE; + target_mode = TARG_MACX_MODE; + } + } else if (arg.contains(QLatin1Char('='))) { + if (after) + _postcmds << arg; + else + _precmds << arg; + } } - if ((string.startsWith(QLatin1Char('"')) && string.endsWith(QLatin1Char('"'))) || - (string.startsWith(QLatin1Char('\'')) && string.endsWith(QLatin1Char('\'')))) - string = string.mid(1, string.length() - 2); + if (!_preconfigs.isEmpty()) + _precmds << (fL1S("CONFIG += ") + _preconfigs.join(fL1S(" "))); + precmds = _precmds.join(fL1S("\n")); + if (!_postconfigs.isEmpty()) + _postcmds << (fL1S("CONFIG += ") + _postconfigs.join(fL1S(" "))); + postcmds = _postcmds.join(fL1S("\n")); - return string; + if (host_mode != HOST_UNKNOWN_MODE) + applyHostMode(); } +void ProFileOption::applyHostMode() +{ + if (host_mode == HOST_WIN_MODE) { + dir_sep = fL1S("\\"); + } else { + dir_sep = fL1S("/"); + } +} + +QString ProFileOption::getEnv(const QString &var) const +{ +#ifndef QT_BOOTSTRAPPED + if (!environment.isEmpty()) + return environment.value(var); +#endif + return QString::fromLocal8Bit(qgetenv(var.toLocal8Bit().constData())); +} + +#ifdef PROEVALUATOR_INIT_PROPS +bool ProFileOption::initProperties(const QString &qmake) +{ + QByteArray data; +#ifndef QT_BOOTSTRAPPED + QProcess proc; + proc.start(qmake, QStringList() << QLatin1String("-query")); + if (!proc.waitForFinished()) + return false; + data = proc.readAll(); +#else + if (FILE *proc = QT_POPEN(QString(IoUtils::shellQuote(qmake) + QLatin1String(" -query")) + .toLocal8Bit(), "r")) { + char buff[1024]; + while (!feof(proc)) + data.append(buff, int(fread(buff, 1, 1023, proc))); + QT_PCLOSE(proc); + } +#endif + foreach (QByteArray line, data.split('\n')) + if (!line.startsWith("QMAKE_")) { + int off = line.indexOf(':'); + if (off < 0) // huh? + continue; + if (line.endsWith('\r')) + line.chop(1); + properties.insert(QString::fromLatin1(line.left(off)), + QString::fromLocal8Bit(line.mid(off + 1))); + } + return true; +} +#endif + /////////////////////////////////////////////////////////////////////// // // ProFileEvaluator::Private // /////////////////////////////////////////////////////////////////////// -class ProFileEvaluator::Private : public AbstractProItemVisitor +class ProFileEvaluator::Private { public: - Private(ProFileEvaluator *q_); + static void initStatics(); + Private(ProFileEvaluator *q_, ProFileOption *option, ProFileParser *parser, + ProFileEvaluatorHandler *handler); + ~Private(); ProFileEvaluator *q; - int m_lineNo; // Error reporting - bool m_verbose; - - /////////////// Reading pro file - - bool read(ProFile *pro); - - ProBlock *currentBlock(); - void updateItem(); - bool parseLine(const QString &line); - void insertVariable(const QString &line, int *i); - void insertOperator(const char op); - void insertComment(const QString &comment); - void enterScope(bool multiLine); - void leaveScope(); - void finalizeBlock(); - - QStack<ProBlock *> m_blockstack; - ProBlock *m_block; - - ProItem *m_commentItem; - QString m_proitem; - QString m_pendingComment; - bool m_syntaxError; - bool m_contNextLine; - bool m_inQuote; - int m_parens; - - /////////////// Evaluating pro file contents - - // implementation of AbstractProItemVisitor - ProItem::ProItemReturn visitBeginProBlock(ProBlock *block); - void visitEndProBlock(ProBlock *block); - ProItem::ProItemReturn visitProLoopIteration(); - void visitProLoopCleanup(); - void visitBeginProVariable(ProVariable *variable); - void visitEndProVariable(ProVariable *variable); - ProItem::ProItemReturn visitBeginProFile(ProFile *value); - ProItem::ProItemReturn visitEndProFile(ProFile *value); - void visitProValue(ProValue *value); - ProItem::ProItemReturn visitProFunction(ProFunction *function); - void visitProOperator(ProOperator *oper); - void visitProCondition(ProCondition *condition); - - QStringList valuesDirect(const QString &variableName) const { return m_valuemap[variableName]; } - QStringList values(const QString &variableName) const; - QStringList values(const QString &variableName, const ProFile *pro) const; - QStringList values(const QString &variableName, const QHash<QString, QStringList> &place, - const ProFile *pro) const; - QString propertyValue(const QString &val) const; + enum VisitReturn { + ReturnFalse, + ReturnTrue, + ReturnBreak, + ReturnNext, + ReturnReturn + }; + + static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr); + ProString getStr(const ushort *&tokPtr); + ProString getHashStr(const ushort *&tokPtr); + void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined); + static ALWAYS_INLINE void skipStr(const ushort *&tokPtr); + static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr); + void skipExpression(const ushort *&tokPtr); + + void visitCmdLine(const QString &cmds); + VisitReturn visitProFile(ProFile *pro, ProFileEvaluatorHandler::EvalFileType type, + ProFileEvaluator::LoadFlags flags); + VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr); + VisitReturn visitProBlock(const ushort *tokPtr); + VisitReturn visitProLoop(const ProString &variable, const ushort *exprPtr, + const ushort *tokPtr); + void visitProFunctionDef(ushort tok, const ProString &name, const ushort *tokPtr); + void visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr); + + static inline const ProString &map(const ProString &var); + QHash<ProString, ProStringList> *findValues(const ProString &variableName, + QHash<ProString, ProStringList>::Iterator *it); + ProStringList &valuesRef(const ProString &variableName); + ProStringList valuesDirect(const ProString &variableName) const; + ProStringList values(const ProString &variableName) const; + QString propertyValue(const QString &val, bool complain) const; + + ProStringList split_value_list(const QString &vals, const ProFile *source = 0); bool isActiveConfig(const QString &config, bool regex = false); - QStringList expandVariableReferences(const QString &value); - void doVariableReplace(QString *str); - QStringList evaluateExpandFunction(const QString &function, const QString &arguments); - QString format(const char *format) const; + ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false); + ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false); + ProStringList evaluateExpandFunction(const ProString &function, const ProString &arguments); + ProStringList evaluateExpandFunction(const ProString &function, const ushort *&tokPtr); + ProStringList evaluateExpandFunction(const ProString &function, const ProStringList &args); + void evalError(const QString &msg) const; QString currentFileName() const; QString currentDirectory() const; ProFile *currentProFile() const; - - ProItem::ProItemReturn evaluateConditionalFunction(const QString &function, const QString &arguments); - bool evaluateFile(const QString &fileName); + QString resolvePath(const QString &fileName) const + { return IoUtils::resolvePath(currentDirectory(), fileName); } + + VisitReturn evaluateConditionalFunction(const ProString &function, const ProString &arguments); + VisitReturn evaluateConditionalFunction(const ProString &function, const ushort *&tokPtr); + VisitReturn evaluateConditionalFunction(const ProString &function, const ProStringList &args); + bool evaluateFileDirect(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type, + ProFileEvaluator::LoadFlags flags); + bool evaluateFile(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type, + ProFileEvaluator::LoadFlags flags); bool evaluateFeatureFile(const QString &fileName); + enum EvalIntoMode { EvalProOnly, EvalWithDefaults, EvalWithSetup }; + bool evaluateFileInto(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type, + QHash<ProString, ProStringList> *values, FunctionDefs *defs, + EvalIntoMode mode); // values are output-only, defs are input-only + + static ALWAYS_INLINE VisitReturn returnBool(bool b) + { return b ? ReturnTrue : ReturnFalse; } + + QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr); + QList<ProStringList> prepareFunctionArgs(const ProString &arguments); + ProStringList evaluateFunction(const FunctionDef &func, const QList<ProStringList> &argumentsList, bool *ok); + VisitReturn evaluateBoolFunction(const FunctionDef &func, const QList<ProStringList> &argumentsList, + const ProString &function); + + bool modesForGenerator(const QString &gen, + ProFileOption::HOST_MODE *host_mode, ProFileOption::TARG_MODE *target_mode) const; + void validateModes() const; + QStringList qmakeMkspecPaths() const; + QStringList qmakeFeaturePaths() const; + + QString expandEnvVars(const QString &str) const; + QString fixPathToLocalOS(const QString &str) const; + QString sysrootify(const QString &path, const QString &baseDir) const; + +#ifndef QT_BOOTSTRAPPED + void runProcess(QProcess *proc, const QString &command, QProcess::ProcessChannel chan) const; +#endif - static inline ProItem::ProItemReturn returnBool(bool b) - { return b ? ProItem::ReturnTrue : ProItem::ReturnFalse; } - - QStringList evaluateFunction(ProBlock *funcPtr, const QStringList &argumentsList, bool *ok); - - QStringList qmakeFeaturePaths(); - - struct State { - bool condition; - bool prevCondition; - } m_sts; - bool m_invertNext; // Short-lived, so not in State int m_skipLevel; + int m_loopLevel; // To report unexpected break() and next()s +#ifdef PROEVALUATOR_CUMULATIVE bool m_cumulative; - bool m_isFirstVariableValue; - QString m_lastVarName; - ProVariable::VariableOperator m_variableOperator; - QString m_origfile; - QString m_oldPath; // To restore the current path to the path - QStack<ProFile*> m_profileStack; // To handle 'include(a.pri), so we can track back to 'a.pro' when finished with 'a.pri' - struct ProLoop { - QString variable; - QStringList oldVarVal; - QStringList list; - int index; - bool infinite; +#else + enum { m_cumulative = 0 }; +#endif + + struct Location { + Location() : pro(0), line(0) {} + Location(ProFile *_pro, int _line) : pro(_pro), line(_line) {} + ProFile *pro; + int line; }; - QStack<ProLoop> m_loopStack; - // we need the following two variables for handling - // CONFIG = foo bar $$CONFIG - QHash<QString, QStringList> m_tempValuemap; // used while evaluating (variable operator value1 value2 ...) - QHash<const ProFile*, QHash<QString, QStringList> > m_tempFilevaluemap; // used while evaluating (variable operator value1 value2 ...) + Location m_current; // Currently evaluated location + QStack<Location> m_locationStack; // All execution location changes + QStack<ProFile *> m_profileStack; // Includes only - QHash<QString, QStringList> m_valuemap; // VariableName must be us-ascii, the content however can be non-us-ascii. - QHash<const ProFile*, QHash<QString, QStringList> > m_filevaluemap; // Variables per include file - QHash<QString, QString> m_properties; QString m_outputDir; - bool m_definingTest; - QString m_definingFunc; - QHash<QString, ProBlock *> m_testFunctions; - QHash<QString, ProBlock *> m_replaceFunctions; - QStringList m_returnValue; - QStack<QHash<QString, QStringList> > m_valuemapStack; - QStack<QHash<const ProFile*, QHash<QString, QStringList> > > m_filevaluemapStack; + int m_listCount; + FunctionDefs m_functionDefs; + ProStringList m_returnValue; + QStack<QHash<ProString, ProStringList> > m_valuemapStack; // VariableName must be us-ascii, the content however can be non-us-ascii. + QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString + + ProFileOption *m_option; + ProFileParser *m_parser; + ProFileEvaluatorHandler *m_handler; + + enum ExpandFunc { + E_INVALID = 0, E_MEMBER, E_FIRST, E_LAST, E_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, + E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, + E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, + E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, + E_REPLACE + }; + + enum TestFunc { + T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, + T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, + T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, + T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF + }; - int m_prevLineNo; // Checking whether we're assigning the same TARGET - ProFile *m_prevProFile; // See m_prevLineNo + enum VarName { + V_LITERAL_DOLLAR, V_LITERAL_HASH, V_LITERAL_WHITESPACE, + V_DIRLIST_SEPARATOR, V_DIR_SEPARATOR, + V_OUT_PWD, V_PWD, V_IN_PWD, + V__FILE_, V__LINE_, V__PRO_FILE_, V__PRO_FILE_PWD_, + V_QMAKE_HOST_arch, V_QMAKE_HOST_name, V_QMAKE_HOST_os, + V_QMAKE_HOST_version, V_QMAKE_HOST_version_string, + V__DATE_, V__QMAKE_CACHE_ + }; }; -Q_DECLARE_TYPEINFO(ProFileEvaluator::Private::State, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(ProFileEvaluator::Private::ProLoop, Q_MOVABLE_TYPE); +static struct { + QString field_sep; + QString strtrue; + QString strfalse; + QString strunix; + QString strmacx; + QString strmac; + QString strwin32; + QString strsymbian; + ProString strCONFIG; + ProString strARGS; + QString strDot; + QString strDotDot; + QString strever; + QString strforever; + ProString strTEMPLATE; + ProString strQMAKE_DIR_SEP; + QHash<ProString, int> expands; + QHash<ProString, int> functions; + QHash<ProString, int> varList; + QHash<ProString, ProString> varMap; + QRegExp reg_variableName; + ProStringList fakeValue; +} statics; + +void ProFileEvaluator::Private::initStatics() +{ + if (!statics.field_sep.isNull()) + return; + + statics.field_sep = QLatin1String(" "); + statics.strtrue = QLatin1String("true"); + statics.strfalse = QLatin1String("false"); + statics.strunix = QLatin1String("unix"); + statics.strmacx = QLatin1String("macx"); + statics.strmac = QLatin1String("mac"); + statics.strwin32 = QLatin1String("win32"); + statics.strsymbian = QLatin1String("symbian"); + statics.strCONFIG = ProString("CONFIG"); + statics.strARGS = ProString("ARGS"); + statics.strDot = QLatin1String("."); + statics.strDotDot = QLatin1String(".."); + statics.strever = QLatin1String("ever"); + statics.strforever = QLatin1String("forever"); + statics.strTEMPLATE = ProString("TEMPLATE"); + statics.strQMAKE_DIR_SEP = ProString("QMAKE_DIR_SEP"); + + statics.reg_variableName.setPattern(QLatin1String("\\$\\(.*\\)")); + statics.reg_variableName.setMinimal(true); + + statics.fakeValue.detach(); // It has to have a unique begin() value + + static const struct { + const char * const name; + const ExpandFunc func; + } expandInits[] = { + { "member", E_MEMBER }, + { "first", E_FIRST }, + { "last", E_LAST }, + { "size", E_SIZE }, + { "cat", E_CAT }, + { "fromfile", E_FROMFILE }, + { "eval", E_EVAL }, + { "list", E_LIST }, + { "sprintf", E_SPRINTF }, + { "join", E_JOIN }, + { "split", E_SPLIT }, + { "basename", E_BASENAME }, + { "dirname", E_DIRNAME }, + { "section", E_SECTION }, + { "find", E_FIND }, + { "system", E_SYSTEM }, + { "unique", E_UNIQUE }, + { "quote", E_QUOTE }, + { "escape_expand", E_ESCAPE_EXPAND }, + { "upper", E_UPPER }, + { "lower", E_LOWER }, + { "re_escape", E_RE_ESCAPE }, + { "files", E_FILES }, + { "prompt", E_PROMPT }, // interactive, so cannot be implemented + { "replace", E_REPLACE } + }; + for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i) + statics.expands.insert(ProString(expandInits[i].name), expandInits[i].func); + + static const struct { + const char * const name; + const TestFunc func; + } testInits[] = { + { "requires", T_REQUIRES }, + { "greaterThan", T_GREATERTHAN }, + { "lessThan", T_LESSTHAN }, + { "equals", T_EQUALS }, + { "isEqual", T_EQUALS }, + { "exists", T_EXISTS }, + { "export", T_EXPORT }, + { "clear", T_CLEAR }, + { "unset", T_UNSET }, + { "eval", T_EVAL }, + { "CONFIG", T_CONFIG }, + { "if", T_IF }, + { "isActiveConfig", T_CONFIG }, + { "system", T_SYSTEM }, + { "return", T_RETURN }, + { "break", T_BREAK }, + { "next", T_NEXT }, + { "defined", T_DEFINED }, + { "contains", T_CONTAINS }, + { "infile", T_INFILE }, + { "count", T_COUNT }, + { "isEmpty", T_ISEMPTY }, + { "load", T_LOAD }, + { "include", T_INCLUDE }, + { "debug", T_DEBUG }, + { "message", T_MESSAGE }, + { "warning", T_MESSAGE }, + { "error", T_MESSAGE }, + }; + for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i) + statics.functions.insert(ProString(testInits[i].name), testInits[i].func); + + static const char * const names[] = { + "LITERAL_DOLLAR", "LITERAL_HASH", "LITERAL_WHITESPACE", + "DIRLIST_SEPARATOR", "DIR_SEPARATOR", + "OUT_PWD", "PWD", "IN_PWD", + "_FILE_", "_LINE_", "_PRO_FILE_", "_PRO_FILE_PWD_", + "QMAKE_HOST.arch", "QMAKE_HOST.name", "QMAKE_HOST.os", + "QMAKE_HOST.version", "QMAKE_HOST.version_string", + "_DATE_", "_QMAKE_CACHE_" + }; + for (unsigned i = 0; i < sizeof(names)/sizeof(names[0]); ++i) + statics.varList.insert(ProString(names[i]), i); + + static const struct { + const char * const oldname, * const newname; + } mapInits[] = { + { "INTERFACES", "FORMS" }, + { "QMAKE_POST_BUILD", "QMAKE_POST_LINK" }, + { "TARGETDEPS", "POST_TARGETDEPS" }, + { "LIBPATH", "QMAKE_LIBDIR" }, + { "QMAKE_EXT_MOC", "QMAKE_EXT_CPP_MOC" }, + { "QMAKE_MOD_MOC", "QMAKE_H_MOD_MOC" }, + { "QMAKE_LFLAGS_SHAPP", "QMAKE_LFLAGS_APP" }, + { "PRECOMPH", "PRECOMPILED_HEADER" }, + { "PRECOMPCPP", "PRECOMPILED_SOURCE" }, + { "INCPATH", "INCLUDEPATH" }, + { "QMAKE_EXTRA_WIN_COMPILERS", "QMAKE_EXTRA_COMPILERS" }, + { "QMAKE_EXTRA_UNIX_COMPILERS", "QMAKE_EXTRA_COMPILERS" }, + { "QMAKE_EXTRA_WIN_TARGETS", "QMAKE_EXTRA_TARGETS" }, + { "QMAKE_EXTRA_UNIX_TARGETS", "QMAKE_EXTRA_TARGETS" }, + { "QMAKE_EXTRA_UNIX_INCLUDES", "QMAKE_EXTRA_INCLUDES" }, + { "QMAKE_EXTRA_UNIX_VARIABLES", "QMAKE_EXTRA_VARIABLES" }, + { "QMAKE_RPATH", "QMAKE_LFLAGS_RPATH" }, + { "QMAKE_FRAMEWORKDIR", "QMAKE_FRAMEWORKPATH" }, + { "QMAKE_FRAMEWORKDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS" } + }; + for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i) + statics.varMap.insert(ProString(mapInits[i].oldname), + ProString(mapInits[i].newname)); +} + +const ProString &ProFileEvaluator::Private::map(const ProString &var) +{ + QHash<ProString, ProString>::ConstIterator it = statics.varMap.constFind(var); + return (it != statics.varMap.constEnd()) ? it.value() : var; +} + -ProFileEvaluator::Private::Private(ProFileEvaluator *q_) - : q(q_) +ProFileEvaluator::Private::Private(ProFileEvaluator *q_, ProFileOption *option, + ProFileParser *parser, ProFileEvaluatorHandler *handler) + : q(q_), m_option(option), m_parser(parser), m_handler(handler) { - // Global parser state - m_prevLineNo = 0; - m_prevProFile = 0; + // So that single-threaded apps don't have to call initialize() for now. + initStatics(); // Configuration, more or less - m_verbose = true; +#ifdef PROEVALUATOR_CUMULATIVE m_cumulative = true; +#endif // Evaluator state - m_sts.condition = false; - m_sts.prevCondition = false; - m_invertNext = false; m_skipLevel = 0; - m_isFirstVariableValue = true; - m_definingFunc.clear(); + m_loopLevel = 0; + m_listCount = 0; + m_valuemapStack.push(QHash<ProString, ProStringList>()); } -bool ProFileEvaluator::Private::read(ProFile *pro) +ProFileEvaluator::Private::~Private() { - QFile file(pro->fileName()); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - q->errorMessage(format("%1 not readable.").arg(pro->fileName())); - return false; - } - - // Parser state - m_block = 0; - m_commentItem = 0; - m_inQuote = false; - m_parens = 0; - m_contNextLine = false; - m_syntaxError = false; - m_lineNo = 1; - m_blockstack.clear(); - m_blockstack.push(pro); - - QTextStream ts(&file); - while (!ts.atEnd()) { - QString line = ts.readLine(); - if (!parseLine(line)) { - q->errorMessage(format(".pro parse failure.")); - return false; - } - ++m_lineNo; - } - return true; } -bool ProFileEvaluator::Private::parseLine(const QString &line0) -{ - if (m_blockstack.isEmpty()) - return false; - - int parens = m_parens; - bool inQuote = m_inQuote; - bool escaped = false; - QString line = line0.simplified(); +//////// Evaluator tools ///////// - for (int i = 0; !m_syntaxError && i < line.length(); ++i) { - ushort c = line.at(i).unicode(); - if (c == '#') { // Yep - no escaping possible - insertComment(line.mid(i + 1)); - escaped = m_contNextLine; - break; - } - if (!escaped) { - if (c == '\\') { - escaped = true; - m_proitem += c; - continue; - } else if (c == '"') { - inQuote = !inQuote; - m_proitem += c; - continue; - } - } else { - escaped = false; - } - if (!inQuote) { - if (c == '(') { - ++parens; - } else if (c == ')') { - --parens; - } else if (!parens) { - if (m_block && (m_block->blockKind() & ProBlock::VariableKind)) { - if (c == ' ') - 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; - } - } - } - - m_proitem += c; - } - 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; - } - return false; - } +uint ProFileEvaluator::Private::getBlockLen(const ushort *&tokPtr) +{ + uint len = *tokPtr++; + len |= (uint)*tokPtr++ << 16; + return len; } -void ProFileEvaluator::Private::finalizeBlock() +ProString ProFileEvaluator::Private::getStr(const ushort *&tokPtr) { - if (m_blockstack.isEmpty()) { - m_syntaxError = true; - } else { - if (m_blockstack.top()->blockKind() & ProBlock::SingleLine) - leaveScope(); - m_block = 0; - m_commentItem = 0; - } + uint len = *tokPtr++; + ProString ret(m_current.pro->items(), tokPtr - m_current.pro->tokPtr(), len, NoHash); + ret.setSource(m_current.pro); + tokPtr += len; + return ret; } -void ProFileEvaluator::Private::insertVariable(const QString &line, int *i) +ProString ProFileEvaluator::Private::getHashStr(const ushort *&tokPtr) { - ProVariable::VariableOperator opkind; - - if (m_proitem.isEmpty()) // Line starting with '=', like a conflict marker - return; - - switch (m_proitem.at(m_proitem.length() - 1).unicode()) { - case '+': - m_proitem.chop(1); - opkind = ProVariable::AddOperator; - break; - case '-': - m_proitem.chop(1); - opkind = ProVariable::RemoveOperator; - break; - case '*': - m_proitem.chop(1); - opkind = ProVariable::UniqueAddOperator; - break; - case '~': - m_proitem.chop(1); - opkind = ProVariable::ReplaceOperator; - break; - default: - opkind = ProVariable::SetOperator; - } + uint hash = getBlockLen(tokPtr); + uint len = *tokPtr++; + ProString ret(m_current.pro->items(), tokPtr - m_current.pro->tokPtr(), len, hash); + tokPtr += len; + return ret; +} - ProBlock *block = m_blockstack.top(); - m_proitem = m_proitem.trimmed(); - ProVariable *variable = new ProVariable(m_proitem, block); - variable->setLineNumber(m_lineNo); - variable->setVariableOperator(opkind); - block->appendItem(variable); - m_block = variable; - - if (!m_pendingComment.isEmpty()) { - m_block->setComment(m_pendingComment); - m_pendingComment.clear(); - } - m_commentItem = variable; +void ProFileEvaluator::Private::skipStr(const ushort *&tokPtr) +{ + uint len = *tokPtr++; + tokPtr += len; +} - m_proitem.clear(); +void ProFileEvaluator::Private::skipHashStr(const ushort *&tokPtr) +{ + tokPtr += 2; + uint len = *tokPtr++; + tokPtr += len; +} - if (opkind == ProVariable::ReplaceOperator) { - // skip util end of line or comment - while (1) { - ++(*i); +// FIXME: this should not build new strings for direct sections. +// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy. +ProStringList ProFileEvaluator::Private::split_value_list(const QString &vals, const ProFile *source) +{ + QString build; + ProStringList ret; + QStack<char> quote; - // end of line? - if (*i >= line.count()) - break; + const ushort SPACE = ' '; + const ushort LPAREN = '('; + const ushort RPAREN = ')'; + const ushort SINGLEQUOTE = '\''; + const ushort DOUBLEQUOTE = '"'; + const ushort BACKSLASH = '\\'; - // comment? - if (line.at(*i).unicode() == '#') { - --(*i); - break; - } + if (!source) + source = currentProFile(); + + ushort unicode; + const QChar *vals_data = vals.data(); + const int vals_len = vals.length(); + for (int x = 0, parens = 0; x < vals_len; x++) { + unicode = vals_data[x].unicode(); + if (x != (int)vals_len-1 && unicode == BACKSLASH && + (vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) { + build += vals_data[x++]; //get that 'escape' + } else if (!quote.isEmpty() && unicode == quote.top()) { + quote.pop(); + } else if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) { + quote.push(unicode); + } else if (unicode == RPAREN) { + --parens; + } else if (unicode == LPAREN) { + ++parens; + } - m_proitem += line.at(*i); + if (!parens && quote.isEmpty() && vals_data[x] == SPACE) { + ret << ProString(build, NoHash).setSource(source); + build.clear(); + } else { + build += vals_data[x]; } - m_proitem = m_proitem.trimmed(); } + if (!build.isEmpty()) + ret << ProString(build, NoHash).setSource(source); + return ret; } -void ProFileEvaluator::Private::insertOperator(const char op) +static void zipEmpty(ProStringList *value) { - updateItem(); - - ProOperator::OperatorKind opkind; - switch(op) { - case '!': - opkind = ProOperator::NotOperator; - break; - case '|': - opkind = ProOperator::OrOperator; - break; - default: - opkind = ProOperator::OrOperator; - } - - ProBlock * const block = currentBlock(); - ProOperator * const proOp = new ProOperator(opkind); - proOp->setLineNumber(m_lineNo); - block->appendItem(proOp); - m_commentItem = proOp; + for (int i = value->size(); --i >= 0;) + if (value->at(i).isEmpty()) + value->remove(i); } -void ProFileEvaluator::Private::insertComment(const QString &comment) +static void insertUnique(ProStringList *varlist, const ProStringList &value) { - updateItem(); - - QString strComment; - if (!m_commentItem) - strComment = m_pendingComment; - else - strComment = m_commentItem->comment(); - - if (strComment.isEmpty()) - strComment = comment; - else { - strComment += QLatin1Char('\n'); - strComment += comment.trimmed(); - } - - strComment = strComment.trimmed(); - - if (!m_commentItem) - m_pendingComment = strComment; - else - m_commentItem->setComment(strComment); + foreach (const ProString &str, value) + if (!str.isEmpty() && !varlist->contains(str)) + varlist->append(str); } -void ProFileEvaluator::Private::enterScope(bool multiLine) +static void removeAll(ProStringList *varlist, const ProString &value) { - updateItem(); - - ProBlock *parent = currentBlock(); - ProBlock *block = new ProBlock(parent); - block->setLineNumber(m_lineNo); - parent->setBlockKind(ProBlock::ScopeKind); - - parent->appendItem(block); - - if (multiLine) - block->setBlockKind(ProBlock::ScopeContentsKind); - else - block->setBlockKind(ProBlock::ScopeContentsKind|ProBlock::SingleLine); - - m_blockstack.push(block); - m_block = 0; + for (int i = varlist->size(); --i >= 0; ) + if (varlist->at(i) == value) + varlist->remove(i); } -void ProFileEvaluator::Private::leaveScope() +static void removeEach(ProStringList *varlist, const ProStringList &value) { - updateItem(); - m_blockstack.pop(); - finalizeBlock(); + foreach (const ProString &str, value) + if (!str.isEmpty()) + removeAll(varlist, str); } -ProBlock *ProFileEvaluator::Private::currentBlock() +static void replaceInList(ProStringList *varlist, + const QRegExp ®exp, const QString &replace, bool global, QString &tmp) { - if (m_block) - return m_block; - - ProBlock *parent = m_blockstack.top(); - m_block = new ProBlock(parent); - m_block->setLineNumber(m_lineNo); - parent->appendItem(m_block); - - if (!m_pendingComment.isEmpty()) { - m_block->setComment(m_pendingComment); - m_pendingComment.clear(); + for (ProStringList::Iterator varit = varlist->begin(); varit != varlist->end(); ) { + QString val = varit->toQString(tmp); + QString copy = val; // Force detach and have a reference value + val.replace(regexp, replace); + if (!val.isSharedWith(copy)) { + if (val.isEmpty()) { + varit = varlist->erase(varit); + } else { + (*varit).setValue(val, NoHash); + ++varit; + } + if (!global) + break; + } else { + ++varit; + } } +} - m_commentItem = m_block; - - return m_block; +QString ProFileEvaluator::Private::expandEnvVars(const QString &str) const +{ + QString string = str; + int rep; + QRegExp reg_variableName = statics.reg_variableName; // Copy for thread safety + while ((rep = reg_variableName.indexIn(string)) != -1) + string.replace(rep, reg_variableName.matchedLength(), + m_option->getEnv(string.mid(rep + 2, reg_variableName.matchedLength() - 3))); + return string; } -void ProFileEvaluator::Private::updateItem() +// This is braindead, but we want qmake compat +QString ProFileEvaluator::Private::fixPathToLocalOS(const QString &str) const { - m_proitem = m_proitem.trimmed(); - if (m_proitem.isEmpty()) - return; + QString string = expandEnvVars(str); - ProBlock *block = currentBlock(); - if (block->blockKind() & ProBlock::VariableKind) { - m_commentItem = new ProValue(m_proitem, static_cast<ProVariable*>(block)); - } else if (m_proitem.endsWith(QLatin1Char(')'))) { - m_commentItem = new ProFunction(m_proitem); - } else { - m_commentItem = new ProCondition(m_proitem); - } - m_commentItem->setLineNumber(m_lineNo); - block->appendItem(m_commentItem); + if (string.length() > 2 && string.at(0).isLetter() && string.at(1) == QLatin1Char(':')) + string[0] = string[0].toLower(); - m_proitem.clear(); +#if defined(Q_OS_WIN32) + string.replace(QLatin1Char('/'), QLatin1Char('\\')); +#else + string.replace(QLatin1Char('\\'), QLatin1Char('/')); +#endif + return string; +} + +static bool isTrue(const ProString &_str, QString &tmp) +{ + const QString &str = _str.toQString(tmp); + return !str.compare(statics.strtrue, Qt::CaseInsensitive) || str.toInt(); } +//////// Evaluator ///////// -ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) +static ALWAYS_INLINE void addStr( + const ProString &str, ProStringList *ret, bool &pending, bool joined) { - if (block->blockKind() & ProBlock::ScopeContentsKind) { - if (!m_definingFunc.isEmpty()) { - if (!m_skipLevel || m_cumulative) { - QHash<QString, ProBlock *> *hash = - (m_definingTest ? &m_testFunctions : &m_replaceFunctions); - if (ProBlock *def = hash->value(m_definingFunc)) - def->deref(); - hash->insert(m_definingFunc, block); - block->ref(); - block->setBlockKind(block->blockKind() | ProBlock::FunctionBodyKind); - } - m_definingFunc.clear(); - return ProItem::ReturnSkip; - } else if (!(block->blockKind() & ProBlock::FunctionBodyKind)) { - if (!m_sts.condition) - ++m_skipLevel; - else - Q_ASSERT(!m_skipLevel); - } + if (joined) { + ret->last().append(str, &pending); } else { - if (!m_skipLevel) { - if (m_sts.condition) { - m_sts.prevCondition = true; - m_sts.condition = false; - } + if (!pending) { + pending = true; + *ret << str; } else { - Q_ASSERT(!m_sts.condition); + ret->last().append(str); } } - return ProItem::ReturnTrue; } -void ProFileEvaluator::Private::visitEndProBlock(ProBlock *block) +static ALWAYS_INLINE void addStrList( + const ProStringList &list, ushort tok, ProStringList *ret, bool &pending, bool joined) { - if ((block->blockKind() & ProBlock::ScopeContentsKind) - && !(block->blockKind() & ProBlock::FunctionBodyKind)) { - if (m_skipLevel) { - Q_ASSERT(!m_sts.condition); - --m_skipLevel; - } else if (!(block->blockKind() & ProBlock::SingleLine)) { - // Conditionals contained inside this block may have changed the state. - // So we reset it here to make an else following us do the right thing. - m_sts.condition = true; + if (!list.isEmpty()) { + if (joined) { + ret->last().append(list, &pending, !(tok & TokQuoted)); + } else { + if (tok & TokQuoted) { + if (!pending) { + pending = true; + *ret << ProString(); + } + ret->last().append(list); + } else { + if (!pending) { + // Another qmake bizzarity: if nothing is pending and the + // first element is empty, it will be eaten + if (!list.at(0).isEmpty()) { + // The common case + pending = true; + *ret += list; + return; + } + } else { + ret->last().append(list.at(0)); + } + // This is somewhat slow, but a corner case + for (int j = 1; j < list.size(); ++j) { + pending = true; + *ret << list.at(j); + } + } } } } -ProItem::ProItemReturn ProFileEvaluator::Private::visitProLoopIteration() -{ - ProLoop &loop = m_loopStack.top(); - - if (loop.infinite) { - if (!loop.variable.isEmpty()) - m_valuemap[loop.variable] = QStringList(QString::number(loop.index++)); - if (loop.index > 1000) { - q->errorMessage(format("ran into infinite loop (> 1000 iterations).")); - return ProItem::ReturnFalse; +void ProFileEvaluator::Private::evaluateExpression( + const ushort *&tokPtr, ProStringList *ret, bool joined) +{ + if (joined) + *ret << ProString(); + bool pending = false; + forever { + ushort tok = *tokPtr++; + if (tok & TokNewStr) + pending = false; + ushort maskedTok = tok & TokMask; + switch (maskedTok) { + case TokLine: + m_current.line = *tokPtr++; + break; + case TokLiteral: + addStr(getStr(tokPtr), ret, pending, joined); + break; + case TokHashLiteral: + addStr(getHashStr(tokPtr), ret, pending, joined); + break; + case TokVariable: + addStrList(values(map(getHashStr(tokPtr))), tok, ret, pending, joined); + break; + case TokProperty: + addStr(ProString(propertyValue( + getStr(tokPtr).toQString(m_tmp1), true), NoHash).setSource(currentProFile()), + ret, pending, joined); + break; + case TokEnvVar: + addStrList(split_value_list(m_option->getEnv(getStr(tokPtr).toQString(m_tmp1))), + tok, ret, pending, joined); + break; + case TokFuncName: { + ProString func = getHashStr(tokPtr); + addStrList(evaluateExpandFunction(func, tokPtr), tok, ret, pending, joined); + break; } + default: + tokPtr--; + return; } - } else { - QString val; - do { - if (loop.index >= loop.list.count()) - return ProItem::ReturnFalse; - val = loop.list.at(loop.index++); - } while (val.isEmpty()); // stupid, but qmake is like that - m_valuemap[loop.variable] = QStringList(val); } - return ProItem::ReturnTrue; -} - -void ProFileEvaluator::Private::visitProLoopCleanup() -{ - ProLoop &loop = m_loopStack.top(); - m_valuemap[loop.variable] = loop.oldVarVal; - m_loopStack.pop_back(); } -void ProFileEvaluator::Private::visitBeginProVariable(ProVariable *variable) +void ProFileEvaluator::Private::skipExpression(const ushort *&pTokPtr) { - m_lastVarName = variable->variable(); - m_variableOperator = variable->variableOperator(); - m_isFirstVariableValue = true; - m_tempValuemap = m_valuemap; - m_tempFilevaluemap = m_filevaluemap; + const ushort *tokPtr = pTokPtr; + forever { + ushort tok = *tokPtr++; + switch (tok) { + case TokLine: + m_current.line = *tokPtr++; + break; + case TokValueTerminator: + case TokFuncTerminator: + pTokPtr = tokPtr; + return; + case TokArgSeparator: + break; + default: + switch (tok & TokMask) { + case TokLiteral: + case TokProperty: + case TokEnvVar: + skipStr(tokPtr); + break; + case TokHashLiteral: + case TokVariable: + skipHashStr(tokPtr); + break; + case TokFuncName: + skipHashStr(tokPtr); + pTokPtr = tokPtr; + skipExpression(pTokPtr); + tokPtr = pTokPtr; + break; + default: + Q_ASSERT_X(false, "skipExpression", "Unrecognized token"); + break; + } + } + } } -void ProFileEvaluator::Private::visitEndProVariable(ProVariable *variable) -{ - Q_UNUSED(variable); - m_valuemap = m_tempValuemap; - m_filevaluemap = m_tempFilevaluemap; - m_lastVarName.clear(); +ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock( + ProFile *pro, const ushort *tokPtr) +{ + m_current.pro = pro; + m_current.line = 0; + return visitProBlock(tokPtr); +} + +ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock( + const ushort *tokPtr) +{ + ProStringList curr; + bool okey = true, or_op = false, invert = false; + uint blockLen; + VisitReturn ret = ReturnTrue; + while (ushort tok = *tokPtr++) { + switch (tok) { + case TokLine: + m_current.line = *tokPtr++; + continue; + case TokAssign: + case TokAppend: + case TokAppendUnique: + case TokRemove: + case TokReplace: + visitProVariable(tok, curr, tokPtr); + curr.clear(); + continue; + case TokBranch: + blockLen = getBlockLen(tokPtr); + if (m_cumulative) { + if (!okey) + m_skipLevel++; + ret = blockLen ? visitProBlock(tokPtr) : ReturnTrue; + tokPtr += blockLen; + blockLen = getBlockLen(tokPtr); + if (!okey) + m_skipLevel--; + else + m_skipLevel++; + if ((ret == ReturnTrue || ret == ReturnFalse) && blockLen) + ret = visitProBlock(tokPtr); + if (okey) + m_skipLevel--; + } else { + if (okey) + ret = blockLen ? visitProBlock(tokPtr) : ReturnTrue; + tokPtr += blockLen; + blockLen = getBlockLen(tokPtr); + if (!okey) + ret = blockLen ? visitProBlock(tokPtr) : ReturnTrue; + } + tokPtr += blockLen; + okey = true, or_op = false; // force next evaluation + break; + case TokForLoop: + if (m_cumulative) { // This is a no-win situation, so just pretend it's no loop + skipHashStr(tokPtr); + uint exprLen = getBlockLen(tokPtr); + tokPtr += exprLen; + blockLen = getBlockLen(tokPtr); + ret = visitProBlock(tokPtr); + } else if (okey != or_op) { + const ProString &variable = getHashStr(tokPtr); + uint exprLen = getBlockLen(tokPtr); + const ushort *exprPtr = tokPtr; + tokPtr += exprLen; + blockLen = getBlockLen(tokPtr); + ret = visitProLoop(variable, exprPtr, tokPtr); + } else { + skipHashStr(tokPtr); + uint exprLen = getBlockLen(tokPtr); + tokPtr += exprLen; + blockLen = getBlockLen(tokPtr); + ret = ReturnTrue; + } + tokPtr += blockLen; + okey = true, or_op = false; // force next evaluation + break; + case TokTestDef: + case TokReplaceDef: + if (m_cumulative || okey != or_op) { + const ProString &name = getHashStr(tokPtr); + blockLen = getBlockLen(tokPtr); + visitProFunctionDef(tok, name, tokPtr); + } else { + skipHashStr(tokPtr); + blockLen = getBlockLen(tokPtr); + } + tokPtr += blockLen; + okey = true, or_op = false; // force next evaluation + continue; + case TokNot: + invert ^= true; + continue; + case TokAnd: + or_op = false; + continue; + case TokOr: + or_op = true; + continue; + case TokCondition: + if (!m_skipLevel && okey != or_op) { + if (curr.size() != 1) { + if (!m_cumulative || !curr.isEmpty()) + evalError(fL1S("Conditional must expand to exactly one word.")); + okey = false; + } else { + okey = isActiveConfig(curr.at(0).toQString(m_tmp2), true) ^ invert; + } + } + or_op = !okey; // tentatively force next evaluation + invert = false; + curr.clear(); + continue; + case TokTestCall: + if (!m_skipLevel && okey != or_op) { + if (curr.size() != 1) { + if (!m_cumulative || !curr.isEmpty()) + evalError(fL1S("Test name must expand to exactly one word.")); + skipExpression(tokPtr); + okey = false; + } else { + ret = evaluateConditionalFunction(curr.at(0), tokPtr); + switch (ret) { + case ReturnTrue: okey = true; break; + case ReturnFalse: okey = false; break; + default: return ret; + } + okey ^= invert; + } + } else if (m_cumulative) { + m_skipLevel++; + if (curr.size() != 1) + skipExpression(tokPtr); + else + evaluateConditionalFunction(curr.at(0), tokPtr); + m_skipLevel--; + } else { + skipExpression(tokPtr); + } + or_op = !okey; // tentatively force next evaluation + invert = false; + curr.clear(); + continue; + default: { + const ushort *oTokPtr = --tokPtr; + evaluateExpression(tokPtr, &curr, false); + if (tokPtr != oTokPtr) + continue; + } + Q_ASSERT_X(false, "visitProBlock", "unexpected item type"); + } + if (ret != ReturnTrue && ret != ReturnFalse) + break; + } + return ret; } -void ProFileEvaluator::Private::visitProOperator(ProOperator *oper) -{ - m_invertNext = (oper->operatorKind() == ProOperator::NotOperator); -} -void ProFileEvaluator::Private::visitProCondition(ProCondition *cond) +void ProFileEvaluator::Private::visitProFunctionDef( + ushort tok, const ProString &name, const ushort *tokPtr) { - if (!m_skipLevel) { - if (!cond->text().compare(QLatin1String("else"), Qt::CaseInsensitive)) { - m_sts.condition = !m_sts.prevCondition; - } else { - m_sts.prevCondition = false; - if (!m_sts.condition && isActiveConfig(cond->text(), true) ^ m_invertNext) - m_sts.condition = true; - } - } - m_invertNext = false; + QHash<ProString, FunctionDef> *hash = + (tok == TokTestDef + ? &m_functionDefs.testFunctions + : &m_functionDefs.replaceFunctions); + hash->insert(name, FunctionDef(m_current.pro, tokPtr - m_current.pro->tokPtr())); } -ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pro) +ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProLoop( + const ProString &_variable, const ushort *exprPtr, const ushort *tokPtr) { - PRE(pro); - m_lineNo = pro->lineNumber(); - if (m_origfile.isEmpty()) - m_origfile = pro->fileName(); - if (m_oldPath.isEmpty()) { - // change the working directory for the initial profile we visit, since - // that is *the* profile. All the other times we reach this function will be due to - // include(file) or load(file) - - m_oldPath = QDir::currentPath(); - - m_profileStack.push(pro); - - const QString mkspecDirectory = propertyValue(QLatin1String("QMAKE_MKSPECS")); - if (!mkspecDirectory.isEmpty()) { - bool cumulative = m_cumulative; - m_cumulative = false; - // This is what qmake does, everything set in the mkspec is also set - // But this also creates a lot of problems - evaluateFile(mkspecDirectory + QLatin1String("/default/qmake.conf")); - evaluateFile(mkspecDirectory + QLatin1String("/features/default_pre.prf")); - m_cumulative = cumulative; + VisitReturn ret = ReturnTrue; + bool infinite = false; + int index = 0; + ProString variable; + ProStringList oldVarVal; + ProString it_list = expandVariableReferences(exprPtr, 0, true).at(0); + if (_variable.isEmpty()) { + if (it_list != statics.strever) { + evalError(fL1S("Invalid loop expression.")); + return ReturnFalse; } - - return returnBool(QDir::setCurrent(pro->directoryName())); + it_list = ProString(statics.strforever); + } else { + variable = map(_variable); + oldVarVal = valuesDirect(variable); } - - return ProItem::ReturnTrue; -} - -ProItem::ProItemReturn ProFileEvaluator::Private::visitEndProFile(ProFile * pro) -{ - PRE(pro); - m_lineNo = pro->lineNumber(); - if (m_profileStack.count() == 1 && !m_oldPath.isEmpty()) { - const QString &mkspecDirectory = propertyValue(QLatin1String("QMAKE_MKSPECS")); - if (!mkspecDirectory.isEmpty()) { - bool cumulative = m_cumulative; - m_cumulative = false; - - evaluateFile(mkspecDirectory + QLatin1String("/features/default_post.prf")); - - QSet<QString> processed; - forever { - bool finished = true; - QStringList configs = valuesDirect(QLatin1String("CONFIG")); - for (int i = configs.size() - 1; i >= 0; --i) { - const QString config = configs[i].toLower(); - if (!processed.contains(config)) { - processed.insert(config); - if (evaluateFile(mkspecDirectory + QLatin1String("/features/") - + config + QLatin1String(".prf"))) { - finished = false; - break; + ProStringList list = valuesDirect(it_list); + if (list.isEmpty()) { + if (it_list == statics.strforever) { + infinite = true; + } else { + const QString &itl = it_list.toQString(m_tmp1); + int dotdot = itl.indexOf(statics.strDotDot); + if (dotdot != -1) { + bool ok; + int start = itl.left(dotdot).toInt(&ok); + if (ok) { + int end = itl.mid(dotdot+2).toInt(&ok); + if (ok) { + if (start < end) { + for (int i = start; i <= end; i++) + list << ProString(QString::number(i), NoHash); + } else { + for (int i = start; i >= end; i--) + list << ProString(QString::number(i), NoHash); } } } - if (finished) - break; } - - foreach (ProBlock *itm, m_replaceFunctions) - itm->deref(); - m_replaceFunctions.clear(); - foreach (ProBlock *itm, m_testFunctions) - itm->deref(); - m_testFunctions.clear(); - - m_cumulative = cumulative; } - - m_profileStack.pop(); - return returnBool(QDir::setCurrent(m_oldPath)); } - return ProItem::ReturnTrue; -} - -static void replaceInList(QStringList *varlist, - const QRegExp ®exp, const QString &replace, bool global) -{ - for (QStringList::Iterator varit = varlist->begin(); varit != varlist->end(); ) { - if ((*varit).contains(regexp)) { - (*varit).replace(regexp, replace); - if ((*varit).isEmpty()) - varit = varlist->erase(varit); - else - ++varit; - if(!global) + m_loopLevel++; + forever { + if (infinite) { + if (!variable.isEmpty()) + m_valuemapStack.top()[variable] = ProStringList(ProString(QString::number(index++), NoHash)); + if (index > 1000) { + evalError(fL1S("ran into infinite loop (> 1000 iterations).")); break; + } } else { - ++varit; + ProString val; + do { + if (index >= list.count()) + goto do_break; + val = list.at(index++); + } while (val.isEmpty()); // stupid, but qmake is like that + m_valuemapStack.top()[variable] = ProStringList(val); + } + + ret = visitProBlock(tokPtr); + switch (ret) { + case ReturnTrue: + case ReturnFalse: + break; + case ReturnNext: + ret = ReturnTrue; + break; + case ReturnBreak: + ret = ReturnTrue; + goto do_break; + default: + goto do_break; } } + do_break: + m_loopLevel--; + + if (!variable.isEmpty()) + m_valuemapStack.top()[variable] = oldVarVal; + return ret; } -void ProFileEvaluator::Private::visitProValue(ProValue *value) +void ProFileEvaluator::Private::visitProVariable( + ushort tok, const ProStringList &curr, const ushort *&tokPtr) { - PRE(value); - m_lineNo = value->lineNumber(); - QString val = value->value(); + int sizeHint = *tokPtr++; - QString varName = m_lastVarName; + if (curr.size() != 1) { + skipExpression(tokPtr); + if (!m_cumulative || !curr.isEmpty()) + evalError(fL1S("Left hand side of assignment must expand to exactly one word.")); + return; + } + const ProString &varName = map(curr.first()); - QStringList v = expandVariableReferences(val); + if (tok == TokReplace) { // ~= + // DEFINES ~= s/a/b/?[gqi] - // Since qmake combines different values for the TARGET variable, we join - // TARGET values that are on the same line. We can't do this later with all - // values because this parser isn't scope-aware, so we'd risk joining - // scope-specific targets together. - if (varName == QLatin1String("TARGET") - && m_lineNo == m_prevLineNo - && currentProFile() == m_prevProFile) { - QStringList targets = m_tempValuemap.value(QLatin1String("TARGET")); - m_tempValuemap.remove(QLatin1String("TARGET")); - QStringList lastTarget(targets.takeLast()); - lastTarget << v.join(QLatin1String(" ")); - targets.push_back(lastTarget.join(QLatin1String(" "))); - v = targets; - } - m_prevLineNo = m_lineNo; - m_prevProFile = currentProFile(); + const ProStringList &varVal = expandVariableReferences(tokPtr, sizeHint, true); + const QString &val = varVal.at(0).toQString(m_tmp1); + if (val.length() < 4 || val.at(0) != QLatin1Char('s')) { + evalError(fL1S("the ~= operator can handle only the s/// function.")); + return; + } + QChar sep = val.at(1); + QStringList func = val.split(sep); + if (func.count() < 3 || func.count() > 4) { + evalError(fL1S("the s/// function expects 3 or 4 arguments.")); + return; + } + + bool global = false, quote = false, case_sense = false; + if (func.count() == 4) { + global = func[3].indexOf(QLatin1Char('g')) != -1; + case_sense = func[3].indexOf(QLatin1Char('i')) == -1; + quote = func[3].indexOf(QLatin1Char('q')) != -1; + } + QString pattern = func[1]; + QString replace = func[2]; + if (quote) + pattern = QRegExp::escape(pattern); + + QRegExp regexp(pattern, case_sense ? Qt::CaseSensitive : Qt::CaseInsensitive); - switch (m_variableOperator) { - case ProVariable::SetOperator: // = + if (!m_skipLevel || m_cumulative) { + // We could make a union of modified and unmodified values, + // but this will break just as much as it fixes, so leave it as is. + replaceInList(&valuesRef(varName), regexp, replace, global, m_tmp2); + } + } else { + ProStringList varVal = expandVariableReferences(tokPtr, sizeHint); + switch (tok) { + default: // whatever - cannot happen + case TokAssign: // = if (!m_cumulative) { if (!m_skipLevel) { - if (m_isFirstVariableValue) { - m_tempValuemap[varName] = v; - m_tempFilevaluemap[currentProFile()][varName] = v; - } else { // handle lines "CONFIG = foo bar" - m_tempValuemap[varName] += v; - m_tempFilevaluemap[currentProFile()][varName] += v; - } + zipEmpty(&varVal); + m_valuemapStack.top()[varName] = varVal; } } else { - // We are greedy for values. - m_tempValuemap[varName] += v; - m_tempFilevaluemap[currentProFile()][varName] += v; + zipEmpty(&varVal); + if (!varVal.isEmpty()) { + // We are greedy for values. But avoid exponential growth. + ProStringList &v = valuesRef(varName); + if (v.isEmpty()) { + v = varVal; + } else { + ProStringList old = v; + v = varVal; + QSet<ProString> has; + has.reserve(v.size()); + foreach (const ProString &s, v) + has.insert(s); + v.reserve(v.size() + old.size()); + foreach (const ProString &s, old) + if (!has.contains(s)) + v << s; + } + } } break; - case ProVariable::UniqueAddOperator: // *= - if (!m_skipLevel || m_cumulative) { - insertUnique(&m_tempValuemap, varName, v); - insertUnique(&m_tempFilevaluemap[currentProFile()], varName, v); - } + case TokAppendUnique: // *= + if (!m_skipLevel || m_cumulative) + insertUnique(&valuesRef(varName), varVal); break; - case ProVariable::AddOperator: // += + case TokAppend: // += if (!m_skipLevel || m_cumulative) { - m_tempValuemap[varName] += v; - m_tempFilevaluemap[currentProFile()][varName] += v; + zipEmpty(&varVal); + valuesRef(varName) += varVal; } break; - case ProVariable::RemoveOperator: // -= + case TokRemove: // -= if (!m_cumulative) { - if (!m_skipLevel) { - removeEach(&m_tempValuemap, varName, v); - removeEach(&m_tempFilevaluemap[currentProFile()], varName, v); - } + if (!m_skipLevel) + removeEach(&valuesRef(varName), varVal); } else { // We are stingy with our values, too. } break; - case ProVariable::ReplaceOperator: // ~= - { - // DEFINES ~= s/a/b/?[gqi] + } + } +} - doVariableReplace(&val); - if (val.length() < 4 || val[0] != QLatin1Char('s')) { - q->logMessage(format("the ~= operator can handle only the s/// function.")); - break; +void ProFileEvaluator::Private::visitCmdLine(const QString &cmds) +{ + if (!cmds.isEmpty()) { + if (ProFile *pro = m_parser->parsedProBlock(fL1S("(command line)"), cmds)) { + m_locationStack.push(m_current); + visitProBlock(pro, pro->tokPtr()); + m_current = m_locationStack.pop(); + pro->deref(); + } + } +} + +ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile( + ProFile *pro, ProFileEvaluatorHandler::EvalFileType type, + ProFileEvaluator::LoadFlags flags) +{ + if (!m_cumulative && !pro->isOk()) + return ReturnFalse; + + m_handler->aboutToEval(currentProFile(), pro, type); + m_profileStack.push(pro); + if (flags & LoadPreFiles) { +#ifdef PROEVALUATOR_THREAD_SAFE + { + QMutexLocker locker(&m_option->mutex); + if (m_option->base_inProgress) { + QThreadPool::globalInstance()->releaseThread(); + m_option->cond.wait(&m_option->mutex); + QThreadPool::globalInstance()->reserveThread(); + } else +#endif + if (m_option->base_valuemap.isEmpty()) { +#ifdef PROEVALUATOR_THREAD_SAFE + m_option->base_inProgress = true; + locker.unlock(); +#endif + +#ifdef PROEVALUATOR_CUMULATIVE + bool cumulative = m_cumulative; + m_cumulative = false; +#endif + + // ### init QMAKE_QMAKE, QMAKE_SH + // ### init QMAKE_EXT_{C,H,CPP,OBJ} + // ### init TEMPLATE_PREFIX + + QString qmake_cache = m_option->cachefile; + if (qmake_cache.isEmpty() && !m_outputDir.isEmpty()) { //find it as it has not been specified + QDir dir(m_outputDir); + forever { + qmake_cache = dir.path() + QLatin1String("/.qmake.cache"); + if (IoUtils::exists(qmake_cache)) + break; + if (!dir.cdUp() || dir.isRoot()) { + qmake_cache.clear(); + break; + } + } } - QChar sep = val.at(1); - QStringList func = val.split(sep); - if (func.count() < 3 || func.count() > 4) { - q->logMessage(format("the s/// function expects 3 or 4 arguments.")); - break; + if (!qmake_cache.isEmpty()) { + qmake_cache = resolvePath(qmake_cache); + QHash<ProString, ProStringList> cache_valuemap; + if (evaluateFileInto(qmake_cache, ProFileEvaluatorHandler::EvalConfigFile, + &cache_valuemap, 0, EvalProOnly)) { + if (m_option->qmakespec.isEmpty()) { + const ProStringList &vals = cache_valuemap.value(ProString("QMAKESPEC")); + if (!vals.isEmpty()) + m_option->qmakespec = vals.first().toQString(); + } + } else { + qmake_cache.clear(); + } } + m_option->cachefile = qmake_cache; + + QStringList mkspec_roots = qmakeMkspecPaths(); - bool global = false, quote = false, case_sense = false; - if (func.count() == 4) { - global = func[3].indexOf(QLatin1Char('g')) != -1; - case_sense = func[3].indexOf(QLatin1Char('i')) == -1; - quote = func[3].indexOf(QLatin1Char('q')) != -1; + QString qmakespec = expandEnvVars(m_option->qmakespec); + if (qmakespec.isEmpty()) { + foreach (const QString &root, mkspec_roots) { + QString mkspec = root + QLatin1String("/default"); + if (IoUtils::fileType(mkspec) == IoUtils::FileIsDir) { + qmakespec = mkspec; + break; + } + } + if (qmakespec.isEmpty()) { + m_handler->configError(fL1S("Could not find qmake configuration directory")); + // Unlike in qmake, not finding the spec is not critical ... + } } - QString pattern = func[1]; - QString replace = func[2]; - if (quote) - pattern = QRegExp::escape(pattern); - - QRegExp regexp(pattern, case_sense ? Qt::CaseSensitive : Qt::CaseInsensitive); - - if (!m_skipLevel || m_cumulative) { - // We could make a union of modified and unmodified values, - // but this will break just as much as it fixes, so leave it as is. - replaceInList(&m_tempValuemap[varName], regexp, replace, global); - replaceInList(&m_tempFilevaluemap[currentProFile()][varName], regexp, replace, global); + + if (IoUtils::isRelativePath(qmakespec)) { + if (IoUtils::exists(currentDirectory() + QLatin1Char('/') + qmakespec + + QLatin1String("/qmake.conf"))) { + qmakespec = currentDirectory() + QLatin1Char('/') + qmakespec; + } else if (!m_outputDir.isEmpty() + && IoUtils::exists(m_outputDir + QLatin1Char('/') + qmakespec + + QLatin1String("/qmake.conf"))) { + qmakespec = m_outputDir + QLatin1Char('/') + qmakespec; + } else { + foreach (const QString &root, mkspec_roots) { + QString mkspec = root + QLatin1Char('/') + qmakespec; + if (IoUtils::exists(mkspec)) { + qmakespec = mkspec; + goto cool; + } + } + m_handler->configError(fL1S("Could not find qmake configuration file")); + // Unlike in qmake, a missing config is not critical ... + qmakespec.clear(); + cool: ; + } } + + if (!qmakespec.isEmpty()) { + m_option->qmakespec = QDir::cleanPath(qmakespec); + + QString spec = m_option->qmakespec + QLatin1String("/qmake.conf"); + if (!evaluateFileDirect(spec, ProFileEvaluatorHandler::EvalConfigFile, + ProFileEvaluator::LoadProOnly)) { + m_handler->configError( + fL1S("Could not read qmake configuration file %1").arg(spec)); + } else if (!m_option->cachefile.isEmpty()) { + evaluateFileDirect(m_option->cachefile, + ProFileEvaluatorHandler::EvalConfigFile, + ProFileEvaluator::LoadProOnly); + } + m_option->qmakespec_name = IoUtils::fileName(m_option->qmakespec).toString(); + if (m_option->qmakespec_name == QLatin1String("default")) { +#ifdef Q_OS_UNIX + char buffer[1024]; + int l = ::readlink(m_option->qmakespec.toLocal8Bit().constData(), buffer, 1024); + if (l != -1) + m_option->qmakespec_name = + IoUtils::fileName(QString::fromLocal8Bit(buffer, l)).toString(); +#else + // We can't resolve symlinks as they do on Unix, so configure.exe puts + // the source of the qmake.conf at the end of the default/qmake.conf in + // the QMAKESPEC_ORG variable. + const ProStringList &spec_org = + m_option->base_valuemap.value(ProString("QMAKESPEC_ORIGINAL")); + if (!spec_org.isEmpty()) + m_option->qmakespec_name = + IoUtils::fileName(spec_org.first().toQString()).toString(); +#endif + } + } + + evaluateFeatureFile(QLatin1String("default_pre.prf")); + + m_option->base_valuemap = m_valuemapStack.top(); + m_option->base_functions = m_functionDefs; + +#ifdef PROEVALUATOR_CUMULATIVE + m_cumulative = cumulative; +#endif + +#ifdef PROEVALUATOR_THREAD_SAFE + locker.relock(); + m_option->base_inProgress = false; + m_option->cond.wakeAll(); +#endif + goto fresh; } - break; +#ifdef PROEVALUATOR_THREAD_SAFE + } +#endif + + m_valuemapStack.top() = m_option->base_valuemap; + m_functionDefs = m_option->base_functions; + fresh: + ProStringList &tgt = m_valuemapStack.top()[ProString("TARGET")]; + if (tgt.isEmpty()) + tgt.append(ProString(QFileInfo(pro->fileName()).baseName(), NoHash)); + + visitCmdLine(m_option->precmds); } - m_isFirstVariableValue = false; -} -ProItem::ProItemReturn ProFileEvaluator::Private::visitProFunction(ProFunction *func) -{ - // Make sure that called subblocks don't inherit & destroy the state - bool invertThis = m_invertNext; - m_invertNext = false; - if (!m_skipLevel) - m_sts.prevCondition = false; - if (m_cumulative || !m_sts.condition) { - QString text = func->text(); - int lparen = text.indexOf(QLatin1Char('(')); - int rparen = text.lastIndexOf(QLatin1Char(')')); - Q_ASSERT(lparen < rparen); - QString arguments = text.mid(lparen + 1, rparen - lparen - 1); - QString funcName = text.left(lparen); - m_lineNo = func->lineNumber(); - ProItem::ProItemReturn result = evaluateConditionalFunction(funcName.trimmed(), arguments); - if (result != ProItem::ReturnFalse && result != ProItem::ReturnTrue) - return result; - if (!m_skipLevel && ((result == ProItem::ReturnTrue) ^ invertThis)) - m_sts.condition = true; + visitProBlock(pro, pro->tokPtr()); + + if (flags & LoadPostFiles) { + visitCmdLine(m_option->postcmds); + + evaluateFeatureFile(QLatin1String("default_post.prf")); + + QSet<QString> processed; + forever { + bool finished = true; + ProStringList configs = valuesDirect(statics.strCONFIG); + for (int i = configs.size() - 1; i >= 0; --i) { + QString config = configs.at(i).toQString(m_tmp1).toLower(); + if (!processed.contains(config)) { + config.detach(); + processed.insert(config); + if (evaluateFeatureFile(config)) { + finished = false; + break; + } + } + } + if (finished) + break; + } } - return ProItem::ReturnTrue; + m_profileStack.pop(); + m_handler->doneWithEval(currentProFile()); + + return ReturnTrue; } -QStringList ProFileEvaluator::Private::qmakeFeaturePaths() +QStringList ProFileEvaluator::Private::qmakeMkspecPaths() const +{ + QStringList ret; + const QString concat = QLatin1String("/mkspecs"); + + QString qmakepath = m_option->getEnv(QLatin1String("QMAKEPATH")); + if (!qmakepath.isEmpty()) + foreach (const QString &it, qmakepath.split(m_option->dirlist_sep)) + ret << QDir::cleanPath(it) + concat; + + QString builtIn = propertyValue(QLatin1String("QT_INSTALL_DATA"), false) + concat; + if (!ret.contains(builtIn)) + ret << builtIn; + + return ret; +} + +QStringList ProFileEvaluator::Private::qmakeFeaturePaths() const { + QString mkspecs_concat = QLatin1String("/mkspecs"); + QString features_concat = QLatin1String("/features"); QStringList concat; - { - const QString base_concat = QDir::separator() + QLatin1String("features"); - concat << base_concat + QDir::separator() + QLatin1String("mac"); - concat << base_concat + QDir::separator() + QLatin1String("macx"); - concat << base_concat + QDir::separator() + QLatin1String("unix"); - concat << base_concat + QDir::separator() + QLatin1String("win32"); - concat << base_concat + QDir::separator() + QLatin1String("mac9"); - concat << base_concat + QDir::separator() + QLatin1String("qnx6"); - concat << base_concat; + + validateModes(); + switch (m_option->target_mode) { + case ProFileOption::TARG_MACX_MODE: + concat << QLatin1String("/features/mac"); + concat << QLatin1String("/features/macx"); + concat << QLatin1String("/features/unix"); + break; + default: // Can't happen, just make the compiler shut up + case ProFileOption::TARG_UNIX_MODE: + concat << QLatin1String("/features/unix"); + break; + case ProFileOption::TARG_WIN_MODE: + concat << QLatin1String("/features/win32"); + break; + case ProFileOption::TARG_SYMBIAN_MODE: + concat << QLatin1String("/features/symbian"); + break; } - const QString mkspecs_concat = QDir::separator() + QLatin1String("mkspecs"); + concat << features_concat; + QStringList feature_roots; - QByteArray mkspec_path = qgetenv("QMAKEFEATURES"); - if (!mkspec_path.isNull()) - feature_roots += splitPathList(QString::fromLocal8Bit(mkspec_path)); - /* - if (prop) - feature_roots += splitPathList(prop->value("QMAKEFEATURES")); - if (!Option::mkfile::cachefile.isEmpty()) { - QString path; - int last_slash = Option::mkfile::cachefile.lastIndexOf(Option::dir_sep); - if (last_slash != -1) - path = Option::fixPathToLocalOS(Option::mkfile::cachefile.left(last_slash)); + + QString mkspec_path = m_option->getEnv(QLatin1String("QMAKEFEATURES")); + if (!mkspec_path.isEmpty()) + foreach (const QString &f, mkspec_path.split(m_option->dirlist_sep)) + feature_roots += resolvePath(f); + + feature_roots += propertyValue(QLatin1String("QMAKEFEATURES"), false).split( + m_option->dirlist_sep, QString::SkipEmptyParts); + + if (!m_option->cachefile.isEmpty()) { + QString path = m_option->cachefile.left(m_option->cachefile.lastIndexOf((ushort)'/')); foreach (const QString &concat_it, concat) feature_roots << (path + concat_it); } - */ - QByteArray qmakepath = qgetenv("QMAKEPATH"); + QString qmakepath = m_option->getEnv(QLatin1String("QMAKEPATH")); if (!qmakepath.isNull()) { - const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath)); + const QStringList lst = qmakepath.split(m_option->dirlist_sep); foreach (const QString &item, lst) { + QString citem = resolvePath(item); foreach (const QString &concat_it, concat) - feature_roots << (item + mkspecs_concat + concat_it); + feature_roots << (citem + mkspecs_concat + concat_it); } } - //if (!Option::mkfile::qmakespec.isEmpty()) - // feature_roots << Option::mkfile::qmakespec + QDir::separator() + "features"; - //if (!Option::mkfile::qmakespec.isEmpty()) { - // QFileInfo specfi(Option::mkfile::qmakespec); - // QDir specdir(specfi.absoluteFilePath()); - // while (!specdir.isRoot()) { - // if (!specdir.cdUp() || specdir.isRoot()) - // break; - // if (QFile::exists(specdir.path() + QDir::separator() + "features")) { - // foreach (const QString &concat_it, concat) - // feature_roots << (specdir.path() + concat_it); - // break; - // } - // } - //} + + if (!m_option->qmakespec.isEmpty()) { + QString qmakespec = resolvePath(m_option->qmakespec); + feature_roots << (qmakespec + features_concat); + + QDir specdir(qmakespec); + while (!specdir.isRoot()) { + if (!specdir.cdUp() || specdir.isRoot()) + break; + if (IoUtils::exists(specdir.path() + features_concat)) { + foreach (const QString &concat_it, concat) + feature_roots << (specdir.path() + concat_it); + break; + } + } + } + foreach (const QString &concat_it, concat) - feature_roots << (propertyValue(QLatin1String("QT_INSTALL_PREFIX")) + + feature_roots << (propertyValue(QLatin1String("QT_INSTALL_PREFIX"), false) + mkspecs_concat + concat_it); foreach (const QString &concat_it, concat) - feature_roots << (propertyValue(QLatin1String("QT_INSTALL_DATA")) + + feature_roots << (propertyValue(QLatin1String("QT_INSTALL_DATA"), false) + mkspecs_concat + concat_it); + + for (int i = 0; i < feature_roots.count(); ++i) + if (!feature_roots.at(i).endsWith((ushort)'/')) + feature_roots[i].append((ushort)'/'); + + feature_roots.removeDuplicates(); + return feature_roots; } -QString ProFileEvaluator::Private::propertyValue(const QString &name) const -{ - if (m_properties.contains(name)) - return m_properties.value(name); - if (name == QLatin1String("QT_INSTALL_PREFIX")) - return QLibraryInfo::location(QLibraryInfo::PrefixPath); - if (name == QLatin1String("QT_INSTALL_DATA")) - return QLibraryInfo::location(QLibraryInfo::DataPath); - if (name == QLatin1String("QT_INSTALL_DOCS")) - return QLibraryInfo::location(QLibraryInfo::DocumentationPath); - if (name == QLatin1String("QT_INSTALL_HEADERS")) - return QLibraryInfo::location(QLibraryInfo::HeadersPath); - if (name == QLatin1String("QT_INSTALL_LIBS")) - return QLibraryInfo::location(QLibraryInfo::LibrariesPath); - if (name == QLatin1String("QT_INSTALL_BINS")) - return QLibraryInfo::location(QLibraryInfo::BinariesPath); - if (name == QLatin1String("QT_INSTALL_PLUGINS")) - return QLibraryInfo::location(QLibraryInfo::PluginsPath); - if (name == QLatin1String("QT_INSTALL_TRANSLATIONS")) - return QLibraryInfo::location(QLibraryInfo::TranslationsPath); - if (name == QLatin1String("QT_INSTALL_CONFIGURATION")) - return QLibraryInfo::location(QLibraryInfo::SettingsPath); - if (name == QLatin1String("QT_INSTALL_EXAMPLES")) - return QLibraryInfo::location(QLibraryInfo::ExamplesPath); - if (name == QLatin1String("QT_INSTALL_DEMOS")) - return QLibraryInfo::location(QLibraryInfo::DemosPath); +QString ProFileEvaluator::Private::propertyValue(const QString &name, bool complain) const +{ + if (m_option->properties.contains(name)) + return m_option->properties.value(name); if (name == QLatin1String("QMAKE_MKSPECS")) - return qmake_mkspec_paths().join(Option::dirlist_sep); + return qmakeMkspecPaths().join(m_option->dirlist_sep); if (name == QLatin1String("QMAKE_VERSION")) return QLatin1String("1.0"); //### FIXME - //return qmake_version(); -#ifdef QT_VERSION_STR - if (name == QLatin1String("QT_VERSION")) - return QLatin1String(QT_VERSION_STR); -#endif - return QLatin1String("UNKNOWN"); //### + if (complain) + evalError(fL1S("Querying unknown property %1").arg(name)); + return QString(); } ProFile *ProFileEvaluator::Private::currentProFile() const @@ -1057,17 +1577,114 @@ QString ProFileEvaluator::Private::currentDirectory() const return cur->directoryName(); } -void ProFileEvaluator::Private::doVariableReplace(QString *str) +QString ProFileEvaluator::Private::sysrootify(const QString &path, const QString &baseDir) const { - *str = expandVariableReferences(*str).join(QString(Option::field_sep)); + const bool isHostSystemPath = m_option->sysroot.isEmpty() || path.startsWith(m_option->sysroot) + || path.startsWith(baseDir) || path.startsWith(m_outputDir); + return isHostSystemPath ? path : m_option->sysroot + path; } -QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &str) +#ifndef QT_BOOTSTRAPPED +void ProFileEvaluator::Private::runProcess(QProcess *proc, const QString &command, + QProcess::ProcessChannel chan) const { - QStringList ret; + proc->setWorkingDirectory(currentDirectory()); + if (!m_option->environment.isEmpty()) + proc->setProcessEnvironment(m_option->environment); +# ifdef Q_OS_WIN + proc->setNativeArguments(QLatin1String("/v:off /s /c \"") + command + QLatin1Char('"')); + proc->start(m_option->getEnv(QLatin1String("COMSPEC")), QStringList()); +# else + proc->start(QLatin1String("/bin/sh"), QStringList() << QLatin1String("-c") << command); +# endif + proc->waitForFinished(-1); + proc->setReadChannel(chan); + QByteArray errout = proc->readAll(); + if (errout.endsWith('\n')) + errout.chop(1); + m_handler->evalError(QString(), 0, QString::fromLocal8Bit(errout)); +} +#endif + +// The (QChar*)current->constData() constructs below avoid pointless detach() calls +// FIXME: This is inefficient. Should not make new string if it is a straight subsegment +static ALWAYS_INLINE void appendChar(ushort unicode, + QString *current, QChar **ptr, ProString *pending) +{ + if (!pending->isEmpty()) { + int len = pending->size(); + current->resize(current->size() + len); + ::memcpy((QChar*)current->constData(), pending->constData(), len * 2); + pending->clear(); + *ptr = (QChar*)current->constData() + len; + } + *(*ptr)++ = QChar(unicode); +} + +static void appendString(const ProString &string, + QString *current, QChar **ptr, ProString *pending) +{ + if (string.isEmpty()) + return; + QChar *uc = (QChar*)current->constData(); + int len; + if (*ptr != uc) { + len = *ptr - uc; + current->resize(current->size() + string.size()); + } else if (!pending->isEmpty()) { + len = pending->size(); + current->resize(current->size() + len + string.size()); + ::memcpy((QChar*)current->constData(), pending->constData(), len * 2); + pending->clear(); + } else { + *pending = string; + return; + } + *ptr = (QChar*)current->constData() + len; + ::memcpy(*ptr, string.constData(), string.size() * 2); + *ptr += string.size(); +} + +static void flushCurrent(ProStringList *ret, + QString *current, QChar **ptr, ProString *pending, bool joined) +{ + QChar *uc = (QChar*)current->constData(); + int len = *ptr - uc; + if (len) { + ret->append(ProString(QString(uc, len), NoHash)); + *ptr = uc; + } else if (!pending->isEmpty()) { + ret->append(*pending); + pending->clear(); + } else if (joined) { + ret->append(ProString()); + } +} + +static inline void flushFinal(ProStringList *ret, + const QString ¤t, const QChar *ptr, const ProString &pending, + const ProString &str, bool replaced, bool joined) +{ + int len = ptr - current.data(); + if (len) { + if (!replaced && len == str.size()) + ret->append(str); + else + ret->append(ProString(QString(current.data(), len), NoHash)); + } else if (!pending.isEmpty()) { + ret->append(pending); + } else if (joined) { + ret->append(ProString()); + } +} + +ProStringList ProFileEvaluator::Private::expandVariableReferences( + const ProString &str, int *pos, bool joined) +{ + ProStringList ret; // if (ok) // *ok = true; - if (str.isEmpty()) + if (str.isEmpty() && !pos) return ret; const ushort LSQUARE = '['; @@ -1082,42 +1699,45 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s const ushort DOT = '.'; const ushort SPACE = ' '; const ushort TAB = '\t'; + const ushort COMMA = ','; const ushort SINGLEQUOTE = '\''; const ushort DOUBLEQUOTE = '"'; - ushort unicode, quote = 0; - const QChar *str_data = str.data(); - const int str_len = str.length(); - - ushort term; - QString var, args; - - int replaced = 0; - QString current; - for (int i = 0; i < str_len; ++i) { - unicode = str_data[i].unicode(); - const int start_var = i; - if (unicode == DOLLAR && str_len > i+2) { - unicode = str_data[++i].unicode(); - if (unicode == DOLLAR) { - term = 0; - var.clear(); - args.clear(); + ushort unicode, quote = 0, parens = 0; + const ushort *str_data = (const ushort *)str.constData(); + const int str_len = str.size(); + + ProString var, args; + + bool replaced = false; + bool putSpace = false; + QString current; // Buffer for successively assembled string segments + current.resize(str.size()); + QChar *ptr = current.data(); + ProString pending; // Buffer for string segments from variables + // Only one of the above buffers can be filled at a given time. + for (int i = pos ? *pos : 0; i < str_len; ++i) { + unicode = str_data[i]; + if (unicode == DOLLAR) { + if (str_len > i+2 && str_data[i+1] == DOLLAR) { + ++i; + ushort term = 0; enum { VAR, ENVIRON, FUNCTION, PROPERTY } var_type = VAR; - unicode = str_data[++i].unicode(); + unicode = str_data[++i]; if (unicode == LSQUARE) { - unicode = str_data[++i].unicode(); + unicode = str_data[++i]; term = RSQUARE; var_type = PROPERTY; } else if (unicode == LCURLY) { - unicode = str_data[++i].unicode(); + unicode = str_data[++i]; var_type = VAR; term = RCURLY; } else if (unicode == LPAREN) { - unicode = str_data[++i].unicode(); + unicode = str_data[++i]; var_type = ENVIRON; term = RPAREN; } + int name_start = i; forever { if (!(unicode & (0xFF<<8)) && unicode != DOT && unicode != UNDERSCORE && @@ -1125,19 +1745,20 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s (unicode < 'a' || unicode > 'z') && (unicode < 'A' || unicode > 'Z') && (unicode < '0' || unicode > '9')) break; - var.append(QChar(unicode)); if (++i == str_len) break; - unicode = str_data[i].unicode(); + unicode = str_data[i]; // at this point, i points to either the 'term' or 'next' character (which is in unicode) } + var = str.mid(name_start, i - name_start); if (var_type == VAR && unicode == LPAREN) { var_type = FUNCTION; + name_start = i + 1; int depth = 0; forever { if (++i == str_len) break; - unicode = str_data[i].unicode(); + unicode = str_data[i]; if (unicode == LPAREN) { depth++; } else if (unicode == RPAREN) { @@ -1145,10 +1766,10 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s break; --depth; } - args.append(QChar(unicode)); } + args = str.mid(name_start, i - name_start); if (++i < str_len) - unicode = str_data[i].unicode(); + unicode = str_data[i]; else unicode = 0; // at this point i is pointing to the 'next' character (which is in unicode) @@ -1156,232 +1777,415 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s } if (term) { if (unicode != term) { - q->logMessage(format("Missing %1 terminator [found %2]") - .arg(QChar(term)) - .arg(unicode ? QString(unicode) : QString::fromLatin1(("end-of-line")))); + evalError(fL1S("Missing %1 terminator [found %2]") + .arg(QChar(term)) + .arg(unicode ? QString(unicode) : fL1S("end-of-line"))); // if (ok) // *ok = false; - return QStringList(); + if (pos) + *pos = str_len; + return ProStringList(); } } else { // move the 'cursor' back to the last char of the thing we were looking at --i; } - // since i never points to the 'next' character, there is no reason for this to be set - unicode = 0; - QStringList replacement; + ProStringList replacement; if (var_type == ENVIRON) { - replacement = split_value_list(QString::fromLocal8Bit(qgetenv(var.toLatin1().constData()))); + replacement = split_value_list(m_option->getEnv(var.toQString(m_tmp1))); } else if (var_type == PROPERTY) { - replacement << propertyValue(var); + replacement << ProString(propertyValue(var.toQString(m_tmp1), true), NoHash); } else if (var_type == FUNCTION) { - replacement << evaluateExpandFunction(var, args); + replacement += evaluateExpandFunction(var, args); } else if (var_type == VAR) { - replacement = values(var); + replacement = values(map(var)); } - if (!(replaced++) && start_var) - current = str.left(start_var); if (!replacement.isEmpty()) { - if (quote) { - current += replacement.join(QString(Option::field_sep)); + if (quote || joined) { + if (putSpace) { + putSpace = false; + if (!replacement.at(0).isEmpty()) // Bizarre, indeed + appendChar(' ', ¤t, &ptr, &pending); + } + appendString(ProString(replacement.join(statics.field_sep), NoHash), + ¤t, &ptr, &pending); } else { - current += replacement.takeFirst(); - if (!replacement.isEmpty()) { - if (!current.isEmpty()) - ret.append(current); - current = replacement.takeLast(); - if (!replacement.isEmpty()) - ret += replacement; + appendString(replacement.at(0), ¤t, &ptr, &pending); + if (replacement.size() > 1) { + flushCurrent(&ret, ¤t, &ptr, &pending, false); + int j = 1; + if (replacement.size() > 2) { + // FIXME: ret.reserve(ret.size() + replacement.size() - 2); + for (; j < replacement.size() - 1; ++j) + ret << replacement.at(j); + } + pending = replacement.at(j); } } + replaced = true; } - } else { - if (replaced) - current.append(QLatin1Char('$')); + continue; } - } - if (quote && unicode == quote) { - unicode = 0; - quote = 0; } else if (unicode == BACKSLASH) { - bool escape = false; - const char *symbols = "[]{}()$\\'\""; - for (const char *s = symbols; *s; ++s) { - if (str_data[i+1].unicode() == (ushort)*s) { - i++; - escape = true; - if (!(replaced++)) - current = str.left(start_var); - current.append(str.at(i)); - break; - } + static const char symbols[] = "[]{}()$\\'\""; + ushort unicode2 = str_data[i+1]; + if (!(unicode2 & 0xff00) && strchr(symbols, unicode2)) { + unicode = unicode2; + ++i; + } + } else if (quote) { + if (unicode == quote) { + quote = 0; + continue; } - if (escape || !replaced) - unicode =0; - } else if (!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { - quote = unicode; - unicode = 0; - if (!(replaced++) && i) - current = str.left(i); - } else if (!quote && (unicode == SPACE || unicode == TAB)) { - unicode = 0; - if (!current.isEmpty()) { - ret.append(current); - current.clear(); + } else { + if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) { + quote = unicode; + continue; + } else if (unicode == SPACE || unicode == TAB) { + if (!joined) + flushCurrent(&ret, ¤t, &ptr, &pending, false); + else if ((ptr - (QChar*)current.constData()) || !pending.isEmpty()) + putSpace = true; + continue; + } else if (pos) { + if (unicode == LPAREN) { + ++parens; + } else if (unicode == RPAREN) { + --parens; + } else if (!parens && unicode == COMMA) { + if (!joined) { + *pos = i + 1; + flushFinal(&ret, current, ptr, pending, str, replaced, false); + return ret; + } + flushCurrent(&ret, ¤t, &ptr, &pending, true); + putSpace = false; + continue; + } } } - if (replaced && unicode) - current.append(QChar(unicode)); + if (putSpace) { + putSpace = false; + appendChar(' ', ¤t, &ptr, &pending); + } + appendChar(unicode, ¤t, &ptr, &pending); } - if (!replaced) - ret = QStringList(str); - else if (!current.isEmpty()) - ret.append(current); + if (pos) + *pos = str_len; + flushFinal(&ret, current, ptr, pending, str, replaced, joined); return ret; } +bool ProFileEvaluator::Private::modesForGenerator(const QString &gen, + ProFileOption::HOST_MODE *host_mode, ProFileOption::TARG_MODE *target_mode) const +{ + if (gen == fL1S("UNIX")) { +#ifdef Q_OS_MAC + *host_mode = ProFileOption::HOST_MACX_MODE; + *target_mode = ProFileOption::TARG_MACX_MODE; +#else + *host_mode = ProFileOption::HOST_UNIX_MODE; + *target_mode = ProFileOption::TARG_UNIX_MODE; +#endif + } else if (gen == fL1S("MSVC.NET") || gen == fL1S("BMAKE") || gen == fL1S("MSBUILD")) { + *host_mode = ProFileOption::HOST_WIN_MODE; + *target_mode = ProFileOption::TARG_WIN_MODE; + } else if (gen == fL1S("MINGW")) { +#if defined(Q_OS_MAC) + *host_mode = ProFileOption::HOST_MACX_MODE; +#elif defined(Q_OS_UNIX) + *host_mode = ProFileOption::HOST_UNIX_MODE; +#else + *host_mode = ProFileOption::HOST_WIN_MODE; +#endif + *target_mode = ProFileOption::TARG_WIN_MODE; + } else if (gen == fL1S("PROJECTBUILDER") || gen == fL1S("XCODE")) { + *host_mode = ProFileOption::HOST_MACX_MODE; + *target_mode = ProFileOption::TARG_MACX_MODE; + } else if (gen == fL1S("SYMBIAN_ABLD") || gen == fL1S("SYMBIAN_SBSV2") + || gen == fL1S("SYMBIAN_UNIX") || gen == fL1S("SYMBIAN_MINGW")) { +#if defined(Q_OS_MAC) + *host_mode = ProFileOption::HOST_MACX_MODE; +#elif defined(Q_OS_UNIX) + *host_mode = ProFileOption::HOST_UNIX_MODE; +#else + *host_mode = ProFileOption::HOST_WIN_MODE; +#endif + *target_mode = ProFileOption::TARG_SYMBIAN_MODE; + } else { + evalError(fL1S("Unknown generator specified: %1").arg(gen)); + return false; + } + return true; +} + +void ProFileEvaluator::Private::validateModes() const +{ + if (m_option->host_mode == ProFileOption::HOST_UNKNOWN_MODE + || m_option->target_mode == ProFileOption::TARG_UNKNOWN_MODE) { + const QHash<ProString, ProStringList> &vals = + m_option->base_valuemap.isEmpty() ? m_valuemapStack[0] : m_option->base_valuemap; + ProFileOption::HOST_MODE host_mode; + ProFileOption::TARG_MODE target_mode; + const ProStringList &gen = vals.value(ProString("MAKEFILE_GENERATOR")); + if (gen.isEmpty()) { + evalError(fL1S("Using OS scope before setting MAKEFILE_GENERATOR")); + } else if (modesForGenerator(gen.at(0).toQString(), &host_mode, &target_mode)) { + if (m_option->host_mode == ProFileOption::HOST_UNKNOWN_MODE) { + m_option->host_mode = host_mode; + m_option->applyHostMode(); + } + + if (m_option->target_mode == ProFileOption::TARG_UNKNOWN_MODE) { + const ProStringList &tgt = vals.value(ProString("TARGET_PLATFORM")); + if (!tgt.isEmpty()) { + const QString &os = tgt.at(0).toQString(); + if (os == statics.strunix) + m_option->target_mode = ProFileOption::TARG_UNIX_MODE; + else if (os == statics.strmacx) + m_option->target_mode = ProFileOption::TARG_MACX_MODE; + else if (os == statics.strsymbian) + m_option->target_mode = ProFileOption::TARG_SYMBIAN_MODE; + else if (os == statics.strwin32) + m_option->target_mode = ProFileOption::TARG_WIN_MODE; + else + evalError(fL1S("Unknown target platform specified: %1").arg(os)); + } else { + m_option->target_mode = target_mode; + } + } + } + } +} + bool ProFileEvaluator::Private::isActiveConfig(const QString &config, bool regex) { // magic types for easy flipping - if (config == QLatin1String("true")) + if (config == statics.strtrue) return true; - if (config == QLatin1String("false")) + if (config == statics.strfalse) return false; - // mkspecs - if ((Option::target_mode == Option::TARG_MACX_MODE - || Option::target_mode == Option::TARG_QNX6_MODE - || Option::target_mode == Option::TARG_UNIX_MODE) - && config == QLatin1String("unix")) - return true; - if (Option::target_mode == Option::TARG_MACX_MODE && config == QLatin1String("macx")) - return true; - if (Option::target_mode == Option::TARG_QNX6_MODE && config == QLatin1String("qnx6")) - return true; - if (Option::target_mode == Option::TARG_MAC9_MODE && config == QLatin1String("mac9")) - return true; - if ((Option::target_mode == Option::TARG_MAC9_MODE - || Option::target_mode == Option::TARG_MACX_MODE) - && config == QLatin1String("mac")) - return true; - if (Option::target_mode == Option::TARG_WIN_MODE && config == QLatin1String("win32")) - return true; + if (config == statics.strunix) { + validateModes(); + return m_option->target_mode == ProFileOption::TARG_UNIX_MODE + || m_option->target_mode == ProFileOption::TARG_MACX_MODE + || m_option->target_mode == ProFileOption::TARG_SYMBIAN_MODE; + } else if (config == statics.strmacx || config == statics.strmac) { + validateModes(); + return m_option->target_mode == ProFileOption::TARG_MACX_MODE; + } else if (config == statics.strsymbian) { + validateModes(); + return m_option->target_mode == ProFileOption::TARG_SYMBIAN_MODE; + } else if (config == statics.strwin32) { + validateModes(); + return m_option->target_mode == ProFileOption::TARG_WIN_MODE; + } - QRegExp re(config, Qt::CaseSensitive, QRegExp::Wildcard); - QString spec = Option::qmakespec; - if ((regex && re.exactMatch(spec)) || (!regex && spec == config)) - return true; + if (regex && (config.contains(QLatin1Char('*')) || config.contains(QLatin1Char('?')))) { + QString cfg = config; + cfg.detach(); // Keep m_tmp out of QRegExp's cache + QRegExp re(cfg, Qt::CaseSensitive, QRegExp::Wildcard); + + // mkspecs + if (re.exactMatch(m_option->qmakespec_name)) + return true; + + // CONFIG variable + int t = 0; + foreach (const ProString &configValue, valuesDirect(statics.strCONFIG)) { + if (re.exactMatch(configValue.toQString(m_tmp[t]))) + return true; + t ^= 1; + } + } else { + // mkspecs + if (m_option->qmakespec_name == config) + return true; + + // CONFIG variable + if (valuesDirect(statics.strCONFIG).contains(ProString(config, NoHash))) + return true; + } return false; } -QStringList ProFileEvaluator::Private::evaluateFunction( - ProBlock *funcPtr, const QStringList &argumentsList, bool *ok) +ProStringList ProFileEvaluator::Private::expandVariableReferences( + const ushort *&tokPtr, int sizeHint, bool joined) +{ + ProStringList ret; + ret.reserve(sizeHint); + forever { + evaluateExpression(tokPtr, &ret, joined); + switch (*tokPtr) { + case TokValueTerminator: + case TokFuncTerminator: + tokPtr++; + return ret; + case TokArgSeparator: + if (joined) { + tokPtr++; + continue; + } + // fallthrough + default: + Q_ASSERT_X(false, "expandVariableReferences", "Unrecognized token"); + break; + } + } +} + +QList<ProStringList> ProFileEvaluator::Private::prepareFunctionArgs(const ushort *&tokPtr) +{ + QList<ProStringList> args_list; + if (*tokPtr != TokFuncTerminator) { + for (;; tokPtr++) { + ProStringList arg; + evaluateExpression(tokPtr, &arg, false); + args_list << arg; + if (*tokPtr == TokFuncTerminator) + break; + Q_ASSERT(*tokPtr == TokArgSeparator); + } + } + tokPtr++; + return args_list; +} + +QList<ProStringList> ProFileEvaluator::Private::prepareFunctionArgs(const ProString &arguments) +{ + QList<ProStringList> args_list; + for (int pos = 0; pos < arguments.size(); ) + args_list << expandVariableReferences(arguments, &pos); + return args_list; +} + +ProStringList ProFileEvaluator::Private::evaluateFunction( + const FunctionDef &func, const QList<ProStringList> &argumentsList, bool *ok) { bool oki; - QStringList ret; + ProStringList ret; if (m_valuemapStack.count() >= 100) { - q->errorMessage(format("ran into infinite recursion (depth > 100).")); + evalError(fL1S("ran into infinite recursion (depth > 100).")); oki = false; } else { - State sts = m_sts; - m_valuemapStack.push(m_valuemap); - m_filevaluemapStack.push(m_filevaluemap); + m_valuemapStack.push(QHash<ProString, ProStringList>()); + m_locationStack.push(m_current); + int loopLevel = m_loopLevel; + m_loopLevel = 0; - QStringList args; + ProStringList args; for (int i = 0; i < argumentsList.count(); ++i) { - QStringList theArgs = expandVariableReferences(argumentsList[i]); - args += theArgs; - m_valuemap[QString::number(i+1)] = theArgs; + args += argumentsList[i]; + m_valuemapStack.top()[ProString(QString::number(i+1))] = argumentsList[i]; } - m_valuemap[QLatin1String("ARGS")] = args; - oki = (funcPtr->Accept(this) != ProItem::ReturnFalse); // True || Return + m_valuemapStack.top()[statics.strARGS] = args; + oki = (visitProBlock(func.pro(), func.tokPtr()) != ReturnFalse); // True || Return ret = m_returnValue; m_returnValue.clear(); - m_valuemap = m_valuemapStack.pop(); - m_filevaluemap = m_filevaluemapStack.pop(); - m_sts = sts; + m_loopLevel = loopLevel; + m_current = m_locationStack.pop(); + m_valuemapStack.pop(); } if (ok) *ok = oki; if (oki) return ret; - return QStringList(); -} - -QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &func, const QString &arguments) -{ - QStringList argumentsList = split_arg_list(arguments); - - if (ProBlock *funcPtr = m_replaceFunctions.value(func, 0)) - return evaluateFunction(funcPtr, argumentsList, 0); - - QStringList args; - for (int i = 0; i < argumentsList.count(); ++i) - args += expandVariableReferences(argumentsList[i]).join(Option::field_sep); - - enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST, - E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, - E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, - E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, - E_REPLACE }; - - static QHash<QString, int> expands; - if (expands.isEmpty()) { - expands.insert(QLatin1String("member"), E_MEMBER); - expands.insert(QLatin1String("first"), E_FIRST); - expands.insert(QLatin1String("last"), E_LAST); - expands.insert(QLatin1String("cat"), E_CAT); - expands.insert(QLatin1String("fromfile"), E_FROMFILE); // implementation disabled (see comment below) - expands.insert(QLatin1String("eval"), E_EVAL); - expands.insert(QLatin1String("list"), E_LIST); - expands.insert(QLatin1String("sprintf"), E_SPRINTF); - expands.insert(QLatin1String("join"), E_JOIN); - expands.insert(QLatin1String("split"), E_SPLIT); - expands.insert(QLatin1String("basename"), E_BASENAME); - expands.insert(QLatin1String("dirname"), E_DIRNAME); - expands.insert(QLatin1String("section"), E_SECTION); - expands.insert(QLatin1String("find"), E_FIND); - expands.insert(QLatin1String("system"), E_SYSTEM); - expands.insert(QLatin1String("unique"), E_UNIQUE); - expands.insert(QLatin1String("quote"), E_QUOTE); - expands.insert(QLatin1String("escape_expand"), E_ESCAPE_EXPAND); - expands.insert(QLatin1String("upper"), E_UPPER); - expands.insert(QLatin1String("lower"), E_LOWER); - expands.insert(QLatin1String("re_escape"), E_RE_ESCAPE); - expands.insert(QLatin1String("files"), E_FILES); - expands.insert(QLatin1String("prompt"), E_PROMPT); // interactive, so cannot be implemented - expands.insert(QLatin1String("replace"), E_REPLACE); + return ProStringList(); +} + +ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateBoolFunction( + const FunctionDef &func, const QList<ProStringList> &argumentsList, + const ProString &function) +{ + bool ok; + ProStringList ret = evaluateFunction(func, argumentsList, &ok); + if (ok) { + if (ret.isEmpty()) + return ReturnTrue; + if (ret.at(0) != statics.strfalse) { + if (ret.at(0) == statics.strtrue) + return ReturnTrue; + int val = ret.at(0).toQString(m_tmp1).toInt(&ok); + if (ok) { + if (val) + return ReturnTrue; + } else { + evalError(fL1S("Unexpected return value from test '%1': %2") + .arg(function.toQString(m_tmp1)) + .arg(ret.join(QLatin1String(" :: ")))); + } + } } - ExpandFunc func_t = ExpandFunc(expands.value(func.toLower())); + return ReturnFalse; +} - QStringList ret; +ProStringList ProFileEvaluator::Private::evaluateExpandFunction( + const ProString &func, const ushort *&tokPtr) +{ + QHash<ProString, FunctionDef>::ConstIterator it = + m_functionDefs.replaceFunctions.constFind(func); + if (it != m_functionDefs.replaceFunctions.constEnd()) + return evaluateFunction(*it, prepareFunctionArgs(tokPtr), 0); + + //why don't the builtin functions just use args_list? --Sam + return evaluateExpandFunction(func, expandVariableReferences(tokPtr, 5, true)); +} + +ProStringList ProFileEvaluator::Private::evaluateExpandFunction( + const ProString &func, const ProString &arguments) +{ + QHash<ProString, FunctionDef>::ConstIterator it = + m_functionDefs.replaceFunctions.constFind(func); + if (it != m_functionDefs.replaceFunctions.constEnd()) + return evaluateFunction(*it, prepareFunctionArgs(arguments), 0); + + //why don't the builtin functions just use args_list? --Sam + int pos = 0; + return evaluateExpandFunction(func, expandVariableReferences(arguments, &pos, true)); +} + +ProStringList ProFileEvaluator::Private::evaluateExpandFunction( + const ProString &func, const ProStringList &args) +{ + ExpandFunc func_t = ExpandFunc(statics.expands.value(func)); + if (func_t == 0) { + const QString &fn = func.toQString(m_tmp1); + const QString &lfn = fn.toLower(); + if (!fn.isSharedWith(lfn)) + func_t = ExpandFunc(statics.expands.value(ProString(lfn))); + } + + ProStringList ret; switch (func_t) { case E_BASENAME: case E_DIRNAME: case E_SECTION: { bool regexp = false; - QString sep, var; + QString sep; + ProString var; int beg = 0; int end = -1; if (func_t == E_SECTION) { if (args.count() != 3 && args.count() != 4) { - q->logMessage(format("%1(var) section(var, sep, begin, end) " - "requires three or four arguments.").arg(func)); + evalError(fL1S("%1(var) section(var, sep, begin, end) requires" + " three or four arguments.").arg(func.toQString(m_tmp1))); } else { var = args[0]; - sep = args[1]; - beg = args[2].toInt(); + sep = args.at(1).toQString(); + beg = args.at(2).toQString(m_tmp2).toInt(); if (args.count() == 4) - end = args[3].toInt(); + end = args.at(3).toQString(m_tmp2).toInt(); } } else { if (args.count() != 1) { - q->logMessage(format("%1(var) requires one argument.").arg(func)); + evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1))); } else { var = args[0]; regexp = true; @@ -1392,67 +2196,81 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun beg = -1; } } - if (!var.isNull()) { - foreach (const QString str, values(var)) { - if (regexp) - ret += str.section(QRegExp(sep), beg, end); - else - ret += str.section(sep, beg, end); + if (!var.isEmpty()) { + if (regexp) { + QRegExp sepRx(sep); + foreach (const ProString &str, values(map(var))) { + const QString &rstr = str.toQString(m_tmp1).section(sepRx, beg, end); + ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr, NoHash).setSource(str)); + } + } else { + foreach (const ProString &str, values(map(var))) { + const QString &rstr = str.toQString(m_tmp1).section(sep, beg, end); + ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr, NoHash).setSource(str)); + } } } break; } case E_SPRINTF: if(args.count() < 1) { - q->logMessage(format("sprintf(format, ...) requires at least one argument")); + evalError(fL1S("sprintf(format, ...) requires at least one argument")); } else { - QString tmp = args.at(0); + QString tmp = args.at(0).toQString(m_tmp1); for (int i = 1; i < args.count(); ++i) - tmp = tmp.arg(args.at(i)); + tmp = tmp.arg(args.at(i).toQString(m_tmp2)); + // Note: this depends on split_value_list() making a deep copy ret = split_value_list(tmp); } break; case E_JOIN: { if (args.count() < 1 || args.count() > 4) { - q->logMessage(format("join(var, glue, before, after) requires one to four arguments.")); + evalError(fL1S("join(var, glue, before, after) requires one to four arguments.")); } else { - QString glue, before, after; + QString glue; + ProString before, after; if (args.count() >= 2) - glue = args[1]; + glue = args.at(1).toQString(m_tmp1); if (args.count() >= 3) before = args[2]; if (args.count() == 4) after = args[3]; - const QStringList &var = values(args.first()); - if (!var.isEmpty()) - ret.append(before + var.join(glue) + after); + const ProStringList &var = values(map(args.at(0))); + if (!var.isEmpty()) { + const ProFile *src = currentProFile(); + foreach (const ProString &v, var) + if (const ProFile *s = v.sourceFile()) { + src = s; + break; + } + ret.append(ProString(before + var.join(glue) + after, NoHash).setSource(src)); + } } break; } - case E_SPLIT: { + case E_SPLIT: if (args.count() != 2) { - q->logMessage(format("split(var, sep) requires one or two arguments")); + evalError(fL1S("split(var, sep) requires one or two arguments")); } else { - const QString &sep = (args.count() == 2) ? args[1] : QString(Option::field_sep); - foreach (const QString &var, values(args.first())) - foreach (const QString &splt, var.split(sep)) - ret.append(splt); + const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep; + foreach (const ProString &var, values(map(args.at(0)))) + foreach (const QString &splt, var.toQString(m_tmp2).split(sep)) + ret << (splt.isSharedWith(m_tmp2) ? var : ProString(splt, NoHash).setSource(var)); } break; - } - case E_MEMBER: { + case E_MEMBER: if (args.count() < 1 || args.count() > 3) { - q->logMessage(format("member(var, start, end) requires one to three arguments.")); + evalError(fL1S("member(var, start, end) requires one to three arguments.")); } else { bool ok = true; - const QStringList var = values(args.first()); + const ProStringList &var = values(map(args.at(0))); int start = 0, end = 0; if (args.count() >= 2) { - QString start_str = args[1]; + const QString &start_str = args.at(1).toQString(m_tmp1); start = start_str.toInt(&ok); if (!ok) { if (args.count() == 2) { - int dotdot = start_str.indexOf(QLatin1String("..")); + int dotdot = start_str.indexOf(statics.strDotDot); if (dotdot != -1) { start = start_str.left(dotdot).toInt(&ok); if (ok) @@ -1460,15 +2278,15 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } } if (!ok) - q->logMessage(format("member() argument 2 (start) '%2' invalid.") - .arg(start_str)); + evalError(fL1S("member() argument 2 (start) '%2' invalid.") + .arg(start_str)); } else { end = start; if (args.count() == 3) - end = args[2].toInt(&ok); + end = args.at(2).toQString(m_tmp1).toInt(&ok); if (!ok) - q->logMessage(format("member() argument 3 (end) '%2' invalid.\n") - .arg(args[2])); + evalError(fL1S("member() argument 3 (end) '%2' invalid.\n") + .arg(args.at(2).toQString(m_tmp1))); } } if (ok) { @@ -1488,13 +2306,12 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } } break; - } case E_FIRST: - case E_LAST: { + case E_LAST: if (args.count() != 1) { - q->logMessage(format("%1(var) requires one argument.").arg(func)); + evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1))); } else { - const QStringList var = values(args.first()); + const ProStringList &var = values(map(args.at(0))); if (!var.isEmpty()) { if (func_t == E_FIRST) ret.append(var[0]); @@ -1503,92 +2320,96 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } } break; - } + case E_SIZE: + if (args.count() != 1) + evalError(fL1S("size(var) requires one argument.")); + else + ret.append(ProString(QString::number(values(map(args.at(0))).size()), NoHash)); + break; case E_CAT: if (args.count() < 1 || args.count() > 2) { - q->logMessage(format("cat(file, singleline=true) requires one or two arguments.")); + evalError(fL1S("cat(file, singleline=true) requires one or two arguments.")); } else { - QString file = args[0]; - file = Option::fixPathToLocalOS(file); + const QString &file = args.at(0).toQString(m_tmp1); bool singleLine = true; if (args.count() > 1) - singleLine = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive)); + singleLine = isTrue(args.at(1), m_tmp2); - QFile qfile(file); + QFile qfile(resolvePath(expandEnvVars(file))); if (qfile.open(QIODevice::ReadOnly)) { QTextStream stream(&qfile); while (!stream.atEnd()) { ret += split_value_list(stream.readLine().trimmed()); if (!singleLine) - ret += QLatin1String("\n"); + ret += ProString("\n", NoHash); } qfile.close(); } } break; -#if 0 // Used only by Qt's configure for caching case E_FROMFILE: if (args.count() != 2) { - q->logMessage(format("fromfile(file, variable) requires two arguments.")); + evalError(fL1S("fromfile(file, variable) requires two arguments.")); } else { - QString file = args[0], seek_variableName = args[1]; - - ProFile pro(Option::fixPathToLocalOS(file)); - - ProFileEvaluator visitor; - visitor.setVerbose(m_verbose); - visitor.setCumulative(m_cumulative); - - if (!visitor.queryProFile(&pro)) - break; - - if (!visitor.accept(&pro)) - break; - - ret = visitor.values(seek_variableName); + QHash<ProString, ProStringList> vars; + QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))); + fn.detach(); + if (evaluateFileInto(fn, ProFileEvaluatorHandler::EvalAuxFile, + &vars, &m_functionDefs, EvalWithDefaults)) + ret = vars.value(map(args.at(1))); } break; -#endif - case E_EVAL: { + case E_EVAL: if (args.count() != 1) { - q->logMessage(format("eval(variable) requires one argument")); - + evalError(fL1S("eval(variable) requires one argument")); } else { - ret += values(args.at(0)); + ret += values(map(args.at(0))); } - break; } + break; case E_LIST: { - static int x = 0; QString tmp; - tmp.sprintf(".QMAKE_INTERNAL_TMP_variableName_%d", x++); - ret = QStringList(tmp); - QStringList lst; - foreach (const QString &arg, args) - lst += split_value_list(arg); - m_valuemap[tmp] = lst; + tmp.sprintf(".QMAKE_INTERNAL_TMP_variableName_%d", m_listCount++); + ret = ProStringList(ProString(tmp, NoHash)); + ProStringList lst; + foreach (const ProString &arg, args) + lst += split_value_list(arg.toQString(m_tmp1), arg.sourceFile()); // Relies on deep copy + m_valuemapStack.top()[ret.at(0)] = lst; break; } case E_FIND: if (args.count() != 2) { - q->logMessage(format("find(var, str) requires two arguments.")); + evalError(fL1S("find(var, str) requires two arguments.")); } else { - QRegExp regx(args[1]); - foreach (const QString &val, values(args.first())) - if (regx.indexIn(val) != -1) + QRegExp regx(args.at(1).toQString()); + int t = 0; + foreach (const ProString &val, values(map(args.at(0)))) { + if (regx.indexIn(val.toQString(m_tmp[t])) != -1) ret += val; + t ^= 1; + } } break; case E_SYSTEM: if (!m_skipLevel) { if (args.count() < 1 || args.count() > 2) { - q->logMessage(format("system(execute) requires one or two arguments.")); + evalError(fL1S("system(execute) requires one or two arguments.")); } else { - char buff[256]; - FILE *proc = QT_POPEN(args[0].toLatin1(), "r"); bool singleLine = true; if (args.count() > 1) - singleLine = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive)); - QString output; + singleLine = isTrue(args.at(1), m_tmp2); + QByteArray output; +#ifndef QT_BOOTSTRAPPED + QProcess proc; + runProcess(&proc, args.at(0).toQString(m_tmp2), QProcess::StandardError); + output = proc.readAllStandardOutput(); + output.replace('\t', ' '); + if (singleLine) + output.replace('\n', ' '); +#else + char buff[256]; + FILE *proc = QT_POPEN(QString(QLatin1String("cd ") + + IoUtils::shellQuote(currentDirectory()) + + QLatin1String(" && ") + args[0]).toLocal8Bit(), "r"); while (proc && !feof(proc)) { int read_in = int(fread(buff, 1, 255, proc)); if (!read_in) @@ -1597,32 +2418,31 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun if ((singleLine && buff[i] == '\n') || buff[i] == '\t') buff[i] = ' '; } - buff[read_in] = '\0'; - output += QLatin1String(buff); + output.append(buff, read_in); } - ret += split_value_list(output); if (proc) QT_PCLOSE(proc); +#endif + ret += split_value_list(QString::fromLocal8Bit(output)); } } break; case E_UNIQUE: if(args.count() != 1) { - q->logMessage(format("unique(var) requires one argument.")); + evalError(fL1S("unique(var) requires one argument.")); } else { - foreach (const QString &var, values(args.first())) - if (!ret.contains(var)) - ret.append(var); + ret = values(map(args.at(0))); + ret.removeDuplicates(); } break; case E_QUOTE: - for (int i = 0; i < args.count(); ++i) - ret += QStringList(args.at(i)); + ret += args; break; case E_ESCAPE_EXPAND: for (int i = 0; i < args.size(); ++i) { - QChar *i_data = args[i].data(); - int i_len = args[i].length(); + QString str = args.at(i).toQString(); + QChar *i_data = str.data(); + int i_len = str.length(); for (int x = 0; x < i_len; ++x) { if (*(i_data+x) == QLatin1Char('\\') && x < i_len-1) { if (*(i_data+x+1) == QLatin1Char('\\')) { @@ -1648,299 +2468,238 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } } } - ret.append(QString(i_data, i_len)); + ret.append(ProString(QString(i_data, i_len), NoHash).setSource(args.at(i))); } break; case E_RE_ESCAPE: - for (int i = 0; i < args.size(); ++i) - ret += QRegExp::escape(args[i]); + for (int i = 0; i < args.size(); ++i) { + const QString &rstr = QRegExp::escape(args.at(i).toQString(m_tmp1)); + ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr, NoHash).setSource(args.at(i))); + } break; case E_UPPER: case E_LOWER: - for (int i = 0; i < args.count(); ++i) - if (func_t == E_UPPER) - ret += args[i].toUpper(); - else - ret += args[i].toLower(); + for (int i = 0; i < args.count(); ++i) { + QString rstr = args.at(i).toQString(m_tmp1); + rstr = (func_t == E_UPPER) ? rstr.toUpper() : rstr.toLower(); + ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr, NoHash).setSource(args.at(i))); + } break; case E_FILES: if (args.count() != 1 && args.count() != 2) { - q->logMessage(format("files(pattern, recursive=false) requires one or two arguments")); + evalError(fL1S("files(pattern, recursive=false) requires one or two arguments")); } else { bool recursive = false; if (args.count() == 2) - recursive = (!args[1].compare(QLatin1String("true"), Qt::CaseInsensitive) || args[1].toInt()); + recursive = isTrue(args.at(1), m_tmp2); QStringList dirs; - QString r = Option::fixPathToLocalOS(args[0]); + QString r = fixPathToLocalOS(args.at(0).toQString(m_tmp1)); + QString pfx; + if (IoUtils::isRelativePath(r)) { + pfx = currentDirectory(); + if (!pfx.endsWith(QLatin1Char('/'))) + pfx += QLatin1Char('/'); + } int slash = r.lastIndexOf(QDir::separator()); if (slash != -1) { - dirs.append(r.left(slash)); + dirs.append(r.left(slash+1)); r = r.mid(slash+1); } else { dirs.append(QString()); } + r.detach(); // Keep m_tmp out of QRegExp's cache const QRegExp regex(r, Qt::CaseSensitive, QRegExp::Wildcard); for (int d = 0; d < dirs.count(); d++) { QString dir = dirs[d]; - if (!dir.isEmpty() && !dir.endsWith(Option::dir_sep)) - dir += QLatin1Char('/'); - - QDir qdir(dir); + QDir qdir(pfx + dir); for (int i = 0; i < (int)qdir.count(); ++i) { - if (qdir[i] == QLatin1String(".") || qdir[i] == QLatin1String("..")) + if (qdir[i] == statics.strDot || qdir[i] == statics.strDotDot) continue; QString fname = dir + qdir[i]; - if (QFileInfo(fname).isDir()) { + if (IoUtils::fileType(pfx + fname) == IoUtils::FileIsDir) { if (recursive) - dirs.append(fname); + dirs.append(fname + QDir::separator()); } if (regex.exactMatch(qdir[i])) - ret += fname; + ret += ProString(fname, NoHash).setSource(currentProFile()); } } } break; case E_REPLACE: if(args.count() != 3 ) { - q->logMessage(format("replace(var, before, after) requires three arguments")); + evalError(fL1S("replace(var, before, after) requires three arguments")); } else { - const QRegExp before(args[1]); - const QString after(args[2]); - foreach (QString val, values(args.first())) - ret += val.replace(before, after); + const QRegExp before(args.at(1).toQString()); + const QString &after(args.at(2).toQString(m_tmp2)); + foreach (const ProString &val, values(map(args.at(0)))) { + QString rstr = val.toQString(m_tmp1); + QString copy = rstr; // Force a detach on modify + rstr.replace(before, after); + ret << (rstr.isSharedWith(m_tmp1) ? val : ProString(rstr, NoHash).setSource(val)); + } } break; - case 0: - q->logMessage(format("'%1' is not a recognized replace function").arg(func)); + case E_INVALID: + evalError(fL1S("'%1' is not a recognized replace function") + .arg(func.toQString(m_tmp1))); break; default: - q->logMessage(format("Function '%1' is not implemented").arg(func)); + evalError(fL1S("Function '%1' is not implemented").arg(func.toQString(m_tmp1))); break; } return ret; } -ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction( - const QString &function, const QString &arguments) +ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateConditionalFunction( + const ProString &function, const ProString &arguments) { - QStringList argumentsList = split_arg_list(arguments); + QHash<ProString, FunctionDef>::ConstIterator it = + m_functionDefs.testFunctions.constFind(function); + if (it != m_functionDefs.testFunctions.constEnd()) + return evaluateBoolFunction(*it, prepareFunctionArgs(arguments), function); - if (ProBlock *funcPtr = m_testFunctions.value(function, 0)) { - bool ok; - QStringList ret = evaluateFunction(funcPtr, argumentsList, &ok); - if (ok) { - if (ret.isEmpty()) { - return ProItem::ReturnTrue; - } else { - if (ret.first() != QLatin1String("false")) { - if (ret.first() == QLatin1String("true")) { - return ProItem::ReturnTrue; - } else { - bool ok; - int val = ret.first().toInt(&ok); - if (ok) { - if (val) - return ProItem::ReturnTrue; - } else { - q->logMessage(format("Unexpected return value from test '%1': %2") - .arg(function).arg(ret.join(QLatin1String(" :: ")))); - } - } - } - } - } - return ProItem::ReturnFalse; - } + //why don't the builtin functions just use args_list? --Sam + int pos = 0; + return evaluateConditionalFunction(function, expandVariableReferences(arguments, &pos, true)); +} - QString sep; - sep.append(Option::field_sep); - QStringList args; - for (int i = 0; i < argumentsList.count(); ++i) - args += expandVariableReferences(argumentsList[i]).join(sep); - - enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, - T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, - T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, - T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF, - T_FOR, T_DEFINE_TEST, T_DEFINE_REPLACE }; - - static QHash<QString, int> functions; - if (functions.isEmpty()) { - functions.insert(QLatin1String("requires"), T_REQUIRES); - functions.insert(QLatin1String("greaterThan"), T_GREATERTHAN); - functions.insert(QLatin1String("lessThan"), T_LESSTHAN); - functions.insert(QLatin1String("equals"), T_EQUALS); - functions.insert(QLatin1String("isEqual"), T_EQUALS); - functions.insert(QLatin1String("exists"), T_EXISTS); - functions.insert(QLatin1String("export"), T_EXPORT); - functions.insert(QLatin1String("clear"), T_CLEAR); - functions.insert(QLatin1String("unset"), T_UNSET); - functions.insert(QLatin1String("eval"), T_EVAL); - functions.insert(QLatin1String("CONFIG"), T_CONFIG); - functions.insert(QLatin1String("if"), T_IF); - functions.insert(QLatin1String("isActiveConfig"), T_CONFIG); - functions.insert(QLatin1String("system"), T_SYSTEM); - functions.insert(QLatin1String("return"), T_RETURN); - functions.insert(QLatin1String("break"), T_BREAK); - functions.insert(QLatin1String("next"), T_NEXT); - functions.insert(QLatin1String("defined"), T_DEFINED); - functions.insert(QLatin1String("contains"), T_CONTAINS); - functions.insert(QLatin1String("infile"), T_INFILE); - functions.insert(QLatin1String("count"), T_COUNT); - functions.insert(QLatin1String("isEmpty"), T_ISEMPTY); - functions.insert(QLatin1String("load"), T_LOAD); //v - functions.insert(QLatin1String("include"), T_INCLUDE); //v - functions.insert(QLatin1String("debug"), T_DEBUG); - functions.insert(QLatin1String("message"), T_MESSAGE); //v - functions.insert(QLatin1String("warning"), T_MESSAGE); //v - functions.insert(QLatin1String("error"), T_MESSAGE); //v - functions.insert(QLatin1String("for"), T_FOR); //v - functions.insert(QLatin1String("defineTest"), T_DEFINE_TEST); //v - functions.insert(QLatin1String("defineReplace"), T_DEFINE_REPLACE); //v - } +ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateConditionalFunction( + const ProString &function, const ushort *&tokPtr) +{ + QHash<ProString, FunctionDef>::ConstIterator it = + m_functionDefs.testFunctions.constFind(function); + if (it != m_functionDefs.testFunctions.constEnd()) + return evaluateBoolFunction(*it, prepareFunctionArgs(tokPtr), function); + + //why don't the builtin functions just use args_list? --Sam + return evaluateConditionalFunction(function, expandVariableReferences(tokPtr, 5, true)); +} - TestFunc func_t = (TestFunc)functions.value(function); +ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateConditionalFunction( + const ProString &function, const ProStringList &args) +{ + TestFunc func_t = (TestFunc)statics.functions.value(function); switch (func_t) { - case T_DEFINE_TEST: - m_definingTest = true; - goto defineFunc; - case T_DEFINE_REPLACE: - m_definingTest = false; - defineFunc: - if (args.count() != 1) { - q->logMessage(format("%s(function) requires one argument.").arg(function)); - return ProItem::ReturnFalse; - } - m_definingFunc = args.first(); - return ProItem::ReturnTrue; case T_DEFINED: if (args.count() < 1 || args.count() > 2) { - q->logMessage(format("defined(function, [\"test\"|\"replace\"])" - " requires one or two arguments.")); - return ProItem::ReturnFalse; + evalError(fL1S("defined(function, [\"test\"|\"replace\"])" + " requires one or two arguments.")); + return ReturnFalse; } if (args.count() > 1) { if (args[1] == QLatin1String("test")) - return returnBool(m_testFunctions.contains(args[0])); + return returnBool(m_functionDefs.testFunctions.contains(args[0])); else if (args[1] == QLatin1String("replace")) - return returnBool(m_replaceFunctions.contains(args[0])); - q->logMessage(format("defined(function, type):" - " unexpected type [%1].\n").arg(args[1])); - return ProItem::ReturnFalse; + return returnBool(m_functionDefs.replaceFunctions.contains(args[0])); + evalError(fL1S("defined(function, type): unexpected type [%1].\n") + .arg(args.at(1).toQString(m_tmp1))); + return ReturnFalse; } - return returnBool(m_replaceFunctions.contains(args[0]) - || m_testFunctions.contains(args[0])); + return returnBool(m_functionDefs.replaceFunctions.contains(args[0]) + || m_functionDefs.testFunctions.contains(args[0])); case T_RETURN: m_returnValue = args; // It is "safe" to ignore returns - due to qmake brokeness // they cannot be used to terminate loops anyway. if (m_skipLevel || m_cumulative) - return ProItem::ReturnTrue; + return ReturnTrue; if (m_valuemapStack.isEmpty()) { - q->logMessage(format("unexpected return().")); - return ProItem::ReturnFalse; + evalError(fL1S("unexpected return().")); + return ReturnFalse; } - return ProItem::ReturnReturn; - case T_EXPORT: + return ReturnReturn; + case T_EXPORT: { if (m_skipLevel && !m_cumulative) - return ProItem::ReturnTrue; + return ReturnTrue; if (args.count() != 1) { - q->logMessage(format("export(variable) requires one argument.")); - return ProItem::ReturnFalse; + evalError(fL1S("export(variable) requires one argument.")); + return ReturnFalse; + } + const ProString &var = map(args.at(0)); + for (int i = m_valuemapStack.size(); --i > 0; ) { + QHash<ProString, ProStringList>::Iterator it = m_valuemapStack[i].find(var); + if (it != m_valuemapStack.at(i).end()) { + if (it->constBegin() == statics.fakeValue.constBegin()) { + // This is stupid, but qmake doesn't propagate deletions + m_valuemapStack[0][var] = ProStringList(); + } else { + m_valuemapStack[0][var] = *it; + } + m_valuemapStack[i].erase(it); + while (--i) + m_valuemapStack[i].remove(var); + break; + } } - for (int i = 0; i < m_valuemapStack.size(); ++i) { - m_valuemapStack[i][args[0]] = m_valuemap[args[0]]; - m_filevaluemapStack[i][currentProFile()][args[0]] = - m_filevaluemap[currentProFile()][args[0]]; + return ReturnTrue; + } + case T_INFILE: + if (args.count() < 2 || args.count() > 3) { + evalError(fL1S("infile(file, var, [values]) requires two or three arguments.")); + } else { + QHash<ProString, ProStringList> vars; + QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))); + fn.detach(); + if (!evaluateFileInto(fn, ProFileEvaluatorHandler::EvalAuxFile, + &vars, &m_functionDefs, EvalWithDefaults)) + return ReturnFalse; + if (args.count() == 2) + return returnBool(vars.contains(args.at(1))); + QRegExp regx; + const QString &qry = args.at(2).toQString(m_tmp1); + if (qry != QRegExp::escape(qry)) { + QString copy = qry; + copy.detach(); + regx.setPattern(copy); + } + int t = 0; + foreach (const ProString &s, vars.value(map(args.at(1)))) { + if ((!regx.isEmpty() && regx.exactMatch(s.toQString(m_tmp[t]))) || s == qry) + return ReturnTrue; + t ^= 1; + } } - return ProItem::ReturnTrue; + return ReturnFalse; #if 0 - case T_INFILE: case T_REQUIRES: - case T_EVAL: #endif - case T_FOR: { - if (m_cumulative) // This is a no-win situation, so just pretend it's no loop - return ProItem::ReturnTrue; - if (m_skipLevel) - return ProItem::ReturnFalse; - if (args.count() > 2 || args.count() < 1) { - q->logMessage(format("for({var, list|var, forever|ever})" - " requires one or two arguments.")); - return ProItem::ReturnFalse; - } - ProLoop loop; - loop.infinite = false; - loop.index = 0; - QString it_list; - if (args.count() == 1) { - doVariableReplace(&args[0]); - it_list = args[0]; - if (args[0] != QLatin1String("ever")) { - q->logMessage(format("for({var, list|var, forever|ever})" - " requires one or two arguments.")); - return ProItem::ReturnFalse; - } - it_list = QLatin1String("forever"); - } else { - loop.variable = args[0]; - loop.oldVarVal = m_valuemap.value(loop.variable); - doVariableReplace(&args[1]); - it_list = args[1]; - } - loop.list = m_valuemap[it_list]; - if (loop.list.isEmpty()) { - if (it_list == QLatin1String("forever")) { - loop.infinite = true; - } else { - int dotdot = it_list.indexOf(QLatin1String("..")); - if (dotdot != -1) { - bool ok; - int start = it_list.left(dotdot).toInt(&ok); - if (ok) { - int end = it_list.mid(dotdot+2).toInt(&ok); - if (ok) { - if (start < end) { - for (int i = start; i <= end; i++) - loop.list << QString::number(i); - } else { - for (int i = start; i >= end; i--) - loop.list << QString::number(i); - } - } - } - } - } + case T_EVAL: { + ProFile *pro = m_parser->parsedProBlock(fL1S("(eval)"), + args.join(statics.field_sep)); + if (!pro) + return ReturnFalse; + m_locationStack.push(m_current); + VisitReturn ret = visitProBlock(pro, pro->tokPtr()); + m_current = m_locationStack.pop(); + pro->deref(); + return ret; } - m_loopStack.push(loop); - m_sts.condition = true; - return ProItem::ReturnLoop; - } case T_BREAK: if (m_skipLevel) - return ProItem::ReturnFalse; - if (!m_loopStack.isEmpty()) - return ProItem::ReturnBreak; - // ### missing: breaking out of multiline blocks - q->logMessage(format("unexpected break().")); - return ProItem::ReturnFalse; + return ReturnFalse; + if (m_loopLevel) + return ReturnBreak; + evalError(fL1S("unexpected break().")); + return ReturnFalse; case T_NEXT: if (m_skipLevel) - return ProItem::ReturnFalse; - if (!m_loopStack.isEmpty()) - return ProItem::ReturnNext; - q->logMessage(format("unexpected next().")); - return ProItem::ReturnFalse; + return ReturnFalse; + if (m_loopLevel) + return ReturnNext; + evalError(fL1S("unexpected next().")); + return ReturnFalse; case T_IF: { + if (m_skipLevel && !m_cumulative) + return ReturnFalse; if (args.count() != 1) { - q->logMessage(format("if(condition) requires one argument.")); - return ProItem::ReturnFalse; + evalError(fL1S("if(condition) requires one argument.")); + return ReturnFalse; } - QString cond = args.first(); - bool escaped = false; // This is more than qmake does + const ProString &cond = args.at(0); bool quoted = false; bool ret = true; bool orOp = false; @@ -1949,83 +2708,69 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction( int parens = 0; QString test; test.reserve(20); - QString args; - args.reserve(50); - const QChar *d = cond.unicode(); - const QChar *ed = d + cond.length(); + QString argsString; + argsString.reserve(50); + const QChar *d = cond.constData(); + const QChar *ed = d + cond.size(); while (d < ed) { ushort c = (d++)->unicode(); - if (!escaped) { - if (c == '\\') { - escaped = true; - args += c; // Assume no-one quotes the test name - continue; - } else if (c == '"') { - quoted = !quoted; - args += c; // Ditto - continue; - } - } else { - escaped = false; - } + bool isOp = false; if (quoted) { - args += c; // Ditto + if (c == '"') + quoted = false; + else if (c == '!' && test.isEmpty()) + invert = true; + else + test += c; + } else if (c == '(') { + isFunc = true; + if (parens) + argsString += c; + ++parens; + } else if (c == ')') { + --parens; + if (parens) + argsString += c; + } else if (!parens) { + if (c == '"') + quoted = true; + else if (c == ':' || c == '|') + isOp = true; + else if (c == '!' && test.isEmpty()) + invert = true; + else + test += c; } else { - bool isOp = false; - if (c == '(') { - isFunc = true; - if (parens) - args += c; - ++parens; - } else if (c == ')') { - --parens; - if (parens) - args += c; - } else if (!parens) { - if (c == ':' || c == '|') - isOp = true; - else if (c == '!') - invert = true; - else - test += c; - } else { - args += c; - } - if (!parens && (isOp || d == ed)) { - // Yes, qmake doesn't shortcut evaluations here. We can't, either, - // as some test functions have side effects. - bool success; - if (isFunc) { - success = evaluateConditionalFunction(test, args); - } else { - success = isActiveConfig(test, true); - } - success ^= invert; - if (orOp) - ret |= success; + argsString += c; + } + if (!quoted && !parens && (isOp || d == ed)) { + if (m_cumulative || (orOp != ret)) { + test = test.trimmed(); + if (isFunc) + ret = evaluateConditionalFunction(ProString(test), ProString(argsString, NoHash)); else - ret &= success; - orOp = (c == '|'); - invert = false; - isFunc = false; - test.clear(); - args.clear(); + ret = isActiveConfig(test, true); + ret ^= invert; } + orOp = (c == '|'); + invert = false; + isFunc = false; + test.clear(); + argsString.clear(); } } return returnBool(ret); } case T_CONFIG: { if (args.count() < 1 || args.count() > 2) { - q->logMessage(format("CONFIG(config) requires one or two arguments.")); - return ProItem::ReturnFalse; - } - if (args.count() == 1) { - //cond = isActiveConfig(args.first()); XXX - return ProItem::ReturnFalse; + evalError(fL1S("CONFIG(config) requires one or two arguments.")); + return ReturnFalse; } - const QStringList mutuals = args[1].split(QLatin1Char('|')); - const QStringList &configs = valuesDirect(QLatin1String("CONFIG")); + if (args.count() == 1) + return returnBool(isActiveConfig(args.at(0).toQString(m_tmp2))); + const QStringList &mutuals = args.at(1).toQString(m_tmp2).split(QLatin1Char('|')); + const ProStringList &configs = valuesDirect(statics.strCONFIG); + for (int i = configs.size() - 1; i >= 0; i--) { for (int mut = 0; mut < mutuals.count(); mut++) { if (configs[i] == mutuals[mut].trimmed()) { @@ -2033,68 +2778,81 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction( } } } - return ProItem::ReturnFalse; + return ReturnFalse; } case T_CONTAINS: { if (args.count() < 2 || args.count() > 3) { - q->logMessage(format("contains(var, val) requires two or three arguments.")); - return ProItem::ReturnFalse; + evalError(fL1S("contains(var, val) requires two or three arguments.")); + return ReturnFalse; } - QRegExp regx(args[1]); - const QStringList &l = values(args.first()); + const QString &qry = args.at(1).toQString(m_tmp1); + QRegExp regx; + if (qry != QRegExp::escape(qry)) { + QString copy = qry; + copy.detach(); + regx.setPattern(copy); + } + const ProStringList &l = values(map(args.at(0))); if (args.count() == 2) { + int t = 0; for (int i = 0; i < l.size(); ++i) { - const QString val = l[i]; - if (regx.exactMatch(val) || val == args[1]) { - return ProItem::ReturnTrue; - } + const ProString &val = l[i]; + if ((!regx.isEmpty() && regx.exactMatch(val.toQString(m_tmp[t]))) || val == qry) + return ReturnTrue; + t ^= 1; } } else { - const QStringList mutuals = args[2].split(QLatin1Char('|')); + const QStringList &mutuals = args.at(2).toQString(m_tmp3).split(QLatin1Char('|')); for (int i = l.size() - 1; i >= 0; i--) { - const QString val = l[i]; + const ProString val = l[i]; for (int mut = 0; mut < mutuals.count(); mut++) { if (val == mutuals[mut].trimmed()) { - return returnBool(regx.exactMatch(val) || val == args[1]); + return returnBool((!regx.isEmpty() + && regx.exactMatch(val.toQString(m_tmp2))) + || val == qry); } } } } - return ProItem::ReturnFalse; + return ReturnFalse; } case T_COUNT: { if (args.count() != 2 && args.count() != 3) { - q->logMessage(format("count(var, count, op=\"equals\") requires two or three arguments.")); - return ProItem::ReturnFalse; + evalError(fL1S("count(var, count, op=\"equals\") requires two or three arguments.")); + return ReturnFalse; } + int cnt = values(map(args.at(0))).count(); if (args.count() == 3) { - QString comp = args[2]; + const ProString &comp = args.at(2); + const int val = args.at(1).toQString(m_tmp1).toInt(); if (comp == QLatin1String(">") || comp == QLatin1String("greaterThan")) { - return returnBool(values(args.first()).count() > args[1].toInt()); + return returnBool(cnt > val); } else if (comp == QLatin1String(">=")) { - return returnBool(values(args.first()).count() >= args[1].toInt()); + return returnBool(cnt >= val); } else if (comp == QLatin1String("<") || comp == QLatin1String("lessThan")) { - return returnBool(values(args.first()).count() < args[1].toInt()); + return returnBool(cnt < val); } else if (comp == QLatin1String("<=")) { - return returnBool(values(args.first()).count() <= args[1].toInt()); + return returnBool(cnt <= val); } else if (comp == QLatin1String("equals") || comp == QLatin1String("isEqual") || comp == QLatin1String("=") || comp == QLatin1String("==")) { - return returnBool(values(args.first()).count() == args[1].toInt()); + return returnBool(cnt == val); } else { - q->logMessage(format("unexpected modifier to count(%2)").arg(comp)); - return ProItem::ReturnFalse; + evalError(fL1S("unexpected modifier to count(%2)").arg(comp.toQString(m_tmp1))); + return ReturnFalse; } } - return returnBool(values(args.first()).count() == args[1].toInt()); + return returnBool(cnt == args.at(1).toQString(m_tmp1).toInt()); } case T_GREATERTHAN: case T_LESSTHAN: { if (args.count() != 2) { - q->logMessage(format("%1(variable, value) requires two arguments.").arg(function)); - return ProItem::ReturnFalse; + evalError(fL1S("%1(variable, value) requires two arguments.") + .arg(function.toQString(m_tmp1))); + return ReturnFalse; } - QString rhs(args[1]), lhs(values(args[0]).join(QString(Option::field_sep))); + const QString &rhs(args.at(1).toQString(m_tmp1)), + &lhs(values(map(args.at(0))).join(statics.field_sep)); bool ok; int rhs_int = rhs.toInt(&ok); if (ok) { // do integer compare @@ -2111,206 +2869,300 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction( } case T_EQUALS: if (args.count() != 2) { - q->logMessage(format("%1(variable, value) requires two arguments.").arg(function)); - return ProItem::ReturnFalse; + evalError(fL1S("%1(variable, value) requires two arguments.") + .arg(function.toQString(m_tmp1))); + return ReturnFalse; } - return returnBool(values(args[0]).join(QString(Option::field_sep)) == args[1]); + return returnBool(values(map(args.at(0))).join(statics.field_sep) + == args.at(1).toQString(m_tmp1)); case T_CLEAR: { if (m_skipLevel && !m_cumulative) - return ProItem::ReturnFalse; + return ReturnFalse; if (args.count() != 1) { - q->logMessage(format("%1(variable) requires one argument.").arg(function)); - return ProItem::ReturnFalse; - } - QHash<QString, QStringList>::Iterator it = m_valuemap.find(args[0]); - if (it == m_valuemap.end()) - return ProItem::ReturnFalse; - it->clear(); - return ProItem::ReturnTrue; + evalError(fL1S("%1(variable) requires one argument.") + .arg(function.toQString(m_tmp1))); + return ReturnFalse; + } + QHash<ProString, ProStringList> *hsh; + QHash<ProString, ProStringList>::Iterator it; + const ProString &var = map(args.at(0)); + if (!(hsh = findValues(var, &it))) + return ReturnFalse; + if (hsh == &m_valuemapStack.top()) + it->clear(); + else + m_valuemapStack.top()[var].clear(); + return ReturnTrue; } case T_UNSET: { if (m_skipLevel && !m_cumulative) - return ProItem::ReturnFalse; + return ReturnFalse; if (args.count() != 1) { - q->logMessage(format("%1(variable) requires one argument.").arg(function)); - return ProItem::ReturnFalse; - } - QHash<QString, QStringList>::Iterator it = m_valuemap.find(args[0]); - if (it == m_valuemap.end()) - return ProItem::ReturnFalse; - m_valuemap.erase(it); - return ProItem::ReturnTrue; + evalError(fL1S("%1(variable) requires one argument.") + .arg(function.toQString(m_tmp1))); + return ReturnFalse; + } + QHash<ProString, ProStringList> *hsh; + QHash<ProString, ProStringList>::Iterator it; + const ProString &var = map(args.at(0)); + if (!(hsh = findValues(var, &it))) + return ReturnFalse; + if (m_valuemapStack.size() == 1) + hsh->erase(it); + else if (hsh == &m_valuemapStack.top()) + *it = statics.fakeValue; + else + m_valuemapStack.top()[var] = statics.fakeValue; + return ReturnTrue; } case T_INCLUDE: { if (m_skipLevel && !m_cumulative) - return ProItem::ReturnFalse; + return ReturnFalse; QString parseInto; // the third optional argument to include() controls warnings // and is not used here - if ((args.count() == 2) || (args.count() == 3)) { - parseInto = args[1]; + if ((args.count() == 2) || (args.count() == 3) ) { + parseInto = args.at(1).toQString(m_tmp2); } else if (args.count() != 1) { - q->logMessage(format("include(file) requires one, two or three arguments.")); - return ProItem::ReturnFalse; - } - QString fileName = args.first(); - // ### this breaks if we have include(c:/reallystupid.pri) but IMHO that's really bad style. - QDir currentProPath(currentDirectory()); - fileName = QDir::cleanPath(currentProPath.absoluteFilePath(fileName)); - State sts = m_sts; - bool ok = evaluateFile(fileName); - m_sts = sts; + evalError(fL1S("include(file, into, silent) requires one, two or three arguments.")); + return ReturnFalse; + } + QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))); + fn.detach(); + bool ok; + if (parseInto.isEmpty()) { + ok = evaluateFile(fn, ProFileEvaluatorHandler::EvalIncludeFile, + ProFileEvaluator::LoadProOnly); + } else { + QHash<ProString, ProStringList> symbols; + if ((ok = evaluateFileInto(fn, ProFileEvaluatorHandler::EvalAuxFile, + &symbols, 0, EvalWithSetup))) { + QHash<ProString, ProStringList> newMap; + for (QHash<ProString, ProStringList>::ConstIterator + it = m_valuemapStack.top().constBegin(), + end = m_valuemapStack.top().constEnd(); + it != end; ++it) { + const QString &ky = it.key().toQString(m_tmp1); + if (!(ky.startsWith(parseInto) && + (ky.length() == parseInto.length() + || ky.at(parseInto.length()) == QLatin1Char('.')))) + newMap[it.key()] = it.value(); + } + for (QHash<ProString, ProStringList>::ConstIterator it = symbols.constBegin(); + it != symbols.constEnd(); ++it) { + const QString &ky = it.key().toQString(m_tmp1); + if (!ky.startsWith(QLatin1Char('.'))) + newMap.insert(ProString(parseInto + QLatin1Char('.') + ky), it.value()); + } + m_valuemapStack.top() = newMap; + } + } return returnBool(ok); } case T_LOAD: { if (m_skipLevel && !m_cumulative) - return ProItem::ReturnFalse; - QString parseInto; + return ReturnFalse; bool ignore_error = false; if (args.count() == 2) { - QString sarg = args[1]; - ignore_error = (!sarg.compare(QLatin1String("true"), Qt::CaseInsensitive) || sarg.toInt()); + ignore_error = isTrue(args.at(1), m_tmp2); } else if (args.count() != 1) { - q->logMessage(format("load(feature) requires one or two arguments.")); - return ProItem::ReturnFalse; + evalError(fL1S("load(feature) requires one or two arguments.")); + return ReturnFalse; } // XXX ignore_error unused - return returnBool(evaluateFeatureFile(args.first())); + return returnBool(evaluateFeatureFile(expandEnvVars(args.at(0).toQString()))); } case T_DEBUG: // Yup - do nothing. Nothing is going to enable debug output anyway. - return ProItem::ReturnFalse; + return ReturnFalse; case T_MESSAGE: { if (args.count() != 1) { - q->logMessage(format("%1(message) requires one argument.").arg(function)); - return ProItem::ReturnFalse; - } - QString msg = fixEnvVariables(args.first()); - q->fileMessage(QString::fromLatin1("Project %1: %2").arg(function.toUpper(), msg)); + evalError(fL1S("%1(message) requires one argument.") + .arg(function.toQString(m_tmp1))); + return ReturnFalse; + } + const QString &msg = expandEnvVars(args.at(0).toQString(m_tmp2)); + if (!m_skipLevel) + m_handler->fileMessage(fL1S("Project %1: %2") + .arg(function.toQString(m_tmp1).toUpper(), msg)); // ### Consider real termination in non-cumulative mode return returnBool(function != QLatin1String("error")); } #if 0 // Way too dangerous to enable. case T_SYSTEM: { if (args.count() != 1) { - q->logMessage(format("system(exec) requires one argument.")); - ProItem::ReturnFalse; - } - return returnBool(system(args.first().toLatin1().constData()) == 0); + evalError(fL1S("system(exec) requires one argument.")); + return ReturnFalse; + } +#ifndef QT_BOOTSTRAPPED + QProcess proc; + proc.setProcessChannelMode(QProcess::MergedChannels); + runProcess(&proc, args.at(0).toQString(m_tmp2), QProcess::StandardOutput); + return returnBool(proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0); +#else + return returnBool(system((QLatin1String("cd ") + + IoUtils::shellQuote(currentDirectory()) + + QLatin1String(" && ") + args.at(0)).toLocal8Bit().constData()) == 0); +#endif } #endif case T_ISEMPTY: { if (args.count() != 1) { - q->logMessage(format("isEmpty(var) requires one argument.")); - return ProItem::ReturnFalse; + evalError(fL1S("isEmpty(var) requires one argument.")); + return ReturnFalse; } - QStringList sl = values(args.first()); + const ProStringList &sl = values(map(args.at(0))); if (sl.count() == 0) { - return ProItem::ReturnTrue; + return ReturnTrue; } else if (sl.count() > 0) { - QString var = sl.first(); + const ProString &var = sl.first(); if (var.isEmpty()) - return ProItem::ReturnTrue; + return ReturnTrue; } - return ProItem::ReturnFalse; + return ReturnFalse; } case T_EXISTS: { if (args.count() != 1) { - q->logMessage(format("exists(file) requires one argument.")); - return ProItem::ReturnFalse; + evalError(fL1S("exists(file) requires one argument.")); + return ReturnFalse; } - QString file = args.first(); - file = Option::fixPathToLocalOS(file); + const QString &file = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))); - if (QFile::exists(file)) { - return ProItem::ReturnTrue; + if (IoUtils::exists(file)) { + return ReturnTrue; } - //regular expression I guess - QString dirstr = currentDirectory(); - int slsh = file.lastIndexOf(Option::dir_sep); - if (slsh != -1) { - dirstr = file.left(slsh+1); - file = file.right(file.length() - slsh - 1); + int slsh = file.lastIndexOf(QLatin1Char('/')); + QString fn = file.mid(slsh+1); + if (fn.contains(QLatin1Char('*')) || fn.contains(QLatin1Char('?'))) { + QString dirstr = file.left(slsh+1); + if (!QDir(dirstr).entryList(QStringList(fn)).isEmpty()) + return ReturnTrue; } - if (file.contains(QLatin1Char('*')) || file.contains(QLatin1Char('?'))) - if (!QDir(dirstr).entryList(QStringList(file)).isEmpty()) - return ProItem::ReturnTrue; - return ProItem::ReturnFalse; + return ReturnFalse; } - case 0: - q->logMessage(format("'%1' is not a recognized test function").arg(function)); - return ProItem::ReturnFalse; + case T_INVALID: + evalError(fL1S("'%1' is not a recognized test function") + .arg(function.toQString(m_tmp1))); + return ReturnFalse; default: - q->logMessage(format("Function '%1' is not implemented").arg(function)); - return ProItem::ReturnFalse; + evalError(fL1S("Function '%1' is not implemented").arg(function.toQString(m_tmp1))); + return ReturnFalse; + } +} + +QHash<ProString, ProStringList> *ProFileEvaluator::Private::findValues( + const ProString &variableName, QHash<ProString, ProStringList>::Iterator *rit) +{ + for (int i = m_valuemapStack.size(); --i >= 0; ) { + QHash<ProString, ProStringList>::Iterator it = m_valuemapStack[i].find(variableName); + if (it != m_valuemapStack[i].end()) { + if (it->constBegin() == statics.fakeValue.constBegin()) + return 0; + *rit = it; + return &m_valuemapStack[i]; + } + } + return 0; +} + +ProStringList &ProFileEvaluator::Private::valuesRef(const ProString &variableName) +{ + QHash<ProString, ProStringList>::Iterator it = m_valuemapStack.top().find(variableName); + if (it != m_valuemapStack.top().end()) + return *it; + for (int i = m_valuemapStack.size() - 1; --i >= 0; ) { + QHash<ProString, ProStringList>::ConstIterator it = m_valuemapStack.at(i).constFind(variableName); + if (it != m_valuemapStack.at(i).constEnd()) { + ProStringList &ret = m_valuemapStack.top()[variableName]; + ret = *it; + return ret; + } + } + return m_valuemapStack.top()[variableName]; +} + +ProStringList ProFileEvaluator::Private::valuesDirect(const ProString &variableName) const +{ + for (int i = m_valuemapStack.size(); --i >= 0; ) { + QHash<ProString, ProStringList>::ConstIterator it = m_valuemapStack.at(i).constFind(variableName); + if (it != m_valuemapStack.at(i).constEnd()) { + if (it->constBegin() == statics.fakeValue.constBegin()) + break; + return *it; + } } + return ProStringList(); } -QStringList ProFileEvaluator::Private::values(const QString &variableName, - const QHash<QString, QStringList> &place, - const ProFile *pro) const -{ - if (variableName == QLatin1String("LITERAL_WHITESPACE")) //a real space in a token - return QStringList(QLatin1String("\t")); - if (variableName == QLatin1String("LITERAL_DOLLAR")) //a real $ - return QStringList(QLatin1String("$")); - if (variableName == QLatin1String("LITERAL_HASH")) //a real # - return QStringList(QLatin1String("#")); - if (variableName == QLatin1String("OUT_PWD")) //the out going dir - return QStringList(m_outputDir); - if (variableName == QLatin1String("PWD") || //current working dir (of _FILE_) - variableName == QLatin1String("IN_PWD")) - return QStringList(currentDirectory()); - if (variableName == QLatin1String("DIR_SEPARATOR")) - return QStringList(Option::dir_sep); - if (variableName == QLatin1String("DIRLIST_SEPARATOR")) - return QStringList(Option::dirlist_sep); - if (variableName == QLatin1String("_LINE_")) //parser line number - return QStringList(QString::number(m_lineNo)); - if (variableName == QLatin1String("_FILE_")) //parser file; qmake is a bit weird here - return QStringList(m_profileStack.size() == 1 ? pro->fileName() : QFileInfo(pro->fileName()).fileName()); - if (variableName == QLatin1String("_DATE_")) //current date/time - return QStringList(QDateTime::currentDateTime().toString()); - if (variableName == QLatin1String("_PRO_FILE_")) - return QStringList(m_origfile); - if (variableName == QLatin1String("_PRO_FILE_PWD_")) - return QStringList(QFileInfo(m_origfile).absolutePath()); - if (variableName == QLatin1String("_QMAKE_CACHE_")) - return QStringList(); // FIXME? - if (variableName.startsWith(QLatin1String("QMAKE_HOST."))) { - QString ret, type = variableName.mid(11); +ProStringList ProFileEvaluator::Private::values(const ProString &variableName) const +{ + QHash<ProString, int>::ConstIterator vli = statics.varList.find(variableName); + if (vli != statics.varList.constEnd()) { + int vlidx = *vli; + QString ret; + switch ((VarName)vlidx) { + case V_LITERAL_WHITESPACE: ret = QLatin1String("\t"); break; + case V_LITERAL_DOLLAR: ret = QLatin1String("$"); break; + case V_LITERAL_HASH: ret = QLatin1String("#"); break; + case V_OUT_PWD: // the outgoing dir (shadow of _PRO_FILE_PWD_) + ret = m_outputDir; + break; + case V_PWD: // containing directory of most nested project/include file + case V_IN_PWD: + ret = currentDirectory(); + break; + case V_DIR_SEPARATOR: + validateModes(); + ret = m_option->dir_sep; + break; + case V_DIRLIST_SEPARATOR: + ret = m_option->dirlist_sep; + break; + case V__LINE_: // currently executed line number + ret = QString::number(m_current.line); + break; + case V__FILE_: // currently executed file + ret = m_current.pro->fileName(); + break; + case V__DATE_: //current date/time + ret = QDateTime::currentDateTime().toString(); + break; + case V__PRO_FILE_: + ret = m_profileStack.first()->fileName(); + break; + case V__PRO_FILE_PWD_: + ret = m_profileStack.first()->directoryName(); + break; + case V__QMAKE_CACHE_: + ret = m_option->cachefile; + break; #if defined(Q_OS_WIN32) - if (type == QLatin1String("os")) { - ret = QLatin1String("Windows"); - } else if (type == QLatin1String("name")) { + case V_QMAKE_HOST_os: ret = QLatin1String("Windows"); break; + case V_QMAKE_HOST_name: { DWORD name_length = 1024; - wchar_t name[1024]; + TCHAR name[1024]; if (GetComputerName(name, &name_length)) - ret = QString::fromWCharArray(name); - } else if (type == QLatin1String("version") || type == QLatin1String("version_string")) { - QSysInfo::WinVersion ver = QSysInfo::WindowsVersion; - if (type == QLatin1String("version")) - ret = QString::number(ver); - else if (ver == QSysInfo::WV_Me) - ret = QLatin1String("WinMe"); - else if (ver == QSysInfo::WV_95) - ret = QLatin1String("Win95"); - else if (ver == QSysInfo::WV_98) - ret = QLatin1String("Win98"); - else if (ver == QSysInfo::WV_NT) - ret = QLatin1String("WinNT"); - else if (ver == QSysInfo::WV_2000) - ret = QLatin1String("Win2000"); - else if (ver == QSysInfo::WV_2000) - ret = QLatin1String("Win2003"); - else if (ver == QSysInfo::WV_XP) - ret = QLatin1String("WinXP"); - else if (ver == QSysInfo::WV_VISTA) - ret = QLatin1String("WinVista"); - else - ret = QLatin1String("Unknown"); - } else if (type == QLatin1String("arch")) { + ret = QString::fromUtf16((ushort*)name, name_length); + break; + } + case V_QMAKE_HOST_version: + ret = QString::number(QSysInfo::WindowsVersion); + break; + case V_QMAKE_HOST_version_string: + switch (QSysInfo::WindowsVersion) { + case QSysInfo::WV_Me: ret = QLatin1String("WinMe"); break; + case QSysInfo::WV_95: ret = QLatin1String("Win95"); break; + case QSysInfo::WV_98: ret = QLatin1String("Win98"); break; + case QSysInfo::WV_NT: ret = QLatin1String("WinNT"); break; + case QSysInfo::WV_2000: ret = QLatin1String("Win2000"); break; + case QSysInfo::WV_2003: ret = QLatin1String("Win2003"); break; + case QSysInfo::WV_XP: ret = QLatin1String("WinXP"); break; + case QSysInfo::WV_VISTA: ret = QLatin1String("WinVista"); break; + default: ret = QLatin1String("Unknown"); break; + } + break; + case V_QMAKE_HOST_arch: SYSTEM_INFO info; GetSystemInfo(&info); switch(info.wProcessorArchitecture) { @@ -2332,115 +3184,154 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName, ret = QLatin1String("Unknown"); break; } - } + break; #elif defined(Q_OS_UNIX) - struct utsname name; - if (!uname(&name)) { - if (type == QLatin1String("os")) - ret = QString::fromLatin1(name.sysname); - else if (type == QLatin1String("name")) - ret = QString::fromLatin1(name.nodename); - else if (type == QLatin1String("version")) - ret = QString::fromLatin1(name.release); - else if (type == QLatin1String("version_string")) - ret = QString::fromLatin1(name.version); - else if (type == QLatin1String("arch")) - ret = QString::fromLatin1(name.machine); - } + case V_QMAKE_HOST_os: + case V_QMAKE_HOST_name: + case V_QMAKE_HOST_version: + case V_QMAKE_HOST_version_string: + case V_QMAKE_HOST_arch: + { + struct utsname name; + const char *what; + if (!uname(&name)) { + switch (vlidx) { + case V_QMAKE_HOST_os: what = name.sysname; break; + case V_QMAKE_HOST_name: what = name.nodename; break; + case V_QMAKE_HOST_version: what = name.release; break; + case V_QMAKE_HOST_version_string: what = name.version; break; + case V_QMAKE_HOST_arch: what = name.machine; break; + } + ret = QString::fromLocal8Bit(what); + } + } #endif - return QStringList(ret); + } + return ProStringList(ProString(ret, NoHash)); } - QStringList result = place[variableName]; + ProStringList result = valuesDirect(variableName); if (result.isEmpty()) { - if (variableName == QLatin1String("TARGET")) { - result.append(QFileInfo(m_origfile).baseName()); - } else if (variableName == QLatin1String("TEMPLATE")) { - result.append(QLatin1String("app")); - } else if (variableName == QLatin1String("QMAKE_DIR_SEP")) { - result.append(Option::dirlist_sep); + if (variableName == statics.strTEMPLATE) { + result.append(ProString("app", NoHash)); + } else if (variableName == statics.strQMAKE_DIR_SEP) { + result.append(ProString(m_option->dirlist_sep, NoHash)); } } return result; } -QStringList ProFileEvaluator::Private::values(const QString &variableName) const +bool ProFileEvaluator::Private::evaluateFileDirect( + const QString &fileName, ProFileEvaluatorHandler::EvalFileType type, + ProFileEvaluator::LoadFlags flags) { - return values(variableName, m_valuemap, currentProFile()); -} - -QStringList ProFileEvaluator::Private::values(const QString &variableName, const ProFile *pro) const -{ - return values(variableName, m_filevaluemap[pro], pro); -} - -ProFile *ProFileEvaluator::parsedProFile(const QString &fileName) -{ - QFileInfo fi(fileName); - if (fi.exists()) { - QString fn = QDir::cleanPath(fi.absoluteFilePath()); - foreach (const ProFile *pf, d->m_profileStack) - if (pf->fileName() == fn) { - errorMessage(d->format("circular inclusion of %1").arg(fn)); - return 0; - } - ProFile *pro = new ProFile(fn); - if (d->read(pro)) - return pro; - delete pro; + if (ProFile *pro = m_parser->parsedProFile(fileName, true)) { + m_locationStack.push(m_current); + bool ok = (visitProFile(pro, type, flags) == ReturnTrue); + m_current = m_locationStack.pop(); + pro->deref(); + return ok; + } else { + return false; } - return 0; } -void ProFileEvaluator::releaseParsedProFile(ProFile *proFile) +bool ProFileEvaluator::Private::evaluateFile( + const QString &fileName, ProFileEvaluatorHandler::EvalFileType type, + ProFileEvaluator::LoadFlags flags) { - delete proFile; -} - -bool ProFileEvaluator::Private::evaluateFile(const QString &fileName) -{ - ProFile *pro = q->parsedProFile(fileName); - if (pro) { - m_profileStack.push(pro); - bool ok = (pro->Accept(this) == ProItem::ReturnTrue); - m_profileStack.pop(); - q->releaseParsedProFile(pro); - return ok; - } else { + if (fileName.isEmpty()) return false; - } + foreach (const ProFile *pf, m_profileStack) + if (pf->fileName() == fileName) { + evalError(fL1S("circular inclusion of %1").arg(fileName)); + return false; + } + return evaluateFileDirect(fileName, type, flags); } bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName) { - QString fn; - foreach (const QString &path, qmakeFeaturePaths()) { - QString fname = path + QLatin1Char('/') + fileName; - if (QFileInfo(fname).exists()) { - fn = fname; - break; + QString fn = fileName; + if (!fn.endsWith(QLatin1String(".prf"))) + fn += QLatin1String(".prf"); + + if ((!fileName.contains((ushort)'/') && !fileName.contains((ushort)'\\')) + || !IoUtils::exists(resolvePath(fn))) { + if (m_option->feature_roots.isEmpty()) + m_option->feature_roots = qmakeFeaturePaths(); + int start_root = 0; + QString currFn = currentFileName(); + if (IoUtils::fileName(currFn) == IoUtils::fileName(fn)) { + for (int root = 0; root < m_option->feature_roots.size(); ++root) + if (currFn == m_option->feature_roots.at(root) + fn) { + start_root = root + 1; + break; + } } - fname += QLatin1String(".prf"); - if (QFileInfo(fname).exists()) { - fn = fname; - break; + for (int root = start_root; root < m_option->feature_roots.size(); ++root) { + QString fname = m_option->feature_roots.at(root) + fn; + if (IoUtils::exists(fname)) { + fn = fname; + goto cool; + } } - } - if (fn.isEmpty()) return false; + + cool: + // It's beyond me why qmake has this inside this if ... + ProStringList &already = valuesRef(ProString("QMAKE_INTERNAL_INCLUDED_FEATURES")); + ProString afn(fn, NoHash); + if (already.contains(afn)) + return true; + already.append(afn); + } else { + fn = resolvePath(fn); + } + +#ifdef PROEVALUATOR_CUMULATIVE bool cumulative = m_cumulative; m_cumulative = false; - bool ok = evaluateFile(fn); +#endif + + // The path is fully normalized already. + bool ok = evaluateFileDirect(fn, ProFileEvaluatorHandler::EvalFeatureFile, + ProFileEvaluator::LoadProOnly); + +#ifdef PROEVALUATOR_CUMULATIVE m_cumulative = cumulative; +#endif return ok; } -QString ProFileEvaluator::Private::format(const char *fmt) const +bool ProFileEvaluator::Private::evaluateFileInto( + const QString &fileName, ProFileEvaluatorHandler::EvalFileType type, + QHash<ProString, ProStringList> *values, FunctionDefs *funcs, EvalIntoMode mode) { - ProFile *pro = currentProFile(); - QString fileName = pro ? pro->fileName() : QLatin1String("Not a file"); - int lineNumber = pro ? m_lineNo : 0; - return QString::fromLatin1("%1(%2):").arg(fileName).arg(lineNumber) + QString::fromAscii(fmt); + ProFileEvaluator visitor(m_option, m_parser, m_handler); +#ifdef PROEVALUATOR_CUMULATIVE + visitor.d->m_cumulative = false; +#endif + visitor.d->m_outputDir = m_outputDir; +// visitor.d->m_valuemapStack.top() = *values; + if (funcs) + visitor.d->m_functionDefs = *funcs; + if (mode == EvalWithDefaults) + visitor.d->evaluateFeatureFile(QLatin1String("default_pre.prf")); + if (!visitor.d->evaluateFile(fileName, type, + (mode == EvalWithSetup) ? ProFileEvaluator::LoadAll : ProFileEvaluator::LoadProOnly)) + return false; + *values = visitor.d->m_valuemapStack.top(); +// if (funcs) +// *funcs = visitor.d->m_functionDefs; + return true; +} + +void ProFileEvaluator::Private::evalError(const QString &message) const +{ + if (!m_skipLevel) + m_handler->evalError(m_current.line ? m_current.pro->fileName() : QString(), + m_current.line, message); } @@ -2450,10 +3341,15 @@ QString ProFileEvaluator::Private::format(const char *fmt) const // /////////////////////////////////////////////////////////////////////// -ProFileEvaluator::ProFileEvaluator() - : d(new Private(this)) +void ProFileEvaluator::initialize() +{ + Private::initStatics(); +} + +ProFileEvaluator::ProFileEvaluator(ProFileOption *option, ProFileParser *parser, + ProFileEvaluatorHandler *handler) + : d(new Private(this, option, parser, handler)) { - Option::init(); } ProFileEvaluator::~ProFileEvaluator() @@ -2463,26 +3359,38 @@ ProFileEvaluator::~ProFileEvaluator() bool ProFileEvaluator::contains(const QString &variableName) const { - return d->m_valuemap.contains(variableName); + return d->m_valuemapStack.top().contains(ProString(variableName)); } -inline QStringList fixEnvVariables(const QStringList &x) +QString ProFileEvaluator::value(const QString &variable) const { - QStringList ret; - foreach (const QString &str, x) - ret << Option::fixString(str, Option::FixEnvVars); - return ret; -} + const QStringList &vals = values(variable); + if (!vals.isEmpty()) + return vals.first(); + return QString(); +} QStringList ProFileEvaluator::values(const QString &variableName) const { - return fixEnvVariables(d->values(variableName)); + const ProStringList &values = d->values(ProString(variableName)); + QStringList ret; + ret.reserve(values.size()); + foreach (const ProString &str, values) + ret << d->expandEnvVars(str.toQString()); + return ret; } QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const { - return fixEnvVariables(d->values(variableName, pro)); + // It makes no sense to put any kind of magic into expanding these + const ProStringList &values = d->m_valuemapStack.at(0).value(ProString(variableName)); + QStringList ret; + ret.reserve(values.size()); + foreach (const ProString &str, values) + if (str.sourceFile() == pro) + ret << d->expandEnvVars(str.toQString()); + return ret; } QStringList ProFileEvaluator::absolutePathValues( @@ -2490,9 +3398,10 @@ QStringList ProFileEvaluator::absolutePathValues( { QStringList result; foreach (const QString &el, values(variable)) { - const QFileInfo info = QFileInfo(baseDirectory, el); - if (info.isDir()) - result << QDir::cleanPath(info.absoluteFilePath()); + QString absEl = IoUtils::isAbsolutePath(el) + ? d->sysrootify(el, baseDirectory) : IoUtils::resolvePath(baseDirectory, el); + if (IoUtils::fileType(absEl) == IoUtils::FileIsDir) + result << QDir::cleanPath(absEl); } return result; } @@ -2503,34 +3412,40 @@ QStringList ProFileEvaluator::absoluteFileValues( { QStringList result; foreach (const QString &el, pro ? values(variable, pro) : values(variable)) { - QFileInfo info(el); - if (info.isAbsolute()) { - if (info.exists()) { - result << QDir::cleanPath(el); + QString absEl; + if (IoUtils::isAbsolutePath(el)) { + const QString elWithSysroot = d->sysrootify(el, baseDirectory); + if (IoUtils::exists(elWithSysroot)) { + result << QDir::cleanPath(elWithSysroot); goto next; } + absEl = elWithSysroot; } else { foreach (const QString &dir, searchDirs) { - QFileInfo info(dir, el); - if (info.isFile()) { - result << QDir::cleanPath(info.filePath()); + QString fn = dir + QLatin1Char('/') + el; + if (IoUtils::exists(fn)) { + result << QDir::cleanPath(fn); goto next; } } if (baseDirectory.isEmpty()) goto next; - info = QFileInfo(baseDirectory, el); + absEl = baseDirectory + QLatin1Char('/') + el; } { - QFileInfo baseInfo(info.absolutePath()); - if (baseInfo.exists()) { - QString wildcard = info.fileName(); + absEl = QDir::cleanPath(absEl); + int nameOff = absEl.lastIndexOf(QLatin1Char('/')); + QString absDir = d->m_tmp1.setRawData(absEl.constData(), nameOff); + if (IoUtils::exists(absDir)) { + QString wildcard = d->m_tmp2.setRawData(absEl.constData() + nameOff + 1, + absEl.length() - nameOff - 1); if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) { - QDir theDir(QDir::cleanPath(baseInfo.filePath())); + wildcard.detach(); // Keep m_tmp out of QRegExp's cache + QDir theDir(absDir); foreach (const QString &fn, theDir.entryList(QStringList(wildcard))) - if (fn != QLatin1String(".") && fn != QLatin1String("..")) - result << theDir.absoluteFilePath(fn); - } + if (fn != statics.strDot && fn != statics.strDotDot) + result << absDir + QLatin1Char('/') + fn; + } // else if (acceptMissing) } } next: ; @@ -2538,86 +3453,41 @@ QStringList ProFileEvaluator::absoluteFileValues( return result; } -ProFileEvaluator::TemplateType ProFileEvaluator::templateType() +ProFileEvaluator::TemplateType ProFileEvaluator::templateType() const { - QStringList templ = values(QLatin1String("TEMPLATE")); + const ProStringList &templ = d->values(statics.strTEMPLATE); if (templ.count() >= 1) { - const QString &t = templ.last(); + const QString &t = templ.at(0).toQString(); if (!t.compare(QLatin1String("app"), Qt::CaseInsensitive)) return TT_Application; if (!t.compare(QLatin1String("lib"), Qt::CaseInsensitive)) return TT_Library; if (!t.compare(QLatin1String("script"), Qt::CaseInsensitive)) return TT_Script; + if (!t.compare(QLatin1String("aux"), Qt::CaseInsensitive)) + return TT_Aux; if (!t.compare(QLatin1String("subdirs"), Qt::CaseInsensitive)) return TT_Subdirs; } return TT_Unknown; } -bool ProFileEvaluator::queryProFile(ProFile *pro) -{ - return d->read(pro); -} - -bool ProFileEvaluator::accept(ProFile *pro) +bool ProFileEvaluator::accept(ProFile *pro, LoadFlags flags) { - return pro->Accept(d); + return d->visitProFile(pro, ProFileEvaluatorHandler::EvalProjectFile, flags) == Private::ReturnTrue; } QString ProFileEvaluator::propertyValue(const QString &name) const { - return d->propertyValue(name); -} - -namespace { - template<class K, class T> void insert(QHash<K,T> *out, const QHash<K,T> &in) - { - typename QHash<K,T>::const_iterator i = in.begin(); - while (i != in.end()) { - out->insert(i.key(), i.value()); - ++i; - } - } -} // anon namespace - -void ProFileEvaluator::addVariables(const QHash<QString, QStringList> &variables) -{ - insert(&(d->m_valuemap), variables); -} - -void ProFileEvaluator::addProperties(const QHash<QString, QString> &properties) -{ - insert(&(d->m_properties), properties); -} - -void ProFileEvaluator::logMessage(const QString &message) -{ - if (d->m_verbose && !d->m_skipLevel) - fprintf(stderr, "%s\n", qPrintable(message)); -} - -void ProFileEvaluator::fileMessage(const QString &message) -{ - if (!d->m_skipLevel) - fprintf(stderr, "%s\n", qPrintable(message)); -} - -void ProFileEvaluator::errorMessage(const QString &message) -{ - if (!d->m_skipLevel) - fprintf(stderr, "%s\n", qPrintable(message)); -} - -void ProFileEvaluator::setVerbose(bool on) -{ - d->m_verbose = on; + return d->propertyValue(name, false); } +#ifdef PROEVALUATOR_CUMULATIVE void ProFileEvaluator::setCumulative(bool on) { d->m_cumulative = on; } +#endif void ProFileEvaluator::setOutputDir(const QString &dir) { diff --git a/tools/linguist/shared/profileevaluator.h b/tools/linguist/shared/profileevaluator.h index d4cdbcd..b3086bf 100644 --- a/tools/linguist/shared/profileevaluator.h +++ b/tools/linguist/shared/profileevaluator.h @@ -42,52 +42,104 @@ #ifndef PROFILEEVALUATOR_H #define PROFILEEVALUATOR_H +#include "proparser_global.h" #include "proitems.h" -#include "abstractproitemvisitor.h" -#include <QtCore/QIODevice> #include <QtCore/QHash> #include <QtCore/QStringList> -#include <QtCore/QStack> - -#if (!defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) && !defined(__SUNPRO_CC) -# define HAVE_TEMPLATE_CLASS_FRIENDS +#ifndef QT_BOOTSTRAPPED +# include <QtCore/QProcess> +#endif +#ifdef PROEVALUATOR_THREAD_SAFE +# include <QtCore/QMutex> +# include <QtCore/QWaitCondition> #endif QT_BEGIN_NAMESPACE -class ProFileEvaluator +struct ProFileOption; +class ProFileParser; + +class PROPARSER_EXPORT ProFileEvaluatorHandler { -#ifdef HAVE_TEMPLATE_CLASS_FRIENDS -private: -#else public: -#endif + // qmake/project configuration error + virtual void configError(const QString &msg) = 0; + // Some error during evaluation + virtual void evalError(const QString &filename, int lineNo, const QString &msg) = 0; + // error() and message() from .pro file + virtual void fileMessage(const QString &msg) = 0; + + enum EvalFileType { EvalProjectFile, EvalIncludeFile, EvalConfigFile, EvalFeatureFile, EvalAuxFile }; + virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type) = 0; + virtual void doneWithEval(ProFile *parent) = 0; +}; + + +class PROPARSER_EXPORT ProFileEvaluator +{ class Private; public: + class FunctionDef { + public: + FunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); } + FunctionDef(const FunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); } + ~FunctionDef() { m_pro->deref(); } + FunctionDef &operator=(const FunctionDef &o) + { + if (this != &o) { + m_pro->deref(); + m_pro = o.m_pro; + m_pro->ref(); + m_offset = o.m_offset; + } + return *this; + } + ProFile *pro() const { return m_pro; } + const ushort *tokPtr() const { return m_pro->tokPtr() + m_offset; } + private: + ProFile *m_pro; + int m_offset; + }; + + struct FunctionDefs { + QHash<ProString, FunctionDef> testFunctions; + QHash<ProString, FunctionDef> replaceFunctions; + }; + enum TemplateType { TT_Unknown = 0, TT_Application, TT_Library, TT_Script, + TT_Aux, TT_Subdirs }; - ProFileEvaluator(); - virtual ~ProFileEvaluator(); + // Call this from a concurrency-free context + static void initialize(); + + ProFileEvaluator(ProFileOption *option, ProFileParser *parser, ProFileEvaluatorHandler *handler); + ~ProFileEvaluator(); - ProFileEvaluator::TemplateType templateType(); - virtual bool contains(const QString &variableName) const; - void setVerbose(bool on); // Default is false + ProFileEvaluator::TemplateType templateType() const; +#ifdef PROEVALUATOR_CUMULATIVE void setCumulative(bool on); // Default is true! +#endif void setOutputDir(const QString &dir); // Default is empty - bool queryProFile(ProFile *pro); - bool accept(ProFile *pro); + enum LoadFlag { + LoadProOnly = 0, + LoadPreFiles = 1, + LoadPostFiles = 2, + LoadAll = LoadPreFiles|LoadPostFiles + }; + Q_DECLARE_FLAGS(LoadFlags, LoadFlag) + bool accept(ProFile *pro, LoadFlags flags = LoadAll); - void addVariables(const QHash<QString, QStringList> &variables); - void addProperties(const QHash<QString, QString> &properties); + bool contains(const QString &variableName) const; + QString value(const QString &variableName) const; QStringList values(const QString &variableName) const; QStringList values(const QString &variableName, const ProFile *pro) const; QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const; @@ -96,21 +148,83 @@ public: const ProFile *pro) const; QString propertyValue(const QString &val) const; - // for our descendents - virtual ProFile *parsedProFile(const QString &fileName); - virtual void releaseParsedProFile(ProFile *proFile); - virtual void logMessage(const QString &msg); - virtual void errorMessage(const QString &msg); // .pro parse errors - virtual void fileMessage(const QString &msg); // error() and message() from .pro file - private: Private *d; -#ifdef HAVE_TEMPLATE_CLASS_FRIENDS - template<typename T> friend class QTypeInfo; + friend struct ProFileOption; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(ProFileEvaluator::LoadFlags) + +// This struct is from qmake, but we are not using everything. +struct PROPARSER_EXPORT ProFileOption +{ + ProFileOption(); + ~ProFileOption(); + + //simply global convenience + //QString libtool_ext; + //QString pkgcfg_ext; + //QString prf_ext; + //QString prl_ext; + //QString ui_ext; + //QStringList h_ext; + //QStringList cpp_ext; + //QString h_moc_ext; + //QString cpp_moc_ext; + //QString obj_ext; + //QString lex_ext; + //QString yacc_ext; + //QString h_moc_mod; + //QString cpp_moc_mod; + //QString lex_mod; + //QString yacc_mod; + QString dir_sep; + QString dirlist_sep; + QString qmakespec; + QString cachefile; + QHash<QString, QString> properties; +#ifndef QT_BOOTSTRAPPED + QProcessEnvironment environment; +#endif + QString sysroot; + + //QString pro_ext; + //QString res_ext; + + // -nocache, -cache, -spec, QMAKESPEC + // -set persistent value + void setCommandLineArguments(const QStringList &args); +#ifdef PROEVALUATOR_INIT_PROPS + bool initProperties(const QString &qmake); +#endif + + private: + friend class ProFileEvaluator; + friend class ProFileEvaluator::Private; + + void applyHostMode(); + QString getEnv(const QString &) const; + + QHash<ProString, ProStringList> base_valuemap; // Cached results of qmake.conf, .qmake.cache & default_pre.prf + ProFileEvaluator::FunctionDefs base_functions; + QStringList feature_roots; + QString qmakespec_name; + QString precmds, postcmds; + enum HOST_MODE { HOST_UNKNOWN_MODE, HOST_UNIX_MODE, HOST_WIN_MODE, HOST_MACX_MODE }; + HOST_MODE host_mode; + enum TARG_MODE { TARG_UNKNOWN_MODE, TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, + TARG_SYMBIAN_MODE }; + TARG_MODE target_mode; +#ifdef PROEVALUATOR_THREAD_SAFE + QMutex mutex; + QWaitCondition cond; + bool base_inProgress; #endif }; +Q_DECLARE_TYPEINFO(ProFileEvaluator::FunctionDef, Q_MOVABLE_TYPE); + QT_END_NAMESPACE #endif // PROFILEEVALUATOR_H diff --git a/tools/linguist/shared/profileparser.cpp b/tools/linguist/shared/profileparser.cpp new file mode 100644 index 0000000..5ba33fc --- /dev/null +++ b/tools/linguist/shared/profileparser.cpp @@ -0,0 +1,1037 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Linguist of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "profileparser.h" + +#include "ioutils.h" +using namespace ProFileEvaluatorInternal; + +#include <QtCore/QFile> +#ifdef PROPARSER_THREAD_SAFE +# include <QtCore/QThreadPool> +#endif + +QT_BEGIN_NAMESPACE + +/////////////////////////////////////////////////////////////////////// +// +// ProFileCache +// +/////////////////////////////////////////////////////////////////////// + +ProFileCache::~ProFileCache() +{ + foreach (const Entry &ent, parsed_files) + if (ent.pro) + ent.pro->deref(); +} + +void ProFileCache::discardFile(const QString &fileName) +{ +#ifdef PROPARSER_THREAD_SAFE + QMutexLocker lck(&mutex); +#endif + QHash<QString, Entry>::Iterator it = parsed_files.find(fileName); + if (it != parsed_files.end()) { + if (it->pro) + it->pro->deref(); + parsed_files.erase(it); + } +} + +void ProFileCache::discardFiles(const QString &prefix) +{ +#ifdef PROPARSER_THREAD_SAFE + QMutexLocker lck(&mutex); +#endif + QHash<QString, Entry>::Iterator + it = parsed_files.begin(), + end = parsed_files.end(); + while (it != end) + if (it.key().startsWith(prefix)) { + if (it->pro) + it->pro->deref(); + it = parsed_files.erase(it); + } else { + ++it; + } +} + + +////////// Parser /////////// + +#define fL1S(s) QString::fromLatin1(s) + +namespace { // MSVC2010 doesn't seem to know the semantics of "static" ... + +static struct { + QString strelse; + QString strfor; + QString strdefineTest; + QString strdefineReplace; +} statics; + +} + +void ProFileParser::initialize() +{ + if (!statics.strelse.isNull()) + return; + + statics.strelse = QLatin1String("else"); + statics.strfor = QLatin1String("for"); + statics.strdefineTest = QLatin1String("defineTest"); + statics.strdefineReplace = QLatin1String("defineReplace"); +} + +ProFileParser::ProFileParser(ProFileCache *cache, ProFileParserHandler *handler) + : m_cache(cache) + , m_handler(handler) +{ + // So that single-threaded apps don't have to call initialize() for now. + initialize(); +} + +ProFile *ProFileParser::parsedProFile(const QString &fileName, bool cache, const QString *contents) +{ + ProFile *pro; + if (cache && m_cache) { + ProFileCache::Entry *ent; +#ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&m_cache->mutex); +#endif + QHash<QString, ProFileCache::Entry>::Iterator it = m_cache->parsed_files.find(fileName); + if (it != m_cache->parsed_files.end()) { + ent = &*it; +#ifdef PROPARSER_THREAD_SAFE + if (ent->locker && !ent->locker->done) { + ++ent->locker->waiters; + QThreadPool::globalInstance()->releaseThread(); + ent->locker->cond.wait(locker.mutex()); + QThreadPool::globalInstance()->reserveThread(); + if (!--ent->locker->waiters) { + delete ent->locker; + ent->locker = 0; + } + } +#endif + if ((pro = ent->pro)) + pro->ref(); + } else { + ent = &m_cache->parsed_files[fileName]; +#ifdef PROPARSER_THREAD_SAFE + ent->locker = new ProFileCache::Entry::Locker; + locker.unlock(); +#endif + pro = new ProFile(fileName); + if (!(!contents ? read(pro) : read(pro, *contents))) { + delete pro; + pro = 0; + } else { + pro->ref(); + } + ent->pro = pro; +#ifdef PROPARSER_THREAD_SAFE + locker.relock(); + if (ent->locker->waiters) { + ent->locker->done = true; + ent->locker->cond.wakeAll(); + } else { + delete ent->locker; + ent->locker = 0; + } +#endif + } + } else { + pro = new ProFile(fileName); + if (!(!contents ? read(pro) : read(pro, *contents))) { + delete pro; + pro = 0; + } + } + return pro; +} + +bool ProFileParser::read(ProFile *pro) +{ + QFile file(pro->fileName()); + if (!file.open(QIODevice::ReadOnly)) { + if (m_handler && IoUtils::exists(pro->fileName())) + m_handler->parseError(QString(), 0, fL1S("%1 not readable.").arg(pro->fileName())); + return false; + } + + QString content(QString::fromLocal8Bit(file.readAll())); + file.close(); + return read(pro, content); +} + +void ProFileParser::putTok(ushort *&tokPtr, ushort tok) +{ + *tokPtr++ = tok; +} + +void ProFileParser::putBlockLen(ushort *&tokPtr, uint len) +{ + *tokPtr++ = (ushort)len; + *tokPtr++ = (ushort)(len >> 16); +} + +void ProFileParser::putBlock(ushort *&tokPtr, const ushort *buf, uint len) +{ + memcpy(tokPtr, buf, len * 2); + tokPtr += len; +} + +void ProFileParser::putHashStr(ushort *&pTokPtr, const ushort *buf, uint len) +{ + uint hash = ProString::hash((const QChar *)buf, len); + ushort *tokPtr = pTokPtr; + *tokPtr++ = (ushort)hash; + *tokPtr++ = (ushort)(hash >> 16); + *tokPtr++ = (ushort)len; + memcpy(tokPtr, buf, len * 2); + pTokPtr = tokPtr + len; +} + +void ProFileParser::finalizeHashStr(ushort *buf, uint len) +{ + buf[-4] = TokHashLiteral; + buf[-1] = len; + uint hash = ProString::hash((const QChar *)buf, len); + buf[-3] = (ushort)hash; + buf[-2] = (ushort)(hash >> 16); +} + +bool ProFileParser::read(ProFile *pro, const QString &in) +{ + m_proFile = pro; + m_lineNo = 1; + + // Final precompiled token stream buffer + QString tokBuff; + // Worst-case size calculations: + // - line marker adds 1 (2-nl) to 1st token of each line + // - empty assignment "A=":2 => + // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + + // TokValueTerminator(1) == 7 (8) + // - non-empty assignment "A=B C":5 => + // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + + // TokLiteral(1) + len(1) + "B"(1) + + // TokLiteral(1) + len(1) + "C"(1) + TokValueTerminator(1) == 13 (14) + // - variable expansion: "$$f":3 => + // TokVariable(1) + hash(2) + len(1) + "f"(1) = 5 + // - function expansion: "$$f()":5 => + // TokFuncName(1) + hash(2) + len(1) + "f"(1) + TokFuncTerminator(1) = 6 + // - scope: "X:":2 => + // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokCondition(1) + + // TokBranch(1) + len(2) + ... + len(2) + ... == 10 + // - test: "X():":4 => + // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokTestCall(1) + TokFuncTerminator(1) + + // TokBranch(1) + len(2) + ... + len(2) + ... == 11 + // - "for(A,B):":9 => + // TokForLoop(1) + hash(2) + len(1) + "A"(1) + + // len(2) + TokLiteral(1) + len(1) + "B"(1) + TokValueTerminator(1) + + // len(2) + ... + TokTerminator(1) == 14 (15) + tokBuff.reserve((in.size() + 1) * 5); + ushort *tokPtr = (ushort *)tokBuff.constData(); // Current writing position + + // Expression precompiler buffer. + QString xprBuff; + xprBuff.reserve(tokBuff.capacity()); // Excessive, but simple + ushort * const buf = (ushort *)xprBuff.constData(); + + // Parser state + m_blockstack.clear(); + m_blockstack.resize(1); + + QStack<ParseCtx> xprStack; + xprStack.reserve(10); + + // We rely on QStrings being null-terminated, so don't maintain a global end pointer. + const ushort *cur = (const ushort *)in.unicode(); + m_canElse = false; + freshLine: + m_state = StNew; + m_invert = false; + m_operator = NoOperator; + m_markLine = m_lineNo; + m_inError = false; + Context context = CtxTest; + int parens = 0; // Braces in value context + int argc = 0; + int wordCount = 0; // Number of words in currently accumulated expression + bool putSpace = false; // Only ever true inside quoted string + bool lineMarked = true; // For in-expression markers + ushort needSep = TokNewStr; // Complementary to putSpace: separator outside quotes + ushort quote = 0; + ushort term = 0; + + ushort *ptr = buf; + ptr += 4; + ushort *xprPtr = ptr; + +#define FLUSH_LHS_LITERAL() \ + do { \ + if ((tlen = ptr - xprPtr)) { \ + finalizeHashStr(xprPtr, tlen); \ + if (needSep) { \ + wordCount++; \ + needSep = 0; \ + } \ + } else { \ + ptr -= 4; \ + } \ + } while (0) + +#define FLUSH_RHS_LITERAL() \ + do { \ + if ((tlen = ptr - xprPtr)) { \ + xprPtr[-2] = TokLiteral | needSep; \ + xprPtr[-1] = tlen; \ + if (needSep) { \ + wordCount++; \ + needSep = 0; \ + } \ + } else { \ + ptr -= 2; \ + } \ + } while (0) + +#define FLUSH_LITERAL() \ + do { \ + if (context == CtxTest) \ + FLUSH_LHS_LITERAL(); \ + else \ + FLUSH_RHS_LITERAL(); \ + } while (0) + +#define FLUSH_VALUE_LIST() \ + do { \ + if (wordCount > 1) { \ + xprPtr = tokPtr; \ + if (*xprPtr == TokLine) \ + xprPtr += 2; \ + tokPtr[-1] = ((*xprPtr & TokMask) == TokLiteral) ? wordCount : 0; \ + } else { \ + tokPtr[-1] = 0; \ + } \ + tokPtr = ptr; \ + putTok(tokPtr, TokValueTerminator); \ + } while (0) + + forever { + ushort c; + + // First, skip leading whitespace + for (;; ++cur) { + c = *cur; + if (c == '\n') { + ++cur; + goto flushLine; + } else if (!c) { + goto flushLine; + } else if (c != ' ' && c != '\t' && c != '\r') { + break; + } + } + + // Then strip comments. Yep - no escaping is possible. + const ushort *end; // End of this line + const ushort *cptr; // Start of next line + for (cptr = cur;; ++cptr) { + c = *cptr; + if (c == '#') { + for (end = cptr; (c = *++cptr);) { + if (c == '\n') { + ++cptr; + break; + } + } + if (end == cur) { // Line with only a comment (sans whitespace) + if (m_markLine == m_lineNo) + m_markLine++; + // Qmake bizarreness: such lines do not affect line continuations + goto ignore; + } + break; + } + if (!c) { + end = cptr; + break; + } + if (c == '\n') { + end = cptr++; + break; + } + } + + // Then look for line continuations. Yep - no escaping here as well. + bool lineCont; + forever { + // We don't have to check for underrun here, as we already determined + // that the line is non-empty. + ushort ec = *(end - 1); + if (ec == '\\') { + --end; + lineCont = true; + break; + } + if (ec != ' ' && ec != '\t' && ec != '\r') { + lineCont = false; + break; + } + --end; + } + + // Finally, do the tokenization + ushort tok, rtok; + int tlen; + newWord: + do { + if (cur == end) + goto lineEnd; + c = *cur++; + } while (c == ' ' || c == '\t'); + forever { + if (c == '$') { + if (*cur == '$') { // may be EOF, EOL, WS, '#' or '\\' if past end + cur++; + if (putSpace) { + putSpace = false; + *ptr++ = ' '; + } + FLUSH_LITERAL(); + if (!lineMarked) { + lineMarked = true; + *ptr++ = TokLine; + *ptr++ = (ushort)m_lineNo; + } + term = 0; + tok = TokVariable; + c = *cur; + if (c == '[') { + ptr += 2; + tok = TokProperty; + term = ']'; + c = *++cur; + } else if (c == '{') { + ptr += 4; + term = '}'; + c = *++cur; + } else if (c == '(') { + // FIXME: could/should expand this immediately + ptr += 2; + tok = TokEnvVar; + term = ')'; + c = *++cur; + } else { + ptr += 4; + } + xprPtr = ptr; + rtok = tok; + while ((c & 0xFF00) || c == '.' || c == '_' || + (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9')) { + *ptr++ = c; + if (++cur == end) { + c = 0; + goto notfunc; + } + c = *cur; + } + if (tok == TokVariable && c == '(') + tok = TokFuncName; + notfunc: + if (quote) + tok |= TokQuoted; + if (needSep) { + tok |= needSep; + wordCount++; + } + tlen = ptr - xprPtr; + if (rtok == TokVariable) { + xprPtr[-4] = tok; + uint hash = ProString::hash((const QChar *)xprPtr, tlen); + xprPtr[-3] = (ushort)hash; + xprPtr[-2] = (ushort)(hash >> 16); + } else { + xprPtr[-2] = tok; + } + xprPtr[-1] = tlen; + if ((tok & TokMask) == TokFuncName) { + cur++; + funcCall: + { + xprStack.resize(xprStack.size() + 1); + ParseCtx &top = xprStack.top(); + top.parens = parens; + top.quote = quote; + top.terminator = term; + top.context = context; + top.argc = argc; + top.wordCount = wordCount; + } + parens = 0; + quote = 0; + term = 0; + argc = 1; + context = CtxArgs; + nextToken: + wordCount = 0; + nextWord: + ptr += (context == CtxTest) ? 4 : 2; + xprPtr = ptr; + needSep = TokNewStr; + goto newWord; + } + if (term) { + cur++; + checkTerm: + if (c != term) { + parseError(fL1S("Missing %1 terminator [found %2]") + .arg(QChar(term)) + .arg(c ? QString(c) : QString::fromLatin1("end-of-line"))); + pro->setOk(false); + m_inError = true; + if (c) + cur--; + // Just parse on, as if there was a terminator ... + } + } + joinToken: + ptr += (context == CtxTest) ? 4 : 2; + xprPtr = ptr; + needSep = 0; + goto nextChr; + } + } else if (c == '\\' && cur != end) { + static const char symbols[] = "[]{}()$\\'\""; + ushort c2 = *cur; + if (!(c2 & 0xff00) && strchr(symbols, c2)) { + c = c2; + cur++; + } + } else if (quote) { + if (c == quote) { + quote = 0; + if (putSpace) { + putSpace = false; + *ptr++ = ' '; + } + goto nextChr; + } else if (c == ' ' || c == '\t') { + putSpace = true; + goto nextChr; + } else if (c == '!' && ptr == xprPtr && context == CtxTest) { + m_invert ^= true; + goto nextChr; + } + } else if (c == '\'' || c == '"') { + quote = c; + goto nextChr; + } else if (c == ' ' || c == '\t') { + FLUSH_LITERAL(); + goto nextWord; + } else if (context == CtxArgs) { + // Function arg context + if (c == '(') { + ++parens; + } else if (c == ')') { + if (--parens < 0) { + FLUSH_RHS_LITERAL(); + *ptr++ = TokFuncTerminator; + int theargc = argc; + { + ParseCtx &top = xprStack.top(); + parens = top.parens; + quote = top.quote; + term = top.terminator; + context = top.context; + argc = top.argc; + wordCount = top.wordCount; + xprStack.resize(xprStack.size() - 1); + } + if (term == ':') { + finalizeCall(tokPtr, buf, ptr, theargc); + goto nextItem; + } else if (term == '}') { + c = (cur == end) ? 0 : *cur++; + goto checkTerm; + } else { + Q_ASSERT(!term); + goto joinToken; + } + } + } else if (!parens && c == ',') { + FLUSH_RHS_LITERAL(); + *ptr++ = TokArgSeparator; + argc++; + goto nextToken; + } + } else if (context == CtxTest) { + // Test or LHS context + if (c == '(') { + FLUSH_LHS_LITERAL(); + if (wordCount != 1) { + if (wordCount) + parseError(fL1S("Extra characters after test expression.")); + else + parseError(fL1S("Opening parenthesis without prior test name.")); + pro->setOk(false); + ptr = buf; // Put empty function name + } + *ptr++ = TokTestCall; + term = ':'; + goto funcCall; + } else if (c == '!' && ptr == xprPtr) { + m_invert ^= true; + goto nextChr; + } else if (c == ':') { + FLUSH_LHS_LITERAL(); + finalizeCond(tokPtr, buf, ptr, wordCount); + if (m_state == StNew) + parseError(fL1S("And operator without prior condition.")); + else + m_operator = AndOperator; + nextItem: + ptr = buf; + goto nextToken; + } else if (c == '|') { + FLUSH_LHS_LITERAL(); + finalizeCond(tokPtr, buf, ptr, wordCount); + if (m_state != StCond) + parseError(fL1S("Or operator without prior condition.")); + else + m_operator = OrOperator; + goto nextItem; + } else if (c == '{') { + FLUSH_LHS_LITERAL(); + finalizeCond(tokPtr, buf, ptr, wordCount); + flushCond(tokPtr); + ++m_blockstack.top().braceLevel; + goto nextItem; + } else if (c == '}') { + FLUSH_LHS_LITERAL(); + finalizeCond(tokPtr, buf, ptr, wordCount); + flushScopes(tokPtr); + closeScope: + if (!m_blockstack.top().braceLevel) { + parseError(fL1S("Excess closing brace.")); + } else if (!--m_blockstack.top().braceLevel + && m_blockstack.count() != 1) { + leaveScope(tokPtr); + m_state = StNew; + m_canElse = false; + m_markLine = m_lineNo; + } + goto nextItem; + } else if (c == '+') { + tok = TokAppend; + goto do2Op; + } else if (c == '-') { + tok = TokRemove; + goto do2Op; + } else if (c == '*') { + tok = TokAppendUnique; + goto do2Op; + } else if (c == '~') { + tok = TokReplace; + do2Op: + if (*cur == '=') { + cur++; + goto doOp; + } + } else if (c == '=') { + tok = TokAssign; + doOp: + FLUSH_LHS_LITERAL(); + flushCond(tokPtr); + putLineMarker(tokPtr); + if (wordCount != 1) { + parseError(fL1S("Assignment needs exactly one word on the left hand side.")); + pro->setOk(false); + // Put empty variable name. + } else { + putBlock(tokPtr, buf, ptr - buf); + } + putTok(tokPtr, tok); + context = CtxValue; + ptr = ++tokPtr; + goto nextToken; + } + } else { // context == CtxValue + if (c == '{') { + ++parens; + } else if (c == '}') { + if (!parens) { + FLUSH_RHS_LITERAL(); + FLUSH_VALUE_LIST(); + context = CtxTest; + goto closeScope; + } + --parens; + } + } + if (putSpace) { + putSpace = false; + *ptr++ = ' '; + } + *ptr++ = c; + nextChr: + if (cur == end) + goto lineEnd; + c = *cur++; + } + + lineEnd: + if (lineCont) { + if (quote) { + putSpace = true; + } else { + FLUSH_LITERAL(); + needSep = TokNewStr; + ptr += (context == CtxTest) ? 4 : 2; + xprPtr = ptr; + } + } else { + c = '\n'; + cur = cptr; + flushLine: + FLUSH_LITERAL(); + if (quote) { + parseError(fL1S("Missing closing %1 quote").arg(QChar(quote))); + if (!xprStack.isEmpty()) { + context = xprStack.at(0).context; + xprStack.clear(); + } + goto flErr; + } else if (!xprStack.isEmpty()) { + parseError(fL1S("Missing closing parenthesis in function call")); + context = xprStack.at(0).context; + xprStack.clear(); + flErr: + pro->setOk(false); + if (context == CtxValue) { + tokPtr[-1] = 0; // sizehint + putTok(tokPtr, TokValueTerminator); + } else { + bogusTest(tokPtr); + } + } else if (context == CtxValue) { + FLUSH_VALUE_LIST(); + } else { + finalizeCond(tokPtr, buf, ptr, wordCount); + } + if (!c) + break; + ++m_lineNo; + goto freshLine; + } + + if (!lineCont) { + cur = cptr; + ++m_lineNo; + goto freshLine; + } + lineMarked = false; + ignore: + cur = cptr; + ++m_lineNo; + } + + flushScopes(tokPtr); + if (m_blockstack.size() > 1) { + parseError(fL1S("Missing closing brace(s).")); + pro->setOk(false); + } + while (m_blockstack.size()) + leaveScope(tokPtr); + xprBuff.clear(); + *pro->itemsRef() = QString(tokBuff.constData(), tokPtr - (ushort *)tokBuff.constData()); + return true; + +#undef FLUSH_VALUE_LIST +#undef FLUSH_LITERAL +#undef FLUSH_LHS_LITERAL +#undef FLUSH_RHS_LITERAL +} + +void ProFileParser::putLineMarker(ushort *&tokPtr) +{ + if (m_markLine) { + *tokPtr++ = TokLine; + *tokPtr++ = (ushort)m_markLine; + m_markLine = 0; + } +} + +void ProFileParser::enterScope(ushort *&tokPtr, bool special, ScopeState state) +{ + m_blockstack.resize(m_blockstack.size() + 1); + m_blockstack.top().special = special; + m_blockstack.top().start = tokPtr; + tokPtr += 2; + m_state = state; + m_canElse = false; + if (special) + m_markLine = m_lineNo; +} + +void ProFileParser::leaveScope(ushort *&tokPtr) +{ + if (m_blockstack.top().inBranch) { + // Put empty else block + putBlockLen(tokPtr, 0); + } + if (ushort *start = m_blockstack.top().start) { + putTok(tokPtr, TokTerminator); + uint len = tokPtr - start - 2; + start[0] = (ushort)len; + start[1] = (ushort)(len >> 16); + } + m_blockstack.resize(m_blockstack.size() - 1); +} + +// If we are on a fresh line, close all open one-line scopes. +void ProFileParser::flushScopes(ushort *&tokPtr) +{ + if (m_state == StNew) { + while (!m_blockstack.top().braceLevel && m_blockstack.size() > 1) + leaveScope(tokPtr); + if (m_blockstack.top().inBranch) { + m_blockstack.top().inBranch = false; + // Put empty else block + putBlockLen(tokPtr, 0); + } + m_canElse = false; + } +} + +// If there is a pending conditional, enter a new scope, otherwise flush scopes. +void ProFileParser::flushCond(ushort *&tokPtr) +{ + if (m_state == StCond) { + putTok(tokPtr, TokBranch); + m_blockstack.top().inBranch = true; + enterScope(tokPtr, false, StNew); + } else { + flushScopes(tokPtr); + } +} + +void ProFileParser::finalizeTest(ushort *&tokPtr) +{ + flushScopes(tokPtr); + putLineMarker(tokPtr); + if (m_operator != NoOperator) { + putTok(tokPtr, (m_operator == AndOperator) ? TokAnd : TokOr); + m_operator = NoOperator; + } + if (m_invert) { + putTok(tokPtr, TokNot); + m_invert = false; + } + m_state = StCond; + m_canElse = true; +} + +void ProFileParser::bogusTest(ushort *&tokPtr) +{ + flushScopes(tokPtr); + m_operator = NoOperator; + m_invert = false; + m_state = StCond; + m_canElse = true; + m_proFile->setOk(false); +} + +void ProFileParser::finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount) +{ + if (wordCount != 1) { + if (wordCount) { + parseError(fL1S("Extra characters after test expression.")); + bogusTest(tokPtr); + } + return; + } + + // Check for magic tokens + if (*uc == TokHashLiteral) { + uint nlen = uc[3]; + ushort *uce = uc + 4 + nlen; + if (uce == ptr) { + m_tmp.setRawData((QChar *)uc + 4, nlen); + if (!m_tmp.compare(statics.strelse, Qt::CaseInsensitive)) { + if (m_invert || m_operator != NoOperator) { + parseError(fL1S("Unexpected operator in front of else.")); + return; + } + BlockScope &top = m_blockstack.top(); + if (m_canElse && (!top.special || top.braceLevel)) { + // A list of tests (the last one likely with side effects), + // but no assignment, scope, etc. + putTok(tokPtr, TokBranch); + // Put empty then block + putBlockLen(tokPtr, 0); + enterScope(tokPtr, false, StCtrl); + return; + } + forever { + BlockScope &top = m_blockstack.top(); + if (top.inBranch && (!top.special || top.braceLevel)) { + top.inBranch = false; + enterScope(tokPtr, false, StCtrl); + return; + } + if (top.braceLevel || m_blockstack.size() == 1) + break; + leaveScope(tokPtr); + } + parseError(fL1S("Unexpected 'else'.")); + return; + } + } + } + + finalizeTest(tokPtr); + putBlock(tokPtr, uc, ptr - uc); + putTok(tokPtr, TokCondition); +} + +void ProFileParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc) +{ + // Check for magic tokens + if (*uc == TokHashLiteral) { + uint nlen = uc[3]; + ushort *uce = uc + 4 + nlen; + if (*uce == TokTestCall) { + uce++; + m_tmp.setRawData((QChar *)uc + 4, nlen); + const QString *defName; + ushort defType; + if (m_tmp == statics.strfor) { + flushCond(tokPtr); + putLineMarker(tokPtr); + if (m_invert || m_operator == OrOperator) { + // '|' could actually work reasonably, but qmake does nonsense here. + parseError(fL1S("Unexpected operator in front of for().")); + return; + } + if (*uce == (TokLiteral|TokNewStr)) { + nlen = uce[1]; + uc = uce + 2 + nlen; + if (*uc == TokFuncTerminator) { + // for(literal) (only "ever" would be legal if qmake was sane) + putTok(tokPtr, TokForLoop); + putHashStr(tokPtr, (ushort *)0, (uint)0); + putBlockLen(tokPtr, 1 + 3 + nlen + 1); + putTok(tokPtr, TokHashLiteral); + putHashStr(tokPtr, uce + 2, nlen); + didFor: + putTok(tokPtr, TokValueTerminator); + enterScope(tokPtr, true, StCtrl); + return; + } else if (*uc == TokArgSeparator && argc == 2) { + // for(var, something) + uc++; + putTok(tokPtr, TokForLoop); + putHashStr(tokPtr, uce + 2, nlen); + doFor: + nlen = ptr - uc; + putBlockLen(tokPtr, nlen + 1); + putBlock(tokPtr, uc, nlen); + goto didFor; + } + } else if (argc == 1) { + // for(non-literal) (this wouldn't be here if qmake was sane) + putTok(tokPtr, TokForLoop); + putHashStr(tokPtr, (ushort *)0, (uint)0); + uc = uce; + goto doFor; + } + parseError(fL1S("Syntax is for(var, list), for(var, forever) or for(ever).")); + return; + } else if (m_tmp == statics.strdefineReplace) { + defName = &statics.strdefineReplace; + defType = TokReplaceDef; + goto deffunc; + } else if (m_tmp == statics.strdefineTest) { + defName = &statics.strdefineTest; + defType = TokTestDef; + deffunc: + flushScopes(tokPtr); + putLineMarker(tokPtr); + if (m_invert) { + parseError(fL1S("Unexpected operator in front of function definition.")); + return; + } + if (*uce == (TokLiteral|TokNewStr)) { + uint nlen = uce[1]; + if (uce[nlen + 2] == TokFuncTerminator) { + if (m_operator != NoOperator) { + putTok(tokPtr, (m_operator == AndOperator) ? TokAnd : TokOr); + m_operator = NoOperator; + } + putTok(tokPtr, defType); + putHashStr(tokPtr, uce + 2, nlen); + uc = uce + 2 + nlen + 1; + enterScope(tokPtr, true, StCtrl); + return; + } + } + parseError(fL1S("%1(function) requires one literal argument.").arg(*defName)); + return; + } + } + } + + finalizeTest(tokPtr); + putBlock(tokPtr, uc, ptr - uc); +} + +void ProFileParser::parseError(const QString &msg) const +{ + if (!m_inError && m_handler) + m_handler->parseError(m_proFile->fileName(), m_lineNo, msg); +} + +QT_END_NAMESPACE diff --git a/tools/linguist/shared/profileparser.h b/tools/linguist/shared/profileparser.h new file mode 100644 index 0000000..643e339 --- /dev/null +++ b/tools/linguist/shared/profileparser.h @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Linguist of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROFILEPARSER_H +#define PROFILEPARSER_H + +#include "proparser_global.h" +#include "proitems.h" +#include <QtCore/QHash> +#include <QtCore/QStack> +#ifdef PROPARSER_THREAD_SAFE +# include <QtCore/QMutex> +# include <QtCore/QWaitCondition> +#endif + +// Be fast even for debug builds +#ifdef __GNUC__ +# define ALWAYS_INLINE inline __attribute__((always_inline)) +#elif defined(_MSC_VER) +# define ALWAYS_INLINE __forceinline +#else +# define ALWAYS_INLINE inline +#endif + +QT_BEGIN_NAMESPACE +class PROPARSER_EXPORT ProFileParserHandler +{ +public: + // Some error during parsing + virtual void parseError(const QString &filename, int lineNo, const QString &msg) = 0; +}; + +class ProFileCache; + +class PROPARSER_EXPORT ProFileParser +{ +public: + // Call this from a concurrency-free context + static void initialize(); + + ProFileParser(ProFileCache *cache, ProFileParserHandler *handler); + + // fileName is expected to be absolute and cleanPath()ed. + // If contents is non-null, it will be used instead of the file's actual content + ProFile *parsedProFile(const QString &fileName, bool cache = false, + const QString *contents = 0); + ProFile *parsedProBlock(const QString &name, const QString &contents) + { return parsedProFile(name, false, &contents); } + +private: + struct BlockScope { + BlockScope() : start(0), braceLevel(0), special(false), inBranch(false) {} + BlockScope(const BlockScope &other) { *this = other; } + ushort *start; // Where this block started; store length here + int braceLevel; // Nesting of braces in scope + bool special; // Single-line conditionals inside loops, etc. cannot have else branches + bool inBranch; // The 'else' branch of the previous TokBranch is still open + }; + + enum ScopeState { + StNew, // Fresh scope + StCtrl, // Control statement (for or else) met on current line + StCond // Conditionals met on current line + }; + + enum Context { CtxTest, CtxValue, CtxArgs }; + struct ParseCtx { + int parens; // Nesting of non-functional parentheses + int argc; // Number of arguments in current function call + int wordCount; // Number of words in current expression + Context context; + ushort quote; // Enclosing quote type + ushort terminator; // '}' if replace function call is braced, ':' if test function + }; + + bool read(ProFile *pro); + bool read(ProFile *pro, const QString &content); + + ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok); + ALWAYS_INLINE void putBlockLen(ushort *&tokPtr, uint len); + ALWAYS_INLINE void putBlock(ushort *&tokPtr, const ushort *buf, uint len); + void putHashStr(ushort *&pTokPtr, const ushort *buf, uint len); + void finalizeHashStr(ushort *buf, uint len); + void putLineMarker(ushort *&tokPtr); + void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount); + void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc); + void finalizeTest(ushort *&tokPtr); + void bogusTest(ushort *&tokPtr); + void enterScope(ushort *&tokPtr, bool special, ScopeState state); + void leaveScope(ushort *&tokPtr); + void flushCond(ushort *&tokPtr); + void flushScopes(ushort *&tokPtr); + + void parseError(const QString &msg) const; + + // Current location + ProFile *m_proFile; + int m_lineNo; + + QStack<BlockScope> m_blockstack; + ScopeState m_state; + int m_markLine; // Put marker for this line + bool m_inError; // Current line had a parsing error; suppress followup error messages + bool m_canElse; // Conditionals met on previous line, but no scope was opened + bool m_invert; // Pending conditional is negated + enum { NoOperator, AndOperator, OrOperator } m_operator; // Pending conditional is ORed/ANDed + + QString m_tmp; // Temporary for efficient toQString + + ProFileCache *m_cache; + ProFileParserHandler *m_handler; + + // This doesn't help gcc 3.3 ... + template<typename T> friend class QTypeInfo; + + friend class ProFileCache; +}; + +class PROPARSER_EXPORT ProFileCache +{ +public: + ProFileCache() {} + ~ProFileCache(); + + void discardFile(const QString &fileName); + void discardFiles(const QString &prefix); + +private: + struct Entry { + ProFile *pro; +#ifdef PROPARSER_THREAD_SAFE + struct Locker { + Locker() : waiters(0), done(false) {} + QWaitCondition cond; + int waiters; + bool done; + }; + Locker *locker; +#endif + }; + + QHash<QString, Entry> parsed_files; +#ifdef PROPARSER_THREAD_SAFE + QMutex mutex; +#endif + + friend class ProFileParser; +}; + +#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) +Q_DECLARE_TYPEINFO(ProFileParser::BlockScope, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(ProFileParser::Context, Q_PRIMITIVE_TYPE); +#endif + +QT_END_NAMESPACE + +#endif // PROFILEPARSER_H diff --git a/tools/linguist/shared/proitems.cpp b/tools/linguist/shared/proitems.cpp index 5c88686..103a788 100644 --- a/tools/linguist/shared/proitems.cpp +++ b/tools/linguist/shared/proitems.cpp @@ -40,319 +40,335 @@ ****************************************************************************/ #include "proitems.h" -#include "abstractproitemvisitor.h" #include <QtCore/QFileInfo> +#include <QtCore/QSet> QT_BEGIN_NAMESPACE -// --------------- ProItem ------------ -void ProItem::setComment(const QString &comment) -{ - m_comment = comment; -} - -QString ProItem::comment() const -{ - return m_comment; -} - -// --------------- ProBlock ---------------- - -ProBlock::ProBlock(ProBlock *parent) -{ - m_blockKind = 0; - m_parent = parent; - m_refCount = 1; -} - -ProBlock::~ProBlock() -{ - foreach (ProItem *itm, m_proitems) - if (itm->kind() == BlockKind) - static_cast<ProBlock *>(itm)->deref(); - else - delete itm; -} - -void ProBlock::appendItem(ProItem *proitem) -{ - m_proitems << proitem; -} +using namespace ProStringConstants; -void ProBlock::setItems(const QList<ProItem *> &proitems) +// from qhash.cpp +uint ProString::hash(const QChar *p, int n) { - m_proitems = proitems; -} + uint h = 0; -QList<ProItem *> ProBlock::items() const -{ - return m_proitems; -} - -void ProBlock::setBlockKind(int blockKind) -{ - m_blockKind = blockKind; + while (n--) { + h = (h << 4) + (*p++).unicode(); + h ^= (h & 0xf0000000) >> 23; + h &= 0x0fffffff; + } + return h; } -int ProBlock::blockKind() const +ProString::ProString() : + m_offset(0), m_length(0), m_file(0), m_hash(0x80000000) { - return m_blockKind; } -void ProBlock::setParent(ProBlock *parent) +ProString::ProString(const ProString &other) : + m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(other.m_hash) { - m_parent = parent; } -ProBlock *ProBlock::parent() const +ProString::ProString(const ProString &other, OmitPreHashing) : + m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(0x80000000) { - return m_parent; } -ProItem::ProItemKind ProBlock::kind() const +ProString::ProString(const QString &str) : + m_string(str), m_offset(0), m_length(str.length()), m_file(0) { - return ProItem::BlockKind; + updatedHash(); } -ProItem::ProItemReturn ProBlock::Accept(AbstractProItemVisitor *visitor) +ProString::ProString(const QString &str, OmitPreHashing) : + m_string(str), m_offset(0), m_length(str.length()), m_file(0), m_hash(0x80000000) { - if (visitor->visitBeginProBlock(this) == ReturnSkip) - return ReturnTrue; - ProItemReturn rt = ReturnTrue; - for (int i = 0; i < m_proitems.count(); ++i) { - rt = m_proitems.at(i)->Accept(visitor); - if (rt != ReturnTrue && rt != ReturnFalse) { - if (rt == ReturnLoop) { - rt = ReturnTrue; - while (visitor->visitProLoopIteration()) - for (int j = i; ++j < m_proitems.count(); ) { - rt = m_proitems.at(j)->Accept(visitor); - if (rt != ReturnTrue && rt != ReturnFalse) { - if (rt == ReturnNext) { - rt = ReturnTrue; - break; - } - if (rt == ReturnBreak) - rt = ReturnTrue; - goto do_break; - } - } - do_break: - visitor->visitProLoopCleanup(); - } - break; - } - } - visitor->visitEndProBlock(this); - return rt; } -// --------------- ProVariable ---------------- -ProVariable::ProVariable(const QString &name, ProBlock *parent) - : ProBlock(parent) +ProString::ProString(const char *str) : + m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0) { - setBlockKind(ProBlock::VariableKind); - m_variable = name; - m_variableKind = SetOperator; + updatedHash(); } -void ProVariable::setVariableOperator(VariableOperator variableKind) +ProString::ProString(const char *str, OmitPreHashing) : + m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0), m_hash(0x80000000) { - m_variableKind = variableKind; } -ProVariable::VariableOperator ProVariable::variableOperator() const +ProString::ProString(const QString &str, int offset, int length) : + m_string(str), m_offset(offset), m_length(length), m_file(0) { - return m_variableKind; + updatedHash(); } -void ProVariable::setVariable(const QString &name) +ProString::ProString(const QString &str, int offset, int length, uint hash) : + m_string(str), m_offset(offset), m_length(length), m_file(0), m_hash(hash) { - m_variable = name; } -QString ProVariable::variable() const +ProString::ProString(const QString &str, int offset, int length, ProStringConstants::OmitPreHashing) : + m_string(str), m_offset(offset), m_length(length), m_file(0), m_hash(0x80000000) { - return m_variable; } -ProItem::ProItemReturn ProVariable::Accept(AbstractProItemVisitor *visitor) +void ProString::setValue(const QString &str) { - visitor->visitBeginProVariable(this); - foreach (ProItem *item, m_proitems) - item->Accept(visitor); // cannot fail - visitor->visitEndProVariable(this); - return ReturnTrue; + m_string = str, m_offset = 0, m_length = str.length(); + updatedHash(); } -// --------------- ProValue ---------------- -ProValue::ProValue(const QString &value, ProVariable *variable) +void ProString::setValue(const QString &str, OmitPreHashing) { - m_variable = variable; - m_value = value; + m_string = str, m_offset = 0, m_length = str.length(), m_hash = 0x80000000; } -void ProValue::setValue(const QString &value) +uint ProString::updatedHash() const { - m_value = value; + return (m_hash = hash(m_string.constData() + m_offset, m_length)); } -QString ProValue::value() const +uint qHash(const ProString &str) { - return m_value; + if (!(str.m_hash & 0x80000000)) + return str.m_hash; + return str.updatedHash(); } -void ProValue::setVariable(ProVariable *variable) +QString ProString::toQString() const { - m_variable = variable; + return m_string.mid(m_offset, m_length); } -ProVariable *ProValue::variable() const +QString &ProString::toQString(QString &tmp) const { - return m_variable; + return tmp.setRawData(m_string.constData() + m_offset, m_length); } -ProItem::ProItemKind ProValue::kind() const +bool ProString::operator==(const ProString &other) const { - return ProItem::ValueKind; + if (m_length != other.m_length) + return false; + return !memcmp(m_string.constData() + m_offset, + other.m_string.constData() + other.m_offset, m_length * 2); } -ProItem::ProItemReturn ProValue::Accept(AbstractProItemVisitor *visitor) +bool ProString::operator==(const QString &other) const { - visitor->visitProValue(this); - return ReturnTrue; + if (m_length != other.length()) + return false; + return !memcmp(m_string.constData() + m_offset, other.constData(), m_length * 2); } -// --------------- ProFunction ---------------- -ProFunction::ProFunction(const QString &text) +bool ProString::operator==(const QLatin1String &other) const { - m_text = text; -} + const ushort *uc = (ushort *)m_string.constData() + m_offset; + const ushort *e = uc + m_length; + const uchar *c = (uchar *)other.latin1(); -void ProFunction::setText(const QString &text) -{ - m_text = text; -} + if (!c) + return isEmpty(); -QString ProFunction::text() const -{ - return m_text; -} - -ProItem::ProItemKind ProFunction::kind() const -{ - return ProItem::FunctionKind; -} - -ProItem::ProItemReturn ProFunction::Accept(AbstractProItemVisitor *visitor) -{ - return visitor->visitProFunction(this); + while (*c) { + if (uc == e || *uc != *c) + return false; + ++uc; + ++c; + } + return (uc == e); +} + +QChar *ProString::prepareAppend(int extraLen) +{ + if (m_string.isDetached() && m_length + extraLen <= m_string.capacity()) { + m_string.reserve(0); // Prevent the resize() below from reallocating + QChar *ptr = (QChar *)m_string.constData(); + if (m_offset) + memmove(ptr, ptr + m_offset, m_length * 2); + ptr += m_length; + m_offset = 0; + m_length += extraLen; + m_string.resize(m_length); + m_hash = 0x80000000; + return ptr; + } else { + QString neu(m_length + extraLen, Qt::Uninitialized); + QChar *ptr = (QChar *)neu.constData(); + memcpy(ptr, m_string.constData() + m_offset, m_length * 2); + ptr += m_length; + *this = ProString(neu, NoHash); + return ptr; + } } -// --------------- ProCondition ---------------- -ProCondition::ProCondition(const QString &text) +// If pending != 0, prefix with space if appending to non-empty non-pending +ProString &ProString::append(const ProString &other, bool *pending) { - m_text = text; + if (other.m_length) { + if (!m_length) { + *this = other; + } else { + QChar *ptr; + if (pending && !*pending) { + ptr = prepareAppend(1 + other.m_length); + *ptr++ = 32; + } else { + ptr = prepareAppend(other.m_length); + } + memcpy(ptr, other.m_string.constData() + other.m_offset, other.m_length * 2); + if (other.m_file) + m_file = other.m_file; + } + if (pending) + *pending = true; + } + return *this; } -void ProCondition::setText(const QString &text) +ProString &ProString::append(const ProStringList &other, bool *pending, bool skipEmpty1st) { - m_text = text; + if (const int sz = other.size()) { + int startIdx = 0; + if (pending && !*pending && skipEmpty1st && other.at(0).isEmpty()) { + if (sz == 1) + return *this; + startIdx = 1; + } + if (!m_length && sz == startIdx + 1) { + *this = other.at(startIdx); + } else { + int totalLength = sz - startIdx; + for (int i = startIdx; i < sz; ++i) + totalLength += other.at(i).size(); + bool putSpace = false; + if (pending && !*pending && m_length) + putSpace = true; + else + totalLength--; + + QChar *ptr = prepareAppend(totalLength); + for (int i = startIdx; i < sz; ++i) { + if (putSpace) + *ptr++ = 32; + else + putSpace = true; + const ProString &str = other.at(i); + memcpy(ptr, str.m_string.constData() + str.m_offset, str.m_length * 2); + ptr += str.m_length; + } + if (other.last().m_file) + m_file = other.last().m_file; + } + if (pending) + *pending = true; + } + return *this; } -QString ProCondition::text() const +QString operator+(const ProString &one, const ProString &two) { - return m_text; + if (two.m_length) { + if (!one.m_length) { + return two.toQString(); + } else { + QString neu(one.m_length + two.m_length, Qt::Uninitialized); + ushort *ptr = (ushort *)neu.constData(); + memcpy(ptr, one.m_string.constData() + one.m_offset, one.m_length * 2); + memcpy(ptr + one.m_length, two.m_string.constData() + two.m_offset, two.m_length * 2); + return neu; + } + } + return one.toQString(); } -ProItem::ProItemKind ProCondition::kind() const -{ - return ProItem::ConditionKind; -} -ProItem::ProItemReturn ProCondition::Accept(AbstractProItemVisitor *visitor) +ProString ProString::mid(int off, int len) const { - visitor->visitProCondition(this); - return ReturnTrue; + ProString ret(*this, NoHash); + if (off > m_length) + off = m_length; + ret.m_offset += off; + ret.m_length -= off; + if (ret.m_length > len) + ret.m_length = len; + return ret; } -// --------------- ProOperator ---------------- -ProOperator::ProOperator(OperatorKind operatorKind) +ProString ProString::trimmed() const { - m_operatorKind = operatorKind; + ProString ret(*this, NoHash); + int cur = m_offset; + int end = cur + m_length; + const QChar *data = m_string.constData(); + for (; cur < end; cur++) + if (!data[cur].isSpace()) { + // No underrun check - we know there is at least one non-whitespace + while (data[end - 1].isSpace()) + end--; + break; + } + ret.m_offset = cur; + ret.m_length = end - cur; + return ret; } -void ProOperator::setOperatorKind(OperatorKind operatorKind) +QString ProStringList::join(const QString &sep) const { - m_operatorKind = operatorKind; -} + int totalLength = 0; + const int sz = size(); -ProOperator::OperatorKind ProOperator::operatorKind() const -{ - return m_operatorKind; -} + for (int i = 0; i < sz; ++i) + totalLength += at(i).size(); -ProItem::ProItemKind ProOperator::kind() const -{ - return ProItem::OperatorKind; -} + if (sz) + totalLength += sep.size() * (sz - 1); -ProItem::ProItemReturn ProOperator::Accept(AbstractProItemVisitor *visitor) -{ - visitor->visitProOperator(this); - return ReturnTrue; + QString res(totalLength, Qt::Uninitialized); + QChar *ptr = (QChar *)res.constData(); + for (int i = 0; i < sz; ++i) { + if (i) { + memcpy(ptr, sep.constData(), sep.size() * 2); + ptr += sep.size(); + } + memcpy(ptr, at(i).constData(), at(i).size() * 2); + ptr += at(i).size(); + } + return res; +} + +void ProStringList::removeDuplicates() +{ + int n = size(); + int j = 0; + QSet<ProString> seen; + seen.reserve(n); + for (int i = 0; i < n; ++i) { + const ProString &s = at(i); + if (seen.contains(s)) + continue; + seen.insert(s); + if (j != i) + (*this)[j] = s; + ++j; + } + if (n != j) + erase(begin() + j, end()); } -// --------------- ProFile ---------------- ProFile::ProFile(const QString &fileName) - : ProBlock(0) + : m_refCount(1), + m_fileName(fileName), + m_ok(true) { - m_modified = false; - setBlockKind(ProBlock::ProFileKind); - m_fileName = fileName; - - QFileInfo fi(fileName); - m_displayFileName = fi.fileName(); - m_directoryName = fi.absolutePath(); + if (!fileName.startsWith(QLatin1Char('('))) + m_directoryName = QFileInfo( // qmake sickness: canonicalize only the directory! + fileName.left(fileName.lastIndexOf(QLatin1Char('/')))).canonicalFilePath(); } ProFile::~ProFile() { } -QString ProFile::displayFileName() const -{ - return m_displayFileName; -} - -QString ProFile::fileName() const -{ - return m_fileName; -} - -QString ProFile::directoryName() const -{ - return m_directoryName; -} - -void ProFile::setModified(bool modified) -{ - m_modified = modified; -} - -bool ProFile::isModified() const -{ - return m_modified; -} - -ProItem::ProItemReturn ProFile::Accept(AbstractProItemVisitor *visitor) -{ - ProItemReturn rt; - if ((rt = visitor->visitBeginProFile(this)) != ReturnTrue) - return rt; - ProBlock::Accept(visitor); // cannot fail - return visitor->visitEndProFile(this); -} - QT_END_NAMESPACE diff --git a/tools/linguist/shared/proitems.h b/tools/linguist/shared/proitems.h index f4bf183..a687410 100644 --- a/tools/linguist/shared/proitems.h +++ b/tools/linguist/shared/proitems.h @@ -42,205 +42,188 @@ #ifndef PROITEMS_H #define PROITEMS_H +#include "proparser_global.h" #include <QtCore/QString> -#include <QtCore/QList> +#include <QtCore/QVector> QT_BEGIN_NAMESPACE -struct AbstractProItemVisitor; - -class ProItem -{ +#ifdef PROPARSER_THREAD_SAFE +typedef QAtomicInt ProItemRefCount; +#else +class ProItemRefCount { public: - enum ProItemKind { - ValueKind, - FunctionKind, - ConditionKind, - OperatorKind, - BlockKind - }; - - enum ProItemReturn { - ReturnFalse, - ReturnTrue, - ReturnBreak, - ReturnNext, - ReturnLoop, - ReturnSkip, - ReturnReturn - }; - - ProItem() : m_lineNumber(0) {} - virtual ~ProItem() {} - - virtual ProItemKind kind() const = 0; - - void setComment(const QString &comment); - QString comment() const; - - virtual ProItemReturn Accept(AbstractProItemVisitor *visitor) = 0; - int lineNumber() const { return m_lineNumber; } - void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; } - + ProItemRefCount(int cnt = 0) : m_cnt(cnt) {} + bool ref() { return ++m_cnt != 0; } + bool deref() { return --m_cnt != 0; } + ProItemRefCount &operator=(int value) { m_cnt = value; return *this; } private: - QString m_comment; - int m_lineNumber; + int m_cnt; }; +#endif -class ProBlock : public ProItem -{ -public: - enum ProBlockKind { - NormalKind = 0x00, - ScopeKind = 0x01, - ScopeContentsKind = 0x02, - VariableKind = 0x04, - ProFileKind = 0x08, - FunctionBodyKind = 0x10, - SingleLine = 0x80 - }; - - ProBlock(ProBlock *parent); - ~ProBlock(); +namespace ProStringConstants { +enum OmitPreHashing { NoHash }; +} - void appendItem(ProItem *proitem); - void setItems(const QList<ProItem *> &proitems); - QList<ProItem *> items() const; +class ProStringList; +class ProFile; - void setBlockKind(int blockKind); - int blockKind() const; - - void setParent(ProBlock *parent); - ProBlock *parent() const; - - void ref() { ++m_refCount; } - void deref() { if (!--m_refCount) delete this; } - - ProItem::ProItemKind kind() const; - - virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); -protected: - QList<ProItem *> m_proitems; -private: - ProBlock *m_parent; - int m_blockKind; - int m_refCount; -}; - -class ProVariable : public ProBlock -{ +class ProString { public: - enum VariableOperator { - AddOperator = 0, - RemoveOperator = 1, - ReplaceOperator = 2, - SetOperator = 3, - UniqueAddOperator = 4 - }; - - ProVariable(const QString &name, ProBlock *parent); + ProString(); + ProString(const ProString &other); + ProString(const ProString &other, ProStringConstants::OmitPreHashing); + explicit ProString(const QString &str); + ProString(const QString &str, ProStringConstants::OmitPreHashing); + explicit ProString(const char *str); + ProString(const char *str, ProStringConstants::OmitPreHashing); + ProString(const QString &str, int offset, int length); + ProString(const QString &str, int offset, int length, uint hash); + ProString(const QString &str, int offset, int length, ProStringConstants::OmitPreHashing); + void setValue(const QString &str); + void setValue(const QString &str, ProStringConstants::OmitPreHashing); + ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; } + ProString &setSource(const ProFile *pro) { m_file = pro; return *this; } + const ProFile *sourceFile() const { return m_file; } + QString toQString() const; + QString &toQString(QString &tmp) const; + ProString &operator+=(const ProString &other); + ProString &append(const ProString &other, bool *pending = 0); + ProString &append(const ProStringList &other, bool *pending = 0, bool skipEmpty1st = false); + bool operator==(const ProString &other) const; + bool operator==(const QString &other) const; + bool operator==(const QLatin1String &other) const; + bool operator!=(const ProString &other) const { return !(*this == other); } + bool operator!=(const QString &other) const { return !(*this == other); } + bool operator!=(const QLatin1String &other) const { return !(*this == other); } + bool isEmpty() const { return !m_length; } + int size() const { return m_length; } + const QChar *constData() const { return m_string.constData() + m_offset; } + ProString mid(int off, int len = -1) const; + ProString left(int len) const { return mid(0, len); } + ProString right(int len) const { return mid(qMax(0, size() - len)); } + ProString trimmed() const; + void clear() { m_string.clear(); m_length = 0; } + + static uint hash(const QChar *p, int n); - void setVariableOperator(VariableOperator variableKind); - VariableOperator variableOperator() const; - - void setVariable(const QString &name); - QString variable() const; - - virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); private: - VariableOperator m_variableKind; - QString m_variable; + QString m_string; + int m_offset, m_length; + const ProFile *m_file; + mutable uint m_hash; + QChar *prepareAppend(int extraLen); + uint updatedHash() const; + friend uint qHash(const ProString &str); + friend QString operator+(const ProString &one, const ProString &two); }; +Q_DECLARE_TYPEINFO(ProString, Q_MOVABLE_TYPE); -class ProValue : public ProItem -{ -public: - ProValue(const QString &value, ProVariable *variable); - - void setValue(const QString &value); - QString value() const; - - void setVariable(ProVariable *variable); - ProVariable *variable() const; +uint qHash(const ProString &str); +QString operator+(const ProString &one, const ProString &two); +inline QString operator+(const ProString &one, const QString &two) + { return one + ProString(two, ProStringConstants::NoHash); } +inline QString operator+(const QString &one, const ProString &two) + { return ProString(one, ProStringConstants::NoHash) + two; } - ProItem::ProItemKind kind() const; - - virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); -private: - QString m_value; - ProVariable *m_variable; -}; - -class ProFunction : public ProItem -{ -public: - explicit ProFunction(const QString &text); - - void setText(const QString &text); - QString text() const; - - ProItem::ProItemKind kind() const; - - virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); -private: - QString m_text; -}; - -class ProCondition : public ProItem -{ +class ProStringList : public QVector<ProString> { public: - explicit ProCondition(const QString &text); - - void setText(const QString &text); - QString text() const; - - ProItem::ProItemKind kind() const; - - virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); -private: - QString m_text; + ProStringList() {} + ProStringList(const ProString &str) { *this << str; } + QString join(const QString &sep) const; + void removeDuplicates(); }; -class ProOperator : public ProItem -{ -public: - enum OperatorKind { - OrOperator = 1, - NotOperator = 2 - }; - - explicit ProOperator(OperatorKind operatorKind); - - void setOperatorKind(OperatorKind operatorKind); - OperatorKind operatorKind() const; - - ProItem::ProItemKind kind() const; - - virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); -private: - OperatorKind m_operatorKind; +// These token definitions affect both ProFileEvaluator and ProWriter +enum ProToken { + TokTerminator = 0, // end of stream (possibly not included in length; must be zero) + TokLine, // line marker: + // - line (1) + TokAssign, // variable = + TokAppend, // variable += + TokAppendUnique, // variable *= + TokRemove, // variable -= + TokReplace, // variable ~= + // previous literal/expansion is a variable manipulation + // - value expression + TokValueTerminator + TokValueTerminator, // assignment value terminator + TokLiteral, // literal string (fully dequoted) + // - length (1) + // - string data (length; unterminated) + TokHashLiteral, // literal string with hash (fully dequoted) + // - hash (2) + // - length (1) + // - string data (length; unterminated) + TokVariable, // qmake variable expansion + // - hash (2) + // - name length (1) + // - name (name length; unterminated) + TokProperty, // qmake property expansion + // - name length (1) + // - name (name length; unterminated) + TokEnvVar, // environment variable expansion + // - name length (1) + // - name (name length; unterminated) + TokFuncName, // replace function expansion + // - hash (2) + // - name length (1) + // - name (name length; unterminated) + // - ((nested expansion + TokArgSeparator)* + nested expansion)? + // - TokFuncTerminator + TokArgSeparator, // function argument separator + TokFuncTerminator, // function argument list terminator + TokCondition, // previous literal/expansion is a conditional + TokTestCall, // previous literal/expansion is a test function call + // - ((nested expansion + TokArgSeparator)* + nested expansion)? + // - TokFuncTerminator + TokNot, // '!' operator + TokAnd, // ':' operator + TokOr, // '|' operator + TokBranch, // branch point: + // - then block length (2) + // - then block + TokTerminator (then block length) + // - else block length (2) + // - else block + TokTerminator (else block length) + TokForLoop, // for loop: + // - variable name: hash (2), length (1), chars (length) + // - expression: length (2), bytes + TokValueTerminator (length) + // - body length (2) + // - body + TokTerminator (body length) + TokTestDef, // test function definition: + TokReplaceDef, // replace function definition: + // - function name: hash (2), length (1), chars (length) + // - body length (2) + // - body + TokTerminator (body length) + TokMask = 0xff, + TokQuoted = 0x100, // The expression is quoted => join expanded stringlist + TokNewStr = 0x200 // Next stringlist element }; -class ProFile : public ProBlock +class PROPARSER_EXPORT ProFile { public: explicit ProFile(const QString &fileName); ~ProFile(); - QString displayFileName() const; - QString fileName() const; - QString directoryName() const; + QString fileName() const { return m_fileName; } + QString directoryName() const { return m_directoryName; } + const QString &items() const { return m_proitems; } + QString *itemsRef() { return &m_proitems; } + const ushort *tokPtr() const { return (const ushort *)m_proitems.constData(); } - void setModified(bool modified); - bool isModified() const; + void ref() { m_refCount.ref(); } + void deref() { if (!m_refCount.deref()) delete this; } - virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); + bool isOk() const { return m_ok; } + void setOk(bool ok) { m_ok = ok; } private: + ProItemRefCount m_refCount; + QString m_proitems; QString m_fileName; - QString m_displayFileName; QString m_directoryName; - bool m_modified; + bool m_ok; }; QT_END_NAMESPACE diff --git a/tools/linguist/shared/proparser.pri b/tools/linguist/shared/proparser.pri index 372247e..829c8cd 100644 --- a/tools/linguist/shared/proparser.pri +++ b/tools/linguist/shared/proparser.pri @@ -1,12 +1,17 @@ INCLUDEPATH *= $$PWD +DEFINES += PROEVALUATOR_CUMULATIVE PROEVALUATOR_INIT_PROPS + HEADERS += \ - $$PWD/abstractproitemvisitor.h \ + $$PWD/proparser_global.h \ + $$PWD/ioutils.h \ $$PWD/proitems.h \ - $$PWD/profileevaluator.h \ - $$PWD/proparserutils.h + $$PWD/profileparser.h \ + $$PWD/profileevaluator.h SOURCES += \ + $$PWD/ioutils.cpp \ $$PWD/proitems.cpp \ - $$PWD/profileevaluator.cpp + $$PWD/profileparser.cpp \ + $$PWD/profileevaluator.cpp diff --git a/tools/qtconfig/previewwidgetbase.h b/tools/linguist/shared/proparser_global.h index 45073a6..2b0b6db 100644 --- a/tools/qtconfig/previewwidgetbase.h +++ b/tools/linguist/shared/proparser_global.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the tools applications of the Qt Toolkit. +** This file is part of the Qt Linguist of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage @@ -39,30 +39,19 @@ ** ****************************************************************************/ -#ifndef PREVIEWWIDGETBASE_H -#define PREVIEWWIDGETBASE_H +#ifndef PROPARSER_GLOBAL_H +#define PROPARSER_GLOBAL_H -#include "ui_previewwidgetbase.h" -#include <QVariant> +#include <QtCore/qglobal.h> -QT_BEGIN_NAMESPACE +#if defined(PROPARSER_AS_LIBRARY) +# if defined(PROPARSER_LIBRARY) +# define PROPARSER_EXPORT Q_DECL_EXPORT +# else +# define PROPARSER_EXPORT Q_DECL_IMPORT +# endif +#else +# define PROPARSER_EXPORT +#endif -class PreviewWidgetBase : public QWidget, public Ui::PreviewWidgetBase -{ - Q_OBJECT - -public: - PreviewWidgetBase(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = 0); - ~PreviewWidgetBase(); - -protected slots: - virtual void languageChange(); - - virtual void init(); - virtual void destroy(); - -}; - -QT_END_NAMESPACE - -#endif // PREVIEWWIDGETBASE_H +#endif diff --git a/tools/linguist/shared/proparserutils.h b/tools/linguist/shared/proparserutils.h deleted file mode 100644 index d567a73..0000000 --- a/tools/linguist/shared/proparserutils.h +++ /dev/null @@ -1,324 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Qt Linguist of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PROPARSERUTILS_H -#define PROPARSERUTILS_H - -#include <QtCore/QDir> -#ifndef QT_BOOTSTRAPPED -#include <QtCore/QLibraryInfo> -#endif - -QT_BEGIN_NAMESPACE - -#ifdef QT_BOOTSTRAPPED -// this is a stripped down version of the one found in QtCore -class QLibraryInfo -{ -public: - enum LibraryLocation - { - PrefixPath, - DocumentationPath, - HeadersPath, - LibrariesPath, - BinariesPath, - PluginsPath, - DataPath, - TranslationsPath, - SettingsPath, - DemosPath, - ExamplesPath - }; - static QString location(LibraryLocation); -}; -#endif - -// Pre- and postcondition macros -#define PRE(cond) do {if (!(cond))qt_assert(#cond,__FILE__,__LINE__);} while (0) -#define POST(cond) do {if (!(cond))qt_assert(#cond,__FILE__,__LINE__);} while (0) - -// This struct is from qmake, but we are not using everything. -struct Option -{ - //simply global convenience - //static QString libtool_ext; - //static QString pkgcfg_ext; - //static QString prf_ext; - //static QString prl_ext; - //static QString ui_ext; - //static QStringList h_ext; - //static QStringList cpp_ext; - //static QString h_moc_ext; - //static QString cpp_moc_ext; - //static QString obj_ext; - //static QString lex_ext; - //static QString yacc_ext; - //static QString h_moc_mod; - //static QString cpp_moc_mod; - //static QString lex_mod; - //static QString yacc_mod; - static QString dir_sep; - static QString dirlist_sep; - static QString qmakespec; - static QChar field_sep; - - enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE, TARG_QNX6_MODE }; - static TARG_MODE target_mode; - //static QString pro_ext; - //static QString res_ext; - - static void init() - { -#ifdef Q_OS_WIN - Option::dirlist_sep = QLatin1Char(';'); - Option::dir_sep = QLatin1Char('\\'); -#else - Option::dirlist_sep = QLatin1Char(':'); - Option::dir_sep = QLatin1Char(QLatin1Char('/')); -#endif - Option::qmakespec = QString::fromLatin1(qgetenv("QMAKESPEC").data()); - Option::field_sep = QLatin1Char(' '); - } - - enum StringFixFlags { - FixNone = 0x00, - FixEnvVars = 0x01, - FixPathCanonicalize = 0x02, - FixPathToLocalSeparators = 0x04, - FixPathToTargetSeparators = 0x08 - }; - static QString fixString(QString string, uchar flags); - - inline static QString fixPathToLocalOS(const QString &in, bool fix_env = true, bool canonical = true) - { - uchar flags = FixPathToLocalSeparators; - if (fix_env) - flags |= FixEnvVars; - if (canonical) - flags |= FixPathCanonicalize; - return fixString(in, flags); - } -}; -#if defined(Q_OS_WIN32) -Option::TARG_MODE Option::target_mode = Option::TARG_WIN_MODE; -#elif defined(Q_OS_MAC) -Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE; -#elif defined(Q_OS_QNX6) -Option::TARG_MODE Option::target_mode = Option::TARG_QNX6_MODE; -#else -Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE; -#endif - -QString Option::qmakespec; -QString Option::dirlist_sep; -QString Option::dir_sep; -QChar Option::field_sep; - -static void insertUnique(QHash<QString, QStringList> *map, - const QString &key, const QStringList &value) -{ - QStringList &sl = (*map)[key]; - foreach (const QString &str, value) - if (!sl.contains(str)) - sl.append(str); -} - -static void removeEach(QHash<QString, QStringList> *map, - const QString &key, const QStringList &value) -{ - QStringList &sl = (*map)[key]; - foreach (const QString &str, value) - sl.removeAll(str); -} - -/* - See ProFileEvaluator::Private::visitProValue(...) - -static QStringList replaceInList(const QStringList &varList, const QRegExp ®exp, - const QString &replace, bool global) -{ - QStringList resultList = varList; - - for (QStringList::Iterator varit = resultList.begin(); varit != resultList.end();) { - if (varit->contains(regexp)) { - *varit = varit->replace(regexp, replace); - if (varit->isEmpty()) - varit = resultList.erase(varit); - else - ++varit; - if (!global) - break; - } else { - ++varit; - } - } - return resultList; -} -*/ - -inline QString fixEnvVariables(const QString &x) -{ - return Option::fixString(x, Option::FixEnvVars); -} - -inline QStringList splitPathList(const QString &paths) -{ - return paths.split(Option::dirlist_sep); -} - -static QStringList split_arg_list(QString params) -{ - int quote = 0; - QStringList args; - - const ushort LPAREN = '('; - const ushort RPAREN = ')'; - const ushort SINGLEQUOTE = '\''; - const ushort DOUBLEQUOTE = '"'; - const ushort COMMA = ','; - const ushort SPACE = ' '; - //const ushort TAB = '\t'; - - ushort unicode; - const QChar *params_data = params.data(); - const int params_len = params.length(); - int last = 0; - while (last < params_len && ((params_data+last)->unicode() == SPACE - /*|| (params_data+last)->unicode() == TAB*/)) - ++last; - for (int x = last, parens = 0; x <= params_len; x++) { - unicode = (params_data+x)->unicode(); - if (x == params_len) { - while (x && (params_data+(x-1))->unicode() == SPACE) - --x; - QString mid(params_data+last, x-last); - if (quote) { - if (mid[0] == quote && mid[(int)mid.length()-1] == quote) - mid = mid.mid(1, mid.length()-2); - quote = 0; - } - args << mid; - break; - } - if (unicode == LPAREN) { - --parens; - } else if (unicode == RPAREN) { - ++parens; - } else if (quote && unicode == quote) { - quote = 0; - } else if (!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { - quote = unicode; - } - if (!parens && !quote && unicode == COMMA) { - QString mid = params.mid(last, x - last).trimmed(); - args << mid; - last = x+1; - while (last < params_len && ((params_data+last)->unicode() == SPACE - /*|| (params_data+last)->unicode() == TAB*/)) - ++last; - } - } - return args; -} - -static QStringList split_value_list(const QString &vals, bool do_semicolon=false) -{ - QString build; - QStringList ret; - QStack<char> quote; - - const ushort LPAREN = '('; - const ushort RPAREN = ')'; - const ushort SINGLEQUOTE = '\''; - const ushort DOUBLEQUOTE = '"'; - const ushort BACKSLASH = '\\'; - const ushort SEMICOLON = ';'; - - ushort unicode; - const QChar *vals_data = vals.data(); - const int vals_len = vals.length(); - for (int x = 0, parens = 0; x < vals_len; x++) { - unicode = vals_data[x].unicode(); - if (x != (int)vals_len-1 && unicode == BACKSLASH && - (vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) { - build += vals_data[x++]; //get that 'escape' - } else if (!quote.isEmpty() && unicode == quote.top()) { - quote.pop(); - } else if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) { - quote.push(unicode); - } else if (unicode == RPAREN) { - --parens; - } else if (unicode == LPAREN) { - ++parens; - } - - if (!parens && quote.isEmpty() && ((do_semicolon && unicode == SEMICOLON) || - vals_data[x] == Option::field_sep)) { - ret << build; - build.clear(); - } else { - build += vals_data[x]; - } - } - if (!build.isEmpty()) - ret << build; - return ret; -} - -static QStringList qmake_mkspec_paths() -{ - QStringList ret; - const QString concat = QDir::separator() + QLatin1String("mkspecs"); - QByteArray qmakepath = qgetenv("QMAKEPATH"); - if (!qmakepath.isEmpty()) { - const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath)); - for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) - ret << ((*it) + concat); - } - ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat; - - return ret; -} - -QT_END_NAMESPACE - -#endif // PROPARSERUTILS_H diff --git a/tools/linguist/shared/qm.cpp b/tools/linguist/shared/qm.cpp index b8cfeca..85af251 100644 --- a/tools/linguist/shared/qm.cpp +++ b/tools/linguist/shared/qm.cpp @@ -503,12 +503,7 @@ bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd) // for squeezed but non-file data, this is what needs to be deleted const uchar *messageArray = 0; const uchar *offsetArray = 0; - const uchar *contextArray = 0; - const uchar *numerusRulesArray = 0; - uint messageLength = 0; uint offsetLength = 0; - uint contextLength = 0; - uint numerusRulesLength = 0; bool ok = true; const uchar *end = data + len; @@ -527,22 +522,13 @@ bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd) break; } - if (tag == Contexts) { - contextArray = data; - contextLength = blockLen; - //qDebug() << "CONTEXTS: " << contextLength << QByteArray((const char *)contextArray, contextLength).toHex(); - } else if (tag == Hashes) { + if (tag == Hashes) { offsetArray = data; offsetLength = blockLen; - //qDebug() << "HASHES: " << offsetLength << QByteArray((const char *)offsetArray, offsetLength).toHex(); + //qDebug() << "HASHES: " << blockLen << QByteArray((const char *)data, blockLen).toHex(); } else if (tag == Messages) { messageArray = data; - messageLength = blockLen; - //qDebug() << "MESSAGES: " << messageLength << QByteArray((const char *)messageArray, messageLength).toHex(); - } else if (tag == NumerusRules) { - numerusRulesArray = data; - numerusRulesLength = blockLen; - //qDebug() << "NUMERUSRULES: " << numerusRulesLength << QByteArray((const char *)numerusRulesArray, numerusRulesLength).toHex(); + //qDebug() << "MESSAGES: " << blockLen << QByteArray((const char *)data, blockLen).toHex(); } data += blockLen; @@ -697,7 +683,7 @@ static bool containsStripped(const Translator &translator, const TranslatorMessa return false; } -static bool saveQM(const Translator &translator, QIODevice &dev, ConversionData &cd) +bool saveQM(const Translator &translator, QIODevice &dev, ConversionData &cd) { Releaser releaser; QLocale::Language l; diff --git a/tools/linguist/shared/simtexth.cpp b/tools/linguist/shared/simtexth.cpp index 31253d6..8933507 100644 --- a/tools/linguist/shared/simtexth.cpp +++ b/tools/linguist/shared/simtexth.cpp @@ -238,9 +238,7 @@ CandidateList similarTextHeuristicCandidates(const Translator *tor, QList<int> scores; CandidateList candidates; - TML all = tor->translatedMessages(); - - foreach (const TranslatorMessage &mtm, all) { + foreach (const TranslatorMessage &mtm, tor->messages()) { if (mtm.type() == TranslatorMessage::Unfinished || mtm.translation().isEmpty()) continue; diff --git a/tools/linguist/shared/translator.cpp b/tools/linguist/shared/translator.cpp index a29372a..bd13bf7 100644 --- a/tools/linguist/shared/translator.cpp +++ b/tools/linguist/shared/translator.cpp @@ -79,7 +79,8 @@ QString QObject::tr(const char *sourceText, const char *, int n) Translator::Translator() : m_codec(QTextCodec::codecForName("ISO-8859-1")), - m_locationsType(AbsoluteLocations) + m_locationsType(AbsoluteLocations), + m_indexOk(true) { } @@ -101,20 +102,58 @@ QList<Translator::FileFormat> &Translator::registeredFileFormats() return theFormats; } +void Translator::addIndex(int idx, const TranslatorMessage &msg) const +{ + if (msg.sourceText().isEmpty() && msg.id().isEmpty()) { + m_ctxCmtIdx[msg.context()] = idx; + } else { + m_msgIdx[TMMKey(msg)] = idx; + if (!msg.id().isEmpty()) + m_idMsgIdx[msg.id()] = idx; + } +} + +void Translator::delIndex(int idx) const +{ + const TranslatorMessage &msg = m_messages.at(idx); + if (msg.sourceText().isEmpty() && msg.id().isEmpty()) { + m_ctxCmtIdx.remove(msg.context()); + } else { + m_msgIdx.remove(TMMKey(msg)); + if (!msg.id().isEmpty()) + m_idMsgIdx.remove(msg.id()); + } +} + +void Translator::ensureIndexed() const +{ + if (!m_indexOk) { + m_indexOk = true; + m_ctxCmtIdx.clear(); + m_idMsgIdx.clear(); + m_msgIdx.clear(); + for (int i = 0; i < m_messages.count(); i++) + addIndex(i, m_messages.at(i)); + } +} + void Translator::replaceSorted(const TranslatorMessage &msg) { int index = find(msg); - if (index == -1) + if (index == -1) { appendSorted(msg); - else + } else { + delIndex(index); m_messages[index] = msg; + addIndex(index, msg); + } } void Translator::extend(const TranslatorMessage &msg) { int index = find(msg); if (index == -1) { - m_messages.append(msg); + append(msg); } else { TranslatorMessage &emsg = m_messages[index]; emsg.addReferenceUniq(msg.fileName(), msg.lineNumber()); @@ -132,16 +171,22 @@ void Translator::extend(const TranslatorMessage &msg) } } +void Translator::insert(int idx, const TranslatorMessage &msg) +{ + addIndex(idx, msg); + m_messages.insert(idx, msg); +} + void Translator::append(const TranslatorMessage &msg) { - m_messages.append(msg); + insert(m_messages.count(), msg); } void Translator::appendSorted(const TranslatorMessage &msg) { int msgLine = msg.lineNumber(); if (msgLine < 0) { - m_messages.append(msg); + append(msg); return; } @@ -189,11 +234,11 @@ void Translator::appendSorted(const TranslatorMessage &msg) thisScore = 1; } if (thisScore > bestScore || (thisScore == bestScore && thisSize > bestSize)) - m_messages.insert(thisIdx, msg); + insert(thisIdx, msg); else if (bestScore) - m_messages.insert(bestIdx, msg); + insert(bestIdx, msg); else - m_messages.append(msg); + append(msg); } static QString guessFormat(const QString &filename, const QString &format) @@ -329,34 +374,20 @@ void Translator::languageAndCountry(const QString &languageCode, } } -bool Translator::release(QFile *iod, ConversionData &cd) const -{ - foreach (const FileFormat &format, registeredFileFormats()) { - if (format.extension == QLatin1String("qm")) - return (*format.saver)(*this, *iod, cd); - } - cd.appendError(QLatin1String("No .qm saver available.")); - return false; -} - int Translator::find(const TranslatorMessage &msg) const { - for (int i = 0; i < m_messages.count(); ++i) { - const TranslatorMessage &tmsg = m_messages.at(i); - if (msg.id().isEmpty() || tmsg.id().isEmpty()) { - if (msg.context() == tmsg.context() - && msg.sourceText() == tmsg.sourceText() - && msg.comment() == tmsg.comment()) - return i; - } else { - if (msg.id() == tmsg.id()) - return i; - } - } - return -1; + ensureIndexed(); + if (msg.id().isEmpty()) + return m_msgIdx.value(TMMKey(msg), -1); + int i = m_idMsgIdx.value(msg.id(), -1); + if (i >= 0) + return i; + i = m_msgIdx.value(TMMKey(msg), -1); + // If both have an id, then find only by id. + return i >= 0 && m_messages.at(i).id().isEmpty() ? i : -1; } -TranslatorMessage Translator::find(const QString &context, +int Translator::find(const QString &context, const QString &comment, const TranslatorMessage::References &refs) const { if (!refs.isEmpty()) { @@ -365,75 +396,68 @@ TranslatorMessage Translator::find(const QString &context, foreach (const TranslatorMessage::Reference &itref, it->allReferences()) foreach (const TranslatorMessage::Reference &ref, refs) if (itref == ref) - return *it; + return it - m_messages.constBegin(); } } - return TranslatorMessage(); -} - -bool Translator::contains(const QString &context) const -{ - foreach (const TranslatorMessage &msg, m_messages) - if (msg.context() == context && msg.sourceText().isEmpty() && msg.id().isEmpty()) - return true; - return false; + return -1; } -TranslatorMessage Translator::find(const QString &context) const +int Translator::find(const QString &context) const { - foreach (const TranslatorMessage &msg, m_messages) - if (msg.context() == context && msg.sourceText().isEmpty() && msg.id().isEmpty()) - return msg; - return TranslatorMessage(); + ensureIndexed(); + return m_ctxCmtIdx.value(context, -1); } void Translator::stripObsoleteMessages() { - TMM newmm; - for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it) - if (it->type() != TranslatorMessage::Obsolete) - newmm.append(*it); - m_messages = newmm; + for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ) + if (it->type() == TranslatorMessage::Obsolete) + it = m_messages.erase(it); + else + ++it; + m_indexOk = false; } void Translator::stripFinishedMessages() { - TMM newmm; - for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it) - if (it->type() != TranslatorMessage::Finished) - newmm.append(*it); - m_messages = newmm; + for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ) + if (it->type() == TranslatorMessage::Finished) + it = m_messages.erase(it); + else + ++it; + m_indexOk = false; } void Translator::stripEmptyContexts() { - TMM newmm; - for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it) - if (it->sourceText() != QLatin1String(ContextComment)) - newmm.append(*it); - m_messages = newmm; + for (TMM::Iterator it = m_messages.begin(); it != m_messages.end();) + if (it->sourceText() == QLatin1String(ContextComment)) + it = m_messages.erase(it); + else + ++it; + m_indexOk = false; } void Translator::stripNonPluralForms() { - TMM newmm; - for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it) - if (it->isPlural()) - newmm.append(*it); - m_messages = newmm; + for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ) + if (!it->isPlural()) + it = m_messages.erase(it); + else + ++it; + m_indexOk = false; } void Translator::stripIdenticalSourceTranslations() { - TMM newmm; - for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it) { + for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ) { // we need to have just one translation, and it be equal to the source - if (it->translations().count() != 1) - newmm.append(*it); - else if (it->translation() != it->sourceText()) - newmm.append(*it); + if (it->translations().count() == 1 && it->translation() == it->sourceText()) + it = m_messages.erase(it); + else + ++it; } - m_messages = newmm; + m_indexOk = false; } void Translator::dropTranslations() @@ -579,6 +603,7 @@ Translator::Duplicates Translator::resolveDuplicates() } if (!omsg->isTranslated() && msg.isTranslated()) omsg->setTranslations(msg.translations()); + m_indexOk = false; m_messages.removeAt(i); } return dups; @@ -610,20 +635,18 @@ void Translator::reportDuplicates(const Duplicates &dupes, // Used by lupdate to be able to search using absolute paths during merging void Translator::makeFileNamesAbsolute(const QDir &originalPath) { - TMM newmm; for (TMM::iterator it = m_messages.begin(); it != m_messages.end(); ++it) { - TranslatorMessage msg = *it; + TranslatorMessage &msg = *it; + TranslatorMessage::References refs = msg.allReferences(); msg.setReferences(TranslatorMessage::References()); - foreach (const TranslatorMessage::Reference &ref, it->allReferences()) { + foreach (const TranslatorMessage::Reference &ref, refs) { QString fileName = ref.fileName(); QFileInfo fi (fileName); if (fi.isRelative()) fileName = originalPath.absoluteFilePath(fileName); msg.addReference(fileName, ref.lineNumber()); } - newmm.append(msg); } - m_messages = newmm; } QList<TranslatorMessage> Translator::messages() const @@ -631,15 +654,6 @@ QList<TranslatorMessage> Translator::messages() const return m_messages; } -QList<TranslatorMessage> Translator::translatedMessages() const -{ - TMM result; - for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it) - if (it->type() == TranslatorMessage::Finished) - result.append(*it); - return result; -} - QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, int numPlurals) { QStringList translations = msg.translations(); @@ -680,9 +694,7 @@ void Translator::normalizeTranslations(ConversionData &cd) tlns.removeLast(); truncated = true; } - TranslatorMessage msg2(msg); - msg2.setTranslations(tlns); - m_messages[i] = msg2; + m_messages[i].setTranslations(tlns); } } if (truncated) diff --git a/tools/linguist/shared/translator.h b/tools/linguist/shared/translator.h index fb9bd2d..3b7bd64 100644 --- a/tools/linguist/shared/translator.h +++ b/tools/linguist/shared/translator.h @@ -118,6 +118,17 @@ public: TranslatorSaveMode m_saveMode; }; +class TMMKey { +public: + TMMKey(const TranslatorMessage &msg) + { context = msg.context(); source = msg.sourceText(); comment = msg.comment(); } + bool operator==(const TMMKey &o) const + { return context == o.context && source == o.source && comment == o.comment; } + QString context, source, comment; +}; +Q_DECLARE_TYPEINFO(TMMKey, Q_MOVABLE_TYPE); +inline uint qHash(const TMMKey &key) { return qHash(key.context) ^ qHash(key.source) ^ qHash(key.comment); } + class Translator { public: @@ -125,14 +136,12 @@ public: bool load(const QString &filename, ConversionData &err, const QString &format /* = "auto" */); bool save(const QString &filename, ConversionData &err, const QString &format /* = "auto" */) const; - bool release(QFile *iod, ConversionData &cd) const; int find(const TranslatorMessage &msg) const; - TranslatorMessage find(const QString &context, + int find(const QString &context, const QString &comment, const TranslatorMessage::References &refs) const; - bool contains(const QString &context) const; - TranslatorMessage find(const QString &context) const; + int find(const QString &context) const; void replaceSorted(const TranslatorMessage &msg); void extend(const TranslatorMessage &msg); // Only for single-location messages @@ -171,7 +180,6 @@ public: void setSourceLanguageCode(const QString &languageCode) { m_sourceLanguage = languageCode; } static QString guessLanguageCodeFromFileName(const QString &fileName); QList<TranslatorMessage> messages() const; - QList<TranslatorMessage> translatedMessages() const; static QStringList normalizedTranslations(const TranslatorMessage &m, int numPlurals); void normalizeTranslations(ConversionData &cd); QStringList normalizedTranslations(const TranslatorMessage &m, ConversionData &cd, bool *ok) const; @@ -179,6 +187,7 @@ public: int messageCount() const { return m_messages.size(); } TranslatorMessage &message(int i) { return m_messages[i]; } const TranslatorMessage &message(int i) const { return m_messages.at(i); } + const TranslatorMessage &constMessage(int i) const { return m_messages.at(i); } void dump() const; // additional file format specific data @@ -212,6 +221,11 @@ public: }; private: + void insert(int idx, const TranslatorMessage &msg); + void addIndex(int idx, const TranslatorMessage &msg) const; + void delIndex(int idx) const; + void ensureIndexed() const; + typedef QList<TranslatorMessage> TMM; // int stores the sequence position. TMM m_messages; @@ -230,11 +244,18 @@ private: QString m_language; QString m_sourceLanguage; ExtraData m_extra; + + mutable bool m_indexOk; + mutable QHash<QString, int> m_ctxCmtIdx; + mutable QHash<QString, int> m_idMsgIdx; + mutable QHash<TMMKey, int> m_msgIdx; }; bool getNumerusInfo(QLocale::Language language, QLocale::Country country, QByteArray *rules, QStringList *forms, const char **gettextRules); +bool saveQM(const Translator &translator, QIODevice &dev, ConversionData &cd); + /* This is a quick hack. The proper way to handle this would be to extend Translator's interface. diff --git a/tools/linguist/tests/tst_lupdate.cpp b/tools/linguist/tests/tst_lupdate.cpp index eb6e865..21d83ef 100644 --- a/tools/linguist/tests/tst_lupdate.cpp +++ b/tools/linguist/tests/tst_lupdate.cpp @@ -118,7 +118,7 @@ void tst_linguist::fetchtr() //qDebug() << "resname:" << resname; ////qDebug() << "resfile:" << resfile; //qDebug() << "resline:" << resline; - //qDebug() << "ressource:" << ressrc; + //qDebug() << "resource:" << ressrc; QCOMPARE(src + ": " + resname, src + ": " + name); QCOMPARE(src + ": " + resline, src + ": " + line); diff --git a/tools/macdeployqt/shared/shared.cpp b/tools/macdeployqt/shared/shared.cpp index 884af99..156f1de 100644 --- a/tools/macdeployqt/shared/shared.cpp +++ b/tools/macdeployqt/shared/shared.cpp @@ -72,7 +72,7 @@ QDebug operator<<(QDebug debug, const FrameworkInfo &info) debug << "Install name" << info.installName << "\n"; debug << "Deployed install name" << info.deployedInstallName << "\n"; debug << "Source file Path" << info.sourceFilePath << "\n"; - debug << "Deployed Directory (relative to bundle)" << info.destinationDirectory << "\n"; + debug << "Destination Directory (relative to bundle)" << info.destinationDirectory << "\n"; return debug; } @@ -84,6 +84,7 @@ inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info) { debug << "Application bundle path" << info.path << "\n"; debug << "Binary path" << info.binaryPath << "\n"; + debug << "Additional libraries" << info.libraryPaths << "\n"; return debug; } @@ -111,7 +112,7 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, bool useDebugLibs) // Don't deploy system libraries. if (trimmed.startsWith("/System/Library/") || (trimmed.startsWith("/usr/lib/") && trimmed.contains("libQt") == false) // exception for libQtuitools and libQtlucene - || trimmed.startsWith("@executable_path")) + || trimmed.startsWith("@executable_path") || trimmed.startsWith("@loader_path") || trimmed.startsWith("@rpath")) return info; enum State {QtPath, FrameworkName, DylibName, Version, End}; @@ -126,7 +127,7 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, bool useDebugLibs) while (part < parts.count()) { const QString currentPart = parts.at(part).simplified() ; ++part; - if (currentPart == "") + if (currentPart.isEmpty()) continue; if (state == QtPath) { @@ -208,6 +209,21 @@ QString findAppBinary(const QString &appBundlePath) return QString(); } +QStringList findAppLibraries(const QString &appBundlePath) +{ + QStringList result; + // dylibs + QDirIterator iter(appBundlePath, QStringList() << QString::fromLatin1("*.dylib"), + QDir::Files, QDirIterator::Subdirectories); + + while (iter.hasNext()) { + iter.next(); + result << iter.fileInfo().filePath(); + } + return result; +} + + QList<FrameworkInfo> getQtFrameworks(const QStringList &otoolLines, bool useDebugLibs) { QList<FrameworkInfo> libraries; @@ -238,11 +254,26 @@ QList<FrameworkInfo> getQtFrameworks(const QString &path, bool useDebugLibs) QStringList outputLines = output.split("\n"); outputLines.removeFirst(); // remove line containing the binary path if (path.contains(".framework") || path.contains(".dylib")) - outputLines.removeFirst(); // frameworks and dylibs lists themselves as a dependency. + outputLines.removeFirst(); // frameworks and dylibs print install name of themselves first. return getQtFrameworks(outputLines, useDebugLibs); } +QList<FrameworkInfo> getQtFrameworksForPaths(const QStringList &paths, bool useDebugLibs) +{ + QList<FrameworkInfo> result; + QSet<QString> existing; + foreach (const QString &path, paths) { + foreach (const FrameworkInfo &info, getQtFrameworks(path, useDebugLibs)) { + if (!existing.contains(info.frameworkPath)) { // avoid duplicates + existing.insert(info.frameworkPath); + result << info; + } + } + } + return result; +} + // copies everything _inside_ sourcePath to destinationPath void recursiveCopy(const QString &sourcePath, const QString &destinationPath) { @@ -264,32 +295,51 @@ void recursiveCopy(const QString &sourcePath, const QString &destinationPath) QString copyFramework(const FrameworkInfo &framework, const QString path) { QString from = framework.sourceFilePath; - QString toDir = path + "/" + framework.destinationDirectory; - QString to = toDir + "/" + framework.binaryName; - if (QFile::exists(from) == false) { + if (!QFile::exists(from)) { LogError() << "no file at" << from; return QString(); } + QFileInfo fromDirInfo(framework.frameworkPath + QLatin1Char('/') + + framework.binaryDirectory); + bool fromDirIsSymLink = fromDirInfo.isSymLink(); + QString unresolvedToDir = path + "/" + framework.destinationDirectory; + QString resolvedToDir; + QString relativeLinkTarget; // will contain the link from Current to e.g. 4 in the Versions directory + if (fromDirIsSymLink) { + // handle the case where framework is referenced with Versions/Current + // which is a symbolic link, so copy to target and recreate as symbolic link + relativeLinkTarget = QDir(fromDirInfo.canonicalPath()) + .relativeFilePath(QFileInfo(fromDirInfo.symLinkTarget()).canonicalFilePath()); + resolvedToDir = QFileInfo(unresolvedToDir).path() + QLatin1Char('/') + relativeLinkTarget; + } else { + resolvedToDir = unresolvedToDir; + } + + QString to = resolvedToDir + "/" + framework.binaryName; + // create the (non-symlink) dir QDir dir; - if (dir.mkpath(toDir) == false) { + if (!dir.mkpath(resolvedToDir)) { LogError() << "could not create destination directory" << to; return QString(); } + if (!QFile::exists(to)) { // copy the binary and resources if that wasn't done before + copyFilePrintStatus(from, to); - if (QFile::exists(to)) { - return QString(); + const QString resourcesSourcePath = framework.frameworkPath + "/Resources"; + const QString resourcesDestianationPath = path + "/Contents/Frameworks/" + framework.frameworkName + "/Resources"; + recursiveCopy(resourcesSourcePath, resourcesDestianationPath); } - copyFilePrintStatus(from, to); - - const QString resourcesSourcePath = framework.frameworkPath + "/Resources"; - const QString resourcesDestianationPath = path + "/Contents/Frameworks/" + framework.frameworkName + "/Resources"; - recursiveCopy(resourcesSourcePath, resourcesDestianationPath); - + // create the Versions/Current symlink dir if necessary + if (fromDirIsSymLink) { + QFile::link(relativeLinkTarget, unresolvedToDir); + LogNormal() << " linked:" << unresolvedToDir; + LogNormal() << " to" << resolvedToDir << "(" << relativeLinkTarget << ")"; + } return to; } @@ -312,13 +362,14 @@ void changeIdentification(const QString &id, const QString &binaryPath) runInstallNameTool(QStringList() << "-id" << id << binaryPath); } -void changeInstallName(const QString &oldName, const QString &newName, const QString &binaryPath) +void changeInstallName(const QString &oldName, const QString &newName, const QStringList &binaryPaths) { LogDebug() << "Using install_name_tool:"; - LogDebug() << " in" << binaryPath; + LogDebug() << " in" << binaryPaths; LogDebug() << " change reference" << oldName; LogDebug() << " to" << newName; - runInstallNameTool(QStringList() << "-change" << oldName << newName << binaryPath); + foreach (const QString &path, binaryPaths) + runInstallNameTool(QStringList() << "-change" << oldName << newName << path); } void runStrip(const QString &binaryPath) @@ -345,23 +396,23 @@ void runStrip(const QString &binaryPath) a list of actually deployed frameworks. */ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, - const QString &bundlePath, const QString &binaryPath, bool useDebugLibs) + const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs) { LogNormal(); - LogNormal() << "Deploying Qt frameworks found inside:" << binaryPath; + LogNormal() << "Deploying Qt frameworks found inside:" << binaryPaths; QStringList copiedFrameworks; - DeploymentInfo deploymenInfo; + DeploymentInfo deploymentInfo; while (frameworks.isEmpty() == false) { const FrameworkInfo framework = frameworks.takeFirst(); copiedFrameworks.append(framework.frameworkName); // Get the qt path from one of the Qt frameworks; - if (deploymenInfo.qtPath.isNull() && framework.frameworkName.contains("Qt") + if (deploymentInfo.qtPath.isNull() && framework.frameworkName.contains("Qt") && framework.frameworkDirectory.contains("/lib")) { - deploymenInfo.qtPath = framework.frameworkDirectory; - deploymenInfo.qtPath.chop(5); // remove "/lib/" + deploymentInfo.qtPath = framework.frameworkDirectory; + deploymentInfo.qtPath.chop(5); // remove "/lib/" } if (framework.installName.startsWith("/@executable_path/")) { @@ -370,7 +421,7 @@ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, } // Install_name_tool the new id into the binary - changeInstallName(framework.installName, framework.deployedInstallName, binaryPath); + changeInstallName(framework.installName, framework.deployedInstallName, binaryPaths); // Copy farmework to app bundle. const QString deployedBinaryPath = copyFramework(framework, bundlePath); @@ -386,7 +437,7 @@ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, QList<FrameworkInfo> dependencies = getQtFrameworks(deployedBinaryPath, useDebugLibs); foreach (FrameworkInfo dependency, dependencies) { - changeInstallName(dependency.installName, dependency.deployedInstallName, deployedBinaryPath); + changeInstallName(dependency.installName, dependency.deployedInstallName, QStringList() << deployedBinaryPath); // Deploy framework if necessary. if (copiedFrameworks.contains(dependency.frameworkName) == false && frameworks.contains(dependency) == false) { @@ -394,8 +445,8 @@ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, } } } - deploymenInfo.deployedFrameworks = copiedFrameworks; - return deploymenInfo; + deploymentInfo.deployedFrameworks = copiedFrameworks; + return deploymentInfo; } DeploymentInfo deployQtFrameworks(const QString &appBundlePath, bool useDebugLibs) @@ -403,7 +454,9 @@ DeploymentInfo deployQtFrameworks(const QString &appBundlePath, bool useDebugLib ApplicationBundleInfo applicationBundle; applicationBundle.path = appBundlePath; applicationBundle.binaryPath = findAppBinary(appBundlePath); - QList<FrameworkInfo> frameworks = getQtFrameworks(applicationBundle.binaryPath, useDebugLibs); + applicationBundle.libraryPaths = findAppLibraries(appBundlePath); + QStringList allBinaryPaths = QStringList() << applicationBundle.binaryPath << applicationBundle.libraryPaths; + QList<FrameworkInfo> frameworks = getQtFrameworksForPaths(allBinaryPaths, useDebugLibs); if (frameworks.isEmpty()) { LogWarning(); LogWarning() << "Could not find any external Qt frameworks to deploy in" << appBundlePath; @@ -411,7 +464,7 @@ DeploymentInfo deployQtFrameworks(const QString &appBundlePath, bool useDebugLib LogWarning() << "If so, you will need to rebuild" << appBundlePath << "before trying again."; return DeploymentInfo(); } else { - return deployQtFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, useDebugLibs); + return deployQtFrameworks(frameworks, applicationBundle.path, allBinaryPaths, useDebugLibs); } } @@ -477,11 +530,11 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl if (pluginName.contains("libphonon_qt7")) { changeInstallName("/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo", "/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore", - destinationPath); + QStringList() << destinationPath); } QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath, useDebugLibs); - deployQtFrameworks(frameworks, appBundleInfo.path, destinationPath, useDebugLibs); + deployQtFrameworks(frameworks, appBundleInfo.path, QStringList() << destinationPath, useDebugLibs); } } // foreach plugins @@ -527,9 +580,9 @@ void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, } -void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QString &appBinaryPath, const QString &absoluteQtPath) +void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QStringList &binaryPaths, const QString &absoluteQtPath) { - LogNormal() << "Changing" << appBinaryPath << "to link against"; + LogNormal() << "Changing" << binaryPaths << "to link against"; LogNormal() << "Qt in" << absoluteQtPath; QString finalQtPath = absoluteQtPath; @@ -539,21 +592,22 @@ void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QString &ap foreach (FrameworkInfo framework, frameworks) { const QString oldBinaryId = framework.installName; const QString newBinaryId = finalQtPath + framework.frameworkName + framework.binaryPath; - changeInstallName(oldBinaryId, newBinaryId, appBinaryPath); + changeInstallName(oldBinaryId, newBinaryId, binaryPaths); } } void changeQtFrameworks(const QString appPath, const QString &qtPath, bool useDebugLibs) { const QString appBinaryPath = findAppBinary(appPath); - const QList<FrameworkInfo> frameworks = getQtFrameworks(appBinaryPath, useDebugLibs); + const QStringList libraryPaths = findAppLibraries(appPath); + const QList<FrameworkInfo> frameworks = getQtFrameworksForPaths(QStringList() << appBinaryPath << libraryPaths, useDebugLibs); if (frameworks.isEmpty()) { LogWarning(); LogWarning() << "Could not find any _external_ Qt frameworks to change in" << appPath; return; } else { const QString absoluteQtPath = QDir(qtPath).absolutePath(); - changeQtFrameworks(frameworks, appBinaryPath, absoluteQtPath); + changeQtFrameworks(frameworks, QStringList() << appBinaryPath << libraryPaths, absoluteQtPath); } } @@ -574,9 +628,13 @@ void createDiskImage(const QString &appBundlePath) } // More dmg options can be found in the hdiutil man page. - QString options = QString("create %1.dmg -srcfolder %1.app -format UDZO -volname %1").arg(appBaseName); + QStringList options = QStringList() + << "create" << dmgName + << "-srcfolder" << appBundlePath + << "-format" << "UDZO" + << "-volname" << appBaseName; QProcess hdutil; - hdutil.start("hdiutil", options.split(' ')); + hdutil.start("hdiutil", options); hdutil.waitForFinished(-1); } diff --git a/tools/macdeployqt/shared/shared.h b/tools/macdeployqt/shared/shared.h index 5eec3cf..ab9ada2 100644 --- a/tools/macdeployqt/shared/shared.h +++ b/tools/macdeployqt/shared/shared.h @@ -77,6 +77,7 @@ class ApplicationBundleInfo public: QString path; QString binaryPath; + QStringList libraryPaths; }; class DeploymentInfo @@ -91,7 +92,7 @@ public: inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info); void changeQtFrameworks(const QString appPath, const QString &qtPath, bool useDebugLibs); -void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QString &appBinaryPath, const QString &qtPath); +void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QStringList &binaryPaths, const QString &qtPath); FrameworkInfo parseOtoolLibraryLine(const QString &line, bool useDebugLibs); QString findAppBinary(const QString &appBundlePath); @@ -103,7 +104,7 @@ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, const QString void createQtConf(const QString &appBundlePath); void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, bool useDebugLibs); void changeIdentification(const QString &id, const QString &binaryPath); -void changeInstallName(const QString &oldName, const QString &newName, const QString &binaryPath); +void changeInstallName(const QString &oldName, const QString &newName, const QStringList &binaryPaths); QString findAppBinary(const QString &appBundlePath); void createDiskImage(const QString &appBundlePath); diff --git a/tools/macdeployqt/tests/tst_deployment_mac.cpp b/tools/macdeployqt/tests/tst_deployment_mac.cpp index 858dc45..5921199 100644 --- a/tools/macdeployqt/tests/tst_deployment_mac.cpp +++ b/tools/macdeployqt/tests/tst_deployment_mac.cpp @@ -230,4 +230,4 @@ void tst_deployment_mac::testFindAppBinarty() QTEST_MAIN(tst_deployment_mac) -#include "tst_deployment_mac.moc"
\ No newline at end of file +#include "tst_deployment_mac.moc" diff --git a/tools/makeqpf/mainwindow.cpp b/tools/makeqpf/mainwindow.cpp index d333bf7..66c9f41 100644 --- a/tools/makeqpf/mainwindow.cpp +++ b/tools/makeqpf/mainwindow.cpp @@ -199,7 +199,7 @@ void MainWindow::on_generate_clicked() if (item->checkState() != Qt::Checked) continue; - QPF::CharacterRange range = qVariantValue<QPF::CharacterRange>(item->data(Qt::UserRole)); + QPF::CharacterRange range = qvariant_cast<QPF::CharacterRange>(item->data(Qt::UserRole)); ranges.append(range); } } @@ -297,7 +297,7 @@ void MainWindow::populateCharacterRanges() item->setText(text); item->setCheckState(Qt::Checked); - item->setData(Qt::UserRole, qVariantFromValue(range)); + item->setData(Qt::UserRole, QVariant::fromValue(range)); } } diff --git a/tools/qdbus/qdbus/qdbus.cpp b/tools/qdbus/qdbus/qdbus.cpp index 1db5e86..757267f 100644 --- a/tools/qdbus/qdbus/qdbus.cpp +++ b/tools/qdbus/qdbus/qdbus.cpp @@ -59,7 +59,7 @@ static bool printArgumentsLiterally = false; static void showUsage() { - printf("Usage: qdbus [--system] [--literal] [servicename] [path] [method] [args]\n" + printf("Usage: qdbus [--system | --address ADDRESS] [--literal] [servicename] [path] [method] [args]\n" "\n" " servicename the service to connect to (e.g., org.freedesktop.DBus)\n" " path the path to the object (e.g., /)\n" @@ -71,6 +71,7 @@ static void showUsage() "\n" "Options:\n" " --system connect to the system bus\n" + " --address ADDRESS connect to the given bus\n" " --literal print replies literally\n"); } @@ -332,7 +333,7 @@ static int placeCall(const QString &service, const QString &path, const QString if (id == int(QMetaType::UChar)) { // special case: QVariant::convert doesn't convert to/from // UChar because it can't decide if it's a character or a number - p = qVariantFromValue<uchar>(p.toUInt()); + p = QVariant::fromValue<uchar>(p.toUInt()); } else if (id < int(QMetaType::User) && id != int(QVariant::Map)) { p.convert(QVariant::Type(id)); if (p.type() == QVariant::Invalid) { @@ -342,7 +343,7 @@ static int placeCall(const QString &service, const QString &path, const QString } } else if (id == qMetaTypeId<QDBusVariant>()) { QDBusVariant tmp(p); - p = qVariantFromValue(tmp); + p = QVariant::fromValue(tmp); } else if (id == qMetaTypeId<QDBusObjectPath>()) { QDBusObjectPath path(argument); if (path.path().isNull()) { @@ -350,7 +351,7 @@ static int placeCall(const QString &service, const QString &path, const QString qPrintable(argument)); return 1; } - p = qVariantFromValue(path); + p = QVariant::fromValue(path); } else if (id == qMetaTypeId<QDBusSignature>()) { QDBusSignature sig(argument); if (sig.signature().isNull()) { @@ -358,7 +359,7 @@ static int placeCall(const QString &service, const QString &path, const QString qPrintable(argument)); return 1; } - p = qVariantFromValue(sig); + p = QVariant::fromValue(sig); } else { fprintf(stderr, "Sorry, can't pass arg of type '%s'.\n", types.at(i).constData()); @@ -454,6 +455,11 @@ int main(int argc, char **argv) if (arg == QLatin1String("--system")) { connection = QDBusConnection::systemBus(); connectionOpened = true; + } else if (arg == QLatin1String("--address")) { + if (!args.isEmpty()) { + connection = QDBusConnection::connectToBus(args.takeFirst(), "bus"); + connectionOpened = true; + } } else if (arg == QLatin1String("--literal")) { printArgumentsLiterally = true; } else if (arg == QLatin1String("--help")) { diff --git a/tools/qdbus/qdbusviewer/qdbusviewer.cpp b/tools/qdbus/qdbusviewer/qdbusviewer.cpp index 5940010..15ad1d9 100644 --- a/tools/qdbus/qdbusviewer/qdbusviewer.cpp +++ b/tools/qdbus/qdbusviewer/qdbusviewer.cpp @@ -217,7 +217,7 @@ void QDBusViewer::setProperty(const BusSignature &sig) QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Set")); QList<QVariant> arguments; - arguments << sig.mInterface << sig.mName << qVariantFromValue(QDBusVariant(value)); + arguments << sig.mInterface << sig.mName << QVariant::fromValue(QDBusVariant(value)); message.setArguments(arguments); c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage))); @@ -283,7 +283,7 @@ void QDBusViewer::callMethod(const BusSignature &sig) // interface wants a variant for (int i = 0; i < args.count(); ++i) { if (types.at(i) == qMetaTypeId<QDBusVariant>()) - args[i] = qVariantFromValue(QDBusVariant(args.at(i))); + args[i] = QVariant::fromValue(QDBusVariant(args.at(i))); } QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, sig.mInterface, diff --git a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp index 602cdac..bc617a9 100644 --- a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -617,7 +617,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf if (property.access != QDBusIntrospection::Property::Read) { hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl << " { setProperty(\"" << property.name - << "\", qVariantFromValue(value)); }" << endl; + << "\", QVariant::fromValue(value)); }" << endl; } hs << endl; @@ -660,7 +660,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos) - hs << " << qVariantFromValue(" << argNames.at(argPos) << ')'; + hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; hs << ";" << endl; } @@ -693,7 +693,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (argPos = 0; argPos < method.inputArgs.count(); ++argPos) - hs << " << qVariantFromValue(" << argNames.at(argPos) << ')'; + hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; hs << ";" << endl; } @@ -940,7 +940,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl << "{" << endl << " // set the value of property " << property.name << endl - << " parent()->setProperty(\"" << property.name << "\", qVariantFromValue(value"; + << " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value"; if (constRefType.contains(QLatin1String("QDBusVariant"))) cs << ".variant()"; cs << "));" << endl diff --git a/tools/qdoc3/codemarker.cpp b/tools/qdoc3/codemarker.cpp index 614419e..705ef6c 100644 --- a/tools/qdoc3/codemarker.cpp +++ b/tools/qdoc3/codemarker.cpp @@ -76,7 +76,7 @@ CodeMarker::~CodeMarker() A code market performs no initialization by default. Marker-specific initialization is performed in subclasses. */ -void CodeMarker::initializeMarker(const Config &config) +void CodeMarker::initializeMarker(const Config& ) // config { } diff --git a/tools/qdoc3/codeparser.cpp b/tools/qdoc3/codeparser.cpp index c7a8912..9ab5f82 100644 --- a/tools/qdoc3/codeparser.cpp +++ b/tools/qdoc3/codeparser.cpp @@ -287,6 +287,9 @@ void CodeParser::processCommonMetaCommand(const Location &location, FakeNode *fake = static_cast<FakeNode *>(node); fake->setTitle(arg); nameToTitle.insert(fake->name(),arg); + if (fake->subType() == Node::Example) { + + } } else location.warning(tr("Ignored '\\%1'").arg(COMMAND_TITLE)); diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index b81e979..743688f 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -49,6 +49,8 @@ #include "text.h" #include "tree.h" +#include <ctype.h> + QT_BEGIN_NAMESPACE /*! @@ -876,26 +878,6 @@ static const char * const keywordTable[] = { "signals", "slots", "emit", 0 }; -static QString untabified(const QString &in) -{ - QString res; - int col = 0; - int i = 0; - - for (; i < (int) in.length(); i++) { - if (in[i] == QChar('\t')) { - res += QString(" " + (col & 0x7)); - col = (col + 8) & ~0x7; - } else { - res += in[i]; - if (in[i] == QChar('\n')) - col = 0; - } - } - - return res; -} - /* @char @class @@ -1155,15 +1137,15 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, "property", "properties"); FastSection qmlsignals(qmlClassNode, - "Signals", + "Signal Handlers", "", - "signal", - "signals"); + "signal handler", + "signal handlers"); FastSection qmlattachedsignals(qmlClassNode, - "Attached Signals", + "Attached Signal Handlers", "", - "signal", - "signals"); + "signal handler", + "signal handlers"); FastSection qmlmethods(qmlClassNode, "Methods", "", @@ -1218,9 +1200,9 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, FastSection qmlproperties(qmlClassNode, "Property Documentation","qmlprop","member","members"); FastSection qmlattachedproperties(qmlClassNode,"Attached Property Documentation","qmlattprop", "member","members"); - FastSection qmlsignals(qmlClassNode,"Signal Documentation","qmlsig","member","members"); - FastSection qmlattachedsignals(qmlClassNode,"Attached Signal Documentation","qmlattsig", - "member","members"); + FastSection qmlsignals(qmlClassNode,"Signal Handler Documentation","qmlsig","handler","handlers"); + FastSection qmlattachedsignals(qmlClassNode,"Attached Signal Handler Documentation","qmlattsig", + "handler","handlers"); FastSection qmlmethods(qmlClassNode,"Method Documentation","qmlmeth","member","members"); FastSection qmlattachedmethods(qmlClassNode,"Attached Method Documentation","qmlattmeth", "member","members"); diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp index 6f5baa0..1a4c344 100644 --- a/tools/qdoc3/cppcodeparser.cpp +++ b/tools/qdoc3/cppcodeparser.cpp @@ -47,7 +47,7 @@ #include <stdio.h> #include <errno.h> - +#include <qdebug.h> #include "codechunk.h" #include "config.h" #include "cppcodeparser.h" @@ -704,7 +704,7 @@ Node *CppCodeParser::processTopicCommand(const Doc& doc, if (command == COMMAND_CLASS) { if (paths.size() > 1) { if (!paths[1].endsWith(".h")) { - ClassNode*cnode = static_cast<ClassNode*>(node); + ClassNode* cnode = static_cast<ClassNode*>(node); cnode->setQmlElement(paths[1]); } } @@ -712,9 +712,9 @@ Node *CppCodeParser::processTopicCommand(const Doc& doc, return node; } else if (command == COMMAND_EXAMPLE) { - FakeNode *fake = new FakeNode(tre->root(), arg, Node::Example); - createExampleFileNodes(fake); - return fake; + ExampleNode* en = new ExampleNode(tre->root(), arg); + createExampleFileNodes(en); + return en; } else if (command == COMMAND_EXTERNALPAGE) { return new FakeNode(tre->root(), arg, Node::ExternalPage); @@ -2349,8 +2349,8 @@ void CppCodeParser::createExampleFileNodes(FakeNode *fake) proFileName, userFriendlyFilePath); if (fullPath.isEmpty()) { - fake->doc().location().warning( - tr("Cannot find file '%1' or '%2'").arg(tmp).arg(proFileName)); + fake->doc().location().warning(tr("Cannot find file '%1' or '%2'").arg(tmp).arg(proFileName)); + fake->doc().location().warning(tr("EXAMPLE PATH DOES NOT EXIST: %1").arg(examplePath)); return; } } @@ -2362,7 +2362,6 @@ void CppCodeParser::createExampleFileNodes(FakeNode *fake) QStringList exampleFiles = Config::getFilesHere(fullPath,exampleNameFilter); QString imagesPath = fullPath + "/images"; QStringList imageFiles = Config::getFilesHere(imagesPath,exampleImageFilter); - if (!exampleFiles.isEmpty()) { // move main.cpp and to the end, if it exists QString mainCpp; @@ -2382,7 +2381,7 @@ void CppCodeParser::createExampleFileNodes(FakeNode *fake) exampleFiles.append(mainCpp); // add any qmake Qt resource files and qmake project files - exampleFiles += Config::getFilesHere(fullPath, "*.qrc *.pro qmldir"); + exampleFiles += Config::getFilesHere(fullPath, "*.qrc *.pro *.qmlproject qmldir"); } foreach (const QString &exampleFile, exampleFiles) diff --git a/tools/qdoc3/ditaxmlgenerator.cpp b/tools/qdoc3/ditaxmlgenerator.cpp index 64f12d6..e3e32a0 100644 --- a/tools/qdoc3/ditaxmlgenerator.cpp +++ b/tools/qdoc3/ditaxmlgenerator.cpp @@ -751,7 +751,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, { writeStartTag(DT_codeblock); xmlWriter().writeAttribute("outputclass","cpp"); - QString chars = trimmedTrailing(atom->string()); + QString chars = trimmedTrailing(atom->string()); writeText(chars, marker, relative); writeEndTag(); // </codeblock> } @@ -2101,9 +2101,10 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark generateSince(qcn, marker); enterSection("h2","Detailed Description"); generateBody(qcn, marker); - if (cn) + if (cn) { generateQmlText(cn->doc().body(), cn, marker, qcn->name()); - generateAlsoList(cn, marker); + generateAlsoList(cn, marker); + } leaveSection(); leaveSection(); // </apiDesc> @@ -3391,6 +3392,7 @@ void DitaXmlGenerator::writeText(const QString& markedCode, "<@type>", "<@type>", "<@headerfile>", "<@headerfile>", "<@func>", "<@func>", + "<@func ", "<@func ", "<@param>", "<@param>", "<@extra>", "<@extra>", "</@link>", "</@link>", @@ -3403,7 +3405,7 @@ void DitaXmlGenerator::writeText(const QString& markedCode, for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle) { bool handled = false; - for (int k = 0; k != 12; ++k) { + for (int k = 0; k != 13; ++k) { const QString & tag = spanTags[2 * k]; if (tag == QStringRef(&src, i, tag.length())) { html += spanTags[2 * k + 1]; @@ -4316,7 +4318,8 @@ void DitaXmlGenerator::generateDetailedQmlMember(const Node* node, writeStartTag(DT_li); writeGuidAttribute((Node*)qpn); QString attr; - if (!qpn->isWritable(myTree)) + const ClassNode* cn = qpn->declarativeCppNode(); + if (cn && !qpn->isWritable(myTree)) attr = "read-only"; if (qpgn->isDefault()) { if (!attr.isEmpty()) diff --git a/tools/qdoc3/doc.cpp b/tools/qdoc3/doc.cpp index 37f68f8..f1f1418 100644 --- a/tools/qdoc3/doc.cpp +++ b/tools/qdoc3/doc.cpp @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QSet<QString>, null_Set_QString) Q_GLOBAL_STATIC(QStringList, null_QStringList) Q_GLOBAL_STATIC(QList<Text>, null_QList_Text) -Q_GLOBAL_STATIC(QStringMap, null_QStringMap) +//Q_GLOBAL_STATIC(QStringMap, null_QStringMap) Q_GLOBAL_STATIC(QStringMultiMap, null_QStringMultiMap) struct Macro @@ -1861,7 +1861,7 @@ void DocParser::startSection(Doc::Sections unit, int cmd) } -void DocParser::endSection(int unit, int endCmd) +void DocParser::endSection(int , int) // (int unit, int endCmd) { leavePara(); append(Atom::SectionRight, QString::number(currentSection)); diff --git a/tools/qdoc3/doc/config/images/arrow_down.png b/tools/qdoc3/doc/config/images/arrow_down.png Binary files differnew file mode 100644 index 0000000..9d01e97 --- /dev/null +++ b/tools/qdoc3/doc/config/images/arrow_down.png diff --git a/tools/qdoc3/doc/config/images/bg_l.png b/tools/qdoc3/doc/config/images/bg_l.png Binary files differnew file mode 100755 index 0000000..90b1da1 --- /dev/null +++ b/tools/qdoc3/doc/config/images/bg_l.png diff --git a/tools/qdoc3/doc/config/images/bg_l_blank.png b/tools/qdoc3/doc/config/images/bg_l_blank.png Binary files differnew file mode 100755 index 0000000..5a9673d --- /dev/null +++ b/tools/qdoc3/doc/config/images/bg_l_blank.png diff --git a/tools/qdoc3/doc/config/images/bg_ll_blank.png b/tools/qdoc3/doc/config/images/bg_ll_blank.png Binary files differnew file mode 100644 index 0000000..95a1c45 --- /dev/null +++ b/tools/qdoc3/doc/config/images/bg_ll_blank.png diff --git a/tools/qdoc3/doc/config/images/bg_r.png b/tools/qdoc3/doc/config/images/bg_r.png Binary files differnew file mode 100755 index 0000000..f0fb121 --- /dev/null +++ b/tools/qdoc3/doc/config/images/bg_r.png diff --git a/tools/qdoc3/doc/config/images/bg_ul_blank.png b/tools/qdoc3/doc/config/images/bg_ul_blank.png Binary files differnew file mode 100644 index 0000000..7051261 --- /dev/null +++ b/tools/qdoc3/doc/config/images/bg_ul_blank.png diff --git a/tools/qdoc3/doc/config/images/box_bg.png b/tools/qdoc3/doc/config/images/box_bg.png Binary files differnew file mode 100755 index 0000000..3322f92 --- /dev/null +++ b/tools/qdoc3/doc/config/images/box_bg.png diff --git a/tools/qdoc3/doc/config/images/breadcrumb.png b/tools/qdoc3/doc/config/images/breadcrumb.png Binary files differnew file mode 100755 index 0000000..0ded551 --- /dev/null +++ b/tools/qdoc3/doc/config/images/breadcrumb.png diff --git a/tools/qdoc3/doc/config/images/bullet_dn.png b/tools/qdoc3/doc/config/images/bullet_dn.png Binary files differnew file mode 100644 index 0000000..f776247 --- /dev/null +++ b/tools/qdoc3/doc/config/images/bullet_dn.png diff --git a/tools/qdoc3/doc/config/images/bullet_gt.png b/tools/qdoc3/doc/config/images/bullet_gt.png Binary files differnew file mode 100755 index 0000000..7561b4e --- /dev/null +++ b/tools/qdoc3/doc/config/images/bullet_gt.png diff --git a/tools/qdoc3/doc/config/images/bullet_sq.png b/tools/qdoc3/doc/config/images/bullet_sq.png Binary files differnew file mode 100755 index 0000000..a84845e --- /dev/null +++ b/tools/qdoc3/doc/config/images/bullet_sq.png diff --git a/tools/qdoc3/doc/config/images/bullet_up.png b/tools/qdoc3/doc/config/images/bullet_up.png Binary files differnew file mode 100644 index 0000000..7de2f06 --- /dev/null +++ b/tools/qdoc3/doc/config/images/bullet_up.png diff --git a/tools/qdoc3/doc/config/images/feedbackground.png b/tools/qdoc3/doc/config/images/feedbackground.png Binary files differnew file mode 100755 index 0000000..3a38d99 --- /dev/null +++ b/tools/qdoc3/doc/config/images/feedbackground.png diff --git a/tools/qdoc3/doc/config/images/header_bg.png b/tools/qdoc3/doc/config/images/header_bg.png Binary files differnew file mode 100644 index 0000000..a436aa6 --- /dev/null +++ b/tools/qdoc3/doc/config/images/header_bg.png diff --git a/tools/qdoc3/doc/config/images/horBar.png b/tools/qdoc3/doc/config/images/horBar.png Binary files differnew file mode 100755 index 0000000..100fe91 --- /dev/null +++ b/tools/qdoc3/doc/config/images/horBar.png diff --git a/tools/qdoc3/doc/config/images/page.png b/tools/qdoc3/doc/config/images/page.png Binary files differnew file mode 100644 index 0000000..1db151b --- /dev/null +++ b/tools/qdoc3/doc/config/images/page.png diff --git a/tools/qdoc3/doc/config/images/page_bg.png b/tools/qdoc3/doc/config/images/page_bg.png Binary files differnew file mode 100755 index 0000000..9b3bd99 --- /dev/null +++ b/tools/qdoc3/doc/config/images/page_bg.png diff --git a/tools/qdoc3/doc/config/images/spinner.gif b/tools/qdoc3/doc/config/images/spinner.gif Binary files differnew file mode 100644 index 0000000..1ed786f --- /dev/null +++ b/tools/qdoc3/doc/config/images/spinner.gif diff --git a/tools/qdoc3/doc/config/images/sprites-combined.png b/tools/qdoc3/doc/config/images/sprites-combined.png Binary files differnew file mode 100755 index 0000000..3a48b21 --- /dev/null +++ b/tools/qdoc3/doc/config/images/sprites-combined.png diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp index 6a99a3b..4629644 100644 --- a/tools/qdoc3/helpprojectwriter.cpp +++ b/tools/qdoc3/helpprojectwriter.cpp @@ -48,6 +48,7 @@ #include "config.h" #include "node.h" #include "tree.h" +#include <qdebug.h> QT_BEGIN_NAMESPACE diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 655c3b4..85ce9ac 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -161,6 +161,9 @@ void HtmlGenerator::initializeGenerator(const Config &config) pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_GENERATEMACREFS); + noBreadCrumbs = config.getBool(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_NOBREADCRUMBS); project = config.getString(CONFIG_PROJECT); @@ -257,6 +260,7 @@ void HtmlGenerator::generateTree(const Tree *tree) generatePageIndex(outputDir() + "/" + fileBase + ".pageindex"); helpProjectWriter->generate(myTree); + generateManifestFiles(); } void HtmlGenerator::startText(const Node * /* relative */, @@ -312,8 +316,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, break; case Atom::BriefLeft: if (relative->type() == Node::Fake) { - skipAhead = skipAtoms(atom, Atom::BriefRight); - break; + if (relative->subType() != Node::Example) { + skipAhead = skipAtoms(atom, Atom::BriefRight); + break; + } } out() << "<p>"; @@ -750,6 +756,15 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << " alt=\"" << protectEnc(text) << "\""; out() << " />"; helpProjectWriter->addExtraFile(fileName); + if ((relative->type() == Node::Fake) && + (relative->subType() == Node::Example)) { + const ExampleNode* cen = static_cast<const ExampleNode*>(relative); + if (cen->imageFileName().isEmpty()) { + ExampleNode* en = const_cast<ExampleNode*>(cen); + en->setImageFileName(fileName); + ExampleNode::exampleNodeMap.insert(en->title(),en); + } + } } if (atom->type() == Atom::Image) out() << "</p>"; @@ -1492,8 +1507,10 @@ void HtmlGenerator::generateBreadCrumbs(const QString &title, const Node *node, CodeMarker *marker) { + if (noBreadCrumbs) + return; + Text breadcrumbs; - if (node->type() == Node::Class) { const ClassNode *cn = static_cast<const ClassNode *>(node); QString name = node->moduleName(); @@ -1780,7 +1797,6 @@ void HtmlGenerator::generateTableOfContents(const Node *node, toc = node->doc().tableOfContents(); if (toc.isEmpty() && !sections && (node->subType() != Node::Module)) return; - bool debug = false; QStringList sectionNumber; int detailsBase = 0; @@ -3706,8 +3722,6 @@ void HtmlGenerator::endLink() inObsoleteLink = false; } -#ifdef QDOC_QML - /*! Generates the summary for the \a section. Only used for sections of QML element documentation. @@ -3764,7 +3778,8 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, out() << "<a name=\"" + refForNode(qpn) + "\"></a>"; - if (!qpn->isWritable(myTree)) { + const ClassNode* cn = qpn->declarativeCppNode(); + if (cn && !qpn->isWritable(myTree)) { out() << "<span class=\"qmlreadonly\">read-only</span>"; } if (qpgn->isDefault()) @@ -4193,7 +4208,6 @@ QString HtmlGenerator::fullDocumentLocation(const Node *node) return ""; } else if (node->type() == Node::Fake) { -#ifdef QDOC_QML if ((node->subType() == Node::QmlClass) || (node->subType() == Node::QmlBasicType)) { QString fb = node->fileBase(); @@ -4201,9 +4215,9 @@ QString HtmlGenerator::fullDocumentLocation(const Node *node) return fb + ".html"; else return Generator::outputPrefix(QLatin1String("QML")) + node->fileBase() + QLatin1String(".html"); - } else -#endif - parentName = node->fileBase() + ".html"; + } + else + parentName = node->fileBase() + ".html"; } else if (node->fileBase().isEmpty()) return ""; @@ -4314,6 +4328,165 @@ QString HtmlGenerator::fullDocumentLocation(const Node *node) return parentName.toLower() + anchorRef; } -#endif +/*! + This function outputs one or more manifest files in XML. + They are used by Creator. + */ +void HtmlGenerator::generateManifestFiles() +{ + generateManifestFile("examples", "example"); + generateManifestFile("demos", "demo"); + ExampleNode::exampleNodeMap.clear(); +} + +/*! + This function is called by generaqteManiferstFile(), once + for each manifest file to be generated. \a manifest is the + type of manifest file. + */ +void HtmlGenerator::generateManifestFile(QString manifest, QString element) +{ + if (ExampleNode::exampleNodeMap.isEmpty()) + return; + QString fileName = manifest +"-manifest.xml"; + QFile file(outputDir() + "/" + fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) + return ; + bool demos = false; + if (manifest == "demos") + demos = true; + + bool proceed = false; + ExampleNodeMap::Iterator i = ExampleNode::exampleNodeMap.begin(); + while (i != ExampleNode::exampleNodeMap.end()) { + const ExampleNode* en = i.value(); + if (demos) { + if (en->name().startsWith("demos")) { + proceed = true; + break; + } + } + else if (!en->name().startsWith("demos")) { + proceed = true; + break; + } + ++i; + } + if (!proceed) + return; + + QXmlStreamWriter writer(&file); + writer.setAutoFormatting(true); + writer.writeStartDocument(); + writer.writeStartElement("instructionals"); + writer.writeAttribute("module", project); + writer.writeStartElement(manifest); + + i = ExampleNode::exampleNodeMap.begin(); + while (i != ExampleNode::exampleNodeMap.end()) { + const ExampleNode* en = i.value(); + if (demos) { + if (!en->name().startsWith("demos")) { + ++i; + continue; + } + } + else if (en->name().startsWith("demos")) { + ++i; + continue; + } + writer.writeStartElement(element); + writer.writeAttribute("name", en->title()); + //QString docUrl = projectUrl + "/" + en->fileBase() + ".html"; + QString docUrl = "%REPLACEME%/" + en->fileBase() + ".html"; + writer.writeAttribute("docUrl", docUrl); + foreach (const Node* child, en->childNodes()) { + if (child->subType() == Node::File) { + QString file = child->name(); + if (file.endsWith(".pro") || file.endsWith(".qmlproject")) { + if (file.startsWith("demos/")) + file = file.mid(6); + writer.writeAttribute("projectPath", file); + break; + } + } + } + //writer.writeAttribute("imageUrl", projectUrl + "/" + en->imageFileName()); + writer.writeAttribute("imageUrl", "%REPLACEME%/" + en->imageFileName()); + writer.writeStartElement("description"); + Text brief = en->doc().briefText(); + if (!brief.isEmpty()) + writer.writeCDATA(brief.toString()); + else + writer.writeCDATA(QString("No description available")); + writer.writeEndElement(); // description + QStringList tags = en->title().toLower().split(" "); + if (!tags.isEmpty()) { + writer.writeStartElement("tags"); + bool wrote_one = false; + for (int n=0; n<tags.size(); ++n) { + QString tag = tags.at(n); + if (tag.at(0).isDigit()) + continue; + if (tag.at(0) == '-') + continue; + if (tag.startsWith("example")) + continue; + if (tag.startsWith("chapter")) + continue; + if (tag.endsWith(":")) + tag.chop(1); + if (n>0 && wrote_one) + writer.writeCharacters(","); + writer.writeCharacters(tag); + wrote_one = true; + } + writer.writeEndElement(); // tags + } + + QString ename = en->name().mid(en->name().lastIndexOf('/')+1); + QSet<QString> usedNames; + foreach (const Node* child, en->childNodes()) { + if (child->subType() == Node::File) { + QString file = child->name(); + QString fileName = file.mid(file.lastIndexOf('/')+1); + QString baseName = fileName; + if ((fileName.count(QChar('.')) > 0) && + (fileName.endsWith(".cpp") || + fileName.endsWith(".h") || + fileName.endsWith(".qml"))) + baseName.truncate(baseName.lastIndexOf(QChar('.'))); + if (baseName.toLower() == ename) { + if (!usedNames.contains(fileName)) { + writer.writeStartElement("fileToOpen"); + if (file.startsWith("demos/")) + file = file.mid(6); + writer.writeCharacters(file); + writer.writeEndElement(); // fileToOpen + usedNames.insert(fileName); + } + } + else if (fileName.toLower().endsWith("main.cpp") || + fileName.toLower().endsWith("main.qml")) { + if (!usedNames.contains(fileName)) { + writer.writeStartElement("fileToOpen"); + if (file.startsWith("demos/")) + file = file.mid(6); + writer.writeCharacters(file); + writer.writeEndElement(); // fileToOpen + usedNames.insert(fileName); + } + } + } + } + writer.writeEndElement(); // example + ++i; + } + + writer.writeEndElement(); // examples + writer.writeEndElement(); // instructionals + writer.writeEndDocument(); + file.close(); +} QT_END_NAMESPACE diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h index e36c562..62a7f605 100644 --- a/tools/qdoc3/htmlgenerator.h +++ b/tools/qdoc3/htmlgenerator.h @@ -87,6 +87,7 @@ class HtmlGenerator : public PageGenerator virtual void terminateGenerator(); virtual QString format(); virtual void generateTree(const Tree *tree); + void generateManifestFiles(); QString protectEnc(const QString &string); static QString protect(const QString &string, const QString &encoding = "ISO-8859-1"); @@ -106,6 +107,8 @@ class HtmlGenerator : public PageGenerator virtual QString linkForNode(const Node *node, const Node *relative); virtual QString refForAtom(Atom *atom, const Node *node); + void generateManifestFile(QString manifest, QString element); + private: enum SubTitleSize { SmallSubTitle, LargeSubTitle }; enum ExtractionMarkType { @@ -266,6 +269,7 @@ class HtmlGenerator : public PageGenerator QString footer; QString address; bool pleaseGenerateMacRef; + bool noBreadCrumbs; QString project; QString projectDescription; QString projectUrl; @@ -296,6 +300,7 @@ class HtmlGenerator : public PageGenerator #define HTMLGENERATOR_GENERATEMACREFS "generatemacrefs" // ### document me #define HTMLGENERATOR_POSTHEADER "postheader" #define HTMLGENERATOR_POSTPOSTHEADER "postpostheader" +#define HTMLGENERATOR_NOBREADCRUMBS "nobreadcrumbs" QT_END_NAMESPACE diff --git a/tools/qdoc3/jscodemarker.cpp b/tools/qdoc3/jscodemarker.cpp index bb9e829..9016988 100644 --- a/tools/qdoc3/jscodemarker.cpp +++ b/tools/qdoc3/jscodemarker.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index 189c28f..709f03f 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -51,6 +51,8 @@ QT_BEGIN_NAMESPACE +ExampleNodeMap ExampleNode::exampleNodeMap; + /*! \class Node \brief The Node class is a node in the Tree. @@ -317,6 +319,38 @@ QString Node::ditaXmlHref() } /*! + If this node is a QML class node, return a pointer to it. + If it is a child of a QML class node, return a pointer to + the QML class node. Otherwise, return 0; + */ +const QmlClassNode* Node::qmlClassNode() const +{ + if (isQmlNode()) { + const Node* n = this; + while (n && n->subType() != Node::QmlClass) + n = n->parent(); + if (n && n->subType() == Node::QmlClass) + return static_cast<const QmlClassNode*>(n); + } + return 0; +} + +/*! + If this node is a QML node, find its QML class node, + and return a pointer to the C++ class node from the + QML class node. That pointer will be null if the QML + class node is a component. It will be non-null if + the QML class node is a QML element. + */ +const ClassNode* Node::declarativeCppNode() const +{ + const QmlClassNode* qcn = qmlClassNode(); + if (qcn) + return qcn->classNode(); + return 0; +} + +/*! \class InnerNode */ @@ -1073,6 +1107,16 @@ QString FakeNode::subTitle() const } /*! + The constructor calls the FakeNode constructor with + \a parent, \a name, and Node::Example. + */ +ExampleNode::ExampleNode(InnerNode* parent, const QString& name) + : FakeNode(parent, name, Node::Example) +{ + // nothing +} + +/*! \class EnumNode */ @@ -1694,37 +1738,6 @@ bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue) } } -static QString valueType(const QString &n) -{ - if (n == "QPoint") - return "QDeclarativePointValueType"; - if (n == "QPointF") - return "QDeclarativePointFValueType"; - if (n == "QSize") - return "QDeclarativeSizeValueType"; - if (n == "QSizeF") - return "QDeclarativeSizeFValueType"; - if (n == "QRect") - return "QDeclarativeRectValueType"; - if (n == "QRectF") - return "QDeclarativeRectFValueType"; - if (n == "QVector2D") - return "QDeclarativeVector2DValueType"; - if (n == "QVector3D") - return "QDeclarativeVector3DValueType"; - if (n == "QVector4D") - return "QDeclarativeVector4DValueType"; - if (n == "QQuaternion") - return "QDeclarativeQuaternionValueType"; - if (n == "QMatrix4x4") - return "QDeclarativeMatrix4x4ValueType"; - if (n == "QEasingCurve") - return "QDeclarativeEasingValueType"; - if (n == "QFont") - return "QDeclarativeFontValueType"; - return QString(); -} - /*! Returns true if a QML property or attached property is read-only. The algorithm for figuring this out is long diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index cb16bea..a08151a 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -58,7 +58,15 @@ QT_BEGIN_NAMESPACE +class Node; +class ClassNode; class InnerNode; +class ExampleNode; +class QmlClassNode; + +typedef QMap<QString, const Node*> NodeMap; +typedef QMultiMap<QString, Node*> NodeMultiMap; +typedef QMap<QString, const ExampleNode*> ExampleNodeMap; class Node { @@ -194,6 +202,8 @@ class Node QString guid() const; QString ditaXmlHref(); QString extractClassName(const QString &string) const; + const QmlClassNode* qmlClassNode() const; + const ClassNode* declarativeCppNode() const; protected: Node(Type type, InnerNode* parent, const QString& name); @@ -380,8 +390,10 @@ class FakeNode : public InnerNode virtual QString title() const; virtual QString fullTitle() const; virtual QString subTitle() const; + virtual QString imageFileName() const { return QString(); } const NodeList &groupMembers() const { return gr; } virtual QString nameForLists() const { return title(); } + virtual void setImageFileName(const QString& ) { } private: SubType sub; @@ -390,7 +402,21 @@ class FakeNode : public InnerNode NodeList gr; }; -#ifdef QDOC_QML +class ExampleNode : public FakeNode +{ + public: + ExampleNode(InnerNode* parent, const QString& name); + virtual ~ExampleNode() { } + virtual QString imageFileName() const { return imageFileName_; } + virtual void setImageFileName(const QString& ifn) { imageFileName_ = ifn; } + + public: + static ExampleNodeMap exampleNodeMap; + + private: + QString imageFileName_; +}; + class QmlClassNode : public FakeNode { public: @@ -482,7 +508,6 @@ class QmlPropertyNode : public LeafNode Trool wri; bool att; }; -#endif class EnumItem { diff --git a/tools/qdoc3/puredocparser.cpp b/tools/qdoc3/puredocparser.cpp index c7db1bf..0f21cbc 100644 --- a/tools/qdoc3/puredocparser.cpp +++ b/tools/qdoc3/puredocparser.cpp @@ -55,6 +55,11 @@ PureDocParser::~PureDocParser() { } +QString PureDocParser::language() +{ + return "qdoc"; +} + QStringList PureDocParser::sourceFileNameFilter() { return QStringList("*.qdoc"); diff --git a/tools/qdoc3/puredocparser.h b/tools/qdoc3/puredocparser.h index 7f0434d..814c829 100644 --- a/tools/qdoc3/puredocparser.h +++ b/tools/qdoc3/puredocparser.h @@ -64,6 +64,7 @@ public: PureDocParser(); virtual ~PureDocParser(); + virtual QString language(); virtual QStringList sourceFileNameFilter(); }; diff --git a/tools/qdoc3/qmlcodemarker.cpp b/tools/qdoc3/qmlcodemarker.cpp index 179598e..1134947 100644 --- a/tools/qdoc3/qmlcodemarker.cpp +++ b/tools/qdoc3/qmlcodemarker.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tools/qdoc3/qmlcodeparser.cpp b/tools/qdoc3/qmlcodeparser.cpp index ae66d6e..c74b6cb 100644 --- a/tools/qdoc3/qmlcodeparser.cpp +++ b/tools/qdoc3/qmlcodeparser.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tools/qdoc3/qmlmarkupvisitor.cpp b/tools/qdoc3/qmlmarkupvisitor.cpp index f7cb606..78f51bf 100644 --- a/tools/qdoc3/qmlmarkupvisitor.cpp +++ b/tools/qdoc3/qmlmarkupvisitor.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tools/qdoc3/qmlmarkupvisitor.h b/tools/qdoc3/qmlmarkupvisitor.h index 0d9e0cf..5681b2d 100644 --- a/tools/qdoc3/qmlmarkupvisitor.h +++ b/tools/qdoc3/qmlmarkupvisitor.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tools/qdoc3/qmlvisitor.cpp b/tools/qdoc3/qmlvisitor.cpp index cdc4e84..a8886de 100644 --- a/tools/qdoc3/qmlvisitor.cpp +++ b/tools/qdoc3/qmlvisitor.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -67,20 +67,32 @@ QmlDocVisitor::~QmlDocVisitor() { } -QDeclarativeJS::AST::SourceLocation QmlDocVisitor::precedingComment(unsigned offset) const +QDeclarativeJS::AST::SourceLocation QmlDocVisitor::precedingComment(quint32 offset) const { - QDeclarativeJS::AST::SourceLocation currentLoc; + QListIterator<QDeclarativeJS::AST::SourceLocation> it(engine->comments()); + it.toBack(); - foreach (const QDeclarativeJS::AST::SourceLocation &loc, engine->comments()) { - if (loc.begin() > lastEndOffset && loc.end() < offset) - currentLoc = loc; - else + while (it.hasPrevious()) { + + QDeclarativeJS::AST::SourceLocation loc = it.previous(); + + if (loc.begin() <= lastEndOffset) + // Return if we reach the end of the preceding structure. break; - } - if (currentLoc.isValid()) { - QString comment = document.mid(currentLoc.offset, currentLoc.length); - if (comment.startsWith("!") || comment.startsWith("*")) - return currentLoc; + + else if (usedComments.contains(loc.begin())) + // Return if we encounter a previously used comment. + break; + + else if (loc.begin() > lastEndOffset && loc.end() < offset) { + + // Only examine multiline comments in order to avoid snippet markers. + if (document.mid(loc.offset - 1, 1) == "*") { + QString comment = document.mid(loc.offset, loc.length); + if (comment.startsWith("!") || comment.startsWith("*")) + return loc; + } + } } return QDeclarativeJS::AST::SourceLocation(); @@ -93,20 +105,18 @@ void QmlDocVisitor::applyDocumentation(QDeclarativeJS::AST::SourceLocation locat if (loc.isValid()) { QString source = document.mid(loc.offset, loc.length); - if (source.startsWith(QLatin1String("!")) || - (source.startsWith(QLatin1String("*")) && - source[1] != QLatin1Char('*'))) { - - Location start(filePath); - start.setLineNo(loc.startLine); - start.setColumnNo(loc.startColumn); - Location finish(filePath); - finish.setLineNo(loc.startLine); - finish.setColumnNo(loc.startColumn); - - Doc doc(start, finish, source.mid(1), commands); - node->setDoc(doc); - } + + Location start(filePath); + start.setLineNo(loc.startLine); + start.setColumnNo(loc.startColumn); + Location finish(filePath); + finish.setLineNo(loc.startLine); + finish.setColumnNo(loc.startColumn); + + Doc doc(start, finish, source.mid(1), commands); + node->setDoc(doc); + + usedComments.insert(loc.offset); } } @@ -152,6 +162,11 @@ bool QmlDocVisitor::visit(QDeclarativeJS::AST::UiImportList *imports) return true; } +void QmlDocVisitor::endVisit(QDeclarativeJS::AST::UiImportList *definition) +{ + lastEndOffset = definition->lastSourceLocation().end(); +} + /*! Visits public member declarations, such as signals and properties. These only include custom signals and properties. @@ -195,7 +210,7 @@ bool QmlDocVisitor::visit(QDeclarativeJS::AST::UiPublicMember *member) qmlPropGroup->setDefault(); QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup, name, type, false); qmlPropNode->setWritable(!member->isReadonlyMember); - applyDocumentation(member->firstSourceLocation(), qmlPropNode); + applyDocumentation(member->firstSourceLocation(), qmlPropGroup); } } break; @@ -204,7 +219,6 @@ bool QmlDocVisitor::visit(QDeclarativeJS::AST::UiPublicMember *member) return false; } - //current->doc = precedingComment(member->firstSourceLocation().begin()); return true; } diff --git a/tools/qdoc3/qmlvisitor.h b/tools/qdoc3/qmlvisitor.h index 34ed8c1..28821a9 100644 --- a/tools/qdoc3/qmlvisitor.h +++ b/tools/qdoc3/qmlvisitor.h @@ -57,6 +57,7 @@ public: virtual ~QmlDocVisitor(); bool visit(QDeclarativeJS::AST::UiImportList *imports); + void endVisit(QDeclarativeJS::AST::UiImportList *definition); bool visit(QDeclarativeJS::AST::UiObjectDefinition *definition); void endVisit(QDeclarativeJS::AST::UiObjectDefinition *definition); @@ -67,7 +68,7 @@ public: bool visit(QDeclarativeJS::AST::IdentifierPropertyName *idproperty); private: - QDeclarativeJS::AST::SourceLocation precedingComment(unsigned offset) const; + QDeclarativeJS::AST::SourceLocation precedingComment(quint32 offset) const; void applyDocumentation(QDeclarativeJS::AST::SourceLocation location, Node *node); QDeclarativeJS::Engine *engine; @@ -77,6 +78,7 @@ private: QString document; QList<QPair<QString, QString> > importList; QSet<QString> commands; + QSet<quint32> usedComments; Tree *tree; InnerNode *current; }; diff --git a/tools/qdoc3/test/assistant.qdocconf b/tools/qdoc3/test/assistant.qdocconf index 4141a03..bb98db4 100644 --- a/tools/qdoc3/test/assistant.qdocconf +++ b/tools/qdoc3/test/assistant.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = Qt Assistant description = Qt Assistant Manual -url = http://doc.qt.nokia.com/4.7/ +url = http://doc.qt.nokia.com/4.8/ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Assistant qhp.Assistant.file = assistant.qhp -qhp.Assistant.namespace = com.trolltech.assistant.474 +qhp.Assistant.namespace = com.trolltech.assistant.480 qhp.Assistant.virtualFolder = qdoc qhp.Assistant.indexTitle = Qt Assistant Manual qhp.Assistant.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.Assistant.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Assistant.filterAttributes = qt 4.7.4 tools assistant +qhp.Assistant.filterAttributes = qt 4.8.0 tools assistant qhp.Assistant.customFilters.Assistant.name = Qt Assistant Manual qhp.Assistant.customFilters.Assistant.filterAttributes = qt tools assistant qhp.Assistant.subprojects = manual examples diff --git a/tools/qdoc3/test/carbide-eclipse-integration.qdocconf b/tools/qdoc3/test/carbide-eclipse-integration.qdocconf index 4d43403..ff50ce6 100644 --- a/tools/qdoc3/test/carbide-eclipse-integration.qdocconf +++ b/tools/qdoc3/test/carbide-eclipse-integration.qdocconf @@ -6,7 +6,7 @@ macro.TheEclipseIntegration = Carbide.c++ HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ - "<td width=\"30%\" align=\"left\">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ + "<td width=\"30%\" align=\"left\">Copyright © 2011 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ "<td width=\"40%\" align=\"center\"><a href=\"http://qt.nokia.com/doc\">Trademarks</a></td>\n" \ "<td width=\"30%\" align=\"right\"><div align=\"right\">Carbide.c++</div></td>\n" \ "</tr></table></div></address>" diff --git a/tools/qdoc3/test/designer.qdocconf b/tools/qdoc3/test/designer.qdocconf index 6c98ddf..f59fdf0 100644 --- a/tools/qdoc3/test/designer.qdocconf +++ b/tools/qdoc3/test/designer.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = Qt Designer description = Qt Designer Manual -url = http://doc.qt.nokia.com/4.7/ +url = http://doc.qt.nokia.com/4.8/ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Designer qhp.Designer.file = designer.qhp -qhp.Designer.namespace = com.trolltech.designer.474 +qhp.Designer.namespace = com.trolltech.designer.480 qhp.Designer.virtualFolder = qdoc qhp.Designer.indexTitle = Qt Designer Manual qhp.Designer.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.Designer.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Designer.filterAttributes = qt 4.7.4 tools designer +qhp.Designer.filterAttributes = qt 4.8.0 tools designer qhp.Designer.customFilters.Designer.name = Qt Designer Manual qhp.Designer.customFilters.Designer.filterAttributes = qt tools designer qhp.Designer.subprojects = manual examples diff --git a/tools/qdoc3/test/jambi.qdocconf b/tools/qdoc3/test/jambi.qdocconf index aa87826..3f4b42d 100644 --- a/tools/qdoc3/test/jambi.qdocconf +++ b/tools/qdoc3/test/jambi.qdocconf @@ -42,7 +42,7 @@ HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0 HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ - "<td width=\"30%\" align=\"left\">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ + "<td width=\"30%\" align=\"left\">Copyright © 2011 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ "<td width=\"40%\" align=\"center\"><a href=\"trademarks.html\">Trademarks</a></td>\n" \ "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt Jambi \\version</div></td>\n" \ "</tr></table></div></address>" diff --git a/tools/qdoc3/test/linguist.qdocconf b/tools/qdoc3/test/linguist.qdocconf index c9d6751..7c4b938 100644 --- a/tools/qdoc3/test/linguist.qdocconf +++ b/tools/qdoc3/test/linguist.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = Qt Linguist description = Qt Linguist Manual -url = http://doc.qt.nokia.com/4.7/ +url = http://doc.qt.nokia.com/4.8/ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Linguist qhp.Linguist.file = linguist.qhp -qhp.Linguist.namespace = com.trolltech.linguist.474 +qhp.Linguist.namespace = com.trolltech.linguist.480 qhp.Linguist.virtualFolder = qdoc qhp.Linguist.indexTitle = Qt Linguist Manual qhp.Linguist.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.Linguist.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Linguist.filterAttributes = qt 4.7.4 tools linguist +qhp.Linguist.filterAttributes = qt 4.8.0 tools linguist qhp.Linguist.customFilters.Linguist.name = Qt Linguist Manual qhp.Linguist.customFilters.Linguist.filterAttributes = qt tools linguist qhp.Linguist.subprojects = manual examples diff --git a/tools/qdoc3/test/qdeclarative.qdocconf b/tools/qdoc3/test/qdeclarative.qdocconf index 8fe9034..2ae2fd6 100644 --- a/tools/qdoc3/test/qdeclarative.qdocconf +++ b/tools/qdoc3/test/qdeclarative.qdocconf @@ -6,7 +6,7 @@ include(qt-defines.qdocconf) project = Qml description = Qml Reference Documentation -url = http://qt.nokia.com/doc/4.7/ +url = http://qt.nokia.com/doc/4.8/ qmlonly = true edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ @@ -21,7 +21,7 @@ edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qml qhp.Qml.file = qml.qhp -qhp.Qml.namespace = com.trolltech.qml.474 +qhp.Qml.namespace = com.trolltech.qml.480 qhp.Qml.virtualFolder = qdoc qhp.Qml.indexTitle = Qml Reference @@ -29,9 +29,9 @@ qhp.Qml.indexTitle = Qml Reference # See also extraimages.HTML qhp.Qml.extraFiles = images/bg_l.png \ images/bg_l_blank.png \ - images/bg_ll_blank.png \ - images/bg_ul_blank.png \ - images/header_bg.png \ + images/bg_ll_blank.png \ + images/bg_ul_blank.png \ + images/header_bg.png \ images/bg_r.png \ images/box_bg.png \ images/breadcrumb.png \ @@ -61,9 +61,9 @@ qhp.Qml.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Qml.filterAttributes = qt 4.7.4 qtrefdoc -qhp.Qml.customFilters.Qt.name = Qt 4.7.4 -qhp.Qml.customFilters.Qt.filterAttributes = qt 4.7.4 +qhp.Qml.filterAttributes = qt 4.8.0 qtrefdoc +qhp.Qml.customFilters.Qt.name = Qt 4.8.0 +qhp.Qml.customFilters.Qt.filterAttributes = qt 4.8.0 qhp.Qml.subprojects = classes qhp.Qml.subprojects.classes.title = Elements qhp.Qml.subprojects.classes.indexTitle = Qml Elements diff --git a/tools/qdoc3/test/qmake.qdocconf b/tools/qdoc3/test/qmake.qdocconf index c5a0f40..56e7f96 100644 --- a/tools/qdoc3/test/qmake.qdocconf +++ b/tools/qdoc3/test/qmake.qdocconf @@ -6,14 +6,14 @@ include(qt-defines.qdocconf) project = QMake description = QMake Manual -url = http://qt.nokia.com/doc/4.7 +url = http://qt.nokia.com/doc/4.8 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = qmake qhp.qmake.file = qmake.qhp -qhp.qmake.namespace = com.trolltech.qmake.474 +qhp.qmake.namespace = com.trolltech.qmake.480 qhp.qmake.virtualFolder = qdoc qhp.qmake.indexTitle = QMake Manual qhp.qmake.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.qmake.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.qmake.filterAttributes = qt 4.7.4 tools qmake +qhp.qmake.filterAttributes = qt 4.8.0 tools qmake qhp.qmake.customFilters.qmake.name = qmake Manual qhp.qmake.customFilters.qmake.filterAttributes = qt tools qmake qhp.qmake.subprojects = manual diff --git a/tools/qdoc3/test/qt-build-docs_ja_JP.qdocconf b/tools/qdoc3/test/qt-build-docs_ja_JP.qdocconf index a14054c..06cc9a0 100644 --- a/tools/qdoc3/test/qt-build-docs_ja_JP.qdocconf +++ b/tools/qdoc3/test/qt-build-docs_ja_JP.qdocconf @@ -17,15 +17,15 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.474 +qhp.Qt.namespace = com.trolltech.qt.480 qhp.Qt.virtualFolder = qdoc qhp.Qt.title = Qt qhp.Qt.indexTitle = Qt qhp.Qt.selectors = fake:example -qhp.Qt.filterAttributes = qt 4.7.4 qtrefdoc ja_JP -qhp.Qt.customFilters.Qt.name = Qt 4.7.4 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.4 +qhp.Qt.filterAttributes = qt 4.8.0 qtrefdoc ja_JP +qhp.Qt.customFilters.Qt.name = Qt 4.8.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.8.0 # Files not referenced in any qdoc file (last four are needed by qtdemo) # See also extraimages.HTML diff --git a/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf b/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf index d4d43b8..1efda05 100644 --- a/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf +++ b/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf @@ -6,7 +6,7 @@ include(qt-defines.qdocconf) project = Qt description = Qt Reference Documentation -url = http://qt.nokia.com/doc/zh_CN/4.7 +url = http://qt.nokia.com/doc/zh_CN/4.8 sourceencoding = UTF-8 outputencoding = UTF-8 @@ -17,15 +17,15 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.474 +qhp.Qt.namespace = com.trolltech.qt.480 qhp.Qt.virtualFolder = qdoc qhp.Qt.title = 教程 qhp.Qt.indexTitle = 教程 qhp.Qt.selectors = fake:example -qhp.Qt.filterAttributes = qt 4.7.4 qtrefdoc zh_CN -qhp.Qt.customFilters.Qt.name = Qt 4.7.4 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.4 +qhp.Qt.filterAttributes = qt 4.8.0 qtrefdoc zh_CN +qhp.Qt.customFilters.Qt.name = Qt 4.8.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.8.0 # Files not referenced in any qdoc file (last four are needed by qtdemo) # See also extraimages.HTML diff --git a/tools/qdoc3/test/qt-cpp-ignore.qdocconf b/tools/qdoc3/test/qt-cpp-ignore.qdocconf index 044eef4..5b41ae3 100644 --- a/tools/qdoc3/test/qt-cpp-ignore.qdocconf +++ b/tools/qdoc3/test/qt-cpp-ignore.qdocconf @@ -73,7 +73,8 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ Q_DECLARATIVE_EXPORT \ Q_GADGET \ QWEBKIT_EXPORT \ - Q_INVOKABLE + Q_INVOKABLE \ + Q_DECL_CONSTEXPR Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_INTERFACE \ Q_DECLARE_METATYPE \ diff --git a/tools/qdoc3/test/qt-defines.qdocconf b/tools/qdoc3/test/qt-defines.qdocconf index 50a355f..aaf935a 100644 --- a/tools/qdoc3/test/qt-defines.qdocconf +++ b/tools/qdoc3/test/qt-defines.qdocconf @@ -10,7 +10,8 @@ defines = Q_QDOC \ Q_BYTE_ORDER \ QT_DEPRECATED \ Q_NO_USING_KEYWORD \ - __cplusplus + __cplusplus \ + Q_COMPILER_INITIALIZER_LISTS versionsym = QT_VERSION_STR diff --git a/tools/qdoc3/test/qt-html-default-styles.qdocconf b/tools/qdoc3/test/qt-html-default-styles.qdocconf index d37ef5d..0db36bc 100644 --- a/tools/qdoc3/test/qt-html-default-styles.qdocconf +++ b/tools/qdoc3/test/qt-html-default-styles.qdocconf @@ -8,8 +8,10 @@ HTML.stylesheets = style/offline.css HTML.scripts = -# Files not referenced in any qdoc file (last four needed by qtdemo) -# See also qhp.Qt.extraFiles +# Files not referenced in any qdoc file, many needed by style sheets. +# These also need to be listed in qhp.Qt.extraFiles with the correct +# directory prefixes. + extraimages.HTML = qt-logo.png \ arrow_down.png \ breadcrumb.png \ diff --git a/tools/qdoc3/test/qt-html-templates-online.qdocconf b/tools/qdoc3/test/qt-html-templates-online.qdocconf index 77ab3c5..3584b68 100644 --- a/tools/qdoc3/test/qt-html-templates-online.qdocconf +++ b/tools/qdoc3/test/qt-html-templates-online.qdocconf @@ -19,7 +19,7 @@ HTML.postheader = \ " </div>\n" \ " <div id=\"shortCut\">\n" \ " <ul>\n" \ - " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.7</a></span></li>\n" \ + " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.8</a></span></li>\n" \ " <li class=\"shortCut-topleft-active\"><a href=\"http://doc.qt.nokia.com\">ALL VERSIONS" \ " </a></li>\n" \ " </ul>\n" \ @@ -181,16 +181,4 @@ HTML.footer = \ " <div id=\"blurpage\">\n" \ " </div>\n" \ "\n" \ - " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n" \ - " <script type=\"text/javascript\">\n" \ - " var _gaq = _gaq || [];\n" \ - " _gaq.push(['_setAccount', 'UA-4457116-5']);\n" \ - " _gaq.push(['_trackPageview']);\n" \ - " (function() {\n" \ - " var ga = document.createElement('script'); " \ - "ga.type = 'text/javascript'; ga.async = true;\n" \ - " ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + " \ - "'.google-analytics.com/ga.js';\n" \ - " var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n" \ - " })();\n" \ - " </script>\n" + " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n" diff --git a/tools/qdoc3/test/qt-html-templates.qdocconf b/tools/qdoc3/test/qt-html-templates.qdocconf index 8a70f3b..4f0cb1f 100644 --- a/tools/qdoc3/test/qt-html-templates.qdocconf +++ b/tools/qdoc3/test/qt-html-templates.qdocconf @@ -55,256 +55,255 @@ qhp.Qt.extraFiles = index.html \ #QtWebKit Guide files qhp.Qt.extraFiles += webkit-guide/anim_accord.htm \ -webkit-guide/anim_demo-rotate.htm \ -webkit-guide/anim_demo-scale.htm \ -webkit-guide/anim_demo-skew.htm \ -webkit-guide/anim_gallery.htm \ -webkit-guide/anim_panel.htm \ -webkit-guide/anim_pulse.htm \ -webkit-guide/anim_skew.htm \ -webkit-guide/anim_slide1.htm \ -webkit-guide/anim_slide2.htm \ -webkit-guide/anim_slide3.htm \ -webkit-guide/anim_tabbedSkew.htm \ -webkit-guide/_copyright.txt \ -webkit-guide/css3_backgrounds.htm \ -webkit-guide/css3_border-img.htm \ -webkit-guide/css3_gradientBack.htm \ -webkit-guide/css3_gradientBackStop.htm \ -webkit-guide/css3_gradientButton.htm \ -webkit-guide/css3_grad-radial.htm \ -webkit-guide/css3_mask-grad.htm \ -webkit-guide/css3_mask-img.htm \ -webkit-guide/css3_multicol.htm \ -webkit-guide/css3_reflect.htm \ -webkit-guide/css3_scroll.htm \ -webkit-guide/css3_sel-nth.htm \ -webkit-guide/css3_shadow.htm \ -webkit-guide/css3_text-overflow.htm \ -webkit-guide/css3_text-shadow.htm \ -webkit-guide/css3_text-stroke.htm \ -webkit-guide/form_tapper.htm \ -webkit-guide/form_toggler.htm \ -webkit-guide/_image_assets.htm \ -webkit-guide/_index.html \ -webkit-guide/layout_link-fmt.htm \ -webkit-guide/layout_tbl-keyhole.htm \ -webkit-guide/mob_condjs.htm \ -webkit-guide/mob_layout.htm \ -webkit-guide/mob_mediaquery.htm \ -webkit-guide/storage.htm \ -webkit-guide/css/anim_accord.css \ -webkit-guide/css/anim_demo-rotate.css \ -webkit-guide/css/anim_demo-scale.css \ -webkit-guide/css/anim_demo-skew.css \ -webkit-guide/css/anim_gallery.css \ -webkit-guide/css/anim_panel.css \ -webkit-guide/css/anim_pulse.css \ -webkit-guide/css/anim_skew.css \ -webkit-guide/css/anim_slide.css \ -webkit-guide/css/anim_tabbedSkew.css \ -webkit-guide/css/css3_backgrounds.css \ -webkit-guide/css/css3_border-img.css \ -webkit-guide/css/css3_gradientBack.css \ -webkit-guide/css/css3_gradientBackStop.css \ -webkit-guide/css/css3_gradientButton.css \ -webkit-guide/css/css3_grad-radial.css \ -webkit-guide/css/css3_mask-grad.css \ -webkit-guide/css/css3_mask-img.css \ -webkit-guide/css/css3_multicol.css \ -webkit-guide/css/css3_reflect.css \ -webkit-guide/css/css3_scroll.css \ -webkit-guide/css/css3_sel-nth.css \ -webkit-guide/css/css3_shadowBlur.css \ -webkit-guide/css/css3_shadow.css \ -webkit-guide/css/css3_text-overflow.css \ -webkit-guide/css/css3_text-shadow.css \ -webkit-guide/css/css3_text-stroke.css \ -webkit-guide/css/form_tapper.css \ -webkit-guide/css/form_toggler.css \ -webkit-guide/css/layout_link-fmt.css \ -webkit-guide/css/layout_tbl-keyhole.css \ -webkit-guide/css/mob_condjs.css \ -webkit-guide/css/mobile.css \ -webkit-guide/css/mob_mediaquery.css \ -webkit-guide/css/mq_desktop.css \ -webkit-guide/css/mqlayout_desktop.css \ -webkit-guide/css/mqlayout_mobile.css \ -webkit-guide/css/mqlayout_touch.css \ -webkit-guide/css/mq_mobile.css \ -webkit-guide/css/mq_touch.css \ -webkit-guide/css/storage.css \ -webkit-guide/img/border-frame.png \ -webkit-guide/img/gal0.png \ -webkit-guide/img/gal1.png \ -webkit-guide/img/gal2.png \ -webkit-guide/img/gal3.png \ -webkit-guide/img/gal4.png \ -webkit-guide/img/gal5.png \ -webkit-guide/img/gal6.png \ -webkit-guide/img/gal7.png \ -webkit-guide/img/gal8.png \ -webkit-guide/img/gradient.jpg \ -webkit-guide/img/gray_icon_close.png \ -webkit-guide/img/ic_ag_016.png \ -webkit-guide/img/ic_ag_032.png \ -webkit-guide/img/ic_ag_036.png \ -webkit-guide/img/ic_ag_048.png \ -webkit-guide/img/ic_al_016.png \ -webkit-guide/img/ic_al_032.png \ -webkit-guide/img/ic_al_036.png \ -webkit-guide/img/ic_al_048.png \ -webkit-guide/img/ic_ar_016.png \ -webkit-guide/img/ic_ar_032.png \ -webkit-guide/img/ic_ar_036.png \ -webkit-guide/img/ic_ar_048.png \ -webkit-guide/img/ic_b_016.png \ -webkit-guide/img/ic_b_032.png \ -webkit-guide/img/ic_b_036.png \ -webkit-guide/img/ic_b_048.png \ -webkit-guide/img/ic_be_016.png \ -webkit-guide/img/ic_be_032.png \ -webkit-guide/img/ic_be_036.png \ -webkit-guide/img/ic_be_048.png \ -webkit-guide/img/ic_c_016.png \ -webkit-guide/img/ic_c_032.png \ -webkit-guide/img/ic_c_036.png \ -webkit-guide/img/ic_c_048.png \ -webkit-guide/img/ic_ca_016.png \ -webkit-guide/img/ic_ca_032.png \ -webkit-guide/img/ic_ca_036.png \ -webkit-guide/img/ic_ca_048.png \ -webkit-guide/img/ic_cl_016.png \ -webkit-guide/img/ic_cl_032.png \ -webkit-guide/img/ic_cl_036.png \ -webkit-guide/img/ic_cl_048.png \ -webkit-guide/img/ic_cu_016.png \ -webkit-guide/img/ic_cu_032.png \ -webkit-guide/img/ic_cu_036.png \ -webkit-guide/img/ic_cu_048.png \ -webkit-guide/img/ic_f_016.png \ -webkit-guide/img/ic_f_032.png \ -webkit-guide/img/ic_f_036.png \ -webkit-guide/img/ic_f_048.png \ -webkit-guide/img/ic_fe_016.png \ -webkit-guide/img/ic_fe_032.png \ -webkit-guide/img/ic_fe_036.png \ -webkit-guide/img/ic_fe_048.png \ -webkit-guide/img/ic_h_016.png \ -webkit-guide/img/ic_h_032.png \ -webkit-guide/img/ic_h_036.png \ -webkit-guide/img/ic_h_048.png \ -webkit-guide/img/ic_he_016.png \ -webkit-guide/img/ic_he_032.png \ -webkit-guide/img/ic_he_036.png \ -webkit-guide/img/ic_he_048.png \ -webkit-guide/img/ic_k_016.png \ -webkit-guide/img/ic_k_032.png \ -webkit-guide/img/ic_k_036.png \ -webkit-guide/img/ic_k_048.png \ -webkit-guide/img/ic_li_016.png \ -webkit-guide/img/ic_li_032.png \ -webkit-guide/img/ic_li_036.png \ -webkit-guide/img/ic_li_048.png \ -webkit-guide/img/ic_mg_016.png \ -webkit-guide/img/ic_mg_032.png \ -webkit-guide/img/ic_mg_036.png \ -webkit-guide/img/ic_mg_048.png \ -webkit-guide/img/ic_n_016.png \ -webkit-guide/img/ic_n_032.png \ -webkit-guide/img/ic_n_036.png \ -webkit-guide/img/ic_n_048.png \ -webkit-guide/img/ic_na_016.png \ -webkit-guide/img/ic_na_032.png \ -webkit-guide/img/ic_na_036.png \ -webkit-guide/img/ic_na_048.png \ -webkit-guide/img/ic_ne_016.png \ -webkit-guide/img/ic_ne_032.png \ -webkit-guide/img/ic_ne_036.png \ -webkit-guide/img/ic_ne_048.png \ -webkit-guide/img/ic_ni_016.png \ -webkit-guide/img/ic_ni_032.png \ -webkit-guide/img/ic_ni_036.png \ -webkit-guide/img/ic_ni_048.png \ -webkit-guide/img/ic_o_016.png \ -webkit-guide/img/ic_o_032.png \ -webkit-guide/img/ic_o_036.png \ -webkit-guide/img/ic_o_048.png \ -webkit-guide/img/icon_check.png \ -webkit-guide/img/icon_check_x24green.png \ -webkit-guide/img/icon_dismiss.png \ -webkit-guide/img/icon_dismiss_x22.png \ -webkit-guide/img/icon_drill-down.png \ -webkit-guide/img/icon_drill-down_x32.png \ -webkit-guide/img/icon_drill-up.png \ -webkit-guide/img/icon_drill-up_x32.png \ -webkit-guide/img/icon_expand-nav.png \ -webkit-guide/img/icon_head-collapsed.png \ -webkit-guide/img/icon_head-collapsed_x13.png \ -webkit-guide/img/icon_head-expanded.png \ -webkit-guide/img/icon_head-expanded_x13.png \ -webkit-guide/img/icon_info.png \ -webkit-guide/img/icon_info_x24.png \ -webkit-guide/img/icon_link-doc.png \ -webkit-guide/img/icon_link-email.png \ -webkit-guide/img/icon_link-external.png \ -webkit-guide/img/icon_link-pdf.png \ -webkit-guide/img/icon_link-ppt.png \ -webkit-guide/img/icon_link-rss.png \ -webkit-guide/img/icon_link-sms.png \ -webkit-guide/img/icon_link-tel.png \ -webkit-guide/img/icon_link-xls.png \ -webkit-guide/img/icon_list-all_circ.png \ -webkit-guide/img/icon_list-all.png \ -webkit-guide/img/icon_nav_end.png \ -webkit-guide/img/icon_nav-start.png \ -webkit-guide/img/icon_nav-top.png \ -webkit-guide/img/icon_nav-up.png \ -webkit-guide/img/icon_question.png \ -webkit-guide/img/icon_scroll-left.png \ -webkit-guide/img/icon_scroll-right.png \ -webkit-guide/img/icon_trash.png \ -webkit-guide/img/ic_pt_016.png \ -webkit-guide/img/ic_pt_032.png \ -webkit-guide/img/ic_pt_036.png \ -webkit-guide/img/ic_pt_048.png \ -webkit-guide/img/ic_si_016.png \ -webkit-guide/img/ic_si_032.png \ -webkit-guide/img/ic_si_036.png \ -webkit-guide/img/ic_si_048.png \ -webkit-guide/img/ic_zn_016.png \ -webkit-guide/img/ic_zn_032.png \ -webkit-guide/img/ic_zn_036.png \ -webkit-guide/img/ic_zn_048.png \ -webkit-guide/img/land1.png \ -webkit-guide/img/land2.png \ -webkit-guide/img/land3.png \ -webkit-guide/img/land4.png \ -webkit-guide/img/land5.png \ -webkit-guide/img/land6.png \ -webkit-guide/img/land7.png \ -webkit-guide/img/land8.png \ -webkit-guide/img/mask.png \ -webkit-guide/img/tnail_gal1.png \ -webkit-guide/img/tnail_gal2.png \ -webkit-guide/img/tnail_gal3.png \ -webkit-guide/img/tnail_gal4.png \ -webkit-guide/img/tnail_gal5.png \ -webkit-guide/img/tnail_gal6.png \ -webkit-guide/img/tnail_gal7.png \ -webkit-guide/img/tnail_gal8.png \ -webkit-guide/js/anim_accord.js \ -webkit-guide/js/anim_gallery.js \ -webkit-guide/js/anim_panel.js \ -webkit-guide/js/anim_skew.js \ -webkit-guide/js/css3_backgrounds.js \ -webkit-guide/js/css3_border-img.js \ -webkit-guide/js/css3_grad-radial.js \ -webkit-guide/js/css3_mask-grad.js \ -webkit-guide/js/css3_mask-img.js \ -webkit-guide/js/css3_text-overflow.js \ -webkit-guide/js/form_tapper.js \ -webkit-guide/js/mob_condjs.js \ -webkit-guide/js/mobile.js \ -webkit-guide/js/storage.js \ - + webkit-guide/anim_demo-rotate.htm \ + webkit-guide/anim_demo-scale.htm \ + webkit-guide/anim_demo-skew.htm \ + webkit-guide/anim_gallery.htm \ + webkit-guide/anim_panel.htm \ + webkit-guide/anim_pulse.htm \ + webkit-guide/anim_skew.htm \ + webkit-guide/anim_slide1.htm \ + webkit-guide/anim_slide2.htm \ + webkit-guide/anim_slide3.htm \ + webkit-guide/anim_tabbedSkew.htm \ + webkit-guide/_copyright.txt \ + webkit-guide/css3_backgrounds.htm \ + webkit-guide/css3_border-img.htm \ + webkit-guide/css3_gradientBack.htm \ + webkit-guide/css3_gradientBackStop.htm \ + webkit-guide/css3_gradientButton.htm \ + webkit-guide/css3_grad-radial.htm \ + webkit-guide/css3_mask-grad.htm \ + webkit-guide/css3_mask-img.htm \ + webkit-guide/css3_multicol.htm \ + webkit-guide/css3_reflect.htm \ + webkit-guide/css3_scroll.htm \ + webkit-guide/css3_sel-nth.htm \ + webkit-guide/css3_shadow.htm \ + webkit-guide/css3_text-overflow.htm \ + webkit-guide/css3_text-shadow.htm \ + webkit-guide/css3_text-stroke.htm \ + webkit-guide/form_tapper.htm \ + webkit-guide/form_toggler.htm \ + webkit-guide/_image_assets.htm \ + webkit-guide/_index.html \ + webkit-guide/layout_link-fmt.htm \ + webkit-guide/layout_tbl-keyhole.htm \ + webkit-guide/mob_condjs.htm \ + webkit-guide/mob_layout.htm \ + webkit-guide/mob_mediaquery.htm \ + webkit-guide/storage.htm \ + webkit-guide/css/anim_accord.css \ + webkit-guide/css/anim_demo-rotate.css \ + webkit-guide/css/anim_demo-scale.css \ + webkit-guide/css/anim_demo-skew.css \ + webkit-guide/css/anim_gallery.css \ + webkit-guide/css/anim_panel.css \ + webkit-guide/css/anim_pulse.css \ + webkit-guide/css/anim_skew.css \ + webkit-guide/css/anim_slide.css \ + webkit-guide/css/anim_tabbedSkew.css \ + webkit-guide/css/css3_backgrounds.css \ + webkit-guide/css/css3_border-img.css \ + webkit-guide/css/css3_gradientBack.css \ + webkit-guide/css/css3_gradientBackStop.css \ + webkit-guide/css/css3_gradientButton.css \ + webkit-guide/css/css3_grad-radial.css \ + webkit-guide/css/css3_mask-grad.css \ + webkit-guide/css/css3_mask-img.css \ + webkit-guide/css/css3_multicol.css \ + webkit-guide/css/css3_reflect.css \ + webkit-guide/css/css3_scroll.css \ + webkit-guide/css/css3_sel-nth.css \ + webkit-guide/css/css3_shadowBlur.css \ + webkit-guide/css/css3_shadow.css \ + webkit-guide/css/css3_text-overflow.css \ + webkit-guide/css/css3_text-shadow.css \ + webkit-guide/css/css3_text-stroke.css \ + webkit-guide/css/form_tapper.css \ + webkit-guide/css/form_toggler.css \ + webkit-guide/css/layout_link-fmt.css \ + webkit-guide/css/layout_tbl-keyhole.css \ + webkit-guide/css/mob_condjs.css \ + webkit-guide/css/mobile.css \ + webkit-guide/css/mob_mediaquery.css \ + webkit-guide/css/mq_desktop.css \ + webkit-guide/css/mqlayout_desktop.css \ + webkit-guide/css/mqlayout_mobile.css \ + webkit-guide/css/mqlayout_touch.css \ + webkit-guide/css/mq_mobile.css \ + webkit-guide/css/mq_touch.css \ + webkit-guide/css/storage.css \ + webkit-guide/img/border-frame.png \ + webkit-guide/img/gal0.png \ + webkit-guide/img/gal1.jpg \ + webkit-guide/img/gal2.jpg \ + webkit-guide/img/gal3.jpg \ + webkit-guide/img/gal4.jpg \ + webkit-guide/img/gal5.jpg \ + webkit-guide/img/gal6.jpg \ + webkit-guide/img/gal7.jpg \ + webkit-guide/img/gal8.jpg \ + webkit-guide/img/gradient.jpg \ + webkit-guide/img/gray_icon_close.png \ + webkit-guide/img/ic_ag_016.png \ + webkit-guide/img/ic_ag_032.png \ + webkit-guide/img/ic_ag_036.png \ + webkit-guide/img/ic_ag_048.png \ + webkit-guide/img/ic_al_016.png \ + webkit-guide/img/ic_al_032.png \ + webkit-guide/img/ic_al_036.png \ + webkit-guide/img/ic_al_048.png \ + webkit-guide/img/ic_ar_016.png \ + webkit-guide/img/ic_ar_032.png \ + webkit-guide/img/ic_ar_036.png \ + webkit-guide/img/ic_ar_048.png \ + webkit-guide/img/ic_b_016.png \ + webkit-guide/img/ic_b_032.png \ + webkit-guide/img/ic_b_036.png \ + webkit-guide/img/ic_b_048.png \ + webkit-guide/img/ic_be_016.png \ + webkit-guide/img/ic_be_032.png \ + webkit-guide/img/ic_be_036.png \ + webkit-guide/img/ic_be_048.png \ + webkit-guide/img/ic_c_016.png \ + webkit-guide/img/ic_c_032.png \ + webkit-guide/img/ic_c_036.png \ + webkit-guide/img/ic_c_048.png \ + webkit-guide/img/ic_ca_016.png \ + webkit-guide/img/ic_ca_032.png \ + webkit-guide/img/ic_ca_036.png \ + webkit-guide/img/ic_ca_048.png \ + webkit-guide/img/ic_cl_016.png \ + webkit-guide/img/ic_cl_032.png \ + webkit-guide/img/ic_cl_036.png \ + webkit-guide/img/ic_cl_048.png \ + webkit-guide/img/ic_cu_016.png \ + webkit-guide/img/ic_cu_032.png \ + webkit-guide/img/ic_cu_036.png \ + webkit-guide/img/ic_cu_048.png \ + webkit-guide/img/ic_f_016.png \ + webkit-guide/img/ic_f_032.png \ + webkit-guide/img/ic_f_036.png \ + webkit-guide/img/ic_f_048.png \ + webkit-guide/img/ic_fe_016.png \ + webkit-guide/img/ic_fe_032.png \ + webkit-guide/img/ic_fe_036.png \ + webkit-guide/img/ic_fe_048.png \ + webkit-guide/img/ic_h_016.png \ + webkit-guide/img/ic_h_032.png \ + webkit-guide/img/ic_h_036.png \ + webkit-guide/img/ic_h_048.png \ + webkit-guide/img/ic_he_016.png \ + webkit-guide/img/ic_he_032.png \ + webkit-guide/img/ic_he_036.png \ + webkit-guide/img/ic_he_048.png \ + webkit-guide/img/ic_k_016.png \ + webkit-guide/img/ic_k_032.png \ + webkit-guide/img/ic_k_036.png \ + webkit-guide/img/ic_k_048.png \ + webkit-guide/img/ic_li_016.png \ + webkit-guide/img/ic_li_032.png \ + webkit-guide/img/ic_li_036.png \ + webkit-guide/img/ic_li_048.png \ + webkit-guide/img/ic_mg_016.png \ + webkit-guide/img/ic_mg_032.png \ + webkit-guide/img/ic_mg_036.png \ + webkit-guide/img/ic_mg_048.png \ + webkit-guide/img/ic_n_016.png \ + webkit-guide/img/ic_n_032.png \ + webkit-guide/img/ic_n_036.png \ + webkit-guide/img/ic_n_048.png \ + webkit-guide/img/ic_na_016.png \ + webkit-guide/img/ic_na_032.png \ + webkit-guide/img/ic_na_036.png \ + webkit-guide/img/ic_na_048.png \ + webkit-guide/img/ic_ne_016.png \ + webkit-guide/img/ic_ne_032.png \ + webkit-guide/img/ic_ne_036.png \ + webkit-guide/img/ic_ne_048.png \ + webkit-guide/img/ic_ni_016.png \ + webkit-guide/img/ic_ni_032.png \ + webkit-guide/img/ic_ni_036.png \ + webkit-guide/img/ic_ni_048.png \ + webkit-guide/img/ic_o_016.png \ + webkit-guide/img/ic_o_032.png \ + webkit-guide/img/ic_o_036.png \ + webkit-guide/img/ic_o_048.png \ + webkit-guide/img/icon_check.png \ + webkit-guide/img/icon_check_x24green.png \ + webkit-guide/img/icon_dismiss.png \ + webkit-guide/img/icon_dismiss_x22.png \ + webkit-guide/img/icon_drill-down.png \ + webkit-guide/img/icon_drill-down_x32.png \ + webkit-guide/img/icon_drill-up.png \ + webkit-guide/img/icon_drill-up_x32.png \ + webkit-guide/img/icon_expand-nav.png \ + webkit-guide/img/icon_head-collapsed.png \ + webkit-guide/img/icon_head-collapsed_x13.png \ + webkit-guide/img/icon_head-expanded.png \ + webkit-guide/img/icon_head-expanded_x13.png \ + webkit-guide/img/icon_info.png \ + webkit-guide/img/icon_info_x24.png \ + webkit-guide/img/icon_link-doc.png \ + webkit-guide/img/icon_link-email.png \ + webkit-guide/img/icon_link-external.png \ + webkit-guide/img/icon_link-pdf.png \ + webkit-guide/img/icon_link-ppt.png \ + webkit-guide/img/icon_link-rss.png \ + webkit-guide/img/icon_link-sms.png \ + webkit-guide/img/icon_link-tel.png \ + webkit-guide/img/icon_link-xls.png \ + webkit-guide/img/icon_list-all_circ.png \ + webkit-guide/img/icon_list-all.png \ + webkit-guide/img/icon_nav_end.png \ + webkit-guide/img/icon_nav-start.png \ + webkit-guide/img/icon_nav-top.png \ + webkit-guide/img/icon_nav-up.png \ + webkit-guide/img/icon_question.png \ + webkit-guide/img/icon_scroll-left.png \ + webkit-guide/img/icon_scroll-right.png \ + webkit-guide/img/icon_trash.png \ + webkit-guide/img/ic_pt_016.png \ + webkit-guide/img/ic_pt_032.png \ + webkit-guide/img/ic_pt_036.png \ + webkit-guide/img/ic_pt_048.png \ + webkit-guide/img/ic_si_016.png \ + webkit-guide/img/ic_si_032.png \ + webkit-guide/img/ic_si_036.png \ + webkit-guide/img/ic_si_048.png \ + webkit-guide/img/ic_zn_016.png \ + webkit-guide/img/ic_zn_032.png \ + webkit-guide/img/ic_zn_036.png \ + webkit-guide/img/ic_zn_048.png \ + webkit-guide/img/land1.jpg \ + webkit-guide/img/land2.jpg \ + webkit-guide/img/land3.jpg \ + webkit-guide/img/land4.jpg \ + webkit-guide/img/land5.jpg \ + webkit-guide/img/land6.jpg \ + webkit-guide/img/land7.jpg \ + webkit-guide/img/land8.jpg \ + webkit-guide/img/mask.png \ + webkit-guide/img/tnail_gal1.png \ + webkit-guide/img/tnail_gal2.png \ + webkit-guide/img/tnail_gal3.png \ + webkit-guide/img/tnail_gal4.png \ + webkit-guide/img/tnail_gal5.png \ + webkit-guide/img/tnail_gal6.png \ + webkit-guide/img/tnail_gal7.png \ + webkit-guide/img/tnail_gal8.png \ + webkit-guide/js/anim_accord.js \ + webkit-guide/js/anim_gallery.js \ + webkit-guide/js/anim_panel.js \ + webkit-guide/js/anim_skew.js \ + webkit-guide/js/css3_backgrounds.js \ + webkit-guide/js/css3_border-img.js \ + webkit-guide/js/css3_grad-radial.js \ + webkit-guide/js/css3_mask-grad.js \ + webkit-guide/js/css3_mask-img.js \ + webkit-guide/js/css3_text-overflow.js \ + webkit-guide/js/form_tapper.js \ + webkit-guide/js/mob_condjs.js \ + webkit-guide/js/mobile.js \ + webkit-guide/js/storage.js diff --git a/tools/qdoc3/test/qt-html-templates_ja_JP-online.qdocconf b/tools/qdoc3/test/qt-html-templates_ja_JP-online.qdocconf index fa15d90..8dc17af 100644 --- a/tools/qdoc3/test/qt-html-templates_ja_JP-online.qdocconf +++ b/tools/qdoc3/test/qt-html-templates_ja_JP-online.qdocconf @@ -24,7 +24,7 @@ HTML.postheader = \ " </div>\n" \ " <div id=\"shortCut\">\n" \ " <ul>\n" \ - " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.7</a></span></li>\n" \ + " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.8</a></span></li>\n" \ " <li class=\"shortCut-topleft-active\"><a href=\"http://qt.nokia.com/doc/\">ALL VERSIONS" \ " </a></li>\n" \ " </ul>\n" \ @@ -149,7 +149,7 @@ HTML.footer = \ " </div> \n" \ " <div class=\"footer\">\n" \ " <p>\n" \ - " <acronym title=\"Copyright\">©</acronym> 2008-2010 Nokia Corporation and/or its\n" \ + " <acronym title=\"Copyright\">©</acronym> 2008-2011 Nokia Corporation and/or its\n" \ " subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation \n" \ " in Finland and/or other countries worldwide.</p>\n" \ " <p>\n" \ diff --git a/tools/qdoc3/test/qt-html-templates_ja_JP.qdocconf b/tools/qdoc3/test/qt-html-templates_ja_JP.qdocconf index 18ed5c1..74a4d14 100644 --- a/tools/qdoc3/test/qt-html-templates_ja_JP.qdocconf +++ b/tools/qdoc3/test/qt-html-templates_ja_JP.qdocconf @@ -36,7 +36,7 @@ HTML.footer = \ " </div> \n" \ " <div class=\"footer\">\n" \ " <p>\n" \ - " <acronym title=\"Copyright\">©</acronym> 2008-2010 Nokia Corporation and/or its\n" \ + " <acronym title=\"Copyright\">©</acronym> 2008-2011 Nokia Corporation and/or its\n" \ " subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation \n" \ " in Finland and/or other countries worldwide.</p>\n" \ " <p>\n" \ diff --git a/tools/qdoc3/test/qt-html-templates_zh_CN-online.qdocconf b/tools/qdoc3/test/qt-html-templates_zh_CN-online.qdocconf index 285ec27..e7e8220 100644 --- a/tools/qdoc3/test/qt-html-templates_zh_CN-online.qdocconf +++ b/tools/qdoc3/test/qt-html-templates_zh_CN-online.qdocconf @@ -24,7 +24,7 @@ HTML.postheader = \ " </div>\n" \ " <div id=\"shortCut\">\n" \ " <ul>\n" \ - " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.7</a></span></li>\n" \ + " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.8</a></span></li>\n" \ " <li class=\"shortCut-topleft-active\"><a href=\"http://qt.nokia.com/doc/\">ALL VERSIONS" \ " </a></li>\n" \ " </ul>\n" \ @@ -149,7 +149,7 @@ HTML.footer = \ " </div> \n" \ " <div class=\"footer\">\n" \ " <p>\n" \ - " <acronym title=\"Copyright\">©</acronym> 2008-2010 Nokia Corporation and/or its\n" \ + " <acronym title=\"Copyright\">©</acronym> 2008-2011 Nokia Corporation and/or its\n" \ " subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation \n" \ " in Finland and/or other countries worldwide.</p>\n" \ " <p>\n" \ diff --git a/tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf b/tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf index 7773aa6..b4c8f7b 100644 --- a/tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf +++ b/tools/qdoc3/test/qt-html-templates_zh_CN.qdocconf @@ -24,7 +24,7 @@ HTML.postheader = \ " </div>\n" \ " <div id=\"shortCut\">\n" \ " <ul>\n" \ - " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.7</a></span></li>\n" \ + " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">Qt 4.8</a></span></li>\n" \ " <li class=\"shortCut-topleft-active\"><a href=\"http://qt.nokia.com/doc/\">ALL VERSIONS" \ " </a></li>\n" \ " </ul>\n" \ @@ -149,7 +149,7 @@ HTML.footer = \ " </div> \n" \ " <div class=\"footer\">\n" \ " <p>\n" \ - " <acronym title=\"Copyright\">©</acronym> 2008-2010 Nokia Corporation and/or its\n" \ + " <acronym title=\"Copyright\">©</acronym> 2008-2011 Nokia Corporation and/or its\n" \ " subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation \n" \ " in Finland and/or other countries worldwide.</p>\n" \ " <p>\n" \ diff --git a/tools/qdoc3/test/qt-project.qdocconf b/tools/qdoc3/test/qt-project.qdocconf index 9c18608..57bf797 100644 --- a/tools/qdoc3/test/qt-project.qdocconf +++ b/tools/qdoc3/test/qt-project.qdocconf @@ -5,8 +5,8 @@ include(qt-defines.qdocconf) project = Qt description = Qt Reference Documentation -url = http://qt.nokia.com/doc/4.7 -version = 4.7.3 +url = http://qt.nokia.com/doc/4.8 +version = 4.8.0 sourceencoding = UTF-8 outputencoding = UTF-8 @@ -15,14 +15,14 @@ naturallanguage = en_US qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.474 +qhp.Qt.namespace = com.trolltech.qt.480 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = -qhp.Qt.filterAttributes = qt 4.7.4 qtrefdoc -qhp.Qt.customFilters.Qt.name = Qt 4.7.4 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.4 +qhp.Qt.filterAttributes = qt 4.8.0 qtrefdoc +qhp.Qt.customFilters.Qt.name = Qt 4.8.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.8.0 qhp.Qt.subprojects = classes overviews examples qhp.Qt.subprojects.classes.title = Classes qhp.Qt.subprojects.classes.indexTitle = Qt's Classes @@ -105,7 +105,7 @@ exampledirs = $QT_SOURCE_TREE/doc/src \ $QT_SOURCE_TREE/examples/tutorials \ $QT_SOURCE_TREE \ $QT_SOURCE_TREE/qmake/examples \ - $QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs + $QT_SOURCE_TREE/src/3rdparty/webkit/Source/WebKit/qt/docs imagedirs = $QT_SOURCE_TREE/doc/src/images \ $QT_SOURCE_TREE/examples \ $QT_SOURCE_TREE/doc/src/declarative/pics \ diff --git a/tools/qdoc3/test/standalone-eclipse-integration.qdocconf b/tools/qdoc3/test/standalone-eclipse-integration.qdocconf index 96c2c98..850a2db 100644 --- a/tools/qdoc3/test/standalone-eclipse-integration.qdocconf +++ b/tools/qdoc3/test/standalone-eclipse-integration.qdocconf @@ -5,7 +5,7 @@ macro.TheEclipseIntegration = The Qt Eclipse Integration HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ - "<td width=\"30%\" align=\"left\">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ + "<td width=\"30%\" align=\"left\">Copyright © 2011 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ "<td width=\"40%\" align=\"center\"><a href=\"http://qt.nokia.com/doc/trademarks.html\">Trademarks</a></td>\n" \ "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt Eclipse Integration 1.5.3</div></td>\n" \ "</tr></table></div></address>" diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index 63d6ea9..21d1db0 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -1544,8 +1544,72 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer, return true; } + /*! - */ + Returns true if the node \a n1 is less than node \a n2. + The comparison is performed by comparing properties of the nodes in order + of increasing complexity. +*/ +bool compareNodes(const Node *n1, const Node *n2) +{ + // Private nodes can occur in any order since they won't normally be + // written to the index. + if (n1->access() == Node::Private && n2->access() == Node::Private) + return true; + + if (n1->location().filePath() < n2->location().filePath()) + return true; + else if (n1->location().filePath() > n2->location().filePath()) + return false; + + if (n1->type() < n2->type()) + return true; + else if (n1->type() > n2->type()) + return false; + + if (n1->name() < n2->name()) + return true; + else if (n1->name() > n2->name()) + return false; + + if (n1->access() < n2->access()) + return true; + else if (n1->access() > n2->access()) + return false; + + if (n1->type() == Node::Function && n2->type() == Node::Function) { + const FunctionNode *f1 = static_cast<const FunctionNode *>(n1); + const FunctionNode *f2 = static_cast<const FunctionNode *>(n2); + + if (f1->isConst() < f2->isConst()) + return true; + else if (f1->isConst() > f2->isConst()) + return false; + + if (f1->signature() < f2->signature()) + return true; + else if (f1->signature() > f2->signature()) + return false; + } + + if (n1->type() == Node::Fake && n2->type() == Node::Fake) { + const FakeNode *f1 = static_cast<const FakeNode *>(n1); + const FakeNode *f2 = static_cast<const FakeNode *>(n2); + if (f1->fullTitle() < f2->fullTitle()) + return true; + else if (f1->fullTitle() > f2->fullTitle()) + return false; + } + + return false; +} + +/*! + Generate index sections for the child nodes of the given \a node + using the \a writer specified. If \a generateInternalNodes is true, + nodes marked as internal will be included in the index; otherwise, + they will be omitted. +*/ void Tree::generateIndexSections(QXmlStreamWriter &writer, const Node *node, bool generateInternalNodes) const @@ -1555,7 +1619,10 @@ void Tree::generateIndexSections(QXmlStreamWriter &writer, if (node->isInnerNode()) { const InnerNode *inner = static_cast<const InnerNode *>(node); - foreach (const Node *child, inner->childNodes()) { + NodeList cnodes = inner->childNodes(); + qSort(cnodes.begin(), cnodes.end(), compareNodes); + + foreach (const Node *child, cnodes) { /* Don't generate anything for a QML property group node. It is just a place holder for a collection of QML property diff --git a/tools/qml/loggerwidget.cpp b/tools/qml/loggerwidget.cpp index cfb5169..a82336b 100644 --- a/tools/qml/loggerwidget.cpp +++ b/tools/qml/loggerwidget.cpp @@ -139,10 +139,10 @@ QAction *LoggerWidget::showAction() void LoggerWidget::readSettings() { QSettings settings; - QString warningsPreferences = settings.value("warnings", "hide").toString(); - if (warningsPreferences == "show") { + QString warningsPreferences = settings.value(QLatin1String("warnings"), QLatin1String("hide")).toString(); + if (warningsPreferences == QLatin1String("show")) { m_visibility = ShowWarnings; - } else if (warningsPreferences == "hide") { + } else if (warningsPreferences == QLatin1String("hide")) { m_visibility = HideWarnings; } else { m_visibility = AutoShowWarnings; @@ -154,15 +154,15 @@ void LoggerWidget::saveSettings() if (m_visibilityOrigin != SettingsOrigin) return; - QString value = "autoShow"; + QString value = QLatin1String("autoShow"); if (defaultVisibility() == ShowWarnings) { - value = "show"; + value = QLatin1String("show"); } else if (defaultVisibility() == HideWarnings) { - value = "hide"; + value = QLatin1String("hide"); } QSettings settings; - settings.setValue("warnings", value); + settings.setValue(QLatin1String("warnings"), value); } void LoggerWidget::warningsPreferenceChanged(QAction *action) diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index fae696c..cf33c4e 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -50,8 +50,8 @@ #include <QDebug> #include <QMessageBox> #include <QAtomicInt> +#include <QLibraryInfo> #include "qdeclarativetester.h" -#include <private/qdeclarativedebughelper_p.h> QT_USE_NAMESPACE @@ -67,7 +67,7 @@ void exitApp(int i) // Debugging output is not visible by default on Windows - // therefore show modal dialog with errors instead. if (!warnings.isEmpty()) { - QMessageBox::warning(0, QApplication::tr("Qt QML Viewer"), warnings); + QMessageBox::warning(0, QApplication::translate("QDeclarativeViewer", "Qt QML Viewer"), warnings); } #endif exit(i); @@ -123,7 +123,7 @@ void myMessageOutput(QtMsgType type, const char *msg) static QDeclarativeViewer* globalViewer = 0; // The qml file that is shown if the user didn't specify a QML file -QString initialFile = "qrc:/startup/startup.qml"; +QString initialFile = QLatin1String("qrc:/startup/startup.qml"); void usage() { @@ -156,7 +156,9 @@ void usage() qWarning(" -P <directory> ........................... prepend to the plugin search path"); #if defined(Q_WS_MAC) qWarning(" -no-opengl ............................... don't use a QGLWidget for the viewport"); + qWarning(" -opengl .................................. use a QGLWidget for the viewport (default)"); #else + qWarning(" -no-opengl ............................... don't use a QGLWidget for the viewport (default)"); qWarning(" -opengl .................................. use a QGLWidget for the viewport"); #endif qWarning(" -script <path> ........................... set the script to use"); @@ -197,7 +199,7 @@ struct ViewerOptions fps(0.0), autorecord_from(0), autorecord_to(0), - dither("none"), + dither(QLatin1String("none")), runScript(false), devkeys(false), cache(0), @@ -334,57 +336,54 @@ static void parseCommandLineOptions(const QStringList &arguments) for (int i = 1; i < arguments.count(); ++i) { bool lastArg = (i == arguments.count() - 1); QString arg = arguments.at(i); - if (arg == "-frameless") { + if (arg == QLatin1String("-frameless")) { opts.frameless = true; - } else if (arg == "-maximized") { + } else if (arg == QLatin1String("-maximized")) { opts.maximized = true; - } else if (arg == "-fullscreen") { + } else if (arg == QLatin1String("-fullscreen")) { opts.fullScreen = true; - } else if (arg == "-stayontop") { + } else if (arg == QLatin1String("-stayontop")) { opts.stayOnTop = true; - } else if (arg == "-netcache") { + } else if (arg == QLatin1String("-netcache")) { if (lastArg) usage(); opts.cache = arguments.at(++i).toInt(); - } else if (arg == "-recordrate") { + } else if (arg == QLatin1String("-recordrate")) { if (lastArg) usage(); opts.fps = arguments.at(++i).toDouble(); - } else if (arg == "-recordfile") { + } else if (arg == QLatin1String("-recordfile")) { if (lastArg) usage(); opts.recordfile = arguments.at(++i); - } else if (arg == "-record") { + } else if (arg == QLatin1String("-record")) { if (lastArg) usage(); opts.recordargs << arguments.at(++i); - } else if (arg == "-recorddither") { + } else if (arg == QLatin1String("-recorddither")) { if (lastArg) usage(); opts.dither = arguments.at(++i); - } else if (arg == "-autorecord") { + } else if (arg == QLatin1String("-autorecord")) { if (lastArg) usage(); QString range = arguments.at(++i); - int dash = range.indexOf('-'); + int dash = range.indexOf(QLatin1Char('-')); if (dash > 0) opts.autorecord_from = range.left(dash).toInt(); opts.autorecord_to = range.mid(dash+1).toInt(); - } else if (arg == "-devicekeys") { + } else if (arg == QLatin1String("-devicekeys")) { opts.devkeys = true; - } else if (arg == "-dragthreshold") { + } else if (arg == QLatin1String("-dragthreshold")) { if (lastArg) usage(); qApp->setStartDragDistance(arguments.at(++i).toInt()); } else if (arg == QLatin1String("-v") || arg == QLatin1String("-version")) { qWarning("Qt QML Viewer version %s", QT_VERSION_STR); exitApp(0); - } else if (arg == "-translation") { + } else if (arg == QLatin1String("-translation")) { if (lastArg) usage(); opts.translationFile = arguments.at(++i); -#if defined(Q_WS_MAC) - } else if (arg == "-no-opengl") { + } else if (arg == QLatin1String("-no-opengl")) { opts.useGL = false; -#else - } else if (arg == "-opengl") { + } else if (arg == QLatin1String("-opengl")) { opts.useGL = true; -#endif - } else if (arg == "-qmlbrowser") { + } else if (arg == QLatin1String("-qmlbrowser")) { opts.useNativeFileBrowser = false; - } else if (arg == "-warnings") { + } else if (arg == QLatin1String("-warnings")) { if (lastArg) usage(); QString warningsStr = arguments.at(++i); if (warningsStr == QLatin1String("show")) { @@ -394,8 +393,8 @@ static void parseCommandLineOptions(const QStringList &arguments) } else { usage(); } - } else if (arg == "-I" || arg == "-L") { - if (arg == "-L") + } else if (arg == QLatin1String("-I") || arg == QLatin1String("-L")) { + if (arg == QLatin1String("-L")) qWarning("-L option provided for compatibility only, use -I instead"); if (lastArg) { QDeclarativeEngine tmpEngine; @@ -404,32 +403,32 @@ static void parseCommandLineOptions(const QStringList &arguments) exitApp(0); } opts.imports << arguments.at(++i); - } else if (arg == "-P") { + } else if (arg == QLatin1String("-P")) { if (lastArg) usage(); opts.plugins << arguments.at(++i); - } else if (arg == "-script") { + } else if (arg == QLatin1String("-script")) { if (lastArg) usage(); opts.script = arguments.at(++i); - } else if (arg == "-scriptopts") { + } else if (arg == QLatin1String("-scriptopts")) { if (lastArg) usage(); opts.scriptopts = arguments.at(++i); - } else if (arg == "-savescript") { + } else if (arg == QLatin1String("-savescript")) { if (lastArg) usage(); opts.script = arguments.at(++i); opts.runScript = false; - } else if (arg == "-playscript") { + } else if (arg == QLatin1String("-playscript")) { if (lastArg) usage(); opts.script = arguments.at(++i); opts.runScript = true; - } else if (arg == "-sizeviewtorootobject") { + } else if (arg == QLatin1String("-sizeviewtorootobject")) { opts.sizeToView = false; - } else if (arg == "-sizerootobjecttoview") { + } else if (arg == QLatin1String("-sizerootobjecttoview")) { opts.sizeToView = true; - } else if (arg == "-experimentalgestures") { + } else if (arg == QLatin1String("-experimentalgestures")) { opts.experimentalGestures = true; - } else if (!arg.startsWith('-')) { + } else if (!arg.startsWith(QLatin1Char('-'))) { fileNames.append(arg); - } else if (true || arg == "-help") { + } else if (true || arg == QLatin1String("-help")) { usage(); } } @@ -528,29 +527,39 @@ int main(int argc, char ** argv) //### default to using raster graphics backend for now bool gsSpecified = false; for (int i = 0; i < argc; ++i) { - QString arg = argv[i]; - if (arg == "-graphicssystem") { + QString arg = QString::fromAscii(argv[i]); + if (arg == QLatin1String("-graphicssystem")) { gsSpecified = true; break; } } if (!gsSpecified) - QApplication::setGraphicsSystem("raster"); + QApplication::setGraphicsSystem(QLatin1String("raster")); #endif - QDeclarativeDebugHelper::enableDebugging(); - Application app(argc, argv); - app.setApplicationName("QtQmlViewer"); - app.setOrganizationName("Nokia"); - app.setOrganizationDomain("nokia.com"); + app.setApplicationName(QLatin1String("QtQmlViewer")); + app.setOrganizationName(QLatin1String("Nokia")); + app.setOrganizationDomain(QLatin1String("nokia.com")); QDeclarativeViewer::registerTypes(); QDeclarativeTester::registerTypes(); parseCommandLineOptions(app.arguments()); + QTranslator translator; + QTranslator qtTranslator; + QString sysLocale = QLocale::system().name(); + if (translator.load(QLatin1String("qmlviewer_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + app.installTranslator(&translator); + if (qtTranslator.load(QLatin1String("qt_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + app.installTranslator(&qtTranslator); + } else { + app.removeTranslator(&translator); + } + } + QTranslator qmlTranslator; if (!opts.translationFile.isEmpty()) { if (qmlTranslator.load(opts.translationFile)) { diff --git a/tools/qml/proxysettings.cpp b/tools/qml/proxysettings.cpp index f30f526..8bc778d 100644 --- a/tools/qml/proxysettings.cpp +++ b/tools/qml/proxysettings.cpp @@ -54,17 +54,17 @@ ProxySettings::ProxySettings (QWidget * parent) #if !defined Q_WS_MAEMO_5 // the onscreen keyboard can't cope with masks - proxyServerEdit->setInputMask ("000.000.000.000;_"); + proxyServerEdit->setInputMask(QLatin1String("000.000.000.000;_")); #endif QIntValidator *validator = new QIntValidator (0, 9999, this); - proxyPortEdit->setValidator (validator); + proxyPortEdit->setValidator(validator); QSettings settings; - proxyCheckBox->setChecked (settings.value ("http_proxy/use", 0).toBool ()); - proxyServerEdit->insert (settings.value ("http_proxy/hostname", "").toString ()); - proxyPortEdit->insert (settings.value ("http_proxy/port", "80").toString ()); - usernameEdit->insert (settings.value ("http_proxy/username", "").toString ()); - passwordEdit->insert (settings.value ("http_proxy/password", "").toString ()); + proxyCheckBox->setChecked(settings.value(QLatin1String("http_proxy/use"), 0).toBool()); + proxyServerEdit->insert(settings.value(QLatin1String("http_proxy/hostname")).toString()); + proxyPortEdit->insert(settings.value(QLatin1String("http_proxy/port"), QLatin1String("80")).toString ()); + usernameEdit->insert(settings.value(QLatin1String("http_proxy/username")).toString ()); + passwordEdit->insert(settings.value(QLatin1String("http_proxy/password")).toString ()); } ProxySettings::~ProxySettings() @@ -75,11 +75,11 @@ void ProxySettings::accept () { QSettings settings; - settings.setValue ("http_proxy/use", proxyCheckBox->isChecked ()); - settings.setValue ("http_proxy/hostname", proxyServerEdit->text ()); - settings.setValue ("http_proxy/port", proxyPortEdit->text ()); - settings.setValue ("http_proxy/username", usernameEdit->text ()); - settings.setValue ("http_proxy/password", passwordEdit->text ()); + settings.setValue(QLatin1String("http_proxy/use"), proxyCheckBox->isChecked()); + settings.setValue(QLatin1String("http_proxy/hostname"), proxyServerEdit->text()); + settings.setValue(QLatin1String("http_proxy/port"), proxyPortEdit->text()); + settings.setValue(QLatin1String("http_proxy/username"), usernameEdit->text()); + settings.setValue(QLatin1String("http_proxy/password"), passwordEdit->text()); QDialog::accept (); } @@ -89,13 +89,13 @@ QNetworkProxy ProxySettings::httpProxy () QSettings settings; QNetworkProxy proxy; - bool proxyInUse = settings.value ("http_proxy/use", 0).toBool (); + bool proxyInUse = settings.value(QLatin1String("http_proxy/use"), 0).toBool(); if (proxyInUse) { proxy.setType (QNetworkProxy::HttpProxy); - proxy.setHostName (settings.value ("http_proxy/hostname", "").toString ());// "192.168.220.5" - proxy.setPort (settings.value ("http_proxy/port", 80).toInt ()); // 8080 - proxy.setUser (settings.value ("http_proxy/username", "").toString ()); - proxy.setPassword (settings.value ("http_proxy/password", "").toString ()); + proxy.setHostName (settings.value(QLatin1String("http_proxy/hostname")).toString());// "192.168.220.5" + proxy.setPort (settings.value(QLatin1String("http_proxy/port"), 80).toInt()); // 8080 + proxy.setUser (settings.value(QLatin1String("http_proxy/username")).toString()); + proxy.setPassword (settings.value(QLatin1String("http_proxy/password")).toString()); //QNetworkProxy::setApplicationProxy (proxy); } else { @@ -107,7 +107,7 @@ QNetworkProxy ProxySettings::httpProxy () bool ProxySettings::httpProxyInUse() { QSettings settings; - return settings.value ("http_proxy/use", 0).toBool (); + return settings.value(QLatin1String("http_proxy/use"), 0).toBool(); } QT_END_NAMESPACE diff --git a/tools/qml/proxysettings_maemo5.ui b/tools/qml/proxysettings_maemo5.ui index 83f0c2a..75875d8 100644 --- a/tools/qml/proxysettings_maemo5.ui +++ b/tools/qml/proxysettings_maemo5.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>449</width> - <height>164</height> + <width>447</width> + <height>162</height> </rect> </property> <property name="windowTitle"> @@ -88,7 +88,7 @@ <item row="1" column="1"> <widget class="QLineEdit" name="proxyPortEdit"> <property name="text"> - <string>8080</string> + <string notr="true">8080</string> </property> </widget> </item> diff --git a/tools/qml/qdeclarativetester.cpp b/tools/qml/qdeclarativetester.cpp index b367661..9700e40 100644 --- a/tools/qml/qdeclarativetester.cpp +++ b/tools/qml/qdeclarativetester.cpp @@ -205,7 +205,7 @@ void QDeclarativeTester::save() QString filename = m_script + QLatin1String(".qml"); QFileInfo filenameInfo(filename); QDir saveDir = filenameInfo.absoluteDir(); - saveDir.mkpath("."); + saveDir.mkpath(QLatin1String(".")); QFile file(filename); file.open(QIODevice::WriteOnly); @@ -224,8 +224,8 @@ void QDeclarativeTester::save() if (!fe.hash.isEmpty()) { ts << " hash: \"" << fe.hash.toHex() << "\"\n"; } else if (!fe.image.isNull()) { - QString filename = filenameInfo.baseName() + "." + QString::number(imgCount) + ".png"; - fe.image.save(m_script + "." + QString::number(imgCount) + ".png"); + QString filename = filenameInfo.baseName() + QLatin1String(".") + QString::number(imgCount) + QLatin1String(".png"); + fe.image.save(m_script + QLatin1String(".") + QString::number(imgCount) + QLatin1String(".png")); imgCount++; ts << " image: \"" << filename << "\"\n"; } @@ -375,7 +375,7 @@ void QDeclarativeTester::updateCurrentTime(int msec) imagefailure(); } if (goodImage != img) { - QString reject(frame->image().toLocalFile() + ".reject.png"); + QString reject(frame->image().toLocalFile() + QLatin1String(".reject.png")); qWarning() << "QDeclarativeTester(" << m_script << "): Image mismatch. Reject saved to:" << reject; img.save(reject); @@ -393,7 +393,7 @@ void QDeclarativeTester::updateCurrentTime(int msec) } } } - QString diff(frame->image().toLocalFile() + ".diff.png"); + QString diff(frame->image().toLocalFile() + QLatin1String(".diff.png")); diffimg.save(diff); qWarning().nospace() << " Diff (" << diffCount << " pixels differed) saved to: " << diff; } diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro index 84ebba8..3d1b84b 100644 --- a/tools/qml/qml.pro +++ b/tools/qml/qml.pro @@ -1,5 +1,5 @@ TEMPLATE = app -CONFIG += qt uic +CONFIG += qt uic declarative_debug DESTDIR = ../../bin include(qml.pri) @@ -10,6 +10,8 @@ INCLUDEPATH += ../../include/QtDeclarative INCLUDEPATH += ../../src/declarative/util INCLUDEPATH += ../../src/declarative/graphicsitems +DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII + target.path = $$[QT_INSTALL_BINS] INSTALLS += target diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index c8af32f..f9961bc 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -265,7 +265,7 @@ public: hz->setValidator(new QDoubleValidator(hz)); #endif for (int i=0; ffmpegprofiles[i].name; ++i) { - profile->addItem(ffmpegprofiles[i].name); + profile->addItem(QString::fromAscii(ffmpegprofiles[i].name)); } } @@ -273,9 +273,9 @@ public: { int i; for (i=0; ffmpegprofiles[i].args[0]; ++i) { - if (ffmpegprofiles[i].args == a) { + if (QString::fromAscii(ffmpegprofiles[i].args) == a) { profile->setCurrentIndex(i); - args->setText(QLatin1String(ffmpegprofiles[i].args)); + args->setText(QString::fromAscii(ffmpegprofiles[i].args)); return; } } @@ -465,14 +465,14 @@ private: } } QSettings settings; - settings.setValue("Cookies",data); + settings.setValue(QLatin1String("Cookies"), data); } void load() { QMutexLocker lock(&mutex); QSettings settings; - QByteArray data = settings.value("Cookies").toByteArray(); + QByteArray data = settings.value(QLatin1String("Cookies")).toByteArray(); setAllCookies(QNetworkCookie::parseCookies(data)); } @@ -490,7 +490,7 @@ public: if (proxyDirty) setupProxy(); QString protocolTag = query.protocolTag(); - if (httpProxyInUse && (protocolTag == "http" || protocolTag == "https")) { + if (httpProxyInUse && (protocolTag == QLatin1String("http") || protocolTag == QLatin1String("https"))) { QList<QNetworkProxy> ret; ret << httpProxy; return ret; @@ -597,7 +597,7 @@ QString QDeclarativeViewer::getVideoFileName() if (convertAvailable) types += tr("GIF Animation")+QLatin1String(" (*.gif)"); types += tr("Individual PNG frames")+QLatin1String(" (*.png)"); if (ffmpegAvailable) types += tr("All ffmpeg formats (*.*)"); - return QFileDialog::getSaveFileName(this, title, "", types.join(";; ")); + return QFileDialog::getSaveFileName(this, title, QString(), types.join(QLatin1String(";; "))); } QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags) @@ -725,18 +725,18 @@ void QDeclarativeViewer::createMenu() connect(reloadAction, SIGNAL(triggered()), this, SLOT(reload())); QAction *snapshotAction = new QAction(tr("&Take Snapshot"), this); - snapshotAction->setShortcut(QKeySequence("F3")); + snapshotAction->setShortcut(QKeySequence(tr("F3"))); connect(snapshotAction, SIGNAL(triggered()), this, SLOT(takeSnapShot())); recordAction = new QAction(tr("Start Recording &Video"), this); - recordAction->setShortcut(QKeySequence("F9")); + recordAction->setShortcut(QKeySequence(tr("F9"))); connect(recordAction, SIGNAL(triggered()), this, SLOT(toggleRecordingWithSelection())); QAction *recordOptions = new QAction(tr("Video &Options..."), this); connect(recordOptions, SIGNAL(triggered()), this, SLOT(chooseRecordingOptions())); QAction *slowAction = new QAction(tr("&Slow Down Animations"), this); - slowAction->setShortcut(QKeySequence("Ctrl+.")); + slowAction->setShortcut(QKeySequence(tr("Ctrl+."))); slowAction->setCheckable(true); connect(slowAction, SIGNAL(triggered(bool)), this, SLOT(setSlowMode(bool))); @@ -755,7 +755,7 @@ void QDeclarativeViewer::createMenu() connect(fullscreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen())); rotateAction = new QAction(tr("Rotate orientation"), this); - rotateAction->setShortcut(QKeySequence("Ctrl+T")); + rotateAction->setShortcut(QKeySequence(tr("Ctrl+T"))); connect(rotateAction, SIGNAL(triggered()), this, SLOT(rotateOrientation())); orientation = new QActionGroup(this); @@ -963,7 +963,7 @@ void QDeclarativeViewer::chooseRecordingOptions() // Profile - recdlg->setArguments(record_args.join(" ")); + recdlg->setArguments(record_args.join(QLatin1String(" "))); if (recdlg->exec()) { // File record_file = recdlg->file->text(); @@ -972,7 +972,7 @@ void QDeclarativeViewer::chooseRecordingOptions() // Rate record_rate = recdlg->videoRate(); // Profile - record_args = recdlg->arguments().split(" ",QString::SkipEmptyParts); + record_args = recdlg->arguments().split(QLatin1Char(' '),QString::SkipEmptyParts); } } @@ -983,8 +983,8 @@ void QDeclarativeViewer::toggleRecordingWithSelection() QString fileName = getVideoFileName(); if (fileName.isEmpty()) return; - if (!fileName.contains(QRegExp(".[^\\/]*$"))) - fileName += ".avi"; + if (!fileName.contains(QRegExp(QLatin1String(".[^\\/]*$")))) + fileName += QLatin1String(".avi"); setRecordFile(fileName); } } @@ -1026,7 +1026,7 @@ void QDeclarativeViewer::openFile() { QString cur = canvas->source().toLocalFile(); if (useQmlFileBrowser) { - open("qrc:/browser/Browser.qml"); + open(QLatin1String("qrc:/browser/Browser.qml")); } else { QString fileName = QFileDialog::getOpenFileName(this, tr("Open QML file"), cur, tr("QML Files (*.qml)")); if (!fileName.isEmpty()) { @@ -1072,7 +1072,7 @@ void QDeclarativeViewer::loadTranslationFile(const QString& directory) void QDeclarativeViewer::loadDummyDataFiles(const QString& directory) { - QDir dir(directory+"/dummydata", "*.qml"); + QDir dir(directory + QLatin1String("/dummydata"), QLatin1String("*.qml")); QStringList list = dir.entryList(); for (int i = 0; i < list.size(); ++i) { QString qml = list.at(i); @@ -1114,14 +1114,14 @@ bool QDeclarativeViewer::open(const QString& file_or_url) delete canvas->rootObject(); canvas->engine()->clearComponentCache(); QDeclarativeContext *ctxt = canvas->rootContext(); - ctxt->setContextProperty("qmlViewer", this); + ctxt->setContextProperty(QLatin1String("qmlViewer"), this); #ifdef Q_OS_SYMBIAN - ctxt->setContextProperty("qmlViewerFolder", "E:\\"); // Documents on your S60 phone + ctxt->setContextProperty(QLatin1String("qmlViewerFolder"), QLatin1String("E:\\")); // Documents on your S60 phone #else - ctxt->setContextProperty("qmlViewerFolder", QDir::currentPath()); + ctxt->setContextProperty(QLatin1String("qmlViewerFolder"), QDir::currentPath()); #endif - ctxt->setContextProperty("runtime", Runtime::instance()); + ctxt->setContextProperty(QLatin1String("runtime"), Runtime::instance()); QString fileName = url.toLocalFile(); if (!fileName.isEmpty()) { @@ -1224,26 +1224,26 @@ bool QDeclarativeViewer::event(QEvent *event) void QDeclarativeViewer::senseImageMagick() { QProcess proc; - proc.start("convert", QStringList() << "-h"); + proc.start(QLatin1String("convert"), QStringList() << QLatin1String("-h")); proc.waitForFinished(2000); - QString help = proc.readAllStandardOutput(); - convertAvailable = help.contains("ImageMagick"); + QString help = QString::fromAscii(proc.readAllStandardOutput()); + convertAvailable = help.contains(QLatin1String("ImageMagick")); } void QDeclarativeViewer::senseFfmpeg() { QProcess proc; - proc.start("ffmpeg", QStringList() << "-h"); + proc.start(QLatin1String("ffmpeg"), QStringList() << QLatin1String("-h")); proc.waitForFinished(2000); - QString ffmpegHelp = proc.readAllStandardOutput(); - ffmpegAvailable = ffmpegHelp.contains("-s "); - ffmpegHelp = tr("Video recording uses ffmpeg:")+"\n\n"+ffmpegHelp; + QString ffmpegHelp = QString::fromAscii(proc.readAllStandardOutput()); + ffmpegAvailable = ffmpegHelp.contains(QLatin1String("-s ")); + ffmpegHelp = tr("Video recording uses ffmpeg:") + QLatin1String("\n\n") + ffmpegHelp; QDialog *d = new QDialog(recdlg); QVBoxLayout *l = new QVBoxLayout(d); QTextBrowser *b = new QTextBrowser(d); QFont f = b->font(); - f.setFamily("courier"); + f.setFamily(QLatin1String("courier")); b->setFont(f); b->setText(ffmpegHelp); l->addWidget(b); @@ -1266,7 +1266,7 @@ void QDeclarativeViewer::setRecording(bool on) recordTimer.start(); frame_fmt = record_file.right(4).toLower(); frame = QImage(canvas->width(),canvas->height(),QImage::Format_RGB32); - if (frame_fmt != ".png" && (!convertAvailable || frame_fmt != ".gif")) { + if (frame_fmt != QLatin1String(".png") && (!convertAvailable || frame_fmt != QLatin1String(".gif"))) { // Stream video to ffmpeg QProcess *proc = new QProcess(this); @@ -1274,19 +1274,19 @@ void QDeclarativeViewer::setRecording(bool on) frame_stream = proc; QStringList args; - args << "-y"; - args << "-r" << QString::number(record_rate); - args << "-f" << "rawvideo"; - args << "-pix_fmt" << (frame_fmt == ".gif" ? "rgb24" : "rgb32"); - args << "-s" << QString("%1x%2").arg(canvas->width()).arg(canvas->height()); - args << "-i" << "-"; + args << QLatin1String("-y"); + args << QLatin1String("-r") << QString::number(record_rate); + args << QLatin1String("-f") << QLatin1String("rawvideo"); + args << QLatin1String("-pix_fmt") << (frame_fmt == QLatin1String(".gif") ? QLatin1String("rgb24") : QLatin1String("rgb32")); + args << QLatin1String("-s") << QString::fromAscii("%1x%2").arg(canvas->width()).arg(canvas->height()); + args << QLatin1String("-i") << QLatin1String("-"); if (record_outsize.isValid()) { - args << "-s" << QString("%1x%2").arg(record_outsize.width()).arg(record_outsize.height()); - args << "-aspect" << QString::number(double(canvas->width())/canvas->height()); + args << QLatin1String("-s") << QString::fromAscii("%1x%2").arg(record_outsize.width()).arg(record_outsize.height()); + args << QLatin1String("-aspect") << QString::number(double(canvas->width())/canvas->height()); } args += record_args; args << record_file; - proc->start("ffmpeg",args); + proc->start(QLatin1String("ffmpeg"), args); } else { // Store frames, save to GIF/PNG @@ -1309,14 +1309,14 @@ void QDeclarativeViewer::setRecording(bool on) QString framename; bool png_output = false; - if (record_file.right(4).toLower()==".png") { - if (record_file.contains('%')) + if (record_file.right(4).toLower() == QLatin1String(".png")) { + if (record_file.contains(QLatin1Char('%'))) framename = record_file; else - framename = record_file.left(record_file.length()-4)+"%04d"+record_file.right(4); + framename = record_file.left(record_file.length()-4) + QLatin1String("%04d") + record_file.right(4); png_output = true; } else { - framename = "tmp-frame%04d.png"; + framename = QLatin1String("tmp-frame%04d.png"); png_output = false; } foreach (QImage* img, frames) { @@ -1327,11 +1327,11 @@ void QDeclarativeViewer::setRecording(bool on) name.sprintf(framename.toLocal8Bit(),frame++); if (record_outsize.isValid()) *img = img->scaled(record_outsize,Qt::IgnoreAspectRatio,Qt::SmoothTransformation); - if (record_dither=="ordered") + if (record_dither==QLatin1String("ordered")) img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::OrderedDither).save(name); - else if (record_dither=="threshold") + else if (record_dither==QLatin1String("threshold")) img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::ThresholdDither).save(name); - else if (record_dither=="floyd") + else if (record_dither==QLatin1String("floyd")) img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither).save(name); else img->save(name); @@ -1341,25 +1341,26 @@ void QDeclarativeViewer::setRecording(bool on) if (!progress.wasCanceled()) { if (png_output) { - framename.replace(QRegExp("%\\d*."),"*"); + framename.replace(QRegExp(QLatin1String("%\\d*.")), QLatin1String("*")); qDebug() << "Wrote frames" << framename; inputs.clear(); // don't remove them } else { // ImageMagick and gifsicle for GIF encoding progress.setLabelText(tr("Converting frames to GIF file...")); QStringList args; - args << "-delay" << QString::number(period/10); + args << QLatin1String("-delay") << QString::number(period/10); args << inputs; args << record_file; qDebug() << "Converting..." << record_file << "(this may take a while)"; - if (0!=QProcess::execute("convert", args)) { + if (0!=QProcess::execute(QLatin1String("convert"), args)) { qWarning() << "Cannot run ImageMagick 'convert' - recorded frames not converted"; inputs.clear(); // don't remove them qDebug() << "Wrote frames tmp-frame*.png"; } else { - if (record_file.right(4).toLower() == ".gif") { + if (record_file.right(4).toLower() == QLatin1String(".gif")) { qDebug() << "Compressing..." << record_file; - if (0!=QProcess::execute("gifsicle", QStringList() << "-O2" << "-o" << record_file << record_file)) + if (0!=QProcess::execute(QLatin1String("gifsicle"), QStringList() << QLatin1String("-O2") + << QLatin1String("-o") << record_file << record_file)) qWarning() << "Cannot run 'gifsicle' - not compressed"; } qDebug() << "Wrote" << record_file; @@ -1392,6 +1393,7 @@ void QDeclarativeViewer::appAboutToQuit() loggerWindow = 0; delete tester; tester = 0; + close(); } void QDeclarativeViewer::autoStartRecording() @@ -1410,7 +1412,7 @@ void QDeclarativeViewer::recordFrame() { canvas->QWidget::render(&frame); if (frame_stream) { - if (frame_fmt == ".gif") { + if (frame_fmt == QLatin1String(".gif")) { // ffmpeg can't do 32bpp with gif QImage rgb24 = frame.convertToFormat(QImage::Format_RGB888); frame_stream->write((char*)rgb24.bits(),rgb24.numBytes()); @@ -1541,8 +1543,8 @@ void QDeclarativeViewer::registerTypes() if (!registered) { // registering only for exposing the DeviceOrientation::Orientation enum - qmlRegisterUncreatableType<DeviceOrientation>("Qt",4,7,"Orientation",""); - qmlRegisterUncreatableType<DeviceOrientation>("QtQuick",1,0,"Orientation",""); + qmlRegisterUncreatableType<DeviceOrientation>("Qt", 4, 7, "Orientation", QString()); + qmlRegisterUncreatableType<DeviceOrientation>("QtQuick", 1, 0, "Orientation", QString()); registered = true; } } diff --git a/tools/qmlplugindump/Info.plist b/tools/qmlplugindump/Info.plist new file mode 100644 index 0000000..f35846d --- /dev/null +++ b/tools/qmlplugindump/Info.plist @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>@TYPEINFO@</string> + <key>CFBundleExecutable</key> + <string>@EXECUTABLE@</string> + <key>CFBundleIdentifier</key> + <string>com.nokia.qt.qmlplugindump</string> + <key>LSUIElement</key> + <string>1</string> +</dict> +</plist> diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp new file mode 100644 index 0000000..6bef8d4 --- /dev/null +++ b/tools/qmlplugindump/main.cpp @@ -0,0 +1,654 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtDeclarative/QtDeclarative> +#include <QtDeclarative/private/qdeclarativemetatype_p.h> +#include <QtDeclarative/private/qdeclarativeopenmetaobject_p.h> +#include <QtDeclarative/QDeclarativeView> + +#include <QtGui/QApplication> + +#include <QtCore/QSet> +#include <QtCore/QMetaObject> +#include <QtCore/QMetaProperty> +#include <QtCore/QDebug> +#include <QtCore/private/qobject_p.h> +#include <QtCore/private/qmetaobject_p.h> + +#include <iostream> + +#include "qmlstreamwriter.h" + +#ifdef QT_SIMULATOR +#include <QtGui/private/qsimulatorconnection_p.h> +#endif + +#ifdef Q_OS_UNIX +#include <signal.h> +#endif + +QString pluginImportPath; +bool verbose = false; + +QString currentProperty; +QString inObjectInstantiation; + +void collectReachableMetaObjects(const QMetaObject *meta, QSet<const QMetaObject *> *metas) +{ + if (! meta || metas->contains(meta)) + return; + + // dynamic meta objects break things badly, so just ignore them + const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate *>(meta->d.data); + if (!(mop->flags & DynamicMetaObject)) + metas->insert(meta); + + collectReachableMetaObjects(meta->superClass(), metas); +} + +void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *metas) +{ + if (! object) + return; + + const QMetaObject *meta = object->metaObject(); + if (verbose) + qDebug() << "Processing object" << meta->className(); + collectReachableMetaObjects(meta, metas); + + for (int index = 0; index < meta->propertyCount(); ++index) { + QMetaProperty prop = meta->property(index); + if (QDeclarativeMetaType::isQObject(prop.userType())) { + if (verbose) + qDebug() << " Processing property" << prop.name(); + currentProperty = QString("%1::%2").arg(meta->className(), prop.name()); + + // if the property was not initialized during construction, + // accessing a member of oo is going to cause a segmentation fault + QObject *oo = QDeclarativeMetaType::toQObject(prop.read(object)); + if (oo && !metas->contains(oo->metaObject())) + collectReachableMetaObjects(oo, metas); + currentProperty.clear(); + } + } +} + +void collectReachableMetaObjects(const QDeclarativeType *ty, QSet<const QMetaObject *> *metas) +{ + collectReachableMetaObjects(ty->metaObject(), metas); + if (ty->attachedPropertiesType()) + collectReachableMetaObjects(ty->attachedPropertiesType(), metas); +} + +/* We want to add the MetaObject for 'Qt' to the list, this is a + simple way to access it. +*/ +class FriendlyQObject: public QObject +{ +public: + static const QMetaObject *qtMeta() { return &staticQtMetaObject; } +}; + +/* When we dump a QMetaObject, we want to list all the types it is exported as. + To do this, we need to find the QDeclarativeTypes associated with this + QMetaObject. +*/ +static QHash<QByteArray, QSet<const QDeclarativeType *> > qmlTypesByCppName; + +static QHash<QByteArray, QByteArray> cppToId; + +/* Takes a C++ type name, such as Qt::LayoutDirection or QString and + maps it to how it should appear in the description file. + + These names need to be unique globally, so we don't change the C++ symbol's + name much. It is mostly used to for explicit translations such as + QString->string and translations for extended QML objects. +*/ +QByteArray convertToId(const QByteArray &cppName) +{ + return cppToId.value(cppName, cppName); +} + +QSet<const QMetaObject *> collectReachableMetaObjects(const QList<QDeclarativeType *> &skip = QList<QDeclarativeType *>()) +{ + QSet<const QMetaObject *> metas; + metas.insert(FriendlyQObject::qtMeta()); + + QHash<QByteArray, QSet<QByteArray> > extensions; + foreach (const QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) { + qmlTypesByCppName[ty->metaObject()->className()].insert(ty); + if (ty->isExtendedType()) { + extensions[ty->typeName()].insert(ty->metaObject()->className()); + } + collectReachableMetaObjects(ty, &metas); + } + + // Adjust exports of the base object if there are extensions. + // For each export of a base object there can be a single extension object overriding it. + // Example: QDeclarativeGraphicsWidget overrides the QtQuick/QGraphicsWidget export + // of QGraphicsWidget. + foreach (const QByteArray &baseCpp, extensions.keys()) { + QSet<const QDeclarativeType *> baseExports = qmlTypesByCppName.value(baseCpp); + + const QSet<QByteArray> extensionCppNames = extensions.value(baseCpp); + foreach (const QByteArray &extensionCppName, extensionCppNames) { + const QSet<const QDeclarativeType *> extensionExports = qmlTypesByCppName.value(extensionCppName); + + // remove extension exports from base imports + // unfortunately the QDeclarativeType pointers don't match, so can't use QSet::substract + QSet<const QDeclarativeType *> newBaseExports; + foreach (const QDeclarativeType *baseExport, baseExports) { + bool match = false; + foreach (const QDeclarativeType *extensionExport, extensionExports) { + if (baseExport->qmlTypeName() == extensionExport->qmlTypeName() + && baseExport->majorVersion() == extensionExport->majorVersion() + && baseExport->minorVersion() == extensionExport->minorVersion()) { + match = true; + break; + } + } + if (!match) + newBaseExports.insert(baseExport); + } + baseExports = newBaseExports; + } + qmlTypesByCppName[baseCpp] = baseExports; + } + + // find even more QMetaObjects by instantiating QML types and running + // over the instances + foreach (QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) { + if (skip.contains(ty)) + continue; + if (ty->isExtendedType()) + continue; + if (!ty->isCreatable()) + continue; + if (ty->typeName() == "QDeclarativeComponent") + continue; + + QByteArray tyName = ty->qmlTypeName(); + tyName = tyName.mid(tyName.lastIndexOf('/') + 1); + if (tyName.isEmpty()) + continue; + + inObjectInstantiation = tyName; + QObject *object = ty->create(); + inObjectInstantiation.clear(); + + if (object) + collectReachableMetaObjects(object, &metas); + else + qWarning() << "Could not create" << tyName; + } + + return metas; +} + + +class Dumper +{ + QmlStreamWriter *qml; + QString relocatableModuleUri; + +public: + Dumper(QmlStreamWriter *qml) : qml(qml) {} + + void setRelocatableModuleUri(const QString &uri) + { + relocatableModuleUri = uri; + } + + void dump(const QMetaObject *meta) + { + qml->writeStartObject("Component"); + + QByteArray id = convertToId(meta->className()); + qml->writeScriptBinding(QLatin1String("name"), enquote(id)); + + for (int index = meta->classInfoCount() - 1 ; index >= 0 ; --index) { + QMetaClassInfo classInfo = meta->classInfo(index); + if (QLatin1String(classInfo.name()) == QLatin1String("DefaultProperty")) { + qml->writeScriptBinding(QLatin1String("defaultProperty"), enquote(QLatin1String(classInfo.value()))); + break; + } + } + + if (meta->superClass()) + qml->writeScriptBinding(QLatin1String("prototype"), enquote(convertToId(meta->superClass()->className()))); + + QSet<const QDeclarativeType *> qmlTypes = qmlTypesByCppName.value(meta->className()); + if (!qmlTypes.isEmpty()) { + QStringList exports; + + foreach (const QDeclarativeType *qmlTy, qmlTypes) { + QString qmlTyName = qmlTy->qmlTypeName(); + // some qmltype names are missing the actual names, ignore that import + if (qmlTyName.endsWith('/')) + continue; + if (qmlTyName.startsWith(relocatableModuleUri + QLatin1Char('/'))) { + qmlTyName.remove(0, relocatableModuleUri.size() + 1); + } + if (qmlTyName.startsWith("./")) { + qmlTyName.remove(0, 2); + } + exports += enquote(QString("%1 %2.%3").arg( + qmlTyName, + QString::number(qmlTy->majorVersion()), + QString::number(qmlTy->minorVersion()))); + } + + // ensure exports are sorted and don't change order when the plugin is dumped again + exports.removeDuplicates(); + qSort(exports); + + qml->writeArrayBinding(QLatin1String("exports"), exports); + + if (const QMetaObject *attachedType = (*qmlTypes.begin())->attachedPropertiesType()) { + qml->writeScriptBinding(QLatin1String("attachedType"), enquote( + convertToId(attachedType->className()))); + } + } + + for (int index = meta->enumeratorOffset(); index < meta->enumeratorCount(); ++index) + dump(meta->enumerator(index)); + + for (int index = meta->propertyOffset(); index < meta->propertyCount(); ++index) + dump(meta->property(index)); + + for (int index = meta->methodOffset(); index < meta->methodCount(); ++index) + dump(meta->method(index)); + + qml->writeEndObject(); + } + + void writeEasingCurve() + { + qml->writeStartObject("Component"); + qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("QEasingCurve"))); + qml->writeScriptBinding(QLatin1String("prototype"), enquote(QLatin1String("QDeclarativeEasingValueType"))); + qml->writeEndObject(); + } + +private: + static QString enquote(const QString &string) + { + return QString("\"%1\"").arg(string); + } + + /* Removes pointer and list annotations from a type name, returning + what was removed in isList and isPointer + */ + static void removePointerAndList(QByteArray *typeName, bool *isList, bool *isPointer) + { + static QByteArray declListPrefix = "QDeclarativeListProperty<"; + + if (typeName->endsWith('*')) { + *isPointer = true; + typeName->truncate(typeName->length() - 1); + removePointerAndList(typeName, isList, isPointer); + } else if (typeName->startsWith(declListPrefix)) { + *isList = true; + typeName->truncate(typeName->length() - 1); // get rid of the suffix '>' + *typeName = typeName->mid(declListPrefix.size()); + removePointerAndList(typeName, isList, isPointer); + } + + *typeName = convertToId(*typeName); + } + + void writeTypeProperties(QByteArray typeName, bool isWritable) + { + bool isList = false, isPointer = false; + removePointerAndList(&typeName, &isList, &isPointer); + + qml->writeScriptBinding(QLatin1String("type"), enquote(typeName)); + if (isList) + qml->writeScriptBinding(QLatin1String("isList"), QLatin1String("true")); + if (!isWritable) + qml->writeScriptBinding(QLatin1String("isReadonly"), QLatin1String("true")); + if (isPointer) + qml->writeScriptBinding(QLatin1String("isPointer"), QLatin1String("true")); + } + + void dump(const QMetaProperty &prop) + { + qml->writeStartObject("Property"); + + qml->writeScriptBinding(QLatin1String("name"), enquote(QString::fromUtf8(prop.name()))); +#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 4)) + if (int revision = prop.revision()) + qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision)); +#endif + writeTypeProperties(prop.typeName(), prop.isWritable()); + + qml->writeEndObject(); + } + + void dump(const QMetaMethod &meth) + { + if (meth.methodType() == QMetaMethod::Signal) { + if (meth.access() != QMetaMethod::Protected) + return; // nothing to do. + } else if (meth.access() != QMetaMethod::Public) { + return; // nothing to do. + } + + QByteArray name = meth.signature(); + int lparenIndex = name.indexOf('('); + if (lparenIndex == -1) { + return; // invalid signature + } + name = name.left(lparenIndex); + + if (meth.methodType() == QMetaMethod::Signal) + qml->writeStartObject(QLatin1String("Signal")); + else + qml->writeStartObject(QLatin1String("Method")); + + qml->writeScriptBinding(QLatin1String("name"), enquote(name)); + +#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 4)) + if (int revision = meth.revision()) + qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision)); +#endif + + const QString typeName = convertToId(meth.typeName()); + if (! typeName.isEmpty()) + qml->writeScriptBinding(QLatin1String("type"), enquote(typeName)); + + for (int i = 0; i < meth.parameterTypes().size(); ++i) { + QByteArray argName = meth.parameterNames().at(i); + + qml->writeStartObject(QLatin1String("Parameter")); + if (! argName.isEmpty()) + qml->writeScriptBinding(QLatin1String("name"), enquote(argName)); + writeTypeProperties(meth.parameterTypes().at(i), true); + qml->writeEndObject(); + } + + qml->writeEndObject(); + } + + void dump(const QMetaEnum &e) + { + qml->writeStartObject(QLatin1String("Enum")); + qml->writeScriptBinding(QLatin1String("name"), enquote(QString::fromUtf8(e.name()))); + + QList<QPair<QString, QString> > namesValues; + for (int index = 0; index < e.keyCount(); ++index) { + namesValues.append(qMakePair(enquote(QString::fromUtf8(e.key(index))), QString::number(e.value(index)))); + } + + qml->writeScriptObjectLiteralBinding(QLatin1String("values"), namesValues); + qml->writeEndObject(); + } +}; + + +enum ExitCode { + EXIT_INVALIDARGUMENTS = 1, + EXIT_SEGV = 2, + EXIT_IMPORTERROR = 3 +}; + +#ifdef Q_OS_UNIX +void sigSegvHandler(int) { + fprintf(stderr, "Error: SEGV\n"); + if (!currentProperty.isEmpty()) + fprintf(stderr, "While processing the property '%s', which probably has uninitialized data.\n", currentProperty.toLatin1().constData()); + if (!inObjectInstantiation.isEmpty()) + fprintf(stderr, "While instantiating the object '%s'.\n", inObjectInstantiation.toLatin1().constData()); + exit(EXIT_SEGV); +} +#endif + +void printUsage(const QString &appName) +{ + qWarning() << qPrintable(QString( + "Usage: %1 [-v] [-notrelocatable] module.uri version [module/import/path]\n" + " %1 [-v] -path path/to/qmldir/directory [version]\n" + " %1 [-v] -builtins\n" + "Example: %1 Qt.labs.particles 4.7 /home/user/dev/qt-install/imports").arg( + appName)); +} + +int main(int argc, char *argv[]) +{ +#ifdef Q_OS_UNIX + // qmldump may crash, but we don't want any crash handlers to pop up + // therefore we intercept the segfault and just exit() ourselves + struct sigaction sigAction; + + sigemptyset(&sigAction.sa_mask); + sigAction.sa_handler = &sigSegvHandler; + sigAction.sa_flags = 0; + + sigaction(SIGSEGV, &sigAction, 0); +#endif + +#ifdef QT_SIMULATOR + // Running this application would bring up the Qt Simulator (since it links QtGui), avoid that! + QtSimulatorPrivate::SimulatorConnection::createStubInstance(); +#endif + QApplication app(argc, argv); + const QStringList args = app.arguments(); + const QString appName = QFileInfo(app.applicationFilePath()).baseName(); + if (args.size() < 2) { + printUsage(appName); + return EXIT_INVALIDARGUMENTS; + } + + QString pluginImportUri; + QString pluginImportVersion; + bool relocatable = true; + enum Action { Uri, Path, Builtins }; + Action action = Uri; + { + QStringList positionalArgs; + foreach (const QString &arg, args) { + if (!arg.startsWith(QLatin1Char('-'))) { + positionalArgs.append(arg); + continue; + } + + if (arg == QLatin1String("--notrelocatable") + || arg == QLatin1String("-notrelocatable")) { + relocatable = false; + } else if (arg == QLatin1String("--path") + || arg == QLatin1String("-path")) { + action = Path; + } else if (arg == QLatin1String("--builtins") + || arg == QLatin1String("-builtins")) { + action = Builtins; + } else if (arg == QLatin1String("-v")) { + verbose = true; + } else { + qWarning() << "Invalid argument: " << arg; + return EXIT_INVALIDARGUMENTS; + } + } + + if (action == Uri) { + if (positionalArgs.size() != 3 && positionalArgs.size() != 4) { + qWarning() << "Incorrect number of positional arguments"; + return EXIT_INVALIDARGUMENTS; + } + pluginImportUri = positionalArgs[1]; + pluginImportVersion = positionalArgs[2]; + if (positionalArgs.size() >= 4) + pluginImportPath = positionalArgs[3]; + } else if (action == Path) { + if (positionalArgs.size() != 2 && positionalArgs.size() != 3) { + qWarning() << "Incorrect number of positional arguments"; + return EXIT_INVALIDARGUMENTS; + } + pluginImportPath = QDir::fromNativeSeparators(positionalArgs[1]); + if (positionalArgs.size() == 3) + pluginImportVersion = positionalArgs[2]; + } else if (action == Builtins) { + if (positionalArgs.size() != 1) { + qWarning() << "Incorrect number of positional arguments"; + return EXIT_INVALIDARGUMENTS; + } + } + } + + QDeclarativeView view; + QDeclarativeEngine *engine = view.engine(); + if (!pluginImportPath.isEmpty()) { + QDir cur = QDir::current(); + cur.cd(pluginImportPath); + pluginImportPath = cur.absolutePath(); + QDir::setCurrent(pluginImportPath); + engine->addImportPath(pluginImportPath); + } + + // find all QMetaObjects reachable from the builtin module + QSet<const QMetaObject *> defaultReachable = collectReachableMetaObjects(); + QList<QDeclarativeType *> defaultTypes = QDeclarativeMetaType::qmlTypes(); + + // this will hold the meta objects we want to dump information of + QSet<const QMetaObject *> metas; + + if (action == Builtins) { + metas = defaultReachable; + } else { + // find a valid QtQuick import + QByteArray importCode; + QDeclarativeType *qtObjectType = QDeclarativeMetaType::qmlType(&QObject::staticMetaObject); + if (!qtObjectType) { + qWarning() << "Could not find QtObject type"; + importCode = QByteArray("import QtQuick 1.0\n"); + } else { + QByteArray module = qtObjectType->qmlTypeName(); + module = module.mid(0, module.lastIndexOf('/')); + importCode = QString("import %1 %2.%3\n").arg(module, + QString::number(qtObjectType->majorVersion()), + QString::number(qtObjectType->minorVersion())).toUtf8(); + } + + // find all QMetaObjects reachable when the specified module is imported + if (action != Path) { + importCode += QString("import %0 %1\n").arg(pluginImportUri, pluginImportVersion).toAscii(); + } else { + // pluginImportVersion can be empty + importCode += QString("import \".\" %2\n").arg(pluginImportVersion).toAscii(); + } + + // create a component with these imports to make sure the imports are valid + // and to populate the declarative meta type system + { + QByteArray code = importCode; + code += "QtObject {}"; + QDeclarativeComponent c(engine); + + c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/typelist.qml")); + c.create(); + if (!c.errors().isEmpty()) { + foreach (const QDeclarativeError &error, c.errors()) + qWarning() << error.toString(); + return EXIT_IMPORTERROR; + } + } + + QSet<const QMetaObject *> candidates = collectReachableMetaObjects(defaultTypes); + candidates.subtract(defaultReachable); + + // Also eliminate meta objects with the same classname. + // This is required because extended objects seem not to share + // a single meta object instance. + QSet<QByteArray> defaultReachableNames; + foreach (const QMetaObject *mo, defaultReachable) + defaultReachableNames.insert(QByteArray(mo->className())); + foreach (const QMetaObject *mo, candidates) { + if (!defaultReachableNames.contains(mo->className())) + metas.insert(mo); + } + } + + // setup static rewrites of type names + cppToId.insert("QString", "string"); + cppToId.insert("QDeclarativeEasingValueType::Type", "Type"); + + // start dumping data + QByteArray bytes; + QmlStreamWriter qml(&bytes); + + qml.writeStartDocument(); + qml.writeLibraryImport(QLatin1String("QtQuick.tooling"), 1, 1); + qml.write("\n" + "// This file describes the plugin-supplied types contained in the library.\n" + "// It is used for QML tooling purposes only.\n" + "\n"); + qml.writeStartObject("Module"); + + // put the metaobjects into a map so they are always dumped in the same order + QMap<QString, const QMetaObject *> nameToMeta; + foreach (const QMetaObject *meta, metas) + nameToMeta.insert(convertToId(meta->className()), meta); + + Dumper dumper(&qml); + if (relocatable) + dumper.setRelocatableModuleUri(pluginImportUri); + foreach (const QMetaObject *meta, nameToMeta) { + dumper.dump(meta); + } + + // define QEasingCurve as an extension of QDeclarativeEasingValueType, this way + // properties using the QEasingCurve type get useful type information. + if (pluginImportUri.isEmpty()) + dumper.writeEasingCurve(); + + qml.writeEndObject(); + qml.writeEndDocument(); + + std::cout << bytes.constData(); + + // workaround to avoid crashes on exit + QTimer timer; + timer.setSingleShot(true); + timer.setInterval(0); + QObject::connect(&timer, SIGNAL(timeout()), &app, SLOT(quit())); + timer.start(); + + return app.exec(); +} diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro new file mode 100644 index 0000000..e9fcdc7 --- /dev/null +++ b/tools/qmlplugindump/qmlplugindump.pro @@ -0,0 +1,37 @@ +TEMPLATE = app +CONFIG += qt uic console +DESTDIR = ../../bin + +QT += declarative + +TARGET = qmlplugindump + +SOURCES += \ + main.cpp \ + qmlstreamwriter.cpp + +HEADERS += \ + qmlstreamwriter.h + +OTHER_FILES += Info.plist +macx: QMAKE_INFO_PLIST = Info.plist + +# Build debug and release versions of the tool on Windows - +# if debug and release versions of Qt have been built. +!build_pass:win32 { + CONFIG -= debug release debug_and_release build_all + + contains(QT_CONFIG,debug):contains(QT_CONFIG,release) { + CONFIG += debug_and_release build_all + } else { + contains(QT_CONFIG,debug): CONFIG += debug + contains(QT_CONFIG,release): CONFIG += release + } +} + +CONFIG(debug, debug|release) { + win32: TARGET = $$join(TARGET,,,d) +} + +target.path = $$[QT_INSTALL_BINS] +INSTALLS += target diff --git a/tools/qmlplugindump/qmlstreamwriter.cpp b/tools/qmlplugindump/qmlstreamwriter.cpp new file mode 100644 index 0000000..ca52a7a --- /dev/null +++ b/tools/qmlplugindump/qmlstreamwriter.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlstreamwriter.h" + +#include <QtCore/QBuffer> +#include <QtCore/QStringList> + +QmlStreamWriter::QmlStreamWriter(QByteArray *array) + : m_indentDepth(0) + , m_pendingLineLength(0) + , m_maybeOneline(false) + , m_stream(new QBuffer(array)) +{ + m_stream->open(QIODevice::WriteOnly); +} + +void QmlStreamWriter::writeStartDocument() +{ +} + +void QmlStreamWriter::writeEndDocument() +{ +} + +void QmlStreamWriter::writeLibraryImport(const QString &uri, int majorVersion, int minorVersion, const QString &as) +{ + m_stream->write(QString("import %1 %2.%3").arg(uri, QString::number(majorVersion), QString::number(minorVersion)).toUtf8()); + if (!as.isEmpty()) + m_stream->write(QString(" as %1").arg(as).toUtf8()); + m_stream->write("\n"); +} + +void QmlStreamWriter::writeStartObject(const QString &component) +{ + flushPotentialLinesWithNewlines(); + writeIndent(); + m_stream->write(QString("%1 {").arg(component).toUtf8()); + ++m_indentDepth; + m_maybeOneline = true; +} + +void QmlStreamWriter::writeEndObject() +{ + if (m_maybeOneline && !m_pendingLines.isEmpty()) { + --m_indentDepth; + for (int i = 0; i < m_pendingLines.size(); ++i) { + m_stream->write(" "); + m_stream->write(m_pendingLines.at(i).trimmed()); + if (i != m_pendingLines.size() - 1) + m_stream->write(";"); + } + m_stream->write(" }\n"); + m_pendingLines.clear(); + m_pendingLineLength = 0; + m_maybeOneline = false; + } else { + if (m_maybeOneline) + flushPotentialLinesWithNewlines(); + --m_indentDepth; + writeIndent(); + m_stream->write("}\n"); + } +} + +void QmlStreamWriter::writeScriptBinding(const QString &name, const QString &rhs) +{ + writePotentialLine(QString("%1: %2").arg(name, rhs).toUtf8()); +} + +void QmlStreamWriter::writeArrayBinding(const QString &name, const QStringList &elements) +{ + flushPotentialLinesWithNewlines(); + writeIndent(); + m_stream->write(QString("%1: [\n").arg(name).toUtf8()); + ++m_indentDepth; + for (int i = 0; i < elements.size(); ++i) { + writeIndent(); + m_stream->write(elements.at(i).toUtf8()); + if (i != elements.size() - 1) { + m_stream->write(",\n"); + } else { + m_stream->write("\n"); + } + } + --m_indentDepth; + writeIndent(); + m_stream->write("]\n"); +} + +void QmlStreamWriter::write(const QString &data) +{ + flushPotentialLinesWithNewlines(); + m_stream->write(data.toUtf8()); +} + +void QmlStreamWriter::writeScriptObjectLiteralBinding(const QString &name, const QList<QPair<QString, QString> > &keyValue) +{ + flushPotentialLinesWithNewlines(); + writeIndent(); + m_stream->write(QString("%1: {\n").arg(name).toUtf8()); + ++m_indentDepth; + for (int i = 0; i < keyValue.size(); ++i) { + const QString key = keyValue.at(i).first; + const QString value = keyValue.at(i).second; + writeIndent(); + m_stream->write(QString("%1: %2").arg(key, value).toUtf8()); + if (i != keyValue.size() - 1) { + m_stream->write(",\n"); + } else { + m_stream->write("\n"); + } + } + --m_indentDepth; + writeIndent(); + m_stream->write("}\n"); +} + +void QmlStreamWriter::writeIndent() +{ + m_stream->write(QByteArray(m_indentDepth * 4, ' ')); +} + +void QmlStreamWriter::writePotentialLine(const QByteArray &line) +{ + m_pendingLines.append(line); + m_pendingLineLength += line.size(); + if (m_pendingLineLength >= 80) { + flushPotentialLinesWithNewlines(); + } +} + +void QmlStreamWriter::flushPotentialLinesWithNewlines() +{ + if (m_maybeOneline) + m_stream->write("\n"); + foreach (const QByteArray &line, m_pendingLines) { + writeIndent(); + m_stream->write(line); + m_stream->write("\n"); + } + m_pendingLines.clear(); + m_pendingLineLength = 0; + m_maybeOneline = false; +} diff --git a/tools/qmlplugindump/qmlstreamwriter.h b/tools/qmlplugindump/qmlstreamwriter.h new file mode 100644 index 0000000..691da3b --- /dev/null +++ b/tools/qmlplugindump/qmlstreamwriter.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLSTREAMWRITER_H +#define QMLSTREAMWRITER_H + +#include <QtCore/QIODevice> +#include <QtCore/QList> +#include <QtCore/QString> +#include <QtCore/QScopedPointer> +#include <QtCore/QPair> + +class QmlStreamWriter +{ +public: + QmlStreamWriter(QByteArray *array); + + void writeStartDocument(); + void writeEndDocument(); + void writeLibraryImport(const QString &uri, int majorVersion, int minorVersion, const QString &as = QString()); + //void writeFilesystemImport(const QString &file, const QString &as = QString()); + void writeStartObject(const QString &component); + void writeEndObject(); + void writeScriptBinding(const QString &name, const QString &rhs); + void writeScriptObjectLiteralBinding(const QString &name, const QList<QPair<QString, QString> > &keyValue); + void writeArrayBinding(const QString &name, const QStringList &elements); + void write(const QString &data); + +private: + void writeIndent(); + void writePotentialLine(const QByteArray &line); + void flushPotentialLinesWithNewlines(); + + int m_indentDepth; + QList<QByteArray> m_pendingLines; + int m_pendingLineLength; + bool m_maybeOneline; + QScopedPointer<QIODevice> m_stream; +}; + +#endif // QMLSTREAMWRITER_H diff --git a/tools/qtconcurrent/codegenerator/src/codegenerator.cpp b/tools/qtconcurrent/codegenerator/src/codegenerator.cpp index b8436b9..c81fe97 100644 --- a/tools/qtconcurrent/codegenerator/src/codegenerator.cpp +++ b/tools/qtconcurrent/codegenerator/src/codegenerator.cpp @@ -134,7 +134,7 @@ const Compound operator+(const Item &a, const char * const text) const Compound operator+(const char * const text, const Item &b) { - return Compound(Text(text), b); + return Compound(Text(text), b); } -}
\ No newline at end of file +} diff --git a/tools/qtconfig/colorbutton.cpp b/tools/qtconfig/colorbutton.cpp index abf4968..3ef287a 100644 --- a/tools/qtconfig/colorbutton.cpp +++ b/tools/qtconfig/colorbutton.cpp @@ -52,19 +52,20 @@ QT_BEGIN_NAMESPACE ColorButton::ColorButton(QWidget *parent) - : QAbstractButton(parent), mousepressed(false) + : QAbstractButton(parent) + , col(Qt::black) + , mousepressed(false) { setAcceptDrops(true); - col = Qt::black; connect(this, SIGNAL(clicked()), SLOT(changeColor())); } ColorButton::ColorButton(const QColor &c, QWidget *parent) : QAbstractButton(parent) + , col(c) { setAcceptDrops(true); - col = c; connect(this, SIGNAL(clicked()), SLOT(changeColor())); } @@ -182,7 +183,7 @@ void ColorButton::mouseReleaseEvent(QMouseEvent *e) void ColorButton::mouseMoveEvent(QMouseEvent *e) { - if (! mousepressed) + if (!mousepressed) return; if ((presspos - e->pos()).manhattanLength() > QApplication::startDragDistance()) { diff --git a/tools/qtconfig/main.cpp b/tools/qtconfig/main.cpp index c243893..64c7661 100644 --- a/tools/qtconfig/main.cpp +++ b/tools/qtconfig/main.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ -#include "ui_previewwidgetbase.h" #include "mainwindow.h" #include <QApplication> #include <QLibraryInfo> diff --git a/tools/qtconfig/mainwindow.cpp b/tools/qtconfig/mainwindow.cpp index 58cb342..a677a04 100644 --- a/tools/qtconfig/mainwindow.cpp +++ b/tools/qtconfig/mainwindow.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ #include "mainwindow.h" +#include "ui_mainwindow.h" + #include "colorbutton.h" #include "previewframe.h" #include "paletteeditoradvanced.h" @@ -59,10 +61,10 @@ #include <QMessageBox> #include <QStyle> #include <QtEvents> -#include <Q3ValueList> #include <QInputContext> #include <QInputContextFactory> #include <QtDebug> +#include <QPixmap> #include <stdlib.h> @@ -73,7 +75,9 @@ #include <phonon/phononnamespace.h> #endif +#ifdef Q_WS_X11 #include <QtGui/private/qt_x11_p.h> +#endif QT_BEGIN_NAMESPACE @@ -154,36 +158,20 @@ static const char *phonon_text = QT_TRANSLATE_NOOP("MainWindow", "<p>It is reccommended to leave all settings on \"Auto\" to let " "Phonon determine your settings automatically."); -static QColorGroup::ColorRole centralFromItem( int item ) -{ - switch( item ) { - case 0: return QColorGroup::Window; - case 1: return QColorGroup::WindowText; - case 2: return QColorGroup::Button; - case 3: return QColorGroup::Base; - case 4: return QColorGroup::Text; - case 5: return QColorGroup::BrightText; - case 6: return QColorGroup::ButtonText; - case 7: return QColorGroup::Highlight; - case 8: return QColorGroup::HighlightedText; - default: return QColorGroup::NColorRoles; - } -} - -static QColorGroup::ColorRole effectFromItem( int item ) +QPalette::ColorGroup MainWindow::groupFromIndex(int item) { - switch( item ) { - case 0: return QColorGroup::Light; - case 1: return QColorGroup::Midlight; - case 2: return QColorGroup::Mid; - case 3: return QColorGroup::Dark; - case 4: return QColorGroup::Shadow; - default: return QColorGroup::NColorRoles; + switch (item) { + case 0: + default: + return QPalette::Active; + case 1: + return QPalette::Inactive; + case 2: + return QPalette::Disabled; } } - static void setStyleHelper(QWidget *w, QStyle *s) { const QObjectList children = w->children(); @@ -195,99 +183,146 @@ static void setStyleHelper(QWidget *w, QStyle *s) w->setStyle(s); } - MainWindow::MainWindow() - : MainWindowBase(0, "main window"), - editPalette(palette()), previewPalette(palette()), previewstyle(0) -{ + : ui(new Ui::MainWindow), + editPalette(palette()), + previewPalette(palette()), + previewstyle(0) +{ + ui->setupUi(this); + statusBar(); + + // signals and slots connections + connect(ui->fontPathLineEdit, SIGNAL(returnPressed()), SLOT(addFontpath())); + connect(ui->addFontPathButton, SIGNAL(clicked()), SLOT(addFontpath())); + connect(ui->addSubstitutionButton, SIGNAL(clicked()), SLOT(addSubstitute())); + connect(ui->browseFontPathButton, SIGNAL(clicked()), SLOT(browseFontpath())); + connect(ui->fontStyleCombo, SIGNAL(activated(int)), SLOT(buildFont())); + connect(ui->pointSizeCombo, SIGNAL(activated(int)), SLOT(buildFont())); + connect(ui->downFontpathButton, SIGNAL(clicked()), SLOT(downFontpath())); + connect(ui->downSubstitutionButton, SIGNAL(clicked()), SLOT(downSubstitute())); + connect(ui->fontFamilyCombo, SIGNAL(activated(QString)), SLOT(familySelected(QString))); + connect(ui->fileExitAction, SIGNAL(triggered()), SLOT(fileExit())); + connect(ui->fileSaveAction, SIGNAL(triggered()), SLOT(fileSave())); + connect(ui->helpAboutAction, SIGNAL(triggered()), SLOT(helpAbout())); + connect(ui->helpAboutQtAction, SIGNAL(triggered()), SLOT(helpAboutQt())); + connect(ui->mainTabWidget, SIGNAL(currentChanged(int)), SLOT(pageChanged(int))); + connect(ui->paletteCombo, SIGNAL(activated(int)), SLOT(paletteSelected(int))); + connect(ui->removeFontpathButton, SIGNAL(clicked()), SLOT(removeFontpath())); + connect(ui->removeSubstitutionButton, SIGNAL(clicked()), SLOT(removeSubstitute())); + connect(ui->toolBoxEffectCombo, SIGNAL(activated(int)), SLOT(somethingModified())); + connect(ui->doubleClickIntervalSpinBox, SIGNAL(valueChanged(int)), SLOT(somethingModified())); + connect(ui->cursorFlashTimeSpinBox, SIGNAL(valueChanged(int)), SLOT(somethingModified())); + connect(ui->wheelScrollLinesSpinBox, SIGNAL(valueChanged(int)), SLOT(somethingModified())); + connect(ui->menuEffectCombo, SIGNAL(activated(int)), SLOT(somethingModified())); + connect(ui->comboEffectCombo, SIGNAL(activated(int)), SLOT(somethingModified())); + connect(ui->audiosinkCombo, SIGNAL(activated(int)), SLOT(somethingModified())); + connect(ui->videomodeCombo, SIGNAL(activated(int)), SLOT(somethingModified())); + connect(ui->toolTipEffectCombo, SIGNAL(activated(int)), SLOT(somethingModified())); + connect(ui->strutWidthSpinBox, SIGNAL(valueChanged(int)), SLOT(somethingModified())); + connect(ui->strutHeightSpinBox, SIGNAL(valueChanged(int)), SLOT(somethingModified())); + connect(ui->effectsCheckBox, SIGNAL(toggled(bool)), SLOT(somethingModified())); + connect(ui->resolveLinksCheckBox, SIGNAL(toggled(bool)), SLOT(somethingModified())); + connect(ui->fontEmbeddingCheckBox, SIGNAL(clicked()), SLOT(somethingModified())); + connect(ui->rtlExtensionsCheckBox, SIGNAL(toggled(bool)), SLOT(somethingModified())); + connect(ui->inputStyleCombo, SIGNAL(activated(int)), SLOT(somethingModified())); + connect(ui->inputMethodCombo, SIGNAL(activated(int)), SLOT(somethingModified())); + connect(ui->guiStyleCombo, SIGNAL(activated(QString)), SLOT(styleSelected(QString))); + connect(ui->familySubstitutionCombo, SIGNAL(activated(QString)), SLOT(substituteSelected(QString))); + connect(ui->tunePaletteButton, SIGNAL(clicked()), SLOT(tunePalette())); + connect(ui->upFontpathButton, SIGNAL(clicked()), SLOT(upFontpath())); + connect(ui->upSubstitutionButton, SIGNAL(clicked()), SLOT(upSubstitute())); + modified = true; desktopThemeName = tr("Desktop Settings (Default)"); + setWindowIcon(QPixmap(":/trolltech/qtconfig/images/appicon.png")); QStringList gstyles = QStyleFactory::keys(); gstyles.sort(); - gstylecombo->addItem(desktopThemeName); - gstylecombo->setItemData(gstylecombo->findText(desktopThemeName), - tr("Choose style and palette based on your desktop settings."), Qt::ToolTipRole); - gstylecombo->insertStringList(gstyles); + ui->guiStyleCombo->addItem(desktopThemeName); + ui->guiStyleCombo->setItemData(ui->guiStyleCombo->findText(desktopThemeName), + tr("Choose style and palette based on your desktop settings."), + Qt::ToolTipRole); + ui->guiStyleCombo->addItems(gstyles); QSettings settings(QLatin1String("Trolltech")); settings.beginGroup(QLatin1String("Qt")); QString currentstyle = settings.value(QLatin1String("style")).toString(); if (currentstyle.isEmpty()) { - gstylecombo->setCurrentItem(gstylecombo->findText(desktopThemeName)); - currentstyle = QLatin1String(QApplication::style()->name()); + ui->guiStyleCombo->setCurrentIndex(ui->guiStyleCombo->findText(desktopThemeName)); + currentstyle = QApplication::style()->objectName(); } else { - int index = gstylecombo->findText(currentstyle, Qt::MatchFixedString); + int index = ui->guiStyleCombo->findText(currentstyle, Qt::MatchFixedString); if (index != -1) { - gstylecombo->setCurrentItem(index); + ui->guiStyleCombo->setCurrentIndex(index); } else { // we give up - gstylecombo->insertItem(QLatin1String("Unknown")); - gstylecombo->setCurrentItem(gstylecombo->count() - 1); + ui->guiStyleCombo->addItem(tr("Unknown")); + ui->guiStyleCombo->setCurrentIndex(ui->guiStyleCombo->count() - 1); } } - buttonMainColor->setColor(palette().color(QPalette::Active, - QColorGroup::Button)); - buttonMainColor2->setColor(palette().color(QPalette::Active, - QColorGroup::Window)); - connect(buttonMainColor, SIGNAL(colorChanged(QColor)), - this, SLOT(buildPalette())); - connect(buttonMainColor2, SIGNAL(colorChanged(QColor)), - this, SLOT(buildPalette())); + ui->buttonMainColor->setColor(palette().color(QPalette::Active, QPalette::Button)); + ui->buttonWindowColor->setColor(palette().color(QPalette::Active, QPalette::Window)); + connect(ui->buttonMainColor, SIGNAL(colorChanged(QColor)), SLOT(buildPalette())); + connect(ui->buttonWindowColor, SIGNAL(colorChanged(QColor)), SLOT(buildPalette())); +#ifdef Q_WS_X11 if (X11->desktopEnvironment == DE_KDE) - colorConfig->hide(); + ui->colorConfig->hide(); else - labelKDENote->hide(); + ui->kdeNoteLabel->hide(); +#else + ui->colorConfig->hide(); + ui->kdeNoteLabel->hide(); +#endif QFontDatabase db; QStringList families = db.families(); - familycombo->insertStringList(families); + ui->fontFamilyCombo->addItems(families); QStringList fs = families; QStringList fs2 = QFont::substitutions(); QStringList::Iterator fsit = fs2.begin(); while (fsit != fs2.end()) { - if (! fs.contains(*fsit)) + if (!fs.contains(*fsit)) fs += *fsit; fsit++; } fs.sort(); - familysubcombo->insertStringList(fs); + ui->familySubstitutionCombo->addItems(fs); - choosesubcombo->insertStringList(families); - Q3ValueList<int> sizes = db.standardSizes(); - Q3ValueList<int>::Iterator it = sizes.begin(); - while (it != sizes.end()) - psizecombo->insertItem(QString::number(*it++)); + ui->chooseSubstitutionCombo->addItems(families); + QList<int> sizes = db.standardSizes(); + foreach(int i, sizes) + ui->pointSizeCombo->addItem(QString::number(i)); - dcispin->setValue(QApplication::doubleClickInterval()); - cfispin->setValue(QApplication::cursorFlashTime()); - wslspin->setValue(QApplication::wheelScrollLines()); + ui->doubleClickIntervalSpinBox->setValue(QApplication::doubleClickInterval()); + ui->cursorFlashTimeSpinBox->setValue(QApplication::cursorFlashTime()); + ui->wheelScrollLinesSpinBox->setValue(QApplication::wheelScrollLines()); // ############# -// resolvelinks->setChecked(qt_resolve_symlinks); + // resolveLinksCheckBox->setChecked(qt_resolve_symlinks); - effectcheckbox->setChecked(QApplication::isEffectEnabled(Qt::UI_General)); - effectbase->setEnabled(effectcheckbox->isChecked()); + ui->effectsCheckBox->setChecked(QApplication::isEffectEnabled(Qt::UI_General)); + ui->effectsFrame->setEnabled(ui->effectsCheckBox->isChecked()); if (QApplication::isEffectEnabled(Qt::UI_FadeMenu)) - menueffect->setCurrentItem(2); + ui->menuEffectCombo->setCurrentIndex(2); else if (QApplication::isEffectEnabled(Qt::UI_AnimateMenu)) - menueffect->setCurrentItem(1); + ui->menuEffectCombo->setCurrentIndex(1); if (QApplication::isEffectEnabled(Qt::UI_AnimateCombo)) - comboeffect->setCurrentItem(1); + ui->comboEffectCombo->setCurrentIndex(1); if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)) - tooltipeffect->setCurrentItem(2); + ui->toolTipEffectCombo->setCurrentIndex(2); else if (QApplication::isEffectEnabled(Qt::UI_AnimateTooltip)) - tooltipeffect->setCurrentItem(1); + ui->toolTipEffectCombo->setCurrentIndex(1); - if ( QApplication::isEffectEnabled( Qt::UI_AnimateToolBox ) ) - toolboxeffect->setCurrentItem( 1 ); + if (QApplication::isEffectEnabled(Qt::UI_AnimateToolBox)) + ui->toolBoxEffectCombo->setCurrentIndex(1); QSize globalStrut = QApplication::globalStrut(); - strutwidth->setValue(globalStrut.width()); - strutheight->setValue(globalStrut.height()); + ui->strutWidthSpinBox->setValue(globalStrut.width()); + ui->strutHeightSpinBox->setValue(globalStrut.height()); // find the default family QStringList::Iterator sit = families.begin(); @@ -306,10 +341,10 @@ MainWindow::MainWindow() if (i == -1) // no clue about the current font i = 0; - familycombo->setCurrentItem(i); + ui->fontFamilyCombo->setCurrentIndex(i); - QStringList styles = db.styles(familycombo->currentText()); - stylecombo->insertStringList(styles); + QStringList styles = db.styles(ui->fontFamilyCombo->currentText()); + ui->fontStyleCombo->addItems(styles); QString stylestring = db.styleString(QApplication::font()); sit = styles.begin(); @@ -328,91 +363,98 @@ MainWindow::MainWindow() i = possible; if (i == -1) // no clue about the current font i = 0; - stylecombo->setCurrentItem(i); + ui->fontStyleCombo->setCurrentIndex(i); i = 0; - for (int psize = QApplication::font().pointSize(); i < psizecombo->count(); ++i) { - const int sz = psizecombo->text(i).toInt(); + for (int psize = QApplication::font().pointSize(); i < ui->pointSizeCombo->count(); ++i) { + const int sz = ui->pointSizeCombo->itemText(i).toInt(); if (sz == psize) { - psizecombo->setCurrentItem(i); + ui->pointSizeCombo->setCurrentIndex(i); break; } else if(sz > psize) { - psizecombo->insertItem(i, QString::number(psize)); - psizecombo->setCurrentItem(i); + ui->pointSizeCombo->insertItem(i, QString::number(psize)); + ui->pointSizeCombo->setCurrentIndex(i); break; } } - QStringList subs = QFont::substitutes(familysubcombo->currentText()); - sublistbox->clear(); - sublistbox->insertStringList(subs); + QStringList subs = QFont::substitutes(ui->familySubstitutionCombo->currentText()); + ui->substitutionsListBox->clear(); + ui->substitutionsListBox->insertItems(0, subs); - rtlExtensions->setChecked(settings.value(QLatin1String("useRtlExtensions"), false).toBool()); + ui->rtlExtensionsCheckBox->setChecked(settings.value(QLatin1String("useRtlExtensions"), false) + .toBool()); #ifdef Q_WS_X11 - inputStyle->setCurrentText(settings.value(QLatin1String("XIMInputStyle"), trUtf8("On The Spot")).toString()); + QString settingsInputStyle = settings.value(QLatin1String("XIMInputStyle")).toString(); + if (!settingsInputStyle.isEmpty()) + ui->inputStyleCombo->setCurrentIndex(ui->inputStyleCombo->findText(settingsInputStyle)); #else - inputStyle->hide(); - inputStyleLabel->hide(); + ui->inputStyleCombo->hide(); + ui->inputStyleLabel->hide(); #endif #if defined(Q_WS_X11) && !defined(QT_NO_XIM) - QStringList inputMethods = QInputContextFactory::keys(); - int inputMethodIndex = -1; + QStringList inputMethodCombo = QInputContextFactory::keys(); + int inputMethodComboIndex = -1; QString defaultInputMethod = settings.value(QLatin1String("DefaultInputMethod"), QLatin1String("xim")).toString(); - for (int i = inputMethods.size()-1; i >= 0; --i) { - const QString &im = inputMethods.at(i); + for (int i = inputMethodCombo.size()-1; i >= 0; --i) { + const QString &im = inputMethodCombo.at(i); if (im.contains(QLatin1String("imsw"))) { - inputMethods.removeAt(i); - if (inputMethodIndex > i) - --inputMethodIndex; + inputMethodCombo.removeAt(i); + if (inputMethodComboIndex > i) + --inputMethodComboIndex; } else if (im == defaultInputMethod) { - inputMethodIndex = i; + inputMethodComboIndex = i; } } - if (inputMethodIndex == -1 && !inputMethods.isEmpty()) - inputMethodIndex = 0; - inputMethod->addItems(inputMethods); - inputMethod->setCurrentIndex(inputMethodIndex); + if (inputMethodComboIndex == -1 && !inputMethodCombo.isEmpty()) + inputMethodComboIndex = 0; + ui->inputMethodCombo->addItems(inputMethodCombo); + ui->inputMethodCombo->setCurrentIndex(inputMethodComboIndex); #else - inputMethod->hide(); - inputMethodLabel->hide(); + ui->inputMethodCombo->hide(); + ui->inputMethodLabel->hide(); #endif - fontembeddingcheckbox->setChecked(settings.value(QLatin1String("embedFonts"), true).toBool()); + ui->fontEmbeddingCheckBox->setChecked(settings.value(QLatin1String("embedFonts"), true) + .toBool()); fontpaths = settings.value(QLatin1String("fontPath")).toStringList(); - fontpathlistbox->insertStringList(fontpaths); - - audiosinkCombo->addItem(tr("Auto (default)"), QLatin1String("Auto")); - audiosinkCombo->setItemData(audiosinkCombo->findText(tr("Auto (default)")), - tr("Choose audio output automatically."), Qt::ToolTipRole); - audiosinkCombo->addItem(tr("aRts"), QLatin1String("artssink")); - audiosinkCombo->setItemData(audiosinkCombo->findText(tr("aRts")), - tr("Experimental aRts support for GStreamer."), Qt::ToolTipRole); + ui->fontpathListBox->insertItems(0, fontpaths); + + ui->audiosinkCombo->addItem(tr("Auto (default)"), QLatin1String("Auto")); + ui->audiosinkCombo->setItemData(ui->audiosinkCombo->findText(tr("Auto (default)")), + tr("Choose audio output automatically."), Qt::ToolTipRole); + ui->audiosinkCombo->addItem(tr("aRts"), QLatin1String("artssink")); + ui->audiosinkCombo->setItemData(ui->audiosinkCombo->findText(tr("aRts")), + tr("Experimental aRts support for GStreamer."), + Qt::ToolTipRole); #ifdef HAVE_PHONON - phononVersionLabel->setText(QLatin1String(Phonon::phononVersion())); + ui->phononVersionLabel->setText(QLatin1String(Phonon::phononVersion())); #endif #ifndef QT_NO_GSTREAMER if (gst_init_check(0, 0, 0)) { gchar *versionString = gst_version_string(); - gstversionLabel->setText(QLatin1String(versionString)); + ui->gstVersionLabel->setText(QLatin1String(versionString)); g_free(versionString); - GList* factoryList = gst_registry_get_feature_list(gst_registry_get_default (), GST_TYPE_ELEMENT_FACTORY); + GList *factoryList = gst_registry_get_feature_list(gst_registry_get_default(), + GST_TYPE_ELEMENT_FACTORY); QString name, klass, description; - for (GList* iter = g_list_first(factoryList) ; iter != NULL ; iter = g_list_next(iter)) { + for (GList *iter = g_list_first(factoryList) ; iter != NULL ; iter = g_list_next(iter)) { GstPluginFeature *feature = GST_PLUGIN_FEATURE(iter->data); klass = QLatin1String(gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature))); if (klass == QLatin1String("Sink/Audio")) { name = QLatin1String(GST_PLUGIN_FEATURE_NAME(feature)); if (name == QLatin1String("sfsink")) - continue; //useless to output audio to file when you cannot set the file path + continue; // useless to output audio to file when you cannot set the file path else if (name == QLatin1String("autoaudiosink")) continue; //This is used implicitly from the auto setting GstElement *sink = gst_element_factory_make (qPrintable(name), NULL); if (sink) { - description = QLatin1String(gst_element_factory_get_description (GST_ELEMENT_FACTORY(feature))); - audiosinkCombo->addItem(name, name); - audiosinkCombo->setItemData(audiosinkCombo->findText(name), description, Qt::ToolTipRole); + description = QLatin1String(gst_element_factory_get_description(GST_ELEMENT_FACTORY(feature))); + ui->audiosinkCombo->addItem(name, name); + ui->audiosinkCombo->setItemData(ui->audiosinkCombo->findText(name), description, + Qt::ToolTipRole); gst_object_unref (sink); } } @@ -420,39 +462,43 @@ MainWindow::MainWindow() g_list_free(factoryList); } #else - tab4->setEnabled(false); - phononLabel->setText(tr("Phonon GStreamer backend not available.")); + ui->phononTab->setEnabled(false); + ui->phononLabel->setText(tr("Phonon GStreamer backend not available.")); #endif - videomodeCombo->addItem(tr("Auto (default)"), QLatin1String("Auto")); - videomodeCombo->setItemData(videomodeCombo->findText(tr("Auto (default)")), tr("Choose render method automatically"), Qt::ToolTipRole); + ui->videomodeCombo->addItem(tr("Auto (default)"), QLatin1String("Auto")); + ui->videomodeCombo->setItemData(ui->videomodeCombo->findText(tr("Auto (default)")), + tr("Choose render method automatically"), Qt::ToolTipRole); #ifdef Q_WS_X11 - videomodeCombo->addItem(tr("X11"), QLatin1String("X11")); - videomodeCombo->setItemData(videomodeCombo->findText(tr("X11")), tr("Use X11 Overlays"), Qt::ToolTipRole); + ui->videomodeCombo->addItem(tr("X11"), QLatin1String("X11")); + ui->videomodeCombo->setItemData(ui->videomodeCombo->findText(tr("X11")), + tr("Use X11 Overlays"), Qt::ToolTipRole); #endif #ifndef QT_NO_OPENGL - videomodeCombo->addItem(tr("OpenGL"), QLatin1String("OpenGL")); - videomodeCombo->setItemData(videomodeCombo->findText(tr("OpenGL")), tr("Use OpenGL if available"), Qt::ToolTipRole); + ui->videomodeCombo->addItem(tr("OpenGL"), QLatin1String("OpenGL")); + ui->videomodeCombo->setItemData(ui->videomodeCombo->findText(tr("OpenGL")), + tr("Use OpenGL if available"), Qt::ToolTipRole); #endif - videomodeCombo->addItem(tr("Software"), QLatin1String("Software")); - videomodeCombo->setItemData(videomodeCombo->findText(tr("Software")), tr("Use simple software rendering"), Qt::ToolTipRole); + ui->videomodeCombo->addItem(tr("Software"), QLatin1String("Software")); + ui->videomodeCombo->setItemData(ui->videomodeCombo->findText(tr("Software")), + tr("Use simple software rendering"), Qt::ToolTipRole); QString audioSink = settings.value(QLatin1String("audiosink"), QLatin1String("Auto")).toString(); QString videoMode = settings.value(QLatin1String("videomode"), QLatin1String("Auto")).toString(); - audiosinkCombo->setCurrentItem(audiosinkCombo->findData(audioSink)); - videomodeCombo->setCurrentItem(videomodeCombo->findData(videoMode)); + ui->audiosinkCombo->setCurrentIndex(ui->audiosinkCombo->findData(audioSink)); + ui->videomodeCombo->setCurrentIndex(ui->videomodeCombo->findData(videoMode)); settings.endGroup(); // Qt - helpview->setText(tr(appearance_text)); + ui->helpView->setText(tr(appearance_text)); setModified(false); updateStyleLayout(); } - MainWindow::~MainWindow() { + delete ui; } #ifdef Q_WS_X11 @@ -472,23 +518,23 @@ void MainWindow::fileSave() QSettings settings(QLatin1String("Trolltech")); settings.beginGroup(QLatin1String("Qt")); QFontDatabase db; - QFont font = db.font(familycombo->currentText(), - stylecombo->currentText(), - psizecombo->currentText().toInt()); + QFont font = db.font(ui->fontFamilyCombo->currentText(), + ui->fontStyleCombo->currentText(), + ui->pointSizeCombo->currentText().toInt()); QStringList actcg, inactcg, discg; - bool overrideDesktopSettings = (gstylecombo->currentText() != desktopThemeName); + bool overrideDesktopSettings = (ui->guiStyleCombo->currentText() != desktopThemeName); if (overrideDesktopSettings) { int i; - for (i = 0; i < QColorGroup::NColorRoles; i++) + for (i = 0; i < QPalette::NColorRoles; i++) actcg << editPalette.color(QPalette::Active, - (QColorGroup::ColorRole) i).name(); - for (i = 0; i < QColorGroup::NColorRoles; i++) + QPalette::ColorRole(i)).name(); + for (i = 0; i < QPalette::NColorRoles; i++) inactcg << editPalette.color(QPalette::Inactive, - (QColorGroup::ColorRole) i).name(); - for (i = 0; i < QColorGroup::NColorRoles; i++) + QPalette::ColorRole(i)).name(); + for (i = 0; i < QPalette::NColorRoles; i++) discg << editPalette.color(QPalette::Disabled, - (QColorGroup::ColorRole) i).name(); + QPalette::ColorRole(i)).name(); } settings.setValue(QLatin1String("font"), font.toString()); @@ -497,59 +543,63 @@ void MainWindow::fileSave() settings.setValue(QLatin1String("Palette/disabled"), discg); settings.setValue(QLatin1String("fontPath"), fontpaths); - settings.setValue(QLatin1String("embedFonts"), fontembeddingcheckbox->isChecked()); - settings.setValue(QLatin1String("style"), overrideDesktopSettings ? gstylecombo->currentText() : QString()); + settings.setValue(QLatin1String("embedFonts"), ui->fontEmbeddingCheckBox->isChecked()); + settings.setValue(QLatin1String("style"), + overrideDesktopSettings ? ui->guiStyleCombo->currentText() : QString()); - settings.setValue(QLatin1String("doubleClickInterval"), dcispin->value()); - settings.setValue(QLatin1String("cursorFlashTime"), cfispin->value() == 9 ? 0 : cfispin->value() ); - settings.setValue(QLatin1String("wheelScrollLines"), wslspin->value()); - settings.setValue(QLatin1String("resolveSymlinks"), resolvelinks->isChecked()); + settings.setValue(QLatin1String("doubleClickInterval"), ui->doubleClickIntervalSpinBox->value()); + settings.setValue(QLatin1String("cursorFlashTime"), + ui->cursorFlashTimeSpinBox->value() == 9 ? 0 : ui->cursorFlashTimeSpinBox->value()); + settings.setValue(QLatin1String("wheelScrollLines"), ui->wheelScrollLinesSpinBox->value()); + settings.setValue(QLatin1String("resolveSymlinks"), ui->resolveLinksCheckBox->isChecked()); - QSize strut(strutwidth->value(), strutheight->value()); + QSize strut(ui->strutWidthSpinBox->value(), ui->strutHeightSpinBox->value()); settings.setValue(QLatin1String("globalStrut/width"), strut.width()); settings.setValue(QLatin1String("globalStrut/height"), strut.height()); - settings.setValue(QLatin1String("useRtlExtensions"), rtlExtensions->isChecked()); + settings.setValue(QLatin1String("useRtlExtensions"), ui->rtlExtensionsCheckBox->isChecked()); #ifdef Q_WS_X11 - QString style = inputStyle->currentText(); + QString style = ui->inputStyleCombo->currentText(); QString str = QLatin1String("On The Spot"); - if ( style == trUtf8( "Over The Spot" ) ) + if (style == tr("Over The Spot")) str = QLatin1String("Over The Spot"); - else if ( style == trUtf8( "Off The Spot" ) ) + else if (style == tr("Off The Spot")) str = QLatin1String("Off The Spot"); - else if ( style == trUtf8( "Root" ) ) + else if (style == tr("Root")) str = QLatin1String("Root"); - settings.setValue( QLatin1String("XIMInputStyle"), str ); + settings.setValue(QLatin1String("XIMInputStyle"), str); #endif #if defined(Q_WS_X11) && !defined(QT_NO_XIM) - settings.setValue(QLatin1String("DefaultInputMethod"), inputMethod->currentText()); + settings.setValue(QLatin1String("DefaultInputMethod"), ui->inputMethodCombo->currentText()); #endif QString audioSink = settings.value(QLatin1String("audiosink"), QLatin1String("Auto")).toString(); QString videoMode = settings.value(QLatin1String("videomode"), QLatin1String("Auto")).toString(); - settings.setValue(QLatin1String("audiosink"), audiosinkCombo->itemData(audiosinkCombo->currentIndex())); - settings.setValue(QLatin1String("videomode"), videomodeCombo->itemData(videomodeCombo->currentIndex())); + settings.setValue(QLatin1String("audiosink"), + ui->audiosinkCombo->itemData(ui->audiosinkCombo->currentIndex())); + settings.setValue(QLatin1String("videomode"), + ui->videomodeCombo->itemData(ui->videomodeCombo->currentIndex())); QStringList effects; - if (effectcheckbox->isChecked()) { + if (ui->effectsCheckBox->isChecked()) { effects << QLatin1String("general"); - switch (menueffect->currentItem()) { + switch (ui->menuEffectCombo->currentIndex()) { case 1: effects << QLatin1String("animatemenu"); break; case 2: effects << QLatin1String("fademenu"); break; } - switch (comboeffect->currentItem()) { + switch (ui->comboEffectCombo->currentIndex()) { case 1: effects << QLatin1String("animatecombo"); break; } - switch (tooltipeffect->currentItem()) { + switch (ui->toolTipEffectCombo->currentIndex()) { case 1: effects << QLatin1String("animatetooltip"); break; case 2: effects << QLatin1String("fadetooltip"); break; } - switch ( toolboxeffect->currentItem() ) { + switch (ui->toolBoxEffectCombo->currentIndex()) { case 1: effects << QLatin1String("animatetoolbox"); break; } } else @@ -573,189 +623,63 @@ void MainWindow::fileSave() #endif // Q_WS_X11 setModified(false); - statusBar()->showMessage(QLatin1String("Saved changes.")); + statusBar()->showMessage(tr("Saved changes.")); } - void MainWindow::fileExit() { qApp->closeAllWindows(); } - void MainWindow::setModified(bool m) { if (modified == m) return; modified = m; - fileSaveAction->setEnabled(m); + ui->fileSaveAction->setEnabled(m); } - void MainWindow::buildPalette() { - int i; - QColorGroup cg; - QColor btn = buttonMainColor->color(); - QColor back = buttonMainColor2->color(); - QPalette automake( btn, back ); - - for (i = 0; i<9; i++) - cg.setColor( centralFromItem(i), automake.active().color( centralFromItem(i) ) ); - - editPalette.setActive( cg ); - buildActiveEffect(); - - cg = editPalette.inactive(); - - QPalette temp( editPalette.active().color( QColorGroup::Button ), - editPalette.active().color( QColorGroup::Window ) ); - - for (i = 0; i<9; i++) - cg.setColor( centralFromItem(i), temp.inactive().color( centralFromItem(i) ) ); - - editPalette.setInactive( cg ); - buildInactiveEffect(); - - cg = editPalette.disabled(); - - for (i = 0; i<9; i++) - cg.setColor( centralFromItem(i), temp.disabled().color( centralFromItem(i) ) ); - - editPalette.setDisabled( cg ); - buildDisabledEffect(); + QPalette temp(ui->buttonMainColor->color(), ui->buttonWindowColor->color()); + for (int i = 0; i < QPalette::NColorGroups; i++) + temp = PaletteEditorAdvanced::buildEffect(QPalette::ColorGroup(i), temp); + editPalette = temp; + setPreviewPalette(editPalette); updateColorButtons(); setModified(true); } - -void MainWindow::buildActiveEffect() -{ - QColorGroup cg = editPalette.active(); - QColor btn = cg.color( QColorGroup::Button ); - - QPalette temp( btn, btn ); - - for (int i = 0; i<5; i++) - cg.setColor( effectFromItem(i), temp.active().color( effectFromItem(i) ) ); - - editPalette.setActive( cg ); - setPreviewPalette( editPalette ); - - updateColorButtons(); -} - - -void MainWindow::buildInactive() -{ - editPalette.setInactive( editPalette.active() ); - buildInactiveEffect(); -} - - -void MainWindow::buildInactiveEffect() -{ - QColorGroup cg = editPalette.inactive(); - - QColor light, midlight, mid, dark, shadow; - QColor btn = cg.color( QColorGroup::Button ); - - light = btn.light(150); - midlight = btn.light(115); - mid = btn.dark(150); - dark = btn.dark(); - shadow = Qt::black; - - cg.setColor( QColorGroup::Light, light ); - cg.setColor( QColorGroup::Midlight, midlight ); - cg.setColor( QColorGroup::Mid, mid ); - cg.setColor( QColorGroup::Dark, dark ); - cg.setColor( QColorGroup::Shadow, shadow ); - - editPalette.setInactive( cg ); - setPreviewPalette( editPalette ); - updateColorButtons(); -} - - -void MainWindow::buildDisabled() -{ - QColorGroup cg = editPalette.active(); - cg.setColor( QColorGroup::ButtonText, Qt::darkGray ); - cg.setColor( QColorGroup::WindowText, Qt::darkGray ); - cg.setColor( QColorGroup::Text, Qt::darkGray ); - cg.setColor( QColorGroup::HighlightedText, Qt::darkGray ); - editPalette.setDisabled( cg ); - - buildDisabledEffect(); -} - - -void MainWindow::buildDisabledEffect() -{ - QColorGroup cg = editPalette.disabled(); - - QColor light, midlight, mid, dark, shadow; - QColor btn = cg.color( QColorGroup::Button ); - - light = btn.light(150); - midlight = btn.light(115); - mid = btn.dark(150); - dark = btn.dark(); - shadow = Qt::black; - - cg.setColor( QColorGroup::Light, light ); - cg.setColor( QColorGroup::Midlight, midlight ); - cg.setColor( QColorGroup::Mid, mid ); - cg.setColor( QColorGroup::Dark, dark ); - cg.setColor( QColorGroup::Shadow, shadow ); - - editPalette.setDisabled( cg ); - setPreviewPalette( editPalette ); - updateColorButtons(); -} - - -void MainWindow::setPreviewPalette( const QPalette& pal ) +void MainWindow::setPreviewPalette(const QPalette &pal) { - QColorGroup cg; + QPalette::ColorGroup colorGroup = groupFromIndex(ui->paletteCombo->currentIndex()); - switch (paletteCombo->currentItem()) { - case 0: - default: - cg = pal.active(); - break; - case 1: - cg = pal.inactive(); - break; - case 2: - cg = pal.disabled(); - break; + for (int i = 0; i < QPalette::NColorGroups; i++) { + for (int j = 0; j < QPalette::NColorRoles; j++) { + QPalette::ColorGroup targetGroup = QPalette::ColorGroup(i); + QPalette::ColorRole targetRole = QPalette::ColorRole(j); + previewPalette.setColor(targetGroup, targetRole, pal.color(colorGroup, targetRole)); + } } - previewPalette.setActive( cg ); - previewPalette.setInactive( cg ); - previewPalette.setDisabled( cg ); - previewFrame->setPreviewPalette(previewPalette); + ui->previewFrame->setPreviewPalette(previewPalette); } - void MainWindow::updateColorButtons() { - buttonMainColor->setColor( editPalette.active().color( QColorGroup::Button )); - buttonMainColor2->setColor( editPalette.active().color( QColorGroup::Window )); + ui->buttonMainColor->setColor(editPalette.color(QPalette::Active, QPalette::Button)); + ui->buttonWindowColor->setColor(editPalette.color(QPalette::Active, QPalette::Window)); } - void MainWindow::tunePalette() { bool ok; QPalette pal = PaletteEditorAdvanced::getPalette(&ok, editPalette, - backgroundMode(), this); - if (! ok) + backgroundRole(), this); + if (!ok) return; editPalette = pal; @@ -763,7 +687,6 @@ void MainWindow::tunePalette() setModified(true); } - void MainWindow::paletteSelected(int) { setPreviewPalette(editPalette); @@ -771,10 +694,10 @@ void MainWindow::paletteSelected(int) void MainWindow::updateStyleLayout() { - QString currentStyle = gstylecombo->currentText(); + QString currentStyle = ui->guiStyleCombo->currentText(); bool autoStyle = (currentStyle == desktopThemeName); - previewFrame->setPreviewVisible(!autoStyle); - groupAutoPalette->setEnabled(currentStyle.toLower() != QLatin1String("gtk") && !autoStyle); + ui->previewFrame->setPreviewVisible(!autoStyle); + ui->buildPaletteGroup->setEnabled(currentStyle.toLower() != QLatin1String("gtk") && !autoStyle); } void MainWindow::styleSelected(const QString &stylename) @@ -786,7 +709,7 @@ void MainWindow::styleSelected(const QString &stylename) style = QStyleFactory::create(stylename); if (!style) return; - setStyleHelper(previewFrame, style); + setStyleHelper(ui->previewFrame, style); delete previewstyle; previewstyle = style; setModified(true); @@ -794,210 +717,191 @@ void MainWindow::styleSelected(const QString &stylename) updateStyleLayout(); } - void MainWindow::familySelected(const QString &family) { QFontDatabase db; QStringList styles = db.styles(family); - stylecombo->clear(); - stylecombo->insertStringList(styles); - familysubcombo->insertItem(family); + ui->fontStyleCombo->clear(); + ui->fontStyleCombo->addItems(styles); + ui->familySubstitutionCombo->addItem(family); buildFont(); } - void MainWindow::buildFont() { QFontDatabase db; - QFont font = db.font(familycombo->currentText(), - stylecombo->currentText(), - psizecombo->currentText().toInt()); - samplelineedit->setFont(font); + QFont font = db.font(ui->fontFamilyCombo->currentText(), + ui->fontStyleCombo->currentText(), + ui->pointSizeCombo->currentText().toInt()); + ui->sampleLineEdit->setFont(font); setModified(true); } - void MainWindow::substituteSelected(const QString &family) { QStringList subs = QFont::substitutes(family); - sublistbox->clear(); - sublistbox->insertStringList(subs); + ui->substitutionsListBox->clear(); + ui->substitutionsListBox->insertItems(0, subs); } - void MainWindow::removeSubstitute() { - if (sublistbox->currentItem() < 0 || - uint(sublistbox->currentItem()) > sublistbox->count()) + if (!ui->substitutionsListBox->currentItem()) return; - int item = sublistbox->currentItem(); - QStringList subs = QFont::substitutes(familysubcombo->currentText()); - subs.removeAt(sublistbox->currentItem()); - sublistbox->clear(); - sublistbox->insertStringList(subs); - if (uint(item) > sublistbox->count()) - item = int(sublistbox->count()) - 1; - sublistbox->setCurrentItem(item); - QFont::removeSubstitution(familysubcombo->currentText()); - QFont::insertSubstitutions(familysubcombo->currentText(), subs); + int row = ui->substitutionsListBox->currentRow(); + QStringList subs = QFont::substitutes(ui->familySubstitutionCombo->currentText()); + subs.removeAt(ui->substitutionsListBox->currentRow()); + ui->substitutionsListBox->clear(); + ui->substitutionsListBox->insertItems(0, subs); + if (row > ui->substitutionsListBox->count()) + row = ui->substitutionsListBox->count() - 1; + ui->substitutionsListBox->setCurrentRow(row); + QFont::removeSubstitution(ui->familySubstitutionCombo->currentText()); + QFont::insertSubstitutions(ui->familySubstitutionCombo->currentText(), subs); setModified(true); } - void MainWindow::addSubstitute() { - if (sublistbox->currentItem() < 0 || - uint(sublistbox->currentItem()) > sublistbox->count()) { - QFont::insertSubstitution(familysubcombo->currentText(), choosesubcombo->currentText()); - QStringList subs = QFont::substitutes(familysubcombo->currentText()); - sublistbox->clear(); - sublistbox->insertStringList(subs); + if (!ui->substitutionsListBox->currentItem()) { + QFont::insertSubstitution(ui->familySubstitutionCombo->currentText(), + ui->chooseSubstitutionCombo->currentText()); + QStringList subs = QFont::substitutes(ui->familySubstitutionCombo->currentText()); + ui->substitutionsListBox->clear(); + ui->substitutionsListBox->insertItems(0, subs); setModified(true); return; } - int item = sublistbox->currentItem(); - QFont::insertSubstitution(familysubcombo->currentText(), choosesubcombo->currentText()); - QStringList subs = QFont::substitutes(familysubcombo->currentText()); - sublistbox->clear(); - sublistbox->insertStringList(subs); - sublistbox->setCurrentItem(item); + int row = ui->substitutionsListBox->currentRow(); + QFont::insertSubstitution(ui->familySubstitutionCombo->currentText(), ui->chooseSubstitutionCombo->currentText()); + QStringList subs = QFont::substitutes(ui->familySubstitutionCombo->currentText()); + ui->substitutionsListBox->clear(); + ui->substitutionsListBox->insertItems(0, subs); + ui->substitutionsListBox->setCurrentRow(row); setModified(true); } - void MainWindow::downSubstitute() { - if (sublistbox->currentItem() < 0 || - uint(sublistbox->currentItem()) >= sublistbox->count()) + if (!ui->substitutionsListBox->currentItem() || ui->substitutionsListBox->currentRow() >= ui->substitutionsListBox->count()) return; - int item = sublistbox->currentItem(); - QStringList subs = QFont::substitutes(familysubcombo->currentText()); - QString fam = subs.at(item); - subs.removeAt(item); - subs.insert(item+1, fam); - sublistbox->clear(); - sublistbox->insertStringList(subs); - sublistbox->setCurrentItem(item + 1); - QFont::removeSubstitution(familysubcombo->currentText()); - QFont::insertSubstitutions(familysubcombo->currentText(), subs); + int row = ui->substitutionsListBox->currentRow(); + QStringList subs = QFont::substitutes(ui->familySubstitutionCombo->currentText()); + QString fam = subs.at(row); + subs.removeAt(row); + subs.insert(row + 1, fam); + ui->substitutionsListBox->clear(); + ui->substitutionsListBox->insertItems(0, subs); + ui->substitutionsListBox->setCurrentRow(row + 1); + QFont::removeSubstitution(ui->familySubstitutionCombo->currentText()); + QFont::insertSubstitutions(ui->familySubstitutionCombo->currentText(), subs); setModified(true); } - void MainWindow::upSubstitute() { - if (sublistbox->currentItem() < 1) + if (!ui->substitutionsListBox->currentItem() || ui->substitutionsListBox->currentRow() < 1) return; - int item = sublistbox->currentItem(); - QStringList subs = QFont::substitutes(familysubcombo->currentText()); - QString fam = subs.at(item); - subs.removeAt(item); - subs.insert(item-1, fam); - sublistbox->clear(); - sublistbox->insertStringList(subs); - sublistbox->setCurrentItem(item - 1); - QFont::removeSubstitution(familysubcombo->currentText()); - QFont::insertSubstitutions(familysubcombo->currentText(), subs); + int row = ui->substitutionsListBox->currentRow(); + QStringList subs = QFont::substitutes(ui->familySubstitutionCombo->currentText()); + QString fam = subs.at(row); + subs.removeAt(row); + subs.insert(row-1, fam); + ui->substitutionsListBox->clear(); + ui->substitutionsListBox->insertItems(0, subs); + ui->substitutionsListBox->setCurrentRow(row - 1); + QFont::removeSubstitution(ui->familySubstitutionCombo->currentText()); + QFont::insertSubstitutions(ui->familySubstitutionCombo->currentText(), subs); setModified(true); } - void MainWindow::removeFontpath() { - if (fontpathlistbox->currentItem() < 0 || - uint(fontpathlistbox->currentItem()) > fontpathlistbox->count()) + if (!ui->fontpathListBox->currentItem()) return; - int item = fontpathlistbox->currentItem(); - fontpaths.removeAt(fontpathlistbox->currentItem()); - fontpathlistbox->clear(); - fontpathlistbox->insertStringList(fontpaths); - if (uint(item) > fontpathlistbox->count()) - item = int(fontpathlistbox->count()) - 1; - fontpathlistbox->setCurrentItem(item); + int row = ui->fontpathListBox->currentRow(); + fontpaths.removeAt(row); + ui->fontpathListBox->clear(); + ui->fontpathListBox->insertItems(0, fontpaths); + if (row > ui->fontpathListBox->count()) + row = ui->fontpathListBox->count() - 1; + ui->fontpathListBox->setCurrentRow(row); setModified(true); } - void MainWindow::addFontpath() { - if (fontpathlineedit->text().isEmpty()) + if (ui->fontPathLineEdit->text().isEmpty()) return; - if (fontpathlistbox->currentItem() < 0 || - uint(fontpathlistbox->currentItem()) > fontpathlistbox->count()) { - fontpaths.append(fontpathlineedit->text()); - fontpathlistbox->clear(); - fontpathlistbox->insertStringList(fontpaths); + if (!ui->fontpathListBox->currentItem()) { + fontpaths.append(ui->fontPathLineEdit->text()); + ui->fontpathListBox->clear(); + ui->fontpathListBox->insertItems(0, fontpaths); setModified(true); return; } - int item = fontpathlistbox->currentItem(); - fontpaths.insert(fontpathlistbox->currentItem()+1, - fontpathlineedit->text()); - fontpathlistbox->clear(); - fontpathlistbox->insertStringList(fontpaths); - fontpathlistbox->setCurrentItem(item); + int row = ui->fontpathListBox->currentRow(); + fontpaths.insert(row + 1, ui->fontPathLineEdit->text()); + ui->fontpathListBox->clear(); + ui->fontpathListBox->insertItems(0, fontpaths); + ui->fontpathListBox->setCurrentRow(row); setModified(true); } - void MainWindow::downFontpath() { - if (fontpathlistbox->currentItem() < 0 || - uint(fontpathlistbox->currentItem()) >= fontpathlistbox->count() - 1) + if (!ui->fontpathListBox->currentItem() + || ui->fontpathListBox->currentRow() >= (ui->fontpathListBox->count() - 1)) { return; + } - int item = fontpathlistbox->currentItem(); - QString fam = fontpaths.at(item); - fontpaths.removeAt(item); - fontpaths.insert(item+1, fam); - fontpathlistbox->clear(); - fontpathlistbox->insertStringList(fontpaths); - fontpathlistbox->setCurrentItem(item + 1); + int row = ui->fontpathListBox->currentRow(); + QString fam = fontpaths.at(row); + fontpaths.removeAt(row); + fontpaths.insert(row + 1, fam); + ui->fontpathListBox->clear(); + ui->fontpathListBox->insertItems(0, fontpaths); + ui->fontpathListBox->setCurrentRow(row + 1); setModified(true); } - void MainWindow::upFontpath() { - if (fontpathlistbox->currentItem() < 1) + if (!ui->fontpathListBox->currentItem() || ui->fontpathListBox->currentRow() < 1) return; - int item = fontpathlistbox->currentItem(); - QString fam = fontpaths.at(item); - fontpaths.removeAt(item); - fontpaths.insert(item-1, fam); - fontpathlistbox->clear(); - fontpathlistbox->insertStringList(fontpaths); - fontpathlistbox->setCurrentItem(item - 1); + int row = ui->fontpathListBox->currentRow(); + QString fam = fontpaths.at(row); + fontpaths.removeAt(row); + fontpaths.insert(row - 1, fam); + ui->fontpathListBox->clear(); + ui->fontpathListBox->insertItems(0, fontpaths); + ui->fontpathListBox->setCurrentRow(row - 1); setModified(true); } - void MainWindow::browseFontpath() { - QString dirname = QFileDialog::getExistingDirectory(QString(), this, 0, - tr("Select a Directory")); + QString dirname = QFileDialog::getExistingDirectory(this, tr("Select a Directory")); if (dirname.isNull()) return; - fontpathlineedit->setText(dirname); + ui->fontPathLineEdit->setText(dirname); } - void MainWindow::somethingModified() { setModified(true); } - void MainWindow::helpAbout() { QMessageBox box(this); @@ -1010,44 +914,43 @@ void MainWindow::helpAbout() box.exec(); } - void MainWindow::helpAboutQt() { QMessageBox::aboutQt(this, tr("Qt Configuration")); } - -void MainWindow::pageChanged(QWidget *page) +void MainWindow::pageChanged(int pageNumber) { - if (page == tab) - helpview->setText(tr(interface_text)); - else if (page == tab1) - helpview->setText(tr(appearance_text)); - else if (page == tab2) - helpview->setText(tr(font_text)); - else if (page == tab3) - helpview->setText(tr(printer_text)); - else if (page == tab4) - helpview->setText(tr(phonon_text)); + QWidget *page = ui->mainTabWidget->widget(pageNumber); + if (page == ui->interfaceTab) + ui->helpView->setText(tr(interface_text)); + else if (page == ui->appearanceTab) + ui->helpView->setText(tr(appearance_text)); + else if (page == ui->fontsTab) + ui->helpView->setText(tr(font_text)); + else if (page == ui->printerTab) + ui->helpView->setText(tr(printer_text)); + else if (page == ui->phononTab) + ui->helpView->setText(tr(phonon_text)); } - void MainWindow::closeEvent(QCloseEvent *e) { if (modified) { - switch(QMessageBox::warning(this, tr("Save Changes"), - tr("Save changes to settings?"), - tr("&Yes"), tr("&No"), tr("&Cancel"), 0, 2)) { - case 0: // save + switch (QMessageBox::warning(this, tr("Save Changes"), + tr("Save changes to settings?"), + (QMessageBox::Yes | QMessageBox::No + | QMessageBox::Cancel))) { + case QMessageBox::Yes: // save qApp->processEvents(); fileSave(); // fall through intended - case 1: // don't save + case QMessageBox::No: // don't save e->accept(); break; - case 2: // cancel + case QMessageBox::Cancel: // cancel e->ignore(); break; diff --git a/tools/qtconfig/mainwindow.h b/tools/qtconfig/mainwindow.h index b9f4a3d..4d3f3a5 100644 --- a/tools/qtconfig/mainwindow.h +++ b/tools/qtconfig/mainwindow.h @@ -42,11 +42,15 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include "mainwindowbase.h" +#include <QtGui/QMainWindow> QT_BEGIN_NAMESPACE -class MainWindow : public MainWindowBase +namespace Ui { + class MainWindow; +} + +class MainWindow : public QMainWindow { Q_OBJECT @@ -56,7 +60,6 @@ public: void closeEvent(QCloseEvent *); - public slots: virtual void buildPalette(); virtual void buildFont(); @@ -79,25 +82,21 @@ public slots: virtual void somethingModified(); virtual void helpAbout(); virtual void helpAboutQt(); - virtual void pageChanged(QWidget *); + virtual void pageChanged(int); private: - void buildActive(); - void buildActiveEffect(); - void buildInactive(); - void buildInactiveEffect(); - void buildDisabled(); - void buildDisabledEffect(); - void updateColorButtons(); void updateFontSample(); void updateStyleLayout(); + static QPalette::ColorGroup groupFromIndex(int); + void setPreviewPalette(const QPalette &); void setModified(bool); + Ui::MainWindow *ui; QString desktopThemeName; QPalette editPalette, previewPalette; QStyle *previewstyle; diff --git a/tools/qtconfig/mainwindowbase.ui b/tools/qtconfig/mainwindow.ui index 4a0411a..3710954 100644 --- a/tools/qtconfig/mainwindowbase.ui +++ b/tools/qtconfig/mainwindow.ui @@ -40,8 +40,8 @@ ** $QT_END_LICENSE$ ** *********************************************************************</comment> - <class>MainWindowBase</class> - <widget class="Q3MainWindow" name="MainWindowBase"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> @@ -54,20 +54,12 @@ <string>Qt Configuration</string> </property> <widget class="QWidget" name="widget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>26</y> - <width>815</width> - <height>690</height> - </rect> - </property> <layout class="QGridLayout" name="gridLayout"> <property name="margin"> <number>8</number> </property> <item row="0" column="0"> - <widget class="QTextEdit" name="helpview"> + <widget class="QTextEdit" name="helpView"> <property name="minimumSize"> <size> <width>200</width> @@ -80,17 +72,17 @@ </widget> </item> <item row="0" column="1"> - <widget class="QTabWidget" name="TabWidget3"> + <widget class="QTabWidget" name="mainTabWidget"> <property name="currentIndex"> <number>0</number> </property> - <widget class="QWidget" name="tab1"> + <widget class="QWidget" name="appearanceTab"> <attribute name="title"> <string>Appearance</string> </attribute> <layout class="QGridLayout" name="gridLayout_5"> <item row="0" column="0"> - <widget class="QGroupBox" name="GroupBox40"> + <widget class="QGroupBox" name="guiStyleGroup"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -114,7 +106,7 @@ <number>8</number> </property> <item> - <widget class="QLabel" name="gstylebuddy"> + <widget class="QLabel" name="guiStyleLabel"> <property name="minimumSize"> <size> <width>0</width> @@ -125,18 +117,18 @@ <string>Select GUI &Style:</string> </property> <property name="buddy"> - <cstring>gstylecombo</cstring> + <cstring>guiStyleCombo</cstring> </property> </widget> </item> <item> - <widget class="QComboBox" name="gstylecombo"/> + <widget class="QComboBox" name="guiStyleCombo"/> </item> </layout> </widget> </item> <item row="3" column="0"> - <widget class="QGroupBox" name="groupPreview"> + <widget class="QGroupBox" name="previewGroup"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> <horstretch>0</horstretch> @@ -148,7 +140,7 @@ </property> <layout class="QGridLayout" name="gridLayout_4"> <item row="0" column="0"> - <widget class="QLabel" name="TextLabel1"> + <widget class="QLabel" name="paletteLabel"> <property name="text"> <string>Select &Palette:</string> </property> @@ -196,7 +188,7 @@ </widget> </item> <item row="1" column="0"> - <widget class="QGroupBox" name="groupAutoPalette"> + <widget class="QGroupBox" name="buildPaletteGroup"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> @@ -222,7 +214,7 @@ <item> <widget class="QLabel" name="labelMainColor"> <property name="text"> - <string>&3-D Effects:</string> + <string>&Button Background:</string> </property> <property name="buddy"> <cstring>buttonMainColor</cstring> @@ -233,7 +225,7 @@ <widget class="ColorButton" name="buttonMainColor" native="true"/> </item> <item> - <widget class="QLabel" name="labelMainColor2"> + <widget class="QLabel" name="labelWindowColor"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>0</horstretch> @@ -262,12 +254,12 @@ <number>0</number> </property> <property name="buddy"> - <cstring>buttonMainColor2</cstring> + <cstring>buttonWindowColor</cstring> </property> </widget> </item> <item> - <widget class="ColorButton" name="buttonMainColor2" native="true"/> + <widget class="ColorButton" name="buttonWindowColor" native="true"/> </item> <item> <spacer name="spacer"> @@ -286,7 +278,7 @@ </spacer> </item> <item> - <widget class="QPushButton" name="btnAdvanced"> + <widget class="QPushButton" name="tunePaletteButton"> <property name="text"> <string>&Tune Palette...</string> </property> @@ -296,7 +288,7 @@ </widget> </item> <item> - <widget class="QLabel" name="labelKDENote"> + <widget class="QLabel" name="kdeNoteLabel"> <property name="text"> <string>Please use the KDE Control Center to set the palette.</string> </property> @@ -307,13 +299,13 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab2"> + <widget class="QWidget" name="fontsTab"> <attribute name="title"> <string>Fonts</string> </attribute> <layout class="QVBoxLayout"> <item> - <widget class="QGroupBox" name="GroupBox1"> + <widget class="QGroupBox" name="defaultFontGroup"> <property name="title"> <string>Default Font</string> </property> @@ -325,7 +317,7 @@ <number>4</number> </property> <item row="1" column="1"> - <widget class="QComboBox" name="stylecombo"> + <widget class="QComboBox" name="fontStyleCombo"> <property name="autoCompletion"> <bool>true</bool> </property> @@ -335,7 +327,7 @@ </widget> </item> <item row="0" column="1"> - <widget class="QComboBox" name="familycombo"> + <widget class="QComboBox" name="fontFamilyCombo"> <property name="autoCompletion"> <bool>true</bool> </property> @@ -345,7 +337,7 @@ </widget> </item> <item row="2" column="1"> - <widget class="QComboBox" name="psizecombo"> + <widget class="QComboBox" name="pointSizeCombo"> <property name="editable"> <bool>true</bool> </property> @@ -358,37 +350,37 @@ </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="stylebuddy"> + <widget class="QLabel" name="fontStyleLabel"> <property name="text"> <string>&Style:</string> </property> <property name="buddy"> - <cstring>stylecombo</cstring> + <cstring>fontStyleCombo</cstring> </property> </widget> </item> <item row="2" column="0"> - <widget class="QLabel" name="psizebuddy"> + <widget class="QLabel" name="pointSizeLabel"> <property name="text"> <string>&Point Size:</string> </property> <property name="buddy"> - <cstring>psizecombo</cstring> + <cstring>pointSizeCombo</cstring> </property> </widget> </item> <item row="0" column="0"> - <widget class="QLabel" name="familybuddy"> + <widget class="QLabel" name="fontFamilyLabel"> <property name="text"> <string>F&amily:</string> </property> <property name="buddy"> - <cstring>familycombo</cstring> + <cstring>fontFamilyCombo</cstring> </property> </widget> </item> <item row="3" column="0" colspan="2"> - <widget class="QLineEdit" name="samplelineedit"> + <widget class="QLineEdit" name="sampleLineEdit"> <property name="text"> <string>Sample Text</string> </property> @@ -401,7 +393,7 @@ </widget> </item> <item> - <widget class="QGroupBox" name="GroupBox2"> + <widget class="QGroupBox" name="fontSubstitutionGroup"> <property name="title"> <string>Font Substitution</string> </property> @@ -421,17 +413,17 @@ <number>0</number> </property> <item> - <widget class="QLabel" name="famsubbuddy"> + <widget class="QLabel" name="familySubstitutionLabel"> <property name="text"> <string>S&elect or Enter a Family:</string> </property> <property name="buddy"> - <cstring>familysubcombo</cstring> + <cstring>familySubstitutionCombo</cstring> </property> </widget> </item> <item> - <widget class="QComboBox" name="familysubcombo"> + <widget class="QComboBox" name="familySubstitutionCombo"> <property name="editable"> <bool>true</bool> </property> @@ -459,14 +451,14 @@ </widget> </item> <item> - <widget class="QLabel" name="TextLabel5"> + <widget class="QLabel" name="substitutionsLabel"> <property name="text"> <string>Current Substitutions:</string> </property> </widget> </item> <item> - <widget class="Q3ListBox" name="sublistbox"/> + <widget class="QListWidget" name="substitutionsListBox"/> </item> <item> <layout class="QHBoxLayout"> @@ -477,21 +469,21 @@ <number>0</number> </property> <item> - <widget class="QPushButton" name="PushButton2"> + <widget class="QPushButton" name="upSubstitutionButton"> <property name="text"> <string>Up</string> </property> </widget> </item> <item> - <widget class="QPushButton" name="PushButton3"> + <widget class="QPushButton" name="downSubstitutionButton"> <property name="text"> <string>Down</string> </property> </widget> </item> <item> - <widget class="QPushButton" name="PushButton4"> + <widget class="QPushButton" name="removeSubstitutionButton"> <property name="text"> <string>Remove</string> </property> @@ -521,17 +513,17 @@ <number>0</number> </property> <item> - <widget class="QLabel" name="choosebuddy"> + <widget class="QLabel" name="chooseSubstitutionLabel"> <property name="text"> <string>Select s&ubstitute Family:</string> </property> <property name="buddy"> - <cstring>choosesubcombo</cstring> + <cstring>chooseSubstitutionCombo</cstring> </property> </widget> </item> <item> - <widget class="QComboBox" name="choosesubcombo"> + <widget class="QComboBox" name="chooseSubstitutionCombo"> <property name="autoCompletion"> <bool>true</bool> </property> @@ -541,7 +533,7 @@ </widget> </item> <item> - <widget class="QPushButton" name="PushButton1"> + <widget class="QPushButton" name="addSubstitutionButton"> <property name="text"> <string>Add</string> </property> @@ -554,13 +546,13 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab"> + <widget class="QWidget" name="interfaceTab"> <attribute name="title"> <string>Interface</string> </attribute> <layout class="QVBoxLayout"> <item> - <widget class="QGroupBox" name="GroupBox4"> + <widget class="QGroupBox" name="feelSettingsGroup"> <property name="title"> <string>Feel Settings</string> </property> @@ -572,7 +564,7 @@ <number>4</number> </property> <item row="0" column="1"> - <widget class="QSpinBox" name="dcispin"> + <widget class="QSpinBox" name="doubleClickIntervalSpinBox"> <property name="suffix"> <string> ms</string> </property> @@ -585,17 +577,17 @@ </widget> </item> <item row="0" column="0"> - <widget class="QLabel" name="dcibuddy"> + <widget class="QLabel" name="doubleClickIntervalLabel"> <property name="text"> <string>&Double Click Interval:</string> </property> <property name="buddy"> - <cstring>dcispin</cstring> + <cstring>doubleClickIntervalSpinBox</cstring> </property> </widget> </item> <item row="1" column="1"> - <widget class="QSpinBox" name="cfispin"> + <widget class="QSpinBox" name="cursorFlashTimeSpinBox"> <property name="specialValueText"> <string>No blinking</string> </property> @@ -611,17 +603,17 @@ </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="cfibuddy"> + <widget class="QLabel" name="cursorFlashTimeLabel"> <property name="text"> <string>&Cursor Flash Time:</string> </property> <property name="buddy"> - <cstring>cfispin</cstring> + <cstring>cursorFlashTimeSpinBox</cstring> </property> </widget> </item> <item row="2" column="1"> - <widget class="QSpinBox" name="wslspin"> + <widget class="QSpinBox" name="wheelScrollLinesSpinBox"> <property name="suffix"> <string> lines</string> </property> @@ -634,17 +626,17 @@ </widget> </item> <item row="2" column="0"> - <widget class="QLabel" name="wslbuddy"> + <widget class="QLabel" name="wheelScrollLinesLabel"> <property name="text"> <string>Wheel &Scroll Lines:</string> </property> <property name="buddy"> - <cstring>wslspin</cstring> + <cstring>wheelScrollLinesSpinBox</cstring> </property> </widget> </item> <item row="3" column="0" colspan="2"> - <widget class="QCheckBox" name="resolvelinks"> + <widget class="QCheckBox" name="resolveLinksCheckBox"> <property name="text"> <string>Resolve symlinks in URLs</string> </property> @@ -654,7 +646,7 @@ </widget> </item> <item> - <widget class="QGroupBox" name="GroupBox3"> + <widget class="QGroupBox" name="guiEffectsGroup"> <property name="title"> <string>GUI Effects</string> </property> @@ -666,7 +658,7 @@ <number>8</number> </property> <item> - <widget class="QCheckBox" name="effectcheckbox"> + <widget class="QCheckBox" name="effectsCheckBox"> <property name="text"> <string>&Enable</string> </property> @@ -676,62 +668,53 @@ </widget> </item> <item> - <widget class="Q3Frame" name="effectbase"> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Plain</enum> - </property> + <widget class="QFrame" name="effectsFrame"> <layout class="QGridLayout"> - <property name="margin"> - <number>0</number> - </property> <property name="spacing"> <number>4</number> </property> <item row="0" column="0"> - <widget class="QLabel" name="meffectbuddy"> + <widget class="QLabel" name="menuEffectLabel"> <property name="text"> <string>&Menu Effect:</string> </property> <property name="buddy"> - <cstring>menueffect</cstring> + <cstring>menuEffectCombo</cstring> </property> </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="ceffectbuddy"> + <widget class="QLabel" name="comboEffectLabel"> <property name="text"> <string>C&omboBox Effect:</string> </property> <property name="buddy"> - <cstring>comboeffect</cstring> + <cstring>comboEffectCombo</cstring> </property> </widget> </item> <item row="2" column="0"> - <widget class="QLabel" name="teffectbuddy"> + <widget class="QLabel" name="toolTipEffectLabel"> <property name="text"> <string>&ToolTip Effect:</string> </property> <property name="buddy"> - <cstring>tooltipeffect</cstring> + <cstring>toolTipEffectCombo</cstring> </property> </widget> </item> <item row="3" column="0"> - <widget class="QLabel" name="beffectbuddy"> + <widget class="QLabel" name="toolBoxEffectLabel"> <property name="text"> <string>Tool&Box Effect:</string> </property> <property name="buddy"> - <cstring>toolboxeffect</cstring> + <cstring>toolBoxEffectCombo</cstring> </property> </widget> </item> <item row="0" column="1"> - <widget class="QComboBox" name="menueffect"> + <widget class="QComboBox" name="menuEffectCombo"> <property name="currentIndex"> <number>0</number> </property> @@ -756,7 +739,7 @@ </widget> </item> <item row="1" column="1"> - <widget class="QComboBox" name="comboeffect"> + <widget class="QComboBox" name="comboEffectCombo"> <item> <property name="text"> <string>Disable</string> @@ -770,7 +753,7 @@ </widget> </item> <item row="2" column="1"> - <widget class="QComboBox" name="tooltipeffect"> + <widget class="QComboBox" name="toolTipEffectCombo"> <item> <property name="text"> <string>Disable</string> @@ -789,7 +772,7 @@ </widget> </item> <item row="3" column="1"> - <widget class="QComboBox" name="toolboxeffect"> + <widget class="QComboBox" name="toolBoxEffectCombo"> <item> <property name="text"> <string>Disable</string> @@ -809,7 +792,7 @@ </widget> </item> <item> - <widget class="QGroupBox" name="GroupBox5"> + <widget class="QGroupBox" name="globalStrutGroup"> <property name="title"> <string>Global Strut</string> </property> @@ -821,27 +804,27 @@ <number>4</number> </property> <item row="0" column="0"> - <widget class="QLabel" name="swbuddy"> + <widget class="QLabel" name="strutWidthLabel"> <property name="text"> <string>Minimum &Width:</string> </property> <property name="buddy"> - <cstring>strutwidth</cstring> + <cstring>strutWidthSpinBox</cstring> </property> </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="shbuddy"> + <widget class="QLabel" name="strutHeightLabel"> <property name="text"> <string>Minimum Hei&ght:</string> </property> <property name="buddy"> - <cstring>strutheight</cstring> + <cstring>strutHeightSpinBox</cstring> </property> </widget> </item> <item row="0" column="1"> - <widget class="QSpinBox" name="strutwidth"> + <widget class="QSpinBox" name="strutWidthSpinBox"> <property name="suffix"> <string> pixels</string> </property> @@ -851,7 +834,7 @@ </widget> </item> <item row="1" column="1"> - <widget class="QSpinBox" name="strutheight"> + <widget class="QSpinBox" name="strutHeightSpinBox"> <property name="suffix"> <string> pixels</string> </property> @@ -864,7 +847,7 @@ </widget> </item> <item> - <widget class="QCheckBox" name="rtlExtensions"> + <widget class="QCheckBox" name="rtlExtensionsCheckBox"> <property name="text"> <string>Enhanced support for languages written right-to-left</string> </property> @@ -878,7 +861,7 @@ </widget> </item> <item> - <widget class="QComboBox" name="inputStyle"> + <widget class="QComboBox" name="inputStyleCombo"> <property name="currentIndex"> <number>0</number> </property> @@ -912,7 +895,7 @@ </widget> </item> <item> - <widget class="QComboBox" name="inputMethod"> + <widget class="QComboBox" name="inputMethodCombo"> <property name="currentIndex"> <number>-1</number> </property> @@ -936,13 +919,13 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab3"> + <widget class="QWidget" name="printerTab"> <attribute name="title"> <string>Printer</string> </attribute> <layout class="QVBoxLayout"> <item> - <widget class="QCheckBox" name="fontembeddingcheckbox"> + <widget class="QCheckBox" name="fontEmbeddingCheckBox"> <property name="text"> <string>Enable Font embedding</string> </property> @@ -952,7 +935,7 @@ </widget> </item> <item> - <widget class="QGroupBox" name="GroupBox10"> + <widget class="QGroupBox" name="fontPathsGroup"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> <horstretch>0</horstretch> @@ -978,28 +961,28 @@ <number>4</number> </property> <item row="1" column="0"> - <widget class="QPushButton" name="PushButton11"> + <widget class="QPushButton" name="upFontpathButton"> <property name="text"> <string>Up</string> </property> </widget> </item> <item row="1" column="2"> - <widget class="QPushButton" name="PushButton13"> + <widget class="QPushButton" name="removeFontpathButton"> <property name="text"> <string>Remove</string> </property> </widget> </item> <item row="1" column="1"> - <widget class="QPushButton" name="PushButton12"> + <widget class="QPushButton" name="downFontpathButton"> <property name="text"> <string>Down</string> </property> </widget> </item> <item row="0" column="0" colspan="3"> - <widget class="Q3ListBox" name="fontpathlistbox"/> + <widget class="QListWidget" name="fontpathListBox"/> </item> </layout> </item> @@ -1028,28 +1011,28 @@ </spacer> </item> <item row="2" column="2"> - <widget class="QPushButton" name="PushButton15"> + <widget class="QPushButton" name="addFontPathButton"> <property name="text"> <string>Add</string> </property> </widget> </item> <item row="2" column="1"> - <widget class="QPushButton" name="PushButton14"> + <widget class="QPushButton" name="browseFontPathButton"> <property name="text"> <string>Browse...</string> </property> </widget> </item> <item row="0" column="0" colspan="3"> - <widget class="QLabel" name="TextLabel15_2"> + <widget class="QLabel" name="browseFontPathLabel"> <property name="text"> <string>Press the <b>Browse</b> button or enter a directory and press Enter to add them to the list.</string> </property> </widget> </item> <item row="1" column="0" colspan="3"> - <widget class="QLineEdit" name="fontpathlineedit"/> + <widget class="QLineEdit" name="fontPathLineEdit"/> </item> </layout> </item> @@ -1058,19 +1041,19 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab4"> + <widget class="QWidget" name="phononTab"> <attribute name="title"> <string>Phonon</string> </attribute> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QGroupBox" name="groupBox_4"> + <widget class="QGroupBox" name="aboutPhononGroup"> <property name="title"> <string>About Phonon</string> </property> <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="0"> - <widget class="QLabel" name="label_7"> + <widget class="QLabel" name="phononVersionBuddyLabel"> <property name="text"> <string>Current Version:</string> </property> @@ -1084,20 +1067,16 @@ </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_5"> + <widget class="QLabel" name="phononWebsiteBuddyLabel"> <property name="text"> <string>Website:</string> </property> </widget> </item> <item row="1" column="1"> - <widget class="QLabel" name="gstversionLabel_3"> + <widget class="QLabel" name="phononWebsiteLabel"> <property name="text"> - <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://phonon.kde.org"><span style=" text-decoration: underline; color:#0000ff;">http://phonon.kde.org</span></a></p></body></html></string> + <string><a href="http://phonon.kde.org">http://phonon.kde.org/</a></string> </property> <property name="openExternalLinks"> <bool>true</bool> @@ -1108,40 +1087,36 @@ p, li { white-space: pre-wrap; } </widget> </item> <item> - <widget class="QGroupBox" name="groupBox_3"> + <widget class="QGroupBox" name="aboutGStreamerGroup"> <property name="title"> <string>About GStreamer</string> </property> <layout class="QGridLayout"> <item row="0" column="0"> - <widget class="QLabel" name="label_3"> + <widget class="QLabel" name="gstVersionBuddyLabel"> <property name="text"> <string>Current Version:</string> </property> </widget> </item> <item row="0" column="1"> - <widget class="QLabel" name="gstversionLabel"> + <widget class="QLabel" name="gstVersionLabel"> <property name="text"> <string>Not available</string> </property> </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_4"> + <widget class="QLabel" name="gstWebsiteBuddyLabel"> <property name="text"> <string>Website:</string> </property> </widget> </item> <item row="1" column="1"> - <widget class="QLabel" name="gstversionLabel_2"> + <widget class="QLabel" name="gstWebsiteLabel"> <property name="text"> - <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://gstreamer.freedesktop.org/"><span style=" text-decoration: underline; color:#0000ff;">http://gstreamer.freedesktop.org/</span></a></p></body></html></string> + <string><a href="http://gstreamer.freedesktop.org/">http://gstreamer.freedesktop.org/</a></string> </property> <property name="openExternalLinks"> <bool>true</bool> @@ -1152,13 +1127,13 @@ p, li { white-space: pre-wrap; } </widget> </item> <item> - <widget class="QGroupBox" name="groupBox"> + <widget class="QGroupBox" name="gstBackendGroup"> <property name="title"> <string>GStreamer backend settings</string> </property> <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="audiosinkLabel"> <property name="text"> <string>Preferred audio sink:</string> </property> @@ -1171,7 +1146,7 @@ p, li { white-space: pre-wrap; } <widget class="QComboBox" name="audiosinkCombo"/> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="videomodeLabel"> <property name="text"> <string>Preferred render method:</string> </property> @@ -1184,7 +1159,7 @@ p, li { white-space: pre-wrap; } <widget class="QComboBox" name="videomodeCombo"/> </item> <item row="2" column="0" colspan="2"> - <widget class="QLabel" name="label_6"> + <widget class="QLabel" name="gstBackendNoteLabel"> <property name="text"> <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1235,41 +1210,38 @@ p, li { white-space: pre-wrap; } </item> </layout> </widget> - <widget class="QMenuBar" name="menubar"> + <widget class="QMenuBar" name="mainMenu"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>815</width> - <height>26</height> + <height>19</height> </rect> </property> - <widget class="QMenu" name="PopupMenu"> + <widget class="QMenu" name="fileMenu"> <property name="geometry"> <rect> - <x>0</x> - <y>0</y> - <width>123</width> - <height>92</height> + <x>203</x> + <y>114</y> + <width>161</width> + <height>110</height> </rect> </property> <property name="title"> <string>&File</string> </property> - <action name=""/> - <action name=""/> - <action name=""/> <addaction name="fileSaveAction"/> <addaction name="separator"/> <addaction name="fileExitAction"/> </widget> - <widget class="QMenu" name="PopupMenu_2"> + <widget class="QMenu" name="saveMenu"> <property name="geometry"> <rect> - <x>0</x> - <y>0</y> - <width>123</width> - <height>90</height> + <x>543</x> + <y>98</y> + <width>161</width> + <height>106</height> </rect> </property> <property name="title"> @@ -1278,12 +1250,9 @@ p, li { white-space: pre-wrap; } <addaction name="helpAboutAction"/> <addaction name="helpAboutQtAction"/> </widget> - <action name=""/> - <action name=""/> - <action name=""/> - <addaction name="PopupMenu"/> + <addaction name="fileMenu"/> <addaction name="separator"/> - <addaction name="PopupMenu_2"/> + <addaction name="saveMenu"/> </widget> <action name="fileSaveAction"> <property name="text"> @@ -1304,7 +1273,7 @@ p, li { white-space: pre-wrap; } <string>Exit</string> </property> <property name="shortcut"> - <string/> + <string>Ctrl+Q</string> </property> </action> <action name="helpAboutAction"> @@ -1329,23 +1298,6 @@ p, li { white-space: pre-wrap; } </widget> <customwidgets> <customwidget> - <class>Q3Frame</class> - <extends>QFrame</extends> - <header>Qt3Support/Q3Frame</header> - <container>1</container> - </customwidget> - <customwidget> - <class>Q3MainWindow</class> - <extends>QWidget</extends> - <header>q3mainwindow.h</header> - <container>1</container> - </customwidget> - <customwidget> - <class>Q3ListBox</class> - <extends>Q3Frame</extends> - <header>q3listbox.h</header> - </customwidget> - <customwidget> <class>ColorButton</class> <extends></extends> <header>colorbutton.h</header> @@ -1357,28 +1309,80 @@ p, li { white-space: pre-wrap; } </customwidget> </customwidgets> <tabstops> - <tabstop>helpview</tabstop> - <tabstop>familycombo</tabstop> - <tabstop>stylecombo</tabstop> - <tabstop>psizecombo</tabstop> - <tabstop>samplelineedit</tabstop> - <tabstop>familysubcombo</tabstop> - <tabstop>PushButton2</tabstop> - <tabstop>PushButton3</tabstop> - <tabstop>PushButton4</tabstop> - <tabstop>choosesubcombo</tabstop> - <tabstop>PushButton1</tabstop> - <tabstop>dcispin</tabstop> - <tabstop>cfispin</tabstop> - <tabstop>wslspin</tabstop> - <tabstop>effectcheckbox</tabstop> - <tabstop>menueffect</tabstop> - <tabstop>comboeffect</tabstop> - <tabstop>tooltipeffect</tabstop> - <tabstop>strutwidth</tabstop> - <tabstop>strutheight</tabstop> - <tabstop>sublistbox</tabstop> + <tabstop>helpView</tabstop> + <tabstop>mainTabWidget</tabstop> + <tabstop>guiStyleCombo</tabstop> + <tabstop>tunePaletteButton</tabstop> + <tabstop>paletteCombo</tabstop> + <tabstop>fontFamilyCombo</tabstop> + <tabstop>fontStyleCombo</tabstop> + <tabstop>pointSizeCombo</tabstop> + <tabstop>sampleLineEdit</tabstop> + <tabstop>familySubstitutionCombo</tabstop> + <tabstop>substitutionsListBox</tabstop> + <tabstop>upSubstitutionButton</tabstop> + <tabstop>downSubstitutionButton</tabstop> + <tabstop>removeSubstitutionButton</tabstop> + <tabstop>chooseSubstitutionCombo</tabstop> + <tabstop>addSubstitutionButton</tabstop> + <tabstop>doubleClickIntervalSpinBox</tabstop> + <tabstop>cursorFlashTimeSpinBox</tabstop> + <tabstop>wheelScrollLinesSpinBox</tabstop> + <tabstop>resolveLinksCheckBox</tabstop> + <tabstop>effectsCheckBox</tabstop> + <tabstop>menuEffectCombo</tabstop> + <tabstop>comboEffectCombo</tabstop> + <tabstop>toolTipEffectCombo</tabstop> + <tabstop>toolBoxEffectCombo</tabstop> + <tabstop>strutWidthSpinBox</tabstop> + <tabstop>strutHeightSpinBox</tabstop> + <tabstop>rtlExtensionsCheckBox</tabstop> + <tabstop>inputStyleCombo</tabstop> + <tabstop>inputMethodCombo</tabstop> + <tabstop>fontEmbeddingCheckBox</tabstop> + <tabstop>fontpathListBox</tabstop> + <tabstop>upFontpathButton</tabstop> + <tabstop>downFontpathButton</tabstop> + <tabstop>removeFontpathButton</tabstop> + <tabstop>fontPathLineEdit</tabstop> + <tabstop>browseFontPathButton</tabstop> + <tabstop>addFontPathButton</tabstop> + <tabstop>audiosinkCombo</tabstop> + <tabstop>videomodeCombo</tabstop> </tabstops> <resources/> - <connections/> + <connections> + <connection> + <sender>effectsCheckBox</sender> + <signal>toggled(bool)</signal> + <receiver>effectsFrame</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>417</x> + <y>257</y> + </hint> + <hint type="destinationlabel"> + <x>578</x> + <y>379</y> + </hint> + </hints> + </connection> + <connection> + <sender>fontEmbeddingCheckBox</sender> + <signal>toggled(bool)</signal> + <receiver>fontPathsGroup</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>449</x> + <y>69</y> + </hint> + <hint type="destinationlabel"> + <x>447</x> + <y>94</y> + </hint> + </hints> + </connection> + </connections> </ui> diff --git a/tools/qtconfig/mainwindowbase.cpp b/tools/qtconfig/mainwindowbase.cpp deleted file mode 100644 index 51a4c42..0000000 --- a/tools/qtconfig/mainwindowbase.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mainwindowbase.h" -#include "colorbutton.h" -#include "previewframe.h" - -#include <QVariant> -#include <QImage> -#include <QPixmap> - -QT_BEGIN_NAMESPACE - -/* - * Constructs a MainWindowBase as a child of 'parent', with the - * name 'name' and widget flags set to 'f'. - * - */ -MainWindowBase::MainWindowBase(QWidget* parent, const char* name, Qt::WindowFlags fl) - : Q3MainWindow(parent, name, fl) -{ - setupUi(this); - - (void)statusBar(); - - // signals and slots connections - connect(fontpathlineedit, SIGNAL(returnPressed()), this, SLOT(addFontpath())); - connect(PushButton15, SIGNAL(clicked()), this, SLOT(addFontpath())); - connect(PushButton1, SIGNAL(clicked()), this, SLOT(addSubstitute())); - connect(PushButton14, SIGNAL(clicked()), this, SLOT(browseFontpath())); - connect(stylecombo, SIGNAL(activated(int)), this, SLOT(buildFont())); - connect(psizecombo, SIGNAL(activated(int)), this, SLOT(buildFont())); - connect(PushButton12, SIGNAL(clicked()), this, SLOT(downFontpath())); - connect(PushButton3, SIGNAL(clicked()), this, SLOT(downSubstitute())); - connect(familycombo, SIGNAL(activated(QString)), this, SLOT(familySelected(QString))); - connect(fileExitAction, SIGNAL(activated()), this, SLOT(fileExit())); - connect(fileSaveAction, SIGNAL(activated()), this, SLOT(fileSave())); - connect(helpAboutAction, SIGNAL(activated()), this, SLOT(helpAbout())); - connect(helpAboutQtAction, SIGNAL(activated()), this, SLOT(helpAboutQt())); - connect(TabWidget3, SIGNAL(currentChanged(QWidget*)), this, SLOT(pageChanged(QWidget*))); - connect(paletteCombo, SIGNAL(activated(int)), this, SLOT(paletteSelected(int))); - connect(PushButton13, SIGNAL(clicked()), this, SLOT(removeFontpath())); - connect(PushButton4, SIGNAL(clicked()), this, SLOT(removeSubstitute())); - connect(effectcheckbox, SIGNAL(toggled(bool)), effectbase, SLOT(setEnabled(bool))); - connect(fontembeddingcheckbox, SIGNAL(toggled(bool)), GroupBox10, SLOT(setEnabled(bool))); - connect(toolboxeffect, SIGNAL(activated(int)), this, SLOT(somethingModified())); - connect(dcispin, SIGNAL(valueChanged(int)), this, SLOT(somethingModified())); - connect(cfispin, SIGNAL(valueChanged(int)), this, SLOT(somethingModified())); - connect(wslspin, SIGNAL(valueChanged(int)), this, SLOT(somethingModified())); - connect(menueffect, SIGNAL(activated(int)), this, SLOT(somethingModified())); - connect(comboeffect, SIGNAL(activated(int)), this, SLOT(somethingModified())); - connect(audiosinkCombo, SIGNAL(activated(int)), this, SLOT(somethingModified())); - connect(videomodeCombo, SIGNAL(activated(int)), this, SLOT(somethingModified())); - connect(tooltipeffect, SIGNAL(activated(int)), this, SLOT(somethingModified())); - connect(strutwidth, SIGNAL(valueChanged(int)), this, SLOT(somethingModified())); - connect(strutheight, SIGNAL(valueChanged(int)), this, SLOT(somethingModified())); - connect(effectcheckbox, SIGNAL(toggled(bool)), this, SLOT(somethingModified())); - connect(resolvelinks, SIGNAL(toggled(bool)), this, SLOT(somethingModified())); - connect(fontembeddingcheckbox, SIGNAL(clicked()), this, SLOT(somethingModified())); - connect(rtlExtensions, SIGNAL(toggled(bool)), this, SLOT(somethingModified())); - connect(inputStyle, SIGNAL(activated(int)), this, SLOT(somethingModified())); - connect(inputMethod, SIGNAL(activated(int)), this, SLOT(somethingModified())); - connect(gstylecombo, SIGNAL(activated(QString)), this, SLOT(styleSelected(QString))); - connect(familysubcombo, SIGNAL(activated(QString)), this, SLOT(substituteSelected(QString))); - connect(btnAdvanced, SIGNAL(clicked()), this, SLOT(tunePalette())); - connect(PushButton11, SIGNAL(clicked()), this, SLOT(upFontpath())); - connect(PushButton2, SIGNAL(clicked()), this, SLOT(upSubstitute())); - init(); -} - -/* - * Destroys the object and frees any allocated resources - */ -MainWindowBase::~MainWindowBase() -{ - destroy(); - // no need to delete child widgets, Qt does it all for us -} - -/* - * Sets the strings of the subwidgets using the current - * language. - */ -void MainWindowBase::languageChange() -{ - retranslateUi(this); -} - -void MainWindowBase::init() -{ -} - -void MainWindowBase::destroy() -{ -} - -void MainWindowBase::addFontpath() -{ - qWarning("MainWindowBase::addFontpath(): Not implemented yet"); -} - -void MainWindowBase::addSubstitute() -{ - qWarning("MainWindowBase::addSubstitute(): Not implemented yet"); -} - -void MainWindowBase::browseFontpath() -{ - qWarning("MainWindowBase::browseFontpath(): Not implemented yet"); -} - -void MainWindowBase::buildFont() -{ - qWarning("MainWindowBase::buildFont(): Not implemented yet"); -} - -void MainWindowBase::buildPalette() -{ - qWarning("MainWindowBase::buildPalette(): Not implemented yet"); -} - -void MainWindowBase::downFontpath() -{ - qWarning("MainWindowBase::downFontpath(): Not implemented yet"); -} - -void MainWindowBase::downSubstitute() -{ - qWarning("MainWindowBase::downSubstitute(): Not implemented yet"); -} - -void MainWindowBase::familySelected( const QString &) -{ - qWarning("MainWindowBase::familySelected( const QString &): Not implemented yet"); -} - -void MainWindowBase::fileExit() -{ - qWarning("MainWindowBase::fileExit(): Not implemented yet"); -} - -void MainWindowBase::fileSave() -{ - qWarning("MainWindowBase::fileSave(): Not implemented yet"); -} - -void MainWindowBase::helpAbout() -{ - qWarning("MainWindowBase::helpAbout(): Not implemented yet"); -} - -void MainWindowBase::helpAboutQt() -{ - qWarning("MainWindowBase::helpAboutQt(): Not implemented yet"); -} - -void MainWindowBase::new_slot() -{ - qWarning("MainWindowBase::new_slot(): Not implemented yet"); -} - -void MainWindowBase::pageChanged( QWidget *) -{ - qWarning("MainWindowBase::pageChanged( QWidget *): Not implemented yet"); -} - -void MainWindowBase::paletteSelected(int) -{ - qWarning("MainWindowBase::paletteSelected(int): Not implemented yet"); -} - -void MainWindowBase::removeFontpath() -{ - qWarning("MainWindowBase::removeFontpath(): Not implemented yet"); -} - -void MainWindowBase::removeSubstitute() -{ - qWarning("MainWindowBase::removeSubstitute(): Not implemented yet"); -} - -void MainWindowBase::somethingModified() -{ - qWarning("MainWindowBase::somethingModified(): Not implemented yet"); -} - -void MainWindowBase::styleSelected( const QString &) -{ - qWarning("MainWindowBase::styleSelected( const QString &): Not implemented yet"); -} - -void MainWindowBase::substituteSelected( const QString &) -{ - qWarning("MainWindowBase::substituteSelected( const QString &): Not implemented yet"); -} - -void MainWindowBase::tunePalette() -{ - qWarning("MainWindowBase::tunePalette(): Not implemented yet"); -} - -void MainWindowBase::upFontpath() -{ - qWarning("MainWindowBase::upFontpath(): Not implemented yet"); -} - -void MainWindowBase::upSubstitute() -{ - qWarning("MainWindowBase::upSubstitute(): Not implemented yet"); -} - -QT_END_NAMESPACE diff --git a/tools/qtconfig/paletteeditoradvanced.cpp b/tools/qtconfig/paletteeditoradvanced.cpp index 436af4c..168890e 100644 --- a/tools/qtconfig/paletteeditoradvanced.cpp +++ b/tools/qtconfig/paletteeditoradvanced.cpp @@ -38,58 +38,74 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - +#include "ui_paletteeditoradvanced.h" #include "paletteeditoradvanced.h" #include "colorbutton.h" -#include <QCheckBox> -#include <QComboBox> -#include <QApplication> -#include <QPushButton> -#include <QPainter> -#include <QGroupBox> - QT_BEGIN_NAMESPACE -PaletteEditorAdvanced::PaletteEditorAdvanced( QWidget * parent, - const char * name, bool modal, Qt::WindowFlags f ) - : PaletteEditorAdvancedBase( parent, name, modal, f ), selectedPalette(0) +PaletteEditorAdvanced::PaletteEditorAdvanced(QWidget *parent) + : QDialog(parent), ui(new Ui::PaletteEditorAdvanced), selectedPalette(0) { - // work around buggy UI file - comboEffect->setEnabled(false); + ui->setupUi(this); + + // create a ColorButton's + buttonCentral = new ColorButton(ui->groupCentral); + buttonCentral->setToolTip(tr("Choose a color")); + buttonCentral->setWhatsThis(tr("Choose a color for the selected central color role.")); + ui->layoutCentral->addWidget(buttonCentral); + ui->labelCentral->setBuddy(buttonCentral); + + buttonEffect = new ColorButton(ui->groupEffect); + buttonEffect->setToolTip(tr("Choose a color")); + buttonEffect->setWhatsThis(tr("Choose a color for the selected effect color role.")); buttonEffect->setEnabled(false); + ui->layoutEffect->addWidget(buttonEffect); + ui->labelEffect->setBuddy(buttonEffect); + + // signals and slots connections + connect(ui->paletteCombo, SIGNAL(activated(int)), SLOT(paletteSelected(int))); + connect(ui->comboCentral, SIGNAL(activated(int)), SLOT(onCentral(int))); + connect(buttonCentral, SIGNAL(clicked()), SLOT(onChooseCentralColor())); + connect(buttonEffect, SIGNAL(clicked()), SLOT(onChooseEffectColor())); + connect(ui->comboEffect, SIGNAL(activated(int)), SLOT(onEffect(int))); + connect(ui->checkBuildEffect, SIGNAL(toggled(bool)), SLOT(onToggleBuildEffects(bool))); + connect(ui->checkBuildEffect, SIGNAL(toggled(bool)), buttonEffect, SLOT(setDisabled(bool))); + connect(ui->checkBuildInactive, SIGNAL(toggled(bool)), SLOT(onToggleBuildInactive(bool))); + connect(ui->checkBuildDisabled, SIGNAL(toggled(bool)), SLOT(onToggleBuildDisabled(bool))); + onToggleBuildEffects(true); editPalette = QApplication::palette(); - setPreviewPalette( editPalette ); } PaletteEditorAdvanced::~PaletteEditorAdvanced() { + delete ui; } -void PaletteEditorAdvanced::onToggleBuildInactive( bool v ) +void PaletteEditorAdvanced::onToggleBuildInactive(bool v) { if (selectedPalette == 1) { - groupCentral->setDisabled(v); - groupEffect->setDisabled(v); + ui->groupCentral->setDisabled(v); + ui->groupEffect->setDisabled(v); } if (v) { - buildInactive(); + build(QPalette::Inactive); updateColorButtons(); } } -void PaletteEditorAdvanced::onToggleBuildDisabled( bool v ) +void PaletteEditorAdvanced::onToggleBuildDisabled(bool v) { if (selectedPalette == 2) { - groupCentral->setDisabled(v); - groupEffect->setDisabled(v); + ui->groupCentral->setDisabled(v); + ui->groupEffect->setDisabled(v); } if (v) { - buildDisabled(); + build(QPalette::Disabled); updateColorButtons(); } } @@ -99,402 +115,204 @@ void PaletteEditorAdvanced::paletteSelected(int p) selectedPalette = p; if(p == 1) { // inactive - groupCentral->setDisabled(checkBuildInactive->isChecked()); - groupEffect->setDisabled(checkBuildInactive->isChecked()); - } - else if (p == 2) { // disabled - groupCentral->setDisabled(checkBuildDisabled->isChecked()); - groupEffect->setDisabled(checkBuildDisabled->isChecked()); - } - else { - groupCentral->setEnabled(true); - groupEffect->setEnabled(true); + ui->groupCentral->setDisabled(ui->checkBuildInactive->isChecked()); + ui->groupEffect->setDisabled(ui->checkBuildInactive->isChecked()); + } else if (p == 2) { // disabled + ui->groupCentral->setDisabled(ui->checkBuildDisabled->isChecked()); + ui->groupEffect->setDisabled(ui->checkBuildDisabled->isChecked()); + } else { + ui->groupCentral->setEnabled(true); + ui->groupEffect->setEnabled(true); } updateColorButtons(); } void PaletteEditorAdvanced::onChooseCentralColor() { - switch(selectedPalette) { - case 0: - default: - mapToActiveCentralRole( buttonCentral->color() ); - break; - case 1: - mapToInactiveCentralRole( buttonCentral->color() ); - break; - case 2: - mapToDisabledCentralRole( buttonCentral->color() ); - break; + QPalette::ColorGroup group = groupFromIndex(selectedPalette); + editPalette.setColor(group, centralFromIndex(ui->comboCentral->currentIndex()), + buttonCentral->color()); + + buildEffect(group); + if (group == QPalette::Active) { + if(ui->checkBuildInactive->isChecked()) + build(QPalette::Inactive); + if(ui->checkBuildDisabled->isChecked()) + build(QPalette::Disabled); } + updateColorButtons(); } void PaletteEditorAdvanced::onChooseEffectColor() { - switch(selectedPalette) { - case 0: - default: - mapToActiveEffectRole( buttonEffect->color() ); - break; - case 1: - mapToInactiveEffectRole( buttonEffect->color() ); - break; - case 2: - mapToDisabledEffectRole( buttonEffect->color() ); - break; + QPalette::ColorGroup group = groupFromIndex(selectedPalette); + editPalette.setColor(group, effectFromIndex(ui->comboEffect->currentIndex()), + buttonEffect->color()); + + if (group == QPalette::Active) { + if(ui->checkBuildInactive->isChecked()) + build(QPalette::Inactive); + if(ui->checkBuildDisabled->isChecked()) + build(QPalette::Disabled); } - updateColorButtons(); -} -void PaletteEditorAdvanced::onToggleBuildEffects( bool on ) -{ - if (!on) return; - buildActiveEffect(); - buildInactiveEffect(); - buildDisabledEffect(); + updateColorButtons(); } -QColorGroup::ColorRole PaletteEditorAdvanced::centralFromItem( int item ) +void PaletteEditorAdvanced::onToggleBuildEffects(bool on) { - switch( item ) { - case 0: - return QColorGroup::Window; - case 1: - return QColorGroup::WindowText; - case 2: - return QColorGroup::Button; - case 3: - return QColorGroup::Base; - case 4: - return QColorGroup::Text; - case 5: - return QColorGroup::BrightText; - case 6: - return QColorGroup::ButtonText; - case 7: - return QColorGroup::Highlight; - case 8: - return QColorGroup::HighlightedText; - default: - return QColorGroup::NColorRoles; + if (on) { + for (int i = 0; i < QPalette::NColorGroups; i++) + buildEffect(QPalette::ColorGroup(i)); } } -QColorGroup::ColorRole PaletteEditorAdvanced::effectFromItem( int item ) - +QPalette::ColorGroup PaletteEditorAdvanced::groupFromIndex(int item) { - switch( item ) { + switch (item) { case 0: - return QColorGroup::Light; + default: + return QPalette::Active; case 1: - return QColorGroup::Midlight; + return QPalette::Inactive; case 2: - return QColorGroup::Mid; - case 3: - return QColorGroup::Dark; - case 4: - return QColorGroup::Shadow; - default: - return QColorGroup::NColorRoles; + return QPalette::Disabled; } } -void PaletteEditorAdvanced::onCentral( int item ) +QPalette::ColorRole PaletteEditorAdvanced::centralFromIndex(int item) { - QColor c; - - switch(selectedPalette) { + switch (item) { case 0: - default: - c = editPalette.active().color( centralFromItem(item) ); - break; + return QPalette::Window; case 1: - c = editPalette.inactive().color( centralFromItem(item) ); - break; + return QPalette::WindowText; case 2: - c = editPalette.disabled().color( centralFromItem(item) ); - break; + return QPalette::Base; + case 3: + return QPalette::AlternateBase; + case 4: + return QPalette::ToolTipBase; + case 5: + return QPalette::ToolTipText; + case 6: + return QPalette::Text; + case 7: + return QPalette::Button; + case 8: + return QPalette::ButtonText; + case 9: + return QPalette::BrightText; + case 10: + return QPalette::Highlight; + case 11: + return QPalette::HighlightedText; + case 12: + return QPalette::Link; + case 13: + return QPalette::LinkVisited; + default: + return QPalette::NoRole; } - - buttonCentral->setColor(c); } -void PaletteEditorAdvanced::onEffect( int item ) +QPalette::ColorRole PaletteEditorAdvanced::effectFromIndex(int item) { - QColor c; - switch(selectedPalette) { + switch (item) { case 0: - default: - c = editPalette.active().color( effectFromItem(item) ); - break; + return QPalette::Light; case 1: - editPalette.inactive().color( effectFromItem(item) ); - break; + return QPalette::Midlight; case 2: - editPalette.disabled().color( effectFromItem(item) ); - break; + return QPalette::Mid; + case 3: + return QPalette::Dark; + case 4: + return QPalette::Shadow; + default: + return QPalette::NoRole; } - buttonEffect->setColor(c); -} - -void PaletteEditorAdvanced::mapToActiveCentralRole( const QColor& c ) -{ - QColorGroup cg = editPalette.active(); - cg.setColor( centralFromItem(comboCentral->currentItem()), c ); - editPalette.setActive( cg ); - - buildActiveEffect(); - if(checkBuildInactive->isChecked()) - buildInactive(); - if(checkBuildDisabled->isChecked()) - buildDisabled(); - - setPreviewPalette( editPalette ); -} - -void PaletteEditorAdvanced::mapToActiveEffectRole( const QColor& c ) -{ - QColorGroup cg = editPalette.active(); - cg.setColor( effectFromItem(comboEffect->currentItem()), c ); - editPalette.setActive( cg ); - - if(checkBuildInactive->isChecked()) - buildInactive(); - if(checkBuildDisabled->isChecked()) - buildDisabled(); - - setPreviewPalette( editPalette ); -} - -void PaletteEditorAdvanced::mapToActivePixmapRole( const QPixmap& pm ) -{ - QColorGroup::ColorRole role = centralFromItem(comboCentral->currentItem()); - QColorGroup cg = editPalette.active(); - if ( !pm.isNull() ) - cg.setBrush( role, QBrush( cg.color( role ), pm ) ); - else - cg.setBrush( role, QBrush( cg.color( role ) ) ); - editPalette.setActive( cg ); - - - buildActiveEffect(); - if(checkBuildInactive->isChecked()) - buildInactive(); - if(checkBuildDisabled->isChecked()) - buildDisabled(); - - setPreviewPalette( editPalette ); -} - -void PaletteEditorAdvanced::mapToInactiveCentralRole( const QColor& c ) -{ - QColorGroup cg = editPalette.inactive(); - cg.setColor( centralFromItem(comboCentral->currentItem()), c ); - editPalette.setInactive( cg ); - - buildInactiveEffect(); - - setPreviewPalette( editPalette ); } -void PaletteEditorAdvanced::mapToInactiveEffectRole( const QColor& c ) +void PaletteEditorAdvanced::onCentral(int item) { - QColorGroup cg = editPalette.inactive(); - cg.setColor( effectFromItem(comboEffect->currentItem()), c ); - editPalette.setInactive( cg ); - - setPreviewPalette( editPalette ); -} - -void PaletteEditorAdvanced::mapToInactivePixmapRole( const QPixmap& pm ) -{ - QColorGroup::ColorRole role = centralFromItem(comboCentral->currentItem()); - QColorGroup cg = editPalette.inactive(); - if ( !pm.isNull() ) - cg.setBrush( role, QBrush( cg.color( role ), pm ) ); - else - cg.setBrush( role, QBrush( cg.color( role ) ) ); - editPalette.setInactive( cg ); - - setPreviewPalette( editPalette ); -} - -void PaletteEditorAdvanced::mapToDisabledCentralRole( const QColor& c ) -{ - QColorGroup cg = editPalette.disabled(); - cg.setColor( centralFromItem(comboCentral->currentItem()), c ); - editPalette.setDisabled( cg ); - - buildDisabledEffect(); - - setPreviewPalette( editPalette ); -} - -void PaletteEditorAdvanced::mapToDisabledEffectRole( const QColor& c ) -{ - QColorGroup cg = editPalette.disabled(); - cg.setColor( effectFromItem(comboEffect->currentItem()), c ); - editPalette.setDisabled( cg ); - - setPreviewPalette( editPalette ); + QColor c = editPalette.color(groupFromIndex(selectedPalette), centralFromIndex(item)); + buttonCentral->setColor(c); } -void PaletteEditorAdvanced::mapToDisabledPixmapRole( const QPixmap& pm ) +void PaletteEditorAdvanced::onEffect(int item) { - QColorGroup::ColorRole role = centralFromItem(comboCentral->currentItem()); - QColorGroup cg = editPalette.disabled(); - if ( !pm.isNull() ) - cg.setBrush( role, QBrush( cg.color( role ), pm ) ); - else - cg.setBrush( role, QBrush( cg.color( role ) ) ); - - editPalette.setDisabled( cg ); - - setPreviewPalette( editPalette ); + QColor c = editPalette.color(groupFromIndex(selectedPalette), effectFromIndex(item)); + buttonEffect->setColor(c); } -void PaletteEditorAdvanced::buildActiveEffect() +QPalette PaletteEditorAdvanced::buildEffect(QPalette::ColorGroup colorGroup, + const QPalette &basePalette) { - QColorGroup cg = editPalette.active(); - QColor btn = cg.color( QColorGroup::Button ); - - QPalette temp( btn, btn ); - - for (int i = 0; i<5; i++) - cg.setColor( effectFromItem(i), temp.active().color( effectFromItem(i) ) ); + QPalette result(basePalette); - editPalette.setActive( cg ); - setPreviewPalette( editPalette ); + if (colorGroup == QPalette::Active) { + QPalette calculatedPalette(basePalette.color(colorGroup, QPalette::Button), + basePalette.color(colorGroup, QPalette::Window)); - updateColorButtons(); -} + for (int i = 0; i < 5; i++) { + QPalette::ColorRole effectRole = effectFromIndex(i); + result.setColor(colorGroup, effectRole, + calculatedPalette.color(colorGroup, effectRole)); + } + } else { + QColor btn = basePalette.color(colorGroup, QPalette::Button); -void PaletteEditorAdvanced::buildInactive() -{ - editPalette.setInactive( editPalette.active() ); - if ( checkBuildEffect->isChecked() ) - buildInactiveEffect(); - else { - setPreviewPalette( editPalette ); - updateColorButtons(); + result.setColor(colorGroup, QPalette::Light, btn.lighter()); + result.setColor(colorGroup, QPalette::Midlight, btn.lighter(115)); + result.setColor(colorGroup, QPalette::Mid, btn.darker(150)); + result.setColor(colorGroup, QPalette::Dark, btn.darker()); + result.setColor(colorGroup, QPalette::Shadow, Qt::black); } + return result; } -void PaletteEditorAdvanced::buildInactiveEffect() +void PaletteEditorAdvanced::buildEffect(QPalette::ColorGroup colorGroup) { - QColorGroup cg = editPalette.inactive(); - - QColor light, midlight, mid, dark, shadow; - QColor btn = cg.color( QColorGroup::Button ); - - light = btn.light(150); - midlight = btn.light(115); - mid = btn.dark(150); - dark = btn.dark(); - shadow = Qt::black; - - cg.setColor( QColorGroup::Light, light ); - cg.setColor( QColorGroup::Midlight, midlight ); - cg.setColor( QColorGroup::Mid, mid ); - cg.setColor( QColorGroup::Dark, dark ); - cg.setColor( QColorGroup::Shadow, shadow ); - - editPalette.setInactive( cg ); - setPreviewPalette( editPalette ); + editPalette = buildEffect(colorGroup, editPalette); updateColorButtons(); } -void PaletteEditorAdvanced::buildDisabled() +void PaletteEditorAdvanced::build(QPalette::ColorGroup colorGroup) { - QColorGroup cg = editPalette.active(); - cg.setColor( QColorGroup::ButtonText, Qt::darkGray ); - cg.setColor( QColorGroup::WindowText, Qt::darkGray ); - cg.setColor( QColorGroup::Text, Qt::darkGray ); - cg.setColor( QColorGroup::HighlightedText, Qt::darkGray ); - editPalette.setDisabled( cg ); - - if ( checkBuildEffect->isChecked() ) - buildDisabledEffect(); - else { - setPreviewPalette( editPalette ); - updateColorButtons(); - } -} - -void PaletteEditorAdvanced::buildDisabledEffect() -{ - QColorGroup cg = editPalette.disabled(); - - QColor light, midlight, mid, dark, shadow; - QColor btn = cg.color( QColorGroup::Button ); - - light = btn.light(150); - midlight = btn.light(115); - mid = btn.dark(150); - dark = btn.dark(); - shadow = Qt::black; + if (colorGroup != QPalette::Active) { + for (int i = 0; i < QPalette::NColorRoles; i++) + editPalette.setColor(colorGroup, QPalette::ColorRole(i), + editPalette.color(QPalette::Active, QPalette::ColorRole(i))); - cg.setColor( QColorGroup::Light, light ); - cg.setColor( QColorGroup::Midlight, midlight ); - cg.setColor( QColorGroup::Mid, mid ); - cg.setColor( QColorGroup::Dark, dark ); - cg.setColor( QColorGroup::Shadow, shadow ); + if (colorGroup == QPalette::Disabled) { + editPalette.setColor(colorGroup, QPalette::ButtonText, Qt::darkGray); + editPalette.setColor(colorGroup, QPalette::WindowText, Qt::darkGray); + editPalette.setColor(colorGroup, QPalette::Text, Qt::darkGray); + editPalette.setColor(colorGroup, QPalette::HighlightedText, Qt::darkGray); + } - editPalette.setDisabled( cg ); - setPreviewPalette( editPalette ); - updateColorButtons(); -} - -void PaletteEditorAdvanced::setPreviewPalette( const QPalette& pal ) -{ - QColorGroup cg; - - switch (selectedPalette) { - case 0: - default: - cg = pal.active(); - break; - case 1: - cg = pal.inactive(); - break; - case 2: - cg = pal.disabled(); - break; + if (ui->checkBuildEffect->isChecked()) + buildEffect(colorGroup); + else + updateColorButtons(); } - previewPalette.setActive( cg ); - previewPalette.setInactive( cg ); - previewPalette.setDisabled( cg ); } void PaletteEditorAdvanced::updateColorButtons() { - QColor central, effect; - switch (selectedPalette) { - case 0: - default: - central = editPalette.active().color( centralFromItem( comboCentral->currentItem() ) ); - effect = editPalette.active().color( effectFromItem( comboEffect->currentItem() ) ); - break; - case 1: - central = editPalette.inactive().color( centralFromItem( comboCentral->currentItem() ) ); - effect = editPalette.inactive().color( effectFromItem( comboEffect->currentItem() ) ); - break; - case 2: - central = editPalette.disabled().color( centralFromItem( comboCentral->currentItem() ) ); - effect = editPalette.disabled().color( effectFromItem( comboEffect->currentItem() ) ); - break; - } - - buttonCentral->setColor(central); - buttonEffect->setColor(effect); + QPalette::ColorGroup colorGroup = groupFromIndex(selectedPalette); + buttonCentral->setColor(editPalette.color(colorGroup, + centralFromIndex(ui->comboCentral->currentIndex()))); + buttonEffect->setColor(editPalette.color(colorGroup, + effectFromIndex(ui->comboEffect->currentIndex()))); } -void PaletteEditorAdvanced::setPal( const QPalette& pal ) +void PaletteEditorAdvanced::setPal(const QPalette &pal) { editPalette = pal; - setPreviewPalette( pal ); updateColorButtons(); } @@ -503,51 +321,51 @@ QPalette PaletteEditorAdvanced::pal() const return editPalette; } -void PaletteEditorAdvanced::setupBackgroundMode( Qt::BackgroundMode mode ) +void PaletteEditorAdvanced::setupBackgroundRole(QPalette::ColorRole role) { int initRole = 0; - switch( mode ) { - case Qt::PaletteBackground: + switch (role) { + case QPalette::Window: initRole = 0; break; - case Qt::PaletteForeground: + case QPalette::WindowText: initRole = 1; break; - case Qt::PaletteButton: + case QPalette::Base: initRole = 2; break; - case Qt::PaletteBase: + case QPalette::AlternateBase: initRole = 3; break; - case Qt::PaletteText: + case QPalette::ToolTipBase: initRole = 4; break; - case Qt::PaletteBrightText: + case QPalette::ToolTipText: initRole = 5; break; - case Qt::PaletteButtonText: + case QPalette::Text: initRole = 6; break; - case Qt::PaletteHighlight: + case QPalette::Button: initRole = 7; break; - case Qt::PaletteHighlightedText: + case QPalette::ButtonText: initRole = 8; break; - case Qt::PaletteLight: + case QPalette::BrightText: initRole = 9; break; - case Qt::PaletteMidlight: + case QPalette::Highlight: initRole = 10; break; - case Qt::PaletteDark: + case QPalette::HighlightedText: initRole = 11; break; - case Qt::PaletteMid: + case QPalette::Link: initRole = 12; break; - case Qt::PaletteShadow: + case QPalette::LinkVisited: initRole = 13; break; default: @@ -555,36 +373,27 @@ void PaletteEditorAdvanced::setupBackgroundMode( Qt::BackgroundMode mode ) break; } - if ( initRole <= -1 ) return; - - if (initRole > 8 ) { - comboEffect->setCurrentItem( initRole - 9 ); - } - else { - comboCentral->setCurrentItem( initRole ); - } + if (initRole != -1) + ui->comboCentral->setCurrentIndex(initRole); } -QPalette PaletteEditorAdvanced::getPalette( bool *ok, const QPalette &init, - Qt::BackgroundMode mode, QWidget* parent, - const char* name ) +QPalette PaletteEditorAdvanced::getPalette(bool *ok, const QPalette &init, + QPalette::ColorRole backgroundRole, QWidget *parent) { - PaletteEditorAdvanced* dlg = new PaletteEditorAdvanced( parent, name, true ); - dlg->setupBackgroundMode( mode ); + PaletteEditorAdvanced *dlg = new PaletteEditorAdvanced(parent); + dlg->setupBackgroundRole(backgroundRole); - if ( init != QPalette() ) - dlg->setPal( init ); + if (init != QPalette()) + dlg->setPal(init); int resultCode = dlg->exec(); QPalette result = init; - if ( resultCode == QDialog::Accepted ) { - if ( ok ) - *ok = true; + if (resultCode == QDialog::Accepted) result = dlg->pal(); - } else { - if ( ok ) - *ok = false; - } + + if (ok) + *ok = resultCode; + delete dlg; return result; } diff --git a/tools/qtconfig/paletteeditoradvanced.h b/tools/qtconfig/paletteeditoradvanced.h index 317f093..737e685 100644 --- a/tools/qtconfig/paletteeditoradvanced.h +++ b/tools/qtconfig/paletteeditoradvanced.h @@ -42,69 +42,65 @@ #ifndef PALETTEEDITORADVANCED_H #define PALETTEEDITORADVANCED_H -#include "paletteeditoradvancedbase.h" +#include <QtGui/QDialog> QT_BEGIN_NAMESPACE -class PaletteEditorAdvanced : public PaletteEditorAdvancedBase +namespace Ui { + class PaletteEditorAdvanced; +} + +class ColorButton; + +class PaletteEditorAdvanced : public QDialog { Q_OBJECT public: - PaletteEditorAdvanced( QWidget * parent=0, const char * name=0, - bool modal=false, Qt::WindowFlags f=0 ); + PaletteEditorAdvanced(QWidget *parent = 0); ~PaletteEditorAdvanced(); - static QPalette getPalette( bool *ok, const QPalette &pal, Qt::BackgroundMode mode = Qt::PaletteBackground, - QWidget* parent = 0, const char* name = 0 ); + static QPalette getPalette(bool *ok, const QPalette &pal, + QPalette::ColorRole backgroundRole = QPalette::Window, + QWidget *parent = 0); + + static QPalette buildEffect(QPalette::ColorGroup colorGroup, const QPalette &basePalette); protected slots: void paletteSelected(int); - void onCentral( int ); - void onEffect( int ); + void onCentral(int); + void onEffect(int); void onChooseCentralColor(); void onChooseEffectColor(); - void onToggleBuildEffects( bool ); - void onToggleBuildInactive( bool ); - void onToggleBuildDisabled( bool ); + void onToggleBuildEffects(bool); + void onToggleBuildInactive(bool); + void onToggleBuildDisabled(bool); protected: - void mapToActiveCentralRole( const QColor& ); - void mapToActiveEffectRole( const QColor& ); - void mapToActivePixmapRole( const QPixmap& ); - void mapToInactiveCentralRole( const QColor& ); - void mapToInactiveEffectRole( const QColor& ); - void mapToInactivePixmapRole( const QPixmap& ); - void mapToDisabledCentralRole( const QColor& ); - void mapToDisabledEffectRole( const QColor& ); - void mapToDisabledPixmapRole( const QPixmap& ); - - - void buildPalette(); - void buildActiveEffect(); - void buildInactive(); - void buildInactiveEffect(); - void buildDisabled(); - void buildDisabledEffect(); + void buildEffect(QPalette::ColorGroup); + void build(QPalette::ColorGroup); private: - void setPreviewPalette( const QPalette& ); void updateColorButtons(); - void setupBackgroundMode( Qt::BackgroundMode ); + void setupBackgroundRole(QPalette::ColorRole); QPalette pal() const; - void setPal( const QPalette& ); + void setPal(const QPalette &); - QColorGroup::ColorRole centralFromItem( int ); - QColorGroup::ColorRole effectFromItem( int ); + static QPalette::ColorGroup groupFromIndex(int); + static QPalette::ColorRole centralFromIndex(int); + static QPalette::ColorRole effectFromIndex(int); QPalette editPalette; - QPalette previewPalette; + + Ui::PaletteEditorAdvanced *ui; int selectedPalette; + ColorButton *buttonCentral; + ColorButton *buttonEffect; }; QT_END_NAMESPACE -#endif +#endif // PALETTEEDITORADVANCED_H diff --git a/tools/qtconfig/paletteeditoradvanced.ui b/tools/qtconfig/paletteeditoradvanced.ui new file mode 100644 index 0000000..d7835bb --- /dev/null +++ b/tools/qtconfig/paletteeditoradvanced.ui @@ -0,0 +1,416 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <comment>********************************************************************* +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>PaletteEditorAdvanced</class> + <widget class="QDialog" name="PaletteEditorAdvanced"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>239</width> + <height>344</height> + </rect> + </property> + <property name="windowTitle"> + <string>Tune Palette</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="paletteComboLabel"> + <property name="text"> + <string>Select &Palette:</string> + </property> + <property name="buddy"> + <cstring>paletteCombo</cstring> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="paletteCombo"> + <item> + <property name="text"> + <string>Active Palette</string> + </property> + </item> + <item> + <property name="text"> + <string>Inactive Palette</string> + </property> + </item> + <item> + <property name="text"> + <string>Disabled Palette</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="autoGroupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Auto</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="checkBuildInactive"> + <property name="text"> + <string>Build inactive palette from active</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBuildDisabled"> + <property name="text"> + <string>Build disabled palette from active</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupCentral"> + <property name="title"> + <string>Central color &roles</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QComboBox" name="comboCentral"> + <property name="toolTip"> + <string>Choose central color role</string> + </property> + <property name="whatsThis"> + <string><b>Select a color role.</b><p>Available central roles are: <ul> <li>Window - general background color.</li> <li>WindowText - general foreground color. </li> <li>Base - used as background color for e.g. text entry widgets, usually white or another light color. </li> <li>Text - the foreground color used with Base. Usually this is the same as WindowText, in what case it must provide good contrast both with Window and Base. </li> <li>Button - general button background color, where buttons need a background different from Window, as in the Macintosh style. </li> <li>ButtonText - a foreground color used with the Button color. </li> <li>Highlight - a color to indicate a selected or highlighted item. </li> <li>HighlightedText - a text color that contrasts to Highlight. </li> <li>BrightText - a text color that is very different from WindowText and contrasts well with e.g. black. </li> </ul> </p></string> + </property> + <item> + <property name="text"> + <string>Window</string> + </property> + </item> + <item> + <property name="text"> + <string>WindowText</string> + </property> + </item> + <item> + <property name="text"> + <string>Base</string> + </property> + </item> + <item> + <property name="text"> + <string>AlternateBase</string> + </property> + </item> + <item> + <property name="text"> + <string>ToolTipBase</string> + </property> + </item> + <item> + <property name="text"> + <string>ToolTipText</string> + </property> + </item> + <item> + <property name="text"> + <string>Text</string> + </property> + </item> + <item> + <property name="text"> + <string>Button</string> + </property> + </item> + <item> + <property name="text"> + <string>ButtonText</string> + </property> + </item> + <item> + <property name="text"> + <string>BrightText</string> + </property> + </item> + <item> + <property name="text"> + <string>Highlight</string> + </property> + </item> + <item> + <property name="text"> + <string>HighlightedText</string> + </property> + </item> + <item> + <property name="text"> + <string>Link</string> + </property> + </item> + <item> + <property name="text"> + <string>LinkVisited</string> + </property> + </item> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="layoutCentral"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="labelCentral"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>&Select Color:</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupEffect"> + <property name="title"> + <string>3-D shadow &effects</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QCheckBox" name="checkBuildEffect"> + <property name="toolTip"> + <string>Generate shadings</string> + </property> + <property name="whatsThis"> + <string>Check to let 3D-effect colors be calculated from button-color.</string> + </property> + <property name="text"> + <string>Build &from button color</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboEffect"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Choose 3D-effect color role</string> + </property> + <property name="whatsThis"> + <string><b>Select a color role.</b><p>Available effect roles are: <ul> <li>Light - lighter than Button color. </li> <li>Midlight - between Button and Light. </li> <li>Mid - between Button and Dark. </li> <li>Dark - darker than Button. </li> <li>Shadow - a very dark color. </li> </ul></string> + </property> + <item> + <property name="text"> + <string>Light</string> + </property> + </item> + <item> + <property name="text"> + <string>Midlight</string> + </property> + </item> + <item> + <property name="text"> + <string>Mid</string> + </property> + </item> + <item> + <property name="text"> + <string>Dark</string> + </property> + </item> + <item> + <property name="text"> + <string>Shadow</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="layoutEffect"> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="labelEffect"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Select Co&lor:</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PaletteEditorAdvanced</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>238</x> + <y>384</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PaletteEditorAdvanced</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>306</x> + <y>390</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>checkBuildEffect</sender> + <signal>toggled(bool)</signal> + <receiver>comboEffect</receiver> + <slot>setDisabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>82</x> + <y>262</y> + </hint> + <hint type="destinationlabel"> + <x>190</x> + <y>262</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/qtconfig/paletteeditoradvancedbase.cpp b/tools/qtconfig/paletteeditoradvancedbase.cpp deleted file mode 100644 index cc9acb9..0000000 --- a/tools/qtconfig/paletteeditoradvancedbase.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "paletteeditoradvancedbase.h" -#include "colorbutton.h" - -#include <QVariant> - -QT_BEGIN_NAMESPACE - -/* - * Constructs a PaletteEditorAdvancedBase as a child of 'parent', with the - * name 'name' and widget flags set to 'f'. - * - * The dialog will by default be modeless, unless you set 'modal' to - * true to construct a modal dialog. - */ -PaletteEditorAdvancedBase::PaletteEditorAdvancedBase(QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl) - : QDialog(parent, name, modal, fl) -{ - setupUi(this); - - - // signals and slots connections - connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept())); - connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject())); - connect(paletteCombo, SIGNAL(activated(int)), this, SLOT(paletteSelected(int))); - connect(comboCentral, SIGNAL(activated(int)), this, SLOT(onCentral(int))); - connect(buttonCentral, SIGNAL(clicked()), this, SLOT(onChooseCentralColor())); - connect(buttonEffect, SIGNAL(clicked()), this, SLOT(onChooseEffectColor())); - connect(comboEffect, SIGNAL(activated(int)), this, SLOT(onEffect(int))); - connect(checkBuildEffect, SIGNAL(toggled(bool)), this, SLOT(onToggleBuildEffects(bool))); - connect(checkBuildEffect, SIGNAL(toggled(bool)), comboEffect, SLOT(setDisabled(bool))); - connect(checkBuildEffect, SIGNAL(toggled(bool)), buttonEffect, SLOT(setDisabled(bool))); - connect(checkBuildInactive, SIGNAL(toggled(bool)), this, SLOT(onToggleBuildInactive(bool))); - connect(checkBuildDisabled, SIGNAL(toggled(bool)), this, SLOT(onToggleBuildDisabled(bool))); - init(); -} - -/* - * Destroys the object and frees any allocated resources - */ -PaletteEditorAdvancedBase::~PaletteEditorAdvancedBase() -{ - destroy(); - // no need to delete child widgets, Qt does it all for us -} - -/* - * Sets the strings of the subwidgets using the current - * language. - */ -void PaletteEditorAdvancedBase::languageChange() -{ - retranslateUi(this); -} - -void PaletteEditorAdvancedBase::init() -{ -} - -void PaletteEditorAdvancedBase::destroy() -{ -} - -void PaletteEditorAdvancedBase::onCentral(int) -{ - qWarning("PaletteEditorAdvancedBase::onCentral(int): Not implemented yet"); -} - -void PaletteEditorAdvancedBase::onChooseCentralColor() -{ - qWarning("PaletteEditorAdvancedBase::onChooseCentralColor(): Not implemented yet"); -} - -void PaletteEditorAdvancedBase::onChooseEffectColor() -{ - qWarning("PaletteEditorAdvancedBase::onChooseEffectColor(): Not implemented yet"); -} - -void PaletteEditorAdvancedBase::onEffect(int) -{ - qWarning("PaletteEditorAdvancedBase::onEffect(int): Not implemented yet"); -} - -void PaletteEditorAdvancedBase::onToggleBuildDisabled(bool) -{ - qWarning("PaletteEditorAdvancedBase::onToggleBuildDisabled(bool): Not implemented yet"); -} - -void PaletteEditorAdvancedBase::onToggleBuildEffects(bool) -{ - qWarning("PaletteEditorAdvancedBase::onToggleBuildEffects(bool): Not implemented yet"); -} - -void PaletteEditorAdvancedBase::onToggleBuildInactive(bool) -{ - qWarning("PaletteEditorAdvancedBase::onToggleBuildInactive(bool): Not implemented yet"); -} - -void PaletteEditorAdvancedBase::paletteSelected(int) -{ - qWarning("PaletteEditorAdvancedBase::paletteSelected(int): Not implemented yet"); -} - -QT_END_NAMESPACE diff --git a/tools/qtconfig/paletteeditoradvancedbase.ui b/tools/qtconfig/paletteeditoradvancedbase.ui deleted file mode 100644 index 9453be2..0000000 --- a/tools/qtconfig/paletteeditoradvancedbase.ui +++ /dev/null @@ -1,617 +0,0 @@ -<ui version="4.0" stdsetdef="1" > - <author></author> - <comment>********************************************************************* -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -*********************************************************************</comment> - <exportmacro></exportmacro> - <class>PaletteEditorAdvancedBase</class> - <widget class="QDialog" name="PaletteEditorAdvancedBase" > - <property name="objectName" > - <string notr="true" >PaletteEditorAdvancedBase</string> - </property> - <property name="enabled" > - <bool>true</bool> - </property> - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>295</width> - <height>346</height> - </rect> - </property> - <property name="windowTitle" > - <string>Tune Palette</string> - </property> - <property name="sizeGripEnabled" > - <bool>true</bool> - </property> - <property name="whatsThis" stdset="0" > - <string><b>Edit Palette</b><p>Change the palette of the current widget or form.</p><p>Use a generated palette or select colors for each color group and each color role.</p><p>The palette can be tested with different widget layouts in the preview section.</p></string> - </property> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>11</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <layout class="QHBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QLabel" name="TextLabel1" > - <property name="objectName" > - <string notr="true" >TextLabel1</string> - </property> - <property name="text" > - <string>Select &Palette:</string> - </property> - <property name="buddy" stdset="0" > - <cstring>paletteCombo</cstring> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="paletteCombo" > - <property name="objectName" > - <string notr="true" >paletteCombo</string> - </property> - <item> - <property name="text" > - <string>Active Palette</string> - </property> - </item> - <item> - <property name="text" > - <string>Inactive Palette</string> - </property> - </item> - <item> - <property name="text" > - <string>Disabled Palette</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item> - <widget class="Q3ButtonGroup" name="ButtonGroup1" > - <property name="objectName" > - <string notr="true" >ButtonGroup1</string> - </property> - <property name="sizePolicy" > - <sizepolicy> - <hsizetype>5</hsizetype> - <vsizetype>4</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="title" > - <string>Auto</string> - </property> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>11</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QCheckBox" name="checkBuildInactive" > - <property name="objectName" > - <string notr="true" >checkBuildInactive</string> - </property> - <property name="text" > - <string>Build inactive palette from active</string> - </property> - <property name="checked" > - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="checkBuildDisabled" > - <property name="objectName" > - <string notr="true" >checkBuildDisabled</string> - </property> - <property name="text" > - <string>Build disabled palette from active</string> - </property> - <property name="checked" > - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="Q3GroupBox" name="groupCentral" > - <property name="objectName" > - <string notr="true" >groupCentral</string> - </property> - <property name="title" > - <string>Central color &roles</string> - </property> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>11</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QComboBox" name="comboCentral" > - <property name="objectName" > - <string notr="true" >comboCentral</string> - </property> - <property name="toolTip" stdset="0" > - <string>Choose central color role</string> - </property> - <property name="whatsThis" stdset="0" > - <string><b>Select a color role.</b><p>Available central roles are: <ul> <li>Window - general background color.</li> <li>WindowText - general foreground color. </li> <li>Base - used as background color for e.g. text entry widgets, usually white or another light color. </li> <li>Text - the foreground color used with Base. Usually this is the same as WindowText, in what case it must provide good contrast both with Window and Base. </li> <li>Button - general button background color, where buttons need a background different from Window, as in the Macintosh style. </li> <li>ButtonText - a foreground color used with the Button color. </li> <li>Highlight - a color to indicate a selected or highlighted item. </li> <li>HighlightedText - a text color that contrasts to Highlight. </li> <li>BrightText - a text color that is very different from WindowText and contrasts well with e.g. black. </li> </ul> </p></string> - </property> - <item> - <property name="text" > - <string>Window</string> - </property> - </item> - <item> - <property name="text" > - <string>WindowText</string> - </property> - </item> - <item> - <property name="text" > - <string>Button</string> - </property> - </item> - <item> - <property name="text" > - <string>Base</string> - </property> - </item> - <item> - <property name="text" > - <string>Text</string> - </property> - </item> - <item> - <property name="text" > - <string>BrightText</string> - </property> - </item> - <item> - <property name="text" > - <string>ButtonText</string> - </property> - </item> - <item> - <property name="text" > - <string>Highlight</string> - </property> - </item> - <item> - <property name="text" > - <string>HighlightedText</string> - </property> - </item> - </widget> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <spacer name="Horizontal_Spacing1" > - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Horizontal</enum> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="labelCentral" > - <property name="objectName" > - <string notr="true" >labelCentral</string> - </property> - <property name="sizePolicy" > - <sizepolicy> - <hsizetype>1</hsizetype> - <vsizetype>1</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize" > - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="text" > - <string>&Select Color:</string> - </property> - <property name="buddy" stdset="0" > - <cstring>buttonCentral</cstring> - </property> - </widget> - </item> - <item> - <widget class="ColorButton" name="buttonCentral" > - <property name="objectName" > - <string notr="true" >buttonCentral</string> - </property> - <property name="sizePolicy" > - <sizepolicy> - <hsizetype>0</hsizetype> - <vsizetype>0</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="focusPolicy" > - <enum>Qt::TabFocus</enum> - </property> - <property name="toolTip" stdset="0" > - <string>Choose a color</string> - </property> - <property name="whatsThis" stdset="0" > - <string>Choose a color for the selected central color role.</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="Q3GroupBox" name="groupEffect" > - <property name="objectName" > - <string notr="true" >groupEffect</string> - </property> - <property name="title" > - <string>3-D shadow &effects</string> - </property> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>11</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <layout class="QHBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QCheckBox" name="checkBuildEffect" > - <property name="objectName" > - <string notr="true" >checkBuildEffect</string> - </property> - <property name="text" > - <string>Build &from button color</string> - </property> - <property name="checked" > - <bool>true</bool> - </property> - <property name="toolTip" stdset="0" > - <string>Generate shadings</string> - </property> - <property name="whatsThis" stdset="0" > - <string>Check to let 3D-effect colors be calculated from button-color.</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboEffect" > - <property name="objectName" > - <string notr="true" >comboEffect</string> - </property> - <property name="toolTip" stdset="0" > - <string>Choose 3D-effect color role</string> - </property> - <property name="whatsThis" stdset="0" > - <string><b>Select a color role.</b><p>Available effect roles are: <ul> <li>Light - lighter than Button color. </li> <li>Midlight - between Button and Light. </li> <li>Mid - between Button and Dark. </li> <li>Dark - darker than Button. </li> <li>Shadow - a very dark color. </li> </ul></string> - </property> - <item> - <property name="text" > - <string>Light</string> - </property> - </item> - <item> - <property name="text" > - <string>Midlight</string> - </property> - </item> - <item> - <property name="text" > - <string>Mid</string> - </property> - </item> - <item> - <property name="text" > - <string>Dark</string> - </property> - </item> - <item> - <property name="text" > - <string>Shadow</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <spacer name="Horizontal_Spacing3" > - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Horizontal</enum> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="labelEffect" > - <property name="objectName" > - <string notr="true" >labelEffect</string> - </property> - <property name="sizePolicy" > - <sizepolicy> - <hsizetype>1</hsizetype> - <vsizetype>1</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize" > - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="text" > - <string>Select Co&lor:</string> - </property> - <property name="buddy" stdset="0" > - <cstring>buttonEffect</cstring> - </property> - </widget> - </item> - <item> - <widget class="ColorButton" name="buttonEffect" > - <property name="objectName" > - <string notr="true" >buttonEffect</string> - </property> - <property name="sizePolicy" > - <sizepolicy> - <hsizetype>0</hsizetype> - <vsizetype>0</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="focusPolicy" > - <enum>Qt::TabFocus</enum> - </property> - <property name="toolTip" stdset="0" > - <string>Choose a color</string> - </property> - <property name="whatsThis" stdset="0" > - <string>Choose a color for the selected effect color role.</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <spacer name="Horizontal_Spacing2" > - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Horizontal</enum> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="buttonOk" > - <property name="objectName" > - <string notr="true" >buttonOk</string> - </property> - <property name="text" > - <string>OK</string> - </property> - <property name="autoDefault" > - <bool>true</bool> - </property> - <property name="default" > - <bool>true</bool> - </property> - <property name="whatsThis" stdset="0" > - <string>Close dialog and apply all changes.</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="buttonCancel" > - <property name="objectName" > - <string notr="true" >buttonCancel</string> - </property> - <property name="text" > - <string>Cancel</string> - </property> - <property name="autoDefault" > - <bool>true</bool> - </property> - <property name="whatsThis" stdset="0" > - <string>Close dialog and discard all changes.</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <pixmapfunction></pixmapfunction> - <customwidgets> - <customwidget> - <class>ColorButton</class> - <extends></extends> - <header location="local" >colorbutton.h</header> - <sizehint> - <width>40</width> - <height>25</height> - </sizehint> - <container>0</container> - <sizepolicy> - <hordata>5</hordata> - <verdata>5</verdata> - </sizepolicy> - <pixmap>image0</pixmap> - <properties> - <property type="Color" >color</property> - <property type="Pixmap" >pixmap</property> - </properties> - </customwidget> - </customwidgets> - <tabstops> - <tabstop>buttonOk</tabstop> - <tabstop>buttonCancel</tabstop> - <tabstop>paletteCombo</tabstop> - <tabstop>checkBuildInactive</tabstop> - <tabstop>checkBuildDisabled</tabstop> - <tabstop>comboCentral</tabstop> - <tabstop>buttonCentral</tabstop> - <tabstop>checkBuildEffect</tabstop> - <tabstop>comboEffect</tabstop> - <tabstop>buttonEffect</tabstop> - </tabstops> - <images> - <image name="image0" > - <data format="XPM.GZ" length="646" >789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data> - </image> - </images> -</ui> diff --git a/tools/qtconfig/previewframe.cpp b/tools/qtconfig/previewframe.cpp index 944e2f9..2c4a675 100644 --- a/tools/qtconfig/previewframe.cpp +++ b/tools/qtconfig/previewframe.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "previewframe.h" +#include "previewwidget.h" #include <QBoxLayout> #include <QPainter> @@ -47,8 +48,8 @@ QT_BEGIN_NAMESPACE -PreviewFrame::PreviewFrame( QWidget *parent, const char *name ) - : QFrame( parent, name ) +PreviewFrame::PreviewFrame(QWidget *parent) + : QFrame(parent) { setMinimumSize(200, 200); setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); @@ -82,23 +83,22 @@ void PreviewFrame::setPreviewVisible(bool visible) workspace->viewport()->update(); } -Workspace::Workspace(PreviewFrame* parent, const char* name) +Workspace::Workspace(PreviewFrame *parent) : QMdiArea(parent) { previewFrame = parent; PreviewWidget *previewWidget = previewFrame->widget(); - setObjectName(QLatin1String(name)); QMdiSubWindow *frame = addSubWindow(previewWidget, Qt::Window); - frame->move(10,10); + frame->move(10, 10); frame->show(); } -void Workspace::paintEvent( QPaintEvent* ) +void Workspace::paintEvent(QPaintEvent *) { - QPainter p (viewport()); + QPainter p(viewport()); p.fillRect(rect(), palette().color(backgroundRole()).dark()); - p.setPen( QPen( Qt::white ) ); - p.drawText ( 0, height() / 2, width(), height(), Qt::AlignHCenter, previewFrame->previewText()); + p.setPen(QPen(Qt::white)); + p.drawText(0, height() / 2, width(), height(), Qt::AlignHCenter, previewFrame->previewText()); } QT_END_NAMESPACE diff --git a/tools/qtconfig/previewframe.h b/tools/qtconfig/previewframe.h index e7847ca..aab2d56 100644 --- a/tools/qtconfig/previewframe.h +++ b/tools/qtconfig/previewframe.h @@ -42,8 +42,6 @@ #ifndef PREVIEWFRAME_H #define PREVIEWFRAME_H -#include "previewwidget.h" - #include <QMdiArea> QT_BEGIN_NAMESPACE @@ -54,28 +52,29 @@ class Workspace : public QMdiArea Q_OBJECT public: - Workspace( PreviewFrame* parent = 0, const char* name = 0 ); + Workspace(PreviewFrame *parent = 0); ~Workspace() {} protected: - void paintEvent( QPaintEvent* ); + void paintEvent(QPaintEvent *); private: PreviewFrame *previewFrame; }; +class PreviewWidget; class PreviewFrame : public QFrame { Q_OBJECT public: - PreviewFrame( QWidget *parent = 0, const char *name = 0 ); + PreviewFrame(QWidget *parent = 0); void setPreviewPalette(QPalette); void setPreviewVisible(bool val); QString previewText() const; PreviewWidget *widget() const { return previewWidget; } private: - Workspace *workspace; - PreviewWidget *previewWidget; + Workspace *workspace; + PreviewWidget *previewWidget; QString m_previewWindowText; }; diff --git a/tools/qtconfig/previewwidget.cpp b/tools/qtconfig/previewwidget.cpp index 011ee4e..c9066df 100644 --- a/tools/qtconfig/previewwidget.cpp +++ b/tools/qtconfig/previewwidget.cpp @@ -40,32 +40,32 @@ ****************************************************************************/ #include "previewwidget.h" +#include "ui_previewwidget.h" #include <QtEvents> QT_BEGIN_NAMESPACE -PreviewWidget::PreviewWidget( QWidget *parent, const char *name ) - : PreviewWidgetBase( parent, name ) +PreviewWidget::PreviewWidget(QWidget *parent) + : QWidget(parent), ui(new Ui::PreviewWidget) { + ui->setupUi(this); + // install event filter on child widgets - QObjectList l = queryList("QWidget"); - for (int i = 0; i < l.size(); ++i) { - QObject * obj = l.at(i); - obj->installEventFilter(this); - ((QWidget*)obj)->setFocusPolicy(Qt::NoFocus); + QList<QWidget *> l = findChildren<QWidget *>(); + foreach(QWidget *w, l) { + w->installEventFilter(this); + w->setFocusPolicy(Qt::NoFocus); } } - -void PreviewWidget::closeEvent(QCloseEvent *e) +PreviewWidget::~PreviewWidget() { - e->ignore(); + delete ui; } - bool PreviewWidget::eventFilter(QObject *, QEvent *e) { - switch ( e->type() ) { + switch (e->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: @@ -81,4 +81,9 @@ bool PreviewWidget::eventFilter(QObject *, QEvent *e) return false; } +void PreviewWidget::closeEvent(QCloseEvent *e) +{ + e->ignore(); +} + QT_END_NAMESPACE diff --git a/tools/qtconfig/previewwidget.h b/tools/qtconfig/previewwidget.h index 65cfb1d..7b33f77 100644 --- a/tools/qtconfig/previewwidget.h +++ b/tools/qtconfig/previewwidget.h @@ -42,21 +42,29 @@ #ifndef PREVIEWWIDGET_H #define PREVIEWWIDGET_H -#include "previewwidgetbase.h" +#include <QtGui/QWidget> QT_BEGIN_NAMESPACE -class PreviewWidget : public PreviewWidgetBase +namespace Ui { + class PreviewWidget; +} + + +class PreviewWidget : public QWidget { Q_OBJECT public: - PreviewWidget( QWidget *parent = 0, const char *name = 0 ); + PreviewWidget(QWidget *parent = 0); + ~PreviewWidget(); - void closeEvent(QCloseEvent *); bool eventFilter(QObject *, QEvent *); +private: + void closeEvent(QCloseEvent *); + Ui::PreviewWidget *ui; }; QT_END_NAMESPACE -#endif +#endif // PREVIEWWIDGET_H diff --git a/tools/qtconfig/previewwidget.ui b/tools/qtconfig/previewwidget.ui new file mode 100644 index 0000000..4bb7a1f --- /dev/null +++ b/tools/qtconfig/previewwidget.ui @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <comment>********************************************************************* +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>PreviewWidget</class> + <widget class="QWidget" name="PreviewWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>398</width> + <height>282</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Preview Window</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QGroupBox" name="GroupBox1"> + <property name="title"> + <string>GroupBox</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>11</number> + </property> + <item> + <widget class="QRadioButton" name="RadioButton1"> + <property name="text"> + <string>RadioButton1</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="RadioButton2"> + <property name="text"> + <string>RadioButton2</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="RadioButton3"> + <property name="text"> + <string>RadioButton3</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="GroupBox2"> + <property name="title"> + <string>GroupBox2</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>11</number> + </property> + <item> + <widget class="QCheckBox" name="CheckBox1"> + <property name="text"> + <string>CheckBox1</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="CheckBox2"> + <property name="text"> + <string>CheckBox2</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QProgressBar" name="ProgressBar1"> + <property name="value"> + <number>50</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLineEdit" name="LineEdit1"> + <property name="text"> + <string>LineEdit</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="ComboBox1"> + <item> + <property name="text"> + <string>ComboBox</string> + </property> + </item> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QSpinBox" name="SpinBox1"/> + </item> + <item> + <widget class="QPushButton" name="PushButton1"> + <property name="text"> + <string>PushButton</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QScrollBar" name="ScrollBar1"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="Slider1"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QTextEdit" name="textView"> + <property name="maximumSize"> + <size> + <width>32767</width> + <height>55</height> + </size> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="html"> + <string><p><a href="http://qt.nokia.com">http://qt.nokia.com</a></p> +<p><a href="http://www.kde.org">http://www.kde.org</a></p></string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="Spacer2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tools/qtconfig/previewwidgetbase.ui b/tools/qtconfig/previewwidgetbase.ui deleted file mode 100644 index 8d36736..0000000 --- a/tools/qtconfig/previewwidgetbase.ui +++ /dev/null @@ -1,340 +0,0 @@ -<ui version="4.0" stdsetdef="1" > - <author></author> - <comment>********************************************************************* -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -*********************************************************************</comment> - <exportmacro></exportmacro> - <class>PreviewWidgetBase</class> - <widget class="QWidget" name="PreviewWidgetBase" > - <property name="objectName" > - <string notr="true" >PreviewWidgetBase</string> - </property> - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>378</width> - <height>236</height> - </rect> - </property> - <property name="sizePolicy" > - <sizepolicy> - <hsizetype>1</hsizetype> - <vsizetype>1</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="windowTitle" > - <string>Preview Window</string> - </property> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>11</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <layout class="QHBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="Q3ButtonGroup" name="ButtonGroup1" > - <property name="objectName" > - <string notr="true" >ButtonGroup1</string> - </property> - <property name="title" > - <string>ButtonGroup</string> - </property> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>11</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QRadioButton" name="RadioButton1" > - <property name="objectName" > - <string notr="true" >RadioButton1</string> - </property> - <property name="text" > - <string>RadioButton1</string> - </property> - <property name="checked" > - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QRadioButton" name="RadioButton2" > - <property name="objectName" > - <string notr="true" >RadioButton2</string> - </property> - <property name="text" > - <string>RadioButton2</string> - </property> - </widget> - </item> - <item> - <widget class="QRadioButton" name="RadioButton3" > - <property name="objectName" > - <string notr="true" >RadioButton3</string> - </property> - <property name="text" > - <string>RadioButton3</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="Q3ButtonGroup" name="ButtonGroup2" > - <property name="objectName" > - <string notr="true" >ButtonGroup2</string> - </property> - <property name="title" > - <string>ButtonGroup2</string> - </property> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>11</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QCheckBox" name="CheckBox1" > - <property name="objectName" > - <string notr="true" >CheckBox1</string> - </property> - <property name="text" > - <string>CheckBox1</string> - </property> - <property name="checked" > - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="CheckBox2" > - <property name="objectName" > - <string notr="true" >CheckBox2</string> - </property> - <property name="text" > - <string>CheckBox2</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QProgressBar" name="ProgressBar1" > - <property name="objectName" > - <string notr="true" >ProgressBar1</string> - </property> - <property name="value" > - <number>50</number> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QVBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QLineEdit" name="LineEdit1" > - <property name="objectName" > - <string notr="true" >LineEdit1</string> - </property> - <property name="text" > - <string>LineEdit</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="ComboBox1" > - <property name="objectName" > - <string notr="true" >ComboBox1</string> - </property> - <item> - <property name="text" > - <string>ComboBox</string> - </property> - </item> - </widget> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="objectName" > - <string notr="true" >unnamed</string> - </property> - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QSpinBox" name="SpinBox1" > - <property name="objectName" > - <string notr="true" >SpinBox1</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="PushButton1" > - <property name="objectName" > - <string notr="true" >PushButton1</string> - </property> - <property name="text" > - <string>PushButton</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QScrollBar" name="ScrollBar1" > - <property name="objectName" > - <string notr="true" >ScrollBar1</string> - </property> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QSlider" name="Slider1" > - <property name="objectName" > - <string notr="true" >Slider1</string> - </property> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QTextEdit" name="textView" > - <property name="objectName" > - <string notr="true" >textView</string> - </property> - <property name="maximumSize" > - <size> - <width>32767</width> - <height>50</height> - </size> - </property> - <property name="readOnly" > - <bool>true</bool> - </property> - <property name="text" > - <string><p> -<a href="http://qt.nokia.com">http://qt.nokia.com</a> -</p> -<p> -<a href="http://www.kde.org">http://www.kde.org</a> -</p></string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </item> - <item> - <spacer name="Spacer2" > - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Vertical</enum> - </property> - </spacer> - </item> - </layout> - </widget> - <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> -</ui> diff --git a/tools/qtconfig/qtconfig.pro b/tools/qtconfig/qtconfig.pro index d1fd320..cb06e5a 100644 --- a/tools/qtconfig/qtconfig.pro +++ b/tools/qtconfig/qtconfig.pro @@ -1,11 +1,10 @@ TEMPLATE = app -CONFIG += qt warn_on x11 +CONFIG += qt warn_on x11 build_all:!build_pass { CONFIG -= build_all CONFIG += release } LANGUAGE = C++ -QT += qt3support contains(QT_CONFIG, gstreamer):LIBS += $$QT_LIBS_GSTREAMER -lgstinterfaces-0.10 -lgstvideo-0.10 -lgstbase-0.10 contains(QT_CONFIG, gstreamer):QMAKE_CXXFLAGS += $$QT_CFLAGS_GSTREAMER @@ -13,19 +12,17 @@ contains(QT_CONFIG, phonon) { QT += phonon DEFINES += HAVE_PHONON } -SOURCES += colorbutton.cpp main.cpp previewframe.cpp previewwidget.cpp mainwindow.cpp paletteeditoradvanced.cpp \ - mainwindowbase.cpp paletteeditoradvancedbase.cpp previewwidgetbase.cpp -HEADERS += colorbutton.h previewframe.h previewwidget.h mainwindow.h paletteeditoradvanced.h \ - mainwindowbase.h paletteeditoradvancedbase.h previewwidgetbase.h +SOURCES += colorbutton.cpp main.cpp previewframe.cpp previewwidget.cpp mainwindow.cpp paletteeditoradvanced.cpp +HEADERS += colorbutton.h previewframe.h previewwidget.h mainwindow.h paletteeditoradvanced.h -FORMS = mainwindowbase.ui paletteeditoradvancedbase.ui previewwidgetbase.ui +FORMS = mainwindow.ui paletteeditoradvanced.ui previewwidget.ui RESOURCES = qtconfig.qrc PROJECTNAME = Qt Configuration -TARGET = qtconfig -DESTDIR = ../../bin +TARGET = qtconfig +DESTDIR = ../../bin target.path=$$[QT_INSTALL_BINS] INSTALLS += target -INCLUDEPATH += . -DBFILE = qtconfig.db +INCLUDEPATH += . +DBFILE = qtconfig.db diff --git a/tools/qtestlib/wince/cetest/bootstrapped.pri b/tools/qtestlib/wince/cetest/bootstrapped.pri index b9c4b2b..56c8ab7 100644 --- a/tools/qtestlib/wince/cetest/bootstrapped.pri +++ b/tools/qtestlib/wince/cetest/bootstrapped.pri @@ -4,11 +4,14 @@ SOURCES += \ $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystementry.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine_win.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemiterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \ diff --git a/tools/qtestlib/wince/cetest/deployment.cpp b/tools/qtestlib/wince/cetest/deployment.cpp index f11600c..6356e5b 100644 --- a/tools/qtestlib/wince/cetest/deployment.cpp +++ b/tools/qtestlib/wince/cetest/deployment.cpp @@ -227,9 +227,9 @@ void DeploymentHandler::initProjectDeploy(QMakeProject* project, DeploymentList return; for (int it = 0; it < list.size(); ++it) { - QString argSource = list.at(it) + QString(".sources"); + QString argSource = list.at(it); QString argPath = list.at(it) + QString(".path"); - if ((project->values(argSource).isEmpty() || project->values(argPath).isEmpty()) && list.at(it) != "deploy") { + if (((project->values(argSource + QString(".files")).isEmpty() && project->values(argSource + QString(".sources")).isEmpty()) || project->values(argPath).isEmpty()) && list.at(it) != "deploy") { debugOutput(QString::fromLatin1("cannot deploy \"%1\" because of missing data.").arg(list.at(it)), 0); continue; } @@ -240,7 +240,7 @@ void DeploymentHandler::initProjectDeploy(QMakeProject* project, DeploymentList if (!addPath.startsWith("/") && !addPath.startsWith(QLatin1String("\\"))) addPath = targetPath + "/" + addPath; - QStringList addSources = project->values(argSource); + QStringList addSources = project->values(argSource + QString(".files")) + project->values(argSource + QString(".sources")); addSources.replaceInStrings(QLatin1String("/"), QLatin1String("\\")); for(int index=0; index < addSources.size(); ++index) { QString dirstr = qmake_getpwd(); @@ -264,7 +264,7 @@ void DeploymentHandler::initProjectDeploy(QMakeProject* project, DeploymentList continue; } QString appendedQmakeDeploy = QString::fromLatin1("_q_make_additional_deploy_%1").arg(addQMakeDeployCounter++); - project->parse(appendedQmakeDeploy + QLatin1String(".sources = \"") + wildInfo.absoluteFilePath()); + project->parse(appendedQmakeDeploy + QLatin1String(".files = \"") + wildInfo.absoluteFilePath()); project->parse(appendedQmakeDeploy + QLatin1String(".path = \"") + addPath); list.append(appendedQmakeDeploy); } @@ -276,7 +276,7 @@ void DeploymentHandler::initProjectDeploy(QMakeProject* project, DeploymentList QStringList additionalEntries = additionalDir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::NoSymLinks); foreach(QString item, additionalEntries) { QString appendedDeploy = QString::fromLatin1("_q_make_additional_deploy_%1").arg(addQMakeDeployCounter++); - project->parse(appendedDeploy + QLatin1String(".sources = \"") + Option::fixPathToLocalOS(additionalDir.absoluteFilePath(item)) + QLatin1String("\"")); + project->parse(appendedDeploy + QLatin1String(".files = \"") + Option::fixPathToLocalOS(additionalDir.absoluteFilePath(item)) + QLatin1String("\"")); QString appendTargetPath = project->values(argPath).join(QLatin1String(" ")); if (appendTargetPath == QLatin1String(".")) appendTargetPath = filestr; diff --git a/tools/qtestlib/wince/cetest/deployment.h b/tools/qtestlib/wince/cetest/deployment.h index f3645e0..a5ef32d 100644 --- a/tools/qtestlib/wince/cetest/deployment.h +++ b/tools/qtestlib/wince/cetest/deployment.h @@ -72,4 +72,4 @@ private: inline void DeploymentHandler::setConnection(AbstractRemoteConnection *connection) { m_connection = connection; } inline AbstractRemoteConnection* DeploymentHandler::connection() const { return m_connection; } -#endif
\ No newline at end of file +#endif diff --git a/tools/qvfb/qvfb.pro b/tools/qvfb/qvfb.pro index c101d00..ca8f4f4 100644 --- a/tools/qvfb/qvfb.pro +++ b/tools/qvfb/qvfb.pro @@ -8,7 +8,7 @@ DESTDIR = ../../bin target.path=$$[QT_INSTALL_BINS] INSTALLS += target -DEPENDPATH = ../../include +DEPENDPATH += ../../include INCLUDEPATH += ../../src/gui/embedded FORMS = config.ui @@ -20,8 +20,8 @@ HEADERS = qvfb.h \ qvfbprotocol.h \ qvfbshmem.h \ qvfbmmap.h \ - ../../src/gui/embedded/qvfbhdr.h \ ../../src/gui/embedded/qlock_p.h \ + ../../src/gui/embedded/qwslock_p.h \ ../../src/gui/embedded/qwssignalhandler_p.h SOURCES = qvfb.cpp \ @@ -33,8 +33,15 @@ SOURCES = qvfb.cpp \ qvfbshmem.cpp \ qvfbmmap.cpp \ ../../src/gui/embedded/qlock.cpp \ + ../../src/gui/embedded/qwslock.cpp \ ../../src/gui/embedded/qwssignalhandler.cpp +!embedded { + DEFINES += QT_NO_QWS_SIGNALHANDLER + HEADERS += ../../src/gui/embedded/qlock_p.h + SOURCES += ../../src/gui/embedded/qlock.cpp +} + include(../shared/deviceskin/deviceskin.pri) contains(QT_CONFIG, opengl) { diff --git a/tools/qvfb/qvfbmmap.cpp b/tools/qvfb/qvfbmmap.cpp index 7e80e37..01c1d9c 100644 --- a/tools/qvfb/qvfbmmap.cpp +++ b/tools/qvfb/qvfbmmap.cpp @@ -48,9 +48,7 @@ #include <unistd.h> #include <sys/ipc.h> #include <sys/types.h> -#include <sys/shm.h> #include <sys/stat.h> -#include <sys/sem.h> #include <sys/mman.h> #include <fcntl.h> #include <errno.h> diff --git a/tools/qvfb/qvfbshmem.cpp b/tools/qvfb/qvfbshmem.cpp index a03b25d..c9a4293 100644 --- a/tools/qvfb/qvfbshmem.cpp +++ b/tools/qvfb/qvfbshmem.cpp @@ -39,10 +39,11 @@ ** ****************************************************************************/ -#include "qlock_p.h" +#include <qplatformdefs.h> #include "qvfbshmem.h" #include "qvfbhdr.h" +#include "qlock_p.h" #include <QFile> #include <QTimer> @@ -53,8 +54,6 @@ #include <sys/types.h> #include <sys/shm.h> #include <sys/stat.h> -#include <sys/sem.h> -#include <sys/mman.h> #include <fcntl.h> #include <errno.h> #include <math.h> @@ -69,27 +68,40 @@ QT_BEGIN_NAMESPACE // live. static QString qws_dataDir(int qws_display_id) { - QByteArray dataDir = QT_VFB_DATADIR(qws_display_id).toLocal8Bit(); - if (mkdir(dataDir, 0700)) { + static QString result; + if (!result.isEmpty()) + return result; + result = QT_VFB_DATADIR(qws_display_id); + QByteArray dataDir = result.toLocal8Bit(); + +#if defined(Q_OS_INTEGRITY) + /* ensure filesystem is ready before starting requests */ + WaitForFileSystemInitialization(); +#endif + + if (QT_MKDIR(dataDir, 0700)) { if (errno != EEXIST) { qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData()); } } - struct stat buf; - if (lstat(dataDir, &buf)) + QT_STATBUF buf; + if (QT_LSTAT(dataDir, &buf)) qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData()); if (!S_ISDIR(buf.st_mode)) qFatal("%s is not a directory", dataDir.constData()); + +#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) && !defined(Q_OS_QNX) if (buf.st_uid != getuid()) qFatal("Qt for Embedded Linux data directory is not owned by user %uh", getuid()); if ((buf.st_mode & 0677) != 0600) qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData()); - dataDir += "/"; +#endif - return QString(dataDir); + result.append(QLatin1Char('/')); + return result; } @@ -130,20 +142,10 @@ QShMemViewProtocol::QShMemViewProtocol(int displayid, const QSize &s, qws_dataDir(displayid); - QString oldPipe = "/tmp/qtembedded-" + username + "/" + QString("QtEmbedded-%1").arg(displayid); - int oldPipeSemkey = ftok(oldPipe.toLatin1().constData(), 'd'); - if (oldPipeSemkey != -1) { - int oldPipeLockId = semget(oldPipeSemkey, 0, 0); - if (oldPipeLockId >= 0){ - sembuf sops; - sops.sem_num = 0; - sops.sem_op = 1; - sops.sem_flg = SEM_UNDO; - int rv; - do { - rv = semop(lockId,&sops,1); - } while (rv == -1 && errno == EINTR); - + { + QString oldPipe = "/tmp/qtembedded-" + username + "/" + QString("QtEmbedded-%1").arg(displayid); + QLock oldPipeLock(oldPipe, 'd', false); + if (oldPipeLock.isValid()) { perror("QShMemViewProtocol::QShMemViewProtocol"); qFatal("Cannot create lock file as an old version of QVFb has " "opened %s. Close other QVFb and try again", diff --git a/tools/qvfb/qvfbview.cpp b/tools/qvfb/qvfbview.cpp index 3f13ecc..91c5380 100644 --- a/tools/qvfb/qvfbview.cpp +++ b/tools/qvfb/qvfbview.cpp @@ -61,12 +61,7 @@ #include <stdlib.h> #include <unistd.h> -#include <sys/ipc.h> #include <sys/types.h> -#include <sys/shm.h> -#include <sys/stat.h> -#include <sys/sem.h> -#include <fcntl.h> #include <errno.h> #include <math.h> diff --git a/tools/runonphone/codasignalhandler.cpp b/tools/runonphone/codasignalhandler.cpp new file mode 100644 index 0000000..0d086b5 --- /dev/null +++ b/tools/runonphone/codasignalhandler.cpp @@ -0,0 +1,579 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QCoreApplication> +#include <QDebug> +#include <QDir> +#include <QFile> +#include <QObject> +#include <QTimer> +#include "codasignalhandler.h" + +static const quint64 DEFAULT_CHUNK_SIZE = 40000; + +class CodaSignalHandlerPrivate +{ + friend class CodaSignalHandler; +public: + CodaSignalHandlerPrivate(); + ~CodaSignalHandlerPrivate(); +private: + SymbianUtils::CodaDevicePtr codaDevice; + QEventLoop *eventLoop; + QTextStream out; + QTextStream err; + int loglevel; + int timeout; + int result; + CodaAction action; + QString copySrcFileName; + QString copyDstFileName; + QString dlSrcFileName; + QString dlDstFileName; + QString appFileName; + QString commandLineArgs; + QString serialPortName; + QString appID; + QByteArray remoteFileHandle; + QScopedPointer<QFile> localFile; + QScopedPointer<QFile> remoteFile; + quint64 putChunkSize; + quint64 putLastChunkSize; + quint64 remoteBytesLeft; + quint64 remoteFileSize; + bool putWriteOk; + bool connected; + bool debugSessionControl; +}; + +CodaSignalHandlerPrivate::CodaSignalHandlerPrivate() + : eventLoop(0), + out(stdout), + err(stderr), + loglevel(0), + timeout(0), + result(0), + action(ActionPingOnly), + putChunkSize(DEFAULT_CHUNK_SIZE), + putLastChunkSize(0), + remoteBytesLeft(0), + remoteFileSize(0), + putWriteOk(false), + connected(false), + debugSessionControl(false) +{ +} + +CodaSignalHandlerPrivate::~CodaSignalHandlerPrivate() +{ + delete eventLoop; + out.flush(); + err.flush(); +} + +void CodaSignalHandler::error(const QString &errorMessage) +{ + reportError(tr("CODA error: %1").arg(errorMessage)); +} + +void CodaSignalHandler::logMessage(const QString &logMessage) +{ + reportMessage(tr("CODA log: %1").arg(logMessage)); +} + +void CodaSignalHandler::serialPong(const QString &codaVersion) +{ + reportMessage(tr("CODA version: %1").arg(codaVersion)); +} + +void CodaSignalHandler::tcfEvent(const Coda::CodaEvent &event) +{ + reportMessage(tr("CODA event: Type: %1 Message: %2").arg(event.type()).arg(event.toString())); + + switch (event.type()) { + case Coda::CodaEvent::LocatorHello: + handleConnected(event); + break; + case Coda::CodaEvent::ProcessExitedEvent: + handleAppExited(event); + break; + default: + reportMessage(tr("CODA unhandled event: Type: %1 Message: %2").arg(event.type()).arg(event.toString())); + break; + } +} + +void CodaSignalHandler::terminate() +{ + if (d->codaDevice) { + disconnect(d->codaDevice.data(), 0, this, 0); + SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(d->codaDevice); + } +} + +void CodaSignalHandler::finished() +{ + if (d->eventLoop) + d->eventLoop->exit(); +} + +void CodaSignalHandler::timeout() +{ + reportError(tr("Unable to connect to CODA device. Operation timed out.")); +} + +int CodaSignalHandler::run() +{ + d->codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getCodaDevice(d->serialPortName); + bool ok = d->codaDevice && d->codaDevice->device()->isOpen(); + if (!ok) { + QString deviceError = "No such port"; + if (d->codaDevice) + deviceError = d->codaDevice->device()->errorString(); + reportError(tr("Could not open serial device: ").arg(deviceError)); + SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(d->codaDevice); + return 1; + } + + if (d->loglevel > 1) { + d->codaDevice->setVerbose(1); + } + + connect(d->codaDevice.data(), SIGNAL(error(const QString &)), this, SLOT(error(const QString &))); + connect(d->codaDevice.data(), SIGNAL(logMessage(const QString &)), this, SLOT(logMessage(const QString &))); + connect(d->codaDevice.data(), SIGNAL(serialPong(const QString &)), this, SLOT(serialPong(const QString &))); + connect(d->codaDevice.data(), SIGNAL(tcfEvent(const Coda::CodaEvent &)), this, SLOT(tcfEvent(const Coda::CodaEvent &))); + connect(this, SIGNAL(done()), this, SLOT(finished())); + + d->codaDevice->sendSerialPing(false); + if (d->timeout > 0) + QTimer::singleShot(d->timeout, this, SLOT(timeout())); + d->eventLoop = new QEventLoop(); + d->eventLoop->exec(); + int result = d->result; + reportMessage(tr("Done.")); + disconnect(d->codaDevice.data(), 0, this, 0); + SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(d->codaDevice); + + QCoreApplication::quit(); + return result; +} + +void CodaSignalHandler::setActionType(CodaAction action) +{ + d->action = CodaAction(d->action | action); +} + +void CodaSignalHandler::setAppFileName(const QString &fileName) +{ + d->appFileName = fileName; +} + +void CodaSignalHandler::setCodaDevice(SymbianUtils::CodaDevicePtr &codaDevice) +{ + d->codaDevice = codaDevice; +} + +void CodaSignalHandler::setCommandLineArgs(const QString &args) +{ + d->commandLineArgs = args; +} + +void CodaSignalHandler::setCopyFileName(const QString &srcName, const QString &dstName) +{ + d->copySrcFileName = srcName; + d->copyDstFileName = dstName; +} + +void CodaSignalHandler::setDownloadFileName(const QString &srcName, const QString &dstName) +{ + d->dlSrcFileName = srcName; + d->dlDstFileName = dstName; +} + +void CodaSignalHandler::setLogLevel(int level) +{ + d->loglevel = level; +} + +void CodaSignalHandler::setSerialPortName(const QString &serialPortName) +{ + d->serialPortName = serialPortName; +} + +void CodaSignalHandler::setTimeout(const int msec) +{ + d->timeout = msec; +} + +void CodaSignalHandler::closeFile() +{ + d->remoteFile.reset(); + if (!d->codaDevice) { + emit done(); + return; + } + + d->codaDevice->sendFileSystemCloseCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleFileSystemClose), + d->remoteFileHandle); +} + +void CodaSignalHandler::handleConnected(const Coda::CodaEvent &event) +{ + if (d->connected) + return; + + const Coda::CodaLocatorHelloEvent &hEvent = static_cast<const Coda::CodaLocatorHelloEvent &>(event); + QStringList services = hEvent.services(); + if (services.contains("DebugSessionControl")) { + d->debugSessionControl = true; + } + d->connected = true; + handleActions(); +} + +void CodaSignalHandler::handleActions() +{ + if (d->action & ActionCopy) { + initFileSending(); + } else if (d->action & ActionInstall) { + initFileInstallation(); + } else if (d->action & ActionRun) { + initAppRunning(); + } else if (d->action & ActionDownload) { + initFileDownloading(); + } else { + emit done(); + } +} + +void CodaSignalHandler::handleAppExited(const Coda::CodaEvent &event) +{ + const Coda::CodaProcessExitedEvent &pEvent = static_cast<const Coda::CodaProcessExitedEvent &>(event); + QString id = pEvent.idString(); + if (!id.compare(d->appID, Qt::CaseInsensitive)) { + d->codaDevice->sendDebugSessionControlSessionEndCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleDebugSessionControlEnd)); + d->action = static_cast<CodaAction>(d->action & ~ActionRun); + handleActions(); + } +} + +void CodaSignalHandler::handleAppRunning(const Coda::CodaCommandResult &result) +{ + if (result.type == Coda::CodaCommandResult::SuccessReply) { + reportMessage(tr("Running...")); + + Coda::JsonValue value = result.values.at(0); + readAppId(value); + } else { + reportError(tr("Launch failed: %1").arg(result.toString())); + } +} + +void CodaSignalHandler::handleDebugSessionControlEnd(const Coda::CodaCommandResult &result) +{ + if (result.type == Coda::CodaCommandResult::SuccessReply) { + // nothing to do + } +} + +void CodaSignalHandler::handleDebugSessionControlStart(const Coda::CodaCommandResult &result) +{ + if (result.type == Coda::CodaCommandResult::SuccessReply) { + d->codaDevice->sendRunProcessCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleAppRunning), + d->appFileName.toAscii(), + d->commandLineArgs.split(' ')); + reportMessage(tr("Launching %1...").arg(QFileInfo(d->appFileName).fileName())); + } else { + reportError(tr("Failed to start CODA debug session control.")); + } +} + +void CodaSignalHandler::handleFileSystemClose(const Coda::CodaCommandResult &result) +{ + if (result.type == Coda::CodaCommandResult::SuccessReply) { + reportMessage(tr("File closed.")); + if (d->action & ActionCopy) { + d->action = static_cast<CodaAction>(d->action & ~ActionCopy); + } else if (d->action & ActionDownload) { + d->action = static_cast<CodaAction>(d->action & ~ActionDownload); + } + handleActions(); + } else { + reportError(tr("Failed to close the remote file: %1").arg(result.toString())); + } +} + +void CodaSignalHandler::handleFileSystemOpen(const Coda::CodaCommandResult &result) +{ + if (result.type != Coda::CodaCommandResult::SuccessReply) { + reportError(tr("Could not open remote file: %1").arg(result.errorString())); + return; + } + + if (result.values.size() < 1 || result.values.at(0).data().isEmpty()) { + reportError(tr("Internal error: No filehandle obtained")); + return; + } + + if (d->action & ActionCopy) { + d->remoteFileHandle = result.values.at(0).data(); + d->remoteFile.reset(new QFile(d->copySrcFileName)); + if (!d->remoteFile->open(QIODevice::ReadOnly)) { // Should not fail, was checked before + reportError(tr("Could not open local file %1").arg(d->copySrcFileName)); + return; + } + putSendNextChunk(); + } else if (d->action & ActionDownload) { + d->remoteFileHandle = result.values.at(0).data(); + d->localFile.reset(new QFile(d->dlDstFileName)); + // remove any existing file with the same name + if (d->localFile->exists() && !d->localFile->remove()) { + reportError(tr("Could not create host file: %1 due to error: %2").arg(d->localFile->fileName(), d->localFile->errorString())); + return; + } + // open local file in write-only mode + if (!d->localFile->open(QFile::WriteOnly)) { + reportError(tr("Could not open host file for writing: %1 due to error: %2").arg(d->localFile->fileName(), d->localFile->errorString())); + return; + } + d->codaDevice->sendFileSystemFstatCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleFileSystemStart), + d->remoteFileHandle); + } +} + +void CodaSignalHandler::handleFileSystemRead(const Coda::CodaCommandResult &result) +{ + if (result.type != Coda::CodaCommandResult::SuccessReply || result.values.size() != 2) { + reportError(tr("Could not read remote file: %1").arg(result.errorString())); + return; + } + + QByteArray data = QByteArray::fromBase64(result.values.at(0).data()); + bool eof = result.values.at(1).toVariant().toBool(); + qint64 written = d->localFile->write(data); + if (written < 0) { + reportError(tr("Could not write data to host file: %1 due to error: %2").arg(d->localFile->fileName(), d->localFile->errorString())); + return; + } + + d->remoteBytesLeft -= written; + if (!eof && d->remoteBytesLeft > 0) { + readNextChunk(); + } + else { + d->localFile->flush(); + d->localFile->close(); + closeFile(); + } +} + +void CodaSignalHandler::handleFileSystemStart(const Coda::CodaCommandResult &result) +{ + if (result.type != Coda::CodaCommandResult::SuccessReply) { + reportError(tr("Could not open remote file: %1").arg(result.errorString())); + return; + } + + if (result.values.size() < 1 || result.values.at(0).children().isEmpty()) { + reportError(tr("Could not get file attributes")); + return; + } + + Coda::JsonValue val = result.values.at(0).findChild("Size"); + d->remoteFileSize = val.isValid() ? val.data().toLong() : -1L; + if (d->remoteFileSize < 0) { + reportError(tr("Could not get file size")); + return; + } + + d->remoteBytesLeft = d->remoteFileSize; + readNextChunk(); +} + +void CodaSignalHandler::handleFileSystemWrite(const Coda::CodaCommandResult &result) +{ + // Close remote file even if copy fails + d->putWriteOk = result; + if (!d->putWriteOk) { + QString fileName = QFileInfo(d->copyDstFileName).fileName(); + reportError(tr("Could not write to file %1 on device: %2").arg(fileName).arg(result.errorString())); + } + + if (!d->putWriteOk || d->putLastChunkSize < d->putChunkSize) { + closeFile(); + } else { + putSendNextChunk(); + } +} + +void CodaSignalHandler::handleSymbianInstall(const Coda::CodaCommandResult &result) +{ + if (result.type == Coda::CodaCommandResult::SuccessReply) { + reportMessage(tr("Installation has finished.")); + d->action = static_cast<CodaAction>(d->action & ~ActionInstall); + handleActions(); + } else { + reportError(tr("Installation failed: %1").arg(result.errorString())); + } +} + +void CodaSignalHandler::initAppRunning() +{ + if (!d->codaDevice || d->appFileName.isEmpty()) { + emit done(); + return; + } + + if (!d->debugSessionControl) { + reportError(tr("CODA DebugSessionControl service not found, please update to CODA v4.0.23 or later.")); + } + + d->codaDevice->sendDebugSessionControlSessionStartCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleDebugSessionControlStart)); +} + +void CodaSignalHandler::initFileDownloading() +{ + if (!d->codaDevice || d->dlSrcFileName.isEmpty()) { + emit done(); + return; + } + + d->codaDevice->sendFileSystemOpenCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleFileSystemOpen), + d->dlSrcFileName.toAscii(), Coda::CodaDevice::FileSystem_TCF_O_READ); + reportMessage(tr("Downloading %1...").arg(QFileInfo(d->dlSrcFileName).fileName())); +} + +void CodaSignalHandler::initFileInstallation() +{ + if (!d->codaDevice || d->copyDstFileName.isEmpty()) { + emit done(); + return; + } + + QString installationDrive = "C"; + d->codaDevice->sendSymbianInstallSilentInstallCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleSymbianInstall), + d->copyDstFileName.toAscii(), + installationDrive.toAscii()); + reportMessage(tr("Installing package \"%1\" on drive %2...").arg(QFileInfo(d->copyDstFileName).fileName(), installationDrive)); +} + +void CodaSignalHandler::initFileSending() +{ + if (!d->codaDevice || d->copySrcFileName.isEmpty()) { + emit done(); + return; + } + + const unsigned flags = + Coda::CodaDevice::FileSystem_TCF_O_WRITE + |Coda::CodaDevice::FileSystem_TCF_O_CREAT + |Coda::CodaDevice::FileSystem_TCF_O_TRUNC; + d->putWriteOk = false; + d->codaDevice->sendFileSystemOpenCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleFileSystemOpen), + d->copyDstFileName.toAscii(), flags); + reportMessage(tr("Copying %1...").arg(QFileInfo(d->copyDstFileName).fileName())); +} + +void CodaSignalHandler::putSendNextChunk() +{ + if (!d->codaDevice || !d->remoteFile) { + emit done(); + return; + } + + // Read and send off next chunk + const quint64 pos = d->remoteFile->pos(); + const QByteArray data = d->remoteFile->read(d->putChunkSize); + if (data.isEmpty()) { + d->putWriteOk = true; + closeFile(); + } else { + d->putLastChunkSize = data.size(); + d->codaDevice->sendFileSystemWriteCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleFileSystemWrite), + d->remoteFileHandle, data, unsigned(pos)); + } +} + +void CodaSignalHandler::readNextChunk() +{ + const quint64 pos = d->remoteFileSize - d->remoteBytesLeft; + const quint64 size = qMin(d->remoteBytesLeft, DEFAULT_CHUNK_SIZE); + d->codaDevice->sendFileSystemReadCommand(Coda::CodaCallback(this, &CodaSignalHandler::handleFileSystemRead), + d->remoteFileHandle, pos, size); +} + +void CodaSignalHandler::readAppId(Coda::JsonValue value) +{ + if (value.isObject()) { + Coda::JsonValue idValue = value.findChild("ID"); + if (idValue.isString()) { + d->appID = idValue.data(); + return; + } + } + + reportError(tr("Could not get process ID of %1.").arg(QFileInfo(d->appFileName).fileName())); +} + +void CodaSignalHandler::reportError(const QString &message) +{ + d->err << message << endl; + d->result = 1; + emit done(); +} + +void CodaSignalHandler::reportMessage(const QString &message) +{ + if (d->loglevel > 0) + d->out << message << endl; +} + +CodaSignalHandler::CodaSignalHandler() + : d(new CodaSignalHandlerPrivate()) +{ +} + +CodaSignalHandler::~CodaSignalHandler() +{ + delete d; +} + diff --git a/tools/runonphone/codasignalhandler.h b/tools/runonphone/codasignalhandler.h new file mode 100644 index 0000000..a978bfa --- /dev/null +++ b/tools/runonphone/codasignalhandler.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CODASIGNALHANDLER_H +#define CODASIGNALHANDLER_H + +#include "symbianutils/codamessage.h" +#include "symbianutils/symbiandevicemanager.h" + +#include "symbianutils/codadevice.h" + +enum CodaAction { + ActionPingOnly = 0x0, + ActionCopy = 0x1, + ActionInstall = 0x2, + ActionCopyInstall = ActionCopy | ActionInstall, + ActionRun = 0x4, + ActionDownload = 0x8, + ActionCopyRun = ActionCopy | ActionRun, + ActionInstallRun = ActionInstall | ActionRun, + ActionCopyInstallRun = ActionCopy | ActionInstall | ActionRun +}; + +class CodaSignalHandlerPrivate; +class CodaSignalHandler : public QObject +{ + Q_OBJECT +public slots: + void error(const QString &errorMessage); + void logMessage(const QString &logMessage); + void serialPong(const QString &codaVersion); + void tcfEvent(const Coda::CodaEvent &event); + void terminate(); +private slots: + void finished(); + void timeout(); +signals: + void done(); +public: + CodaSignalHandler(); + ~CodaSignalHandler(); + void init(); + int run(); + void setActionType(CodaAction action); + void setAppFileName(const QString &fileName); + void setCodaDevice(SymbianUtils::CodaDevicePtr &codeDevice); + void setCommandLineArgs(const QString &args); + void setCopyFileName(const QString &srcName, const QString &dstName); + void setDownloadFileName(const QString &srcName, const QString &dstName); + void setLogLevel(int level); + void setSerialPortName(const QString &serialPortName); + void setTimeout(const int msec); +private: + void closeFile(); + void handleConnected(const Coda::CodaEvent &event); + void handleActions(); + void handleAppExited(const Coda::CodaEvent &event); + void handleAppRunning(const Coda::CodaCommandResult &result); + void handleDebugSessionControlEnd(const Coda::CodaCommandResult &result); + void handleDebugSessionControlStart(const Coda::CodaCommandResult &result); + void handleFileSystemClose(const Coda::CodaCommandResult &result); + void handleFileSystemOpen(const Coda::CodaCommandResult &result); + void handleFileSystemRead(const Coda::CodaCommandResult &result); + void handleFileSystemStart(const Coda::CodaCommandResult &result); + void handleFileSystemWrite(const Coda::CodaCommandResult &result); + void handleSymbianInstall(const Coda::CodaCommandResult &result); + void initAppRunning(); + void initFileDownloading(); + void initFileInstallation(); + void initFileSending(); + void putSendNextChunk(); + void readNextChunk(); + void readAppId(Coda::JsonValue value); + void reportError(const QString &message); + void reportMessage(const QString &message); + + CodaSignalHandlerPrivate *d; +}; + +#endif // CODESIGNALHANDLER_H diff --git a/tools/runonphone/main.cpp b/tools/runonphone/main.cpp index 257ec79..af349eb 100644 --- a/tools/runonphone/main.cpp +++ b/tools/runonphone/main.cpp @@ -45,10 +45,13 @@ #include <QScopedPointer> #include <QTimer> #include <QFileInfo> +#include "symbianutils/codadevice.h" #include "symbianutils/trkutils.h" #include "symbianutils/trkdevice.h" #include "symbianutils/launcher.h" +#include "symbianutils/symbiandevicemanager.h" +#include "codasignalhandler.h" #include "trksignalhandler.h" #include "serenum.h" #include "ossignalconverter.h" @@ -56,19 +59,22 @@ void printUsage(QTextStream& outstream, QString exeName) { outstream << exeName << " [options] [program] [program arguments]" << endl - << "-s, --sis <file> specify sis file to install" << endl + << "-s, --sis <local file> specify sis file to install" << endl << "-p, --portname <COMx> specify COM port to use by device name" << endl << "-f, --portfriendlyname <substring> specify COM port to use by friendly name" << endl << "-t, --timeout <milliseconds> terminate test if timeout occurs" << endl << "-v, --verbose show debugging output" << endl << "-q, --quiet hide progress messages" << endl + << "-u, --upload <local file> <remote file> upload file to phone" << endl << "-d, --download <remote file> <local file> copy file from phone to PC after running test" << endl << "--nocrashlog Don't capture call stack if test crashes" << endl << "--crashlogpath <dir> Path to save crash logs (default=working dir)" << endl + << "--coda Use CODA instead of TRK (default agent)" << endl << endl << "USB COM ports can usually be autodetected, use -p or -f to force a specific port." << endl + << "TRK is the default debugging agent, use --coda option when using CODA instead of TRK." << endl << "If using System TRK, it is possible to copy the program directly to sys/bin on the phone." << endl - << "-s can be used with both System and Application TRK to install the program" << endl; + << "-s can be used with both System and Application TRK/CODA to install the program" << endl; } #define CHECK_PARAMETER_EXISTS if(!it.hasNext()) { printUsage(outstream, args[0]); return 1; } @@ -84,11 +90,14 @@ int main(int argc, char *argv[]) QStringList args = QCoreApplication::arguments(); QTextStream outstream(stdout); QTextStream errstream(stderr); + QString uploadLocalFile; + QString uploadRemoteFile; QString downloadRemoteFile; QString downloadLocalFile; int loglevel=1; int timeout=0; bool crashlog = true; + bool coda = false; QString crashlogpath; QListIterator<QString> it(args); it.next(); //skip name of program @@ -112,11 +121,26 @@ int main(int argc, char *argv[]) return 1; } } + else if (arg == "--upload" || arg == "-u") { + CHECK_PARAMETER_EXISTS + uploadLocalFile = it.next(); + if (!QFileInfo(uploadLocalFile).exists()) { + errstream << "Executable file (" << uploadLocalFile << ") doesn't exist" << endl; + return 1; + } + CHECK_PARAMETER_EXISTS + uploadRemoteFile = it.next(); + } else if (arg == "--download" || arg == "-d") { CHECK_PARAMETER_EXISTS downloadRemoteFile = it.next(); CHECK_PARAMETER_EXISTS downloadLocalFile = it.next(); + QFileInfo downloadInfo(downloadLocalFile); + if (downloadInfo.exists() && !downloadInfo.isFile()) { + errstream << downloadLocalFile << " is not a file." << endl; + return 1; + } } else if (arg == "--timeout" || arg == "-t") { CHECK_PARAMETER_EXISTS @@ -127,6 +151,8 @@ int main(int argc, char *argv[]) return 1; } } + else if (arg == "--coda") + coda = true; else if (arg == "--verbose" || arg == "-v") loglevel=2; else if (arg == "--quiet" || arg == "-q") @@ -147,12 +173,19 @@ int main(int argc, char *argv[]) } } - if (exeFile.isEmpty() && sisFile.isEmpty() && + if (exeFile.isEmpty() && sisFile.isEmpty() && + (uploadLocalFile.isEmpty() || uploadRemoteFile.isEmpty()) && (downloadLocalFile.isEmpty() || downloadRemoteFile.isEmpty())) { printUsage(outstream, args[0]); return 1; } + if (!uploadLocalFile.isEmpty() && (!downloadLocalFile.isEmpty() || !downloadRemoteFile.isEmpty())) { + errstream << "Upload option can't be used together with download" << endl; + printUsage(outstream, args[0]); + return 1; + } + if (serialPortName.isEmpty()) { if (loglevel > 0) outstream << "Detecting serial ports" << endl; @@ -180,75 +213,117 @@ int main(int argc, char *argv[]) } } + CodaSignalHandler codaHandler; QScopedPointer<trk::Launcher> launcher; - launcher.reset(new trk::Launcher(trk::Launcher::ActionPingOnly)); + TrkSignalHandler trkHandler; QFileInfo info(exeFile); - if (!sisFile.isEmpty()) { - launcher->addStartupActions(trk::Launcher::ActionCopyInstall); - launcher->setCopyFileName(sisFile, "c:\\data\\testtemp.sis"); - launcher->setInstallFileName("c:\\data\\testtemp.sis"); - } - else if (info.exists()) { - launcher->addStartupActions(trk::Launcher::ActionCopy); - launcher->setCopyFileName(exeFile, QString("c:\\sys\\bin\\") + info.fileName()); - } - if (!exeFile.isEmpty()) { - launcher->addStartupActions(trk::Launcher::ActionRun); - launcher->setFileName(QString("c:\\sys\\bin\\") + info.fileName()); - launcher->setCommandLineArgs(cmdLine); - } - if (!downloadRemoteFile.isEmpty() && !downloadLocalFile.isEmpty()) { - launcher->addStartupActions(trk::Launcher::ActionDownload); - launcher->setDownloadFileName(downloadRemoteFile, downloadLocalFile); - } - if (loglevel > 0) - outstream << "Connecting to target via " << serialPortName << endl; - launcher->setTrkServerName(serialPortName); + QFileInfo uploadInfo(uploadLocalFile); + + if (coda) { + codaHandler.setSerialPortName(serialPortName); + codaHandler.setLogLevel(loglevel); + + if (!sisFile.isEmpty()) { + codaHandler.setActionType(ActionCopyInstall); + QString dstName = "c:\\data\\testtemp.sis"; + codaHandler.setCopyFileName(sisFile, dstName); + } + else if (!uploadLocalFile.isEmpty() && uploadInfo.exists()) { + codaHandler.setActionType(ActionCopy); + codaHandler.setCopyFileName(uploadLocalFile, uploadRemoteFile); + } + if (!exeFile.isEmpty()) { + codaHandler.setActionType(ActionRun); + codaHandler.setAppFileName(QString("c:\\sys\\bin\\") + info.fileName()); + codaHandler.setCommandLineArgs(cmdLine.join(QLatin1String(", "))); + } + if (!downloadRemoteFile.isEmpty() && !downloadLocalFile.isEmpty()) { + codaHandler.setActionType(ActionDownload); + codaHandler.setDownloadFileName(downloadRemoteFile, downloadLocalFile); + } + + if (loglevel > 0) + outstream << "Connecting to target via " << serialPortName << endl; + + if (timeout > 0) + codaHandler.setTimeout(timeout); + + QObject::connect(OsSignalConverter::instance(), SIGNAL(terminate()), &codaHandler, SLOT(terminate()), Qt::QueuedConnection); + return codaHandler.run(); + + } else { + launcher.reset(new trk::Launcher(trk::Launcher::ActionPingOnly)); + QStringList srcNames, dstNames; + if (!sisFile.isEmpty()) { + launcher->addStartupActions(trk::Launcher::ActionCopyInstall); + srcNames.append(sisFile); + QLatin1String dstName("c:\\data\\testtemp.sis"); + dstNames.append(dstName); + launcher->setInstallFileNames(QStringList(dstName)); + } + if (!uploadLocalFile.isEmpty() && uploadInfo.exists()) { + launcher->addStartupActions(trk::Launcher::ActionCopy); + srcNames.append(uploadLocalFile); + dstNames.append(uploadRemoteFile); + } + launcher->setCopyFileNames(srcNames, dstNames); + if (!exeFile.isEmpty()) { + launcher->addStartupActions(trk::Launcher::ActionRun); + launcher->setFileName(QString("c:\\sys\\bin\\") + info.fileName()); + launcher->setCommandLineArgs(cmdLine.join(QLatin1String(" "))); + } + if (!downloadRemoteFile.isEmpty() && !downloadLocalFile.isEmpty()) { + launcher->addStartupActions(trk::Launcher::ActionDownload); + launcher->setDownloadFileName(downloadRemoteFile, downloadLocalFile); + } + if (loglevel > 0) + outstream << "Connecting to target via " << serialPortName << endl; + launcher->setTrkServerName(serialPortName); - if (loglevel > 1) - launcher->setVerbose(1); + if (loglevel > 1) + launcher->setVerbose(1); - TrkSignalHandler handler; - handler.setLogLevel(loglevel); - handler.setCrashLogging(crashlog); - handler.setCrashLogPath(crashlogpath); + trkHandler.setLogLevel(loglevel); + trkHandler.setCrashLogging(crashlog); + trkHandler.setCrashLogPath(crashlogpath); - QObject::connect(launcher.data(), SIGNAL(copyingStarted()), &handler, SLOT(copyingStarted())); - QObject::connect(launcher.data(), SIGNAL(canNotConnect(const QString &)), &handler, SLOT(canNotConnect(const QString &))); - QObject::connect(launcher.data(), SIGNAL(canNotCreateFile(const QString &, const QString &)), &handler, SLOT(canNotCreateFile(const QString &, const QString &))); - QObject::connect(launcher.data(), SIGNAL(canNotWriteFile(const QString &, const QString &)), &handler, SLOT(canNotWriteFile(const QString &, const QString &))); - QObject::connect(launcher.data(), SIGNAL(canNotCloseFile(const QString &, const QString &)), &handler, SLOT(canNotCloseFile(const QString &, const QString &))); - QObject::connect(launcher.data(), SIGNAL(installingStarted()), &handler, SLOT(installingStarted())); - QObject::connect(launcher.data(), SIGNAL(canNotInstall(const QString &, const QString &)), &handler, SLOT(canNotInstall(const QString &, const QString &))); - QObject::connect(launcher.data(), SIGNAL(installingFinished()), &handler, SLOT(installingFinished())); - QObject::connect(launcher.data(), SIGNAL(startingApplication()), &handler, SLOT(startingApplication())); - QObject::connect(launcher.data(), SIGNAL(applicationRunning(uint)), &handler, SLOT(applicationRunning(uint))); - QObject::connect(launcher.data(), SIGNAL(canNotRun(const QString &)), &handler, SLOT(canNotRun(const QString &))); - QObject::connect(launcher.data(), SIGNAL(applicationOutputReceived(const QString &)), &handler, SLOT(applicationOutputReceived(const QString &))); - QObject::connect(launcher.data(), SIGNAL(copyProgress(int)), &handler, SLOT(copyProgress(int))); - QObject::connect(launcher.data(), SIGNAL(stateChanged(int)), &handler, SLOT(stateChanged(int))); - QObject::connect(launcher.data(), SIGNAL(processStopped(uint,uint,uint,QString)), &handler, SLOT(stopped(uint,uint,uint,QString))); - QObject::connect(launcher.data(), SIGNAL(libraryLoaded(trk::Library)), &handler, SLOT(libraryLoaded(trk::Library))); - QObject::connect(launcher.data(), SIGNAL(libraryUnloaded(trk::Library)), &handler, SLOT(libraryUnloaded(trk::Library))); - QObject::connect(launcher.data(), SIGNAL(registersAndCallStackReadComplete(const QList<uint> &,const QByteArray &)), &handler, SLOT(registersAndCallStackReadComplete(const QList<uint> &,const QByteArray &))); - QObject::connect(&handler, SIGNAL(resume(uint,uint)), launcher.data(), SLOT(resumeProcess(uint,uint))); - QObject::connect(&handler, SIGNAL(terminate()), launcher.data(), SLOT(terminate())); - QObject::connect(&handler, SIGNAL(getRegistersAndCallStack(uint,uint)), launcher.data(), SLOT(getRegistersAndCallStack(uint,uint))); - QObject::connect(launcher.data(), SIGNAL(finished()), &handler, SLOT(finished())); + QObject::connect(launcher.data(), SIGNAL(copyingStarted(const QString &)), &trkHandler, SLOT(copyingStarted(const QString &))); + QObject::connect(launcher.data(), SIGNAL(canNotConnect(const QString &)), &trkHandler, SLOT(canNotConnect(const QString &))); + QObject::connect(launcher.data(), SIGNAL(canNotCreateFile(const QString &, const QString &)), &trkHandler, SLOT(canNotCreateFile(const QString &, const QString &))); + QObject::connect(launcher.data(), SIGNAL(canNotWriteFile(const QString &, const QString &)), &trkHandler, SLOT(canNotWriteFile(const QString &, const QString &))); + QObject::connect(launcher.data(), SIGNAL(canNotCloseFile(const QString &, const QString &)), &trkHandler, SLOT(canNotCloseFile(const QString &, const QString &))); + QObject::connect(launcher.data(), SIGNAL(installingStarted(const QString &)), &trkHandler, SLOT(installingStarted(const QString &))); + QObject::connect(launcher.data(), SIGNAL(canNotInstall(const QString &, const QString &)), &trkHandler, SLOT(canNotInstall(const QString &, const QString &))); + QObject::connect(launcher.data(), SIGNAL(installingFinished()), &trkHandler, SLOT(installingFinished())); + QObject::connect(launcher.data(), SIGNAL(startingApplication()), &trkHandler, SLOT(startingApplication())); + QObject::connect(launcher.data(), SIGNAL(applicationRunning(uint)), &trkHandler, SLOT(applicationRunning(uint))); + QObject::connect(launcher.data(), SIGNAL(canNotRun(const QString &)), &trkHandler, SLOT(canNotRun(const QString &))); + QObject::connect(launcher.data(), SIGNAL(applicationOutputReceived(const QString &)), &trkHandler, SLOT(applicationOutputReceived(const QString &))); + QObject::connect(launcher.data(), SIGNAL(copyProgress(int)), &trkHandler, SLOT(copyProgress(int))); + QObject::connect(launcher.data(), SIGNAL(stateChanged(int)), &trkHandler, SLOT(stateChanged(int))); + QObject::connect(launcher.data(), SIGNAL(processStopped(uint,uint,uint,QString)), &trkHandler, SLOT(stopped(uint,uint,uint,QString))); + QObject::connect(launcher.data(), SIGNAL(libraryLoaded(trk::Library)), &trkHandler, SLOT(libraryLoaded(trk::Library))); + QObject::connect(launcher.data(), SIGNAL(libraryUnloaded(trk::Library)), &trkHandler, SLOT(libraryUnloaded(trk::Library))); + QObject::connect(launcher.data(), SIGNAL(registersAndCallStackReadComplete(const QList<uint> &,const QByteArray &)), &trkHandler, SLOT(registersAndCallStackReadComplete(const QList<uint> &,const QByteArray &))); + QObject::connect(&trkHandler, SIGNAL(resume(uint,uint)), launcher.data(), SLOT(resumeProcess(uint,uint))); + QObject::connect(&trkHandler, SIGNAL(terminate()), launcher.data(), SLOT(terminate())); + QObject::connect(&trkHandler, SIGNAL(getRegistersAndCallStack(uint,uint)), launcher.data(), SLOT(getRegistersAndCallStack(uint,uint))); + QObject::connect(launcher.data(), SIGNAL(finished()), &trkHandler, SLOT(finished())); - QObject::connect(OsSignalConverter::instance(), SIGNAL(terminate()), launcher.data(), SLOT(terminate()), Qt::QueuedConnection); + QObject::connect(OsSignalConverter::instance(), SIGNAL(terminate()), launcher.data(), SLOT(terminate()), Qt::QueuedConnection); - QTimer timer; - timer.setSingleShot(true); - QObject::connect(&timer, SIGNAL(timeout()), &handler, SLOT(timeout())); - if (timeout > 0) { - timer.start(timeout); - } + QTimer timer; + timer.setSingleShot(true); + QObject::connect(&timer, SIGNAL(timeout()), &trkHandler, SLOT(timeout())); + if (timeout > 0) { + timer.start(timeout); + } - QString errorMessage; - if (!launcher->startServer(&errorMessage)) { - errstream << errorMessage << endl; - return 1; + QString errorMessage; + if (!launcher->startServer(&errorMessage)) { + errstream << errorMessage << endl; + return 1; + } } return a.exec(); diff --git a/tools/runonphone/runonphone.pro b/tools/runonphone/runonphone.pro index 7ff361c..d006a05 100644 --- a/tools/runonphone/runonphone.pro +++ b/tools/runonphone/runonphone.pro @@ -1,27 +1,29 @@ TEMPLATE = app QT -= gui -CONFIG += console +CONFIG += console static CONFIG -= app_bundle include(symbianutils/symbianutils.pri) SOURCES += main.cpp \ trksignalhandler.cpp \ - ossignalconverter.cpp + ossignalconverter.cpp \ + codasignalhandler.cpp HEADERS += trksignalhandler.h \ serenum.h \ ossignalconverter.h \ - ossignalconverter_p.h + ossignalconverter_p.h \ + codasignalhandler.h DEFINES += SYMBIANUTILS_INCLUDE_PRI windows { SOURCES += serenum_win.cpp LIBS += -lsetupapi \ - -luuid \ - -ladvapi32 + -luuid \ + -ladvapi32 } else:unix:!symbian { SOURCES += serenum_unix.cpp diff --git a/tools/runonphone/serenum_unix.cpp b/tools/runonphone/serenum_unix.cpp index eef3b18..9a33dab 100644 --- a/tools/runonphone/serenum_unix.cpp +++ b/tools/runonphone/serenum_unix.cpp @@ -100,7 +100,7 @@ QList<SerialPortId> enumerateSerialPorts(int loglevel) // data transmission. // the extra info stores that as a index for the interface if (buf[0] >= 5 && buf[1] == 36 && buf[2] == 6) { // CDC Union - for (int i = 4; i < buf[0]; i++) + for (int i = 3; i < buf[0]; i++) usableInterfaces.append((int) buf[i]); } size -= buf[0]; @@ -146,37 +146,27 @@ QList<SerialPortId> enumerateSerialPorts(int loglevel) // second loop to find the actual data interface. foreach (int i, usableInterfaces) { - for (int m = 0; m < usbConfig.bNumInterfaces; ++m) { - for (int o = 0; o < usbConfig.interface[m].num_altsetting; ++o) { - struct usb_interface_descriptor &descriptor = usbConfig.interface[m].altsetting[o]; - if (descriptor.bInterfaceNumber != i) - continue; - if (descriptor.bInterfaceClass == 10) { // "CDC Data" - if (loglevel > 1) { - qDebug() << " found the data port" - << "bus:" << bus->dirname - << "device" << device->filename - << "interface" << descriptor.bInterfaceNumber; - } #ifdef Q_OS_MAC - eligibleInterfaces << QString("^cu\\.usbmodem.*%1$") - .arg(QString("%1").arg(descriptor.bInterfaceNumber, 1, 16).toUpper()); + eligibleInterfaces << QString("^cu\\.usbmodem.*%1$") + .arg(QString("%1").arg(i, 1, 16).toUpper()); + eligibleInterfacesInfo << InterfaceInfo(manufacturerString, productString, device->descriptor.idVendor, device->descriptor.idProduct); #else - // ### manufacturer and product strings are only readable as root :( - if (!manufacturerString.isEmpty() && !productString.isEmpty()) { - eligibleInterfaces << QString("usb-%1_%2-if%3") - .arg(manufacturerString.replace(QChar(' '), QChar('_'))) - .arg(productString.replace(QChar(' '), QChar('_'))) - .arg(i, 2, 16, QChar('0')); - } else { - eligibleInterfaces << QString("if%1").arg(i, 2, 16, QChar('0')); // fix! - } -#endif - eligibleInterfacesInfo << InterfaceInfo(manufacturerString, productString, device->descriptor.idVendor, device->descriptor.idProduct); - } - } + // ### manufacturer and product strings are only readable as root :( + if (!manufacturerString.isEmpty() && !productString.isEmpty()) { + eligibleInterfaces << QString("usb-%1_%2-if%3") + .arg(manufacturerString.replace(QChar(' '), QChar('_'))) + .arg(productString.replace(QChar(' '), QChar('_'))) + .arg(i, 2, 16, QChar('0')); + } else { + eligibleInterfaces << QString("if%1").arg(i, 2, 16, QChar('0')); // fix! } +#endif } +#ifndef Q_OS_MAC + // On mac, we need a 1-1 mapping between eligibleInterfaces and eligibleInterfacesInfo + // in order to find the friendly name for an interface + eligibleInterfacesInfo << InterfaceInfo(manufacturerString, productString, device->descriptor.idVendor, device->descriptor.idProduct); +#endif } } } @@ -200,7 +190,8 @@ QList<SerialPortId> enumerateSerialPorts(int loglevel) if (loglevel > 1) qDebug() << " found device file:" << info.fileName() << endl; #ifdef Q_OS_MAC - friendlyName = eligibleInterfacesInfo[eligibleInterfaces.indexOf(iface)].product; + InterfaceInfo info = eligibleInterfacesInfo[eligibleInterfaces.indexOf(iface)]; + friendlyName = info.manufacturer + " " + info.product; #endif usable = true; break; diff --git a/tools/runonphone/symbianutils/codadevice.cpp b/tools/runonphone/symbianutils/codadevice.cpp new file mode 100644 index 0000000..751f84e --- /dev/null +++ b/tools/runonphone/symbianutils/codadevice.cpp @@ -0,0 +1,1501 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "codadevice.h" +#include "json.h" +#include "trkutils.h" + +#include <QtNetwork/QAbstractSocket> +#include <QtCore/QDebug> +#include <QtCore/QVector> +#include <QtCore/QQueue> +#include <QtCore/QTextStream> +#include <QtCore/QDateTime> +#include <QtCore/QFileInfo> + +enum { debug = 0 }; + +static const char tcpMessageTerminatorC[] = "\003\001"; + +// Serial Ping: 0xfc,0x1f +static const char serialPingC[] = "\xfc\x1f"; +// Serial Pong: 0xfc,0xf1, followed by version info +static const char serialPongC[] = "\xfc\xf1"; + +static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]"; + +/* Serial messages > (1K - 2) have to chunked in order to pass the USB + * router as '0xfe char(chunkCount - 1) data' ... '0x0 char(chunkCount - 2) data' + * ... '0x0 0x0 last-data' */ +static const unsigned serialChunkLength = 0x400; // 1K max USB router +static const int maxSerialMessageLength = 0x10000; // given chunking scheme + +static const char validProtocolIdStart = (char)0x90; +static const char validProtocolIdEnd = (char)0x95; +static const char codaProtocolId = (char)0x92; +static const unsigned char serialChunkingStart = 0xfe; +static const unsigned char serialChunkingContinuation = 0x0; +enum { SerialChunkHeaderSize = 2 }; + +// Create USB router frame +static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target, char protocolId) +{ + target->append(char(0x01)); + target->append(protocolId); + appendShort(target, ushort(data.size()), trk::BigEndian); + target->append(data); +} + +// Split in chunks of 1K according to CODA protocol chunking +static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn) +{ + // Reserve 2 header bytes + static const int chunkSize = serialChunkLength - SerialChunkHeaderSize; + const int size = dataIn.size(); + QByteArray frame; + // Do we need to split? + if (size < chunkSize) { // Nope, all happy. + frame.reserve(size + 4); + encodeSerialFrame(dataIn, &frame, codaProtocolId); + return frame; + } + // Split. + unsigned chunkCount = size / chunkSize; + if (size % chunkSize) + chunkCount++; + if (debug) + qDebug("Serial: Splitting message of %d bytes into %u chunks of %d", size, chunkCount, chunkSize); + + frame.reserve((4 + serialChunkLength) * chunkCount); + int pos = 0; + for (unsigned c = chunkCount - 1; pos < size ; c--) { + QByteArray chunk; // chunk with long message start/continuation code + chunk.reserve(serialChunkLength); + chunk.append(pos ? serialChunkingContinuation : serialChunkingStart); + chunk.append(char(static_cast<unsigned char>(c))); // Avoid any signedness issues. + const int chunkEnd = qMin(pos + chunkSize, size); + chunk.append(dataIn.mid(pos, chunkEnd - pos)); + encodeSerialFrame(chunk, &frame, codaProtocolId); + pos = chunkEnd; + } + if (debug > 1) + qDebug("Serial chunked:\n%s", qPrintable(Coda::formatData(frame))); + return frame; +} + +namespace Coda { +// ------------- CodaCommandError + +CodaCommandError::CodaCommandError() : timeMS(0), code(0), alternativeCode(0) +{ +} + +void CodaCommandError::clear() +{ + timeMS = 0; + code = alternativeCode = 0; + format.clear(); + alternativeOrganization.clear(); +} + +QDateTime CodaCommandResult::tcfTimeToQDateTime(quint64 tcfTimeMS) +{ + const QDateTime time(QDate(1970, 1, 1)); + return time.addMSecs(tcfTimeMS); +} + +void CodaCommandError::write(QTextStream &str) const +{ + if (isError()) { + if (debug && timeMS) + str << CodaCommandResult::tcfTimeToQDateTime(timeMS).toString(Qt::ISODate) << ": "; + str << "'" << format << '\'' //for symbian the format is the real error message + << " Code: " << code; + if (!alternativeOrganization.isEmpty()) + str << " ('" << alternativeOrganization << "', code: " << alternativeCode << ')'; + } else{ + str << "<No error>"; + } +} + +QString CodaCommandError::toString() const +{ + QString rc; + QTextStream str(&rc); + write(str); + return rc; +} + +bool CodaCommandError::isError() const +{ + return timeMS != 0 || code != 0 || !format.isEmpty() || alternativeCode != 0; +} + +/* {"Time":1277459762255,"Code":1,"AltCode":-6,"AltOrg":"POSIX","Format":"Unknown error: -6"} */ +bool CodaCommandError::parse(const QVector<JsonValue> &values) +{ + // Parse an arbitrary hash (that could as well be a command response) + // and check for error elements. It looks like sometimes errors are appended + // to other values. + unsigned errorKeyCount = 0; + clear(); + do { + if (values.isEmpty()) + break; + // Errors are mostly appended, except for FileSystem::open, in which case + // a string "null" file handle (sic!) follows the error. + const int last = values.size() - 1; + const int checkIndex = last == 1 && values.at(last).data() == "null" ? + last - 1 : last; + if (values.at(checkIndex).type() != JsonValue::Object) + break; + foreach (const JsonValue &c, values.at(checkIndex).children()) { + if (c.name() == "Time") { + timeMS = c.data().toULongLong(); + errorKeyCount++; + } else if (c.name() == "Code") { + code = c.data().toLongLong(); + errorKeyCount++; + } else if (c.name() == "Format") { + format = c.data(); + errorKeyCount++; + } else if (c.name() == "AltCode") { + alternativeCode = c.data().toULongLong(); + errorKeyCount++; + } else if (c.name() == "AltOrg") { + alternativeOrganization = c.data(); + errorKeyCount++; + } + } + } while (false); + const bool errorFound = errorKeyCount >= 2u; // Should be at least 'Time', 'Code'. + if (!errorFound) + clear(); + if (debug) { + qDebug("CodaCommandError::parse: Found error %d (%u): ", errorFound, errorKeyCount); + if (!values.isEmpty()) + qDebug() << values.back().toString(); + } + return errorFound; +} + +// ------------ CodaCommandResult + +CodaCommandResult::CodaCommandResult(Type t) : + type(t), service(LocatorService) +{ +} + +CodaCommandResult::CodaCommandResult(char typeChar, Services s, + const QByteArray &r, + const QVector<JsonValue> &v, + const QVariant &ck) : + type(FailReply), service(s), request(r), values(v), cookie(ck) +{ + switch (typeChar) { + case 'N': + type = FailReply; + break; + case 'P': + type = ProgressReply; + break; + case 'R': + type = commandError.parse(values) ? CommandErrorReply : SuccessReply; + break; + default: + qWarning("Unknown TCF reply type '%c'", typeChar); + } +} + +QString CodaCommandResult::errorString() const +{ + QString rc; + QTextStream str(&rc); + + switch (type) { + case SuccessReply: + case ProgressReply: + str << "<No error>"; + return rc; + case FailReply: + str << "NAK"; + return rc; + case CommandErrorReply: + commandError.write(str); + break; + } + if (debug) { + // Append the failed command for reference + str << " (Command was: '"; + QByteArray printableRequest = request; + printableRequest.replace('\0', '|'); + str << printableRequest << "')"; + } + return rc; +} + +QString CodaCommandResult::toString() const +{ + QString rc; + QTextStream str(&rc); + str << "Command answer "; + switch (type) { + case SuccessReply: + str << "[success]"; + break; + case CommandErrorReply: + str << "[command error]"; + break; + case FailReply: + str << "[fail (NAK)]"; + break; + case ProgressReply: + str << "[progress]"; + break; + } + str << ", " << values.size() << " values(s) to request: '"; + QByteArray printableRequest = request; + printableRequest.replace('\0', '|'); + str << printableRequest << "' "; + if (cookie.isValid()) + str << " cookie: " << cookie.toString(); + str << '\n'; + for (int i = 0, count = values.size(); i < count; i++) + str << '#' << i << ' ' << values.at(i).toString() << '\n'; + if (type == CommandErrorReply) + str << "Error: " << errorString(); + return rc; +} + +CodaStatResponse::CodaStatResponse() : size(0) +{ +} + +struct CodaSendQueueEntry +{ + typedef CodaDevice::MessageType MessageType; + + explicit CodaSendQueueEntry(MessageType mt, + int tok, + Services s, + const QByteArray &d, + const CodaCallback &cb= CodaCallback(), + const QVariant &ck = QVariant()) : + messageType(mt), service(s), data(d), token(tok), cookie(ck), callback(cb) {} + + MessageType messageType; + Services service; + QByteArray data; + int token; + QVariant cookie; + CodaCallback callback; + unsigned specialHandling; +}; + +struct CodaDevicePrivate { + typedef CodaDevice::IODevicePtr IODevicePtr; + typedef QHash<int, CodaSendQueueEntry> TokenWrittenMessageMap; + + CodaDevicePrivate(); + + const QByteArray m_tcpMessageTerminator; + + IODevicePtr m_device; + unsigned m_verbose; + QByteArray m_readBuffer; + QByteArray m_serialBuffer; // for chunked messages + int m_token; + QQueue<CodaSendQueueEntry> m_sendQueue; + TokenWrittenMessageMap m_writtenMessages; + QVector<QByteArray> m_registerNames; + QVector<QByteArray> m_fakeGetMRegisterValues; + bool m_serialFrame; + bool m_serialPingOnly; +}; + +CodaDevicePrivate::CodaDevicePrivate() : + m_tcpMessageTerminator(tcpMessageTerminatorC), + m_verbose(0), m_token(0), m_serialFrame(false), m_serialPingOnly(false) +{ +} + +CodaDevice::CodaDevice(QObject *parent) : + QObject(parent), d(new CodaDevicePrivate) +{ + if (debug) setVerbose(true); +} + +CodaDevice::~CodaDevice() +{ + delete d; +} + +QVector<QByteArray> CodaDevice::registerNames() const +{ + return d->m_registerNames; +} + +void CodaDevice::setRegisterNames(const QVector<QByteArray>& n) +{ + d->m_registerNames = n; + if (d->m_verbose) { + QString msg; + QTextStream str(&msg); + const int count = n.size(); + str << "Registers (" << count << "): "; + for (int i = 0; i < count; i++) + str << '#' << i << '=' << n.at(i) << ' '; + emitLogMessage(msg); + } +} + +CodaDevice::IODevicePtr CodaDevice::device() const +{ + return d->m_device; +} + +CodaDevice::IODevicePtr CodaDevice::takeDevice() +{ + const IODevicePtr old = d->m_device; + if (!old.isNull()) { + old.data()->disconnect(this); + d->m_device = IODevicePtr(); + } + d->m_readBuffer.clear(); + d->m_token = 0; + d->m_sendQueue.clear(); + return old; +} + +void CodaDevice::setDevice(const IODevicePtr &dp) +{ + if (dp.data() == d->m_device.data()) + return; + if (dp.isNull()) { + emitLogMessage(QLatin1String("Internal error: Attempt to set NULL device.")); + return; + } + takeDevice(); + d->m_device = dp; + connect(dp.data(), SIGNAL(readyRead()), this, SLOT(slotDeviceReadyRead())); + if (QAbstractSocket *s = qobject_cast<QAbstractSocket *>(dp.data())) { + connect(s, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotDeviceError())); + connect(s, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(slotDeviceSocketStateChanged())); + } +} + +void CodaDevice::slotDeviceError() +{ + const QString message = d->m_device->errorString(); + emitLogMessage(message); + emit error(message); +} + +void CodaDevice::slotDeviceSocketStateChanged() +{ + if (const QAbstractSocket *s = qobject_cast<const QAbstractSocket *>(d->m_device.data())) { + const QAbstractSocket::SocketState st = s->state(); + switch (st) { + case QAbstractSocket::UnconnectedState: + emitLogMessage(QLatin1String("Unconnected")); + break; + case QAbstractSocket::HostLookupState: + emitLogMessage(QLatin1String("HostLookupState")); + break; + case QAbstractSocket::ConnectingState: + emitLogMessage(QLatin1String("Connecting")); + break; + case QAbstractSocket::ConnectedState: + emitLogMessage(QLatin1String("Connected")); + break; + case QAbstractSocket::ClosingState: + emitLogMessage(QLatin1String("Closing")); + break; + default: + emitLogMessage(QString::fromLatin1("State %1").arg(st)); + break; + } + } +} + +static inline QString debugMessage(QByteArray message, const char *prefix = 0) +{ + const bool isBinary = !message.isEmpty() && message.at(0) < 0; + if (isBinary) { + message = message.toHex(); // Some serial special message + } else { + message.replace('\0', '|'); + } + const QString messageS = QString::fromLatin1(message); + return prefix ? + (QLatin1String(prefix) + messageS) : messageS; +} + +void CodaDevice::slotDeviceReadyRead() +{ + const QByteArray newData = d->m_device->readAll(); + d->m_readBuffer += newData; + if (debug) + qDebug("ReadBuffer: %s", qPrintable(trk::stringFromArray(newData))); + if (d->m_serialFrame) { + deviceReadyReadSerial(); + } else { + deviceReadyReadTcp(); + } +} + +// Find a serial header in input stream '0x1', '0x92', 'lenH', 'lenL' +// and return message position and size. +QPair<int, int> CodaDevice::findSerialHeader(QByteArray &in) +{ + static const char header1 = 0x1; + // Header should in theory always be at beginning of + // buffer. Warn if there are bogus data in-between. + + while (in.size() >= 4) { + if (in.at(0) == header1 && in.at(1) == codaProtocolId) { + // Good packet + const int length = trk::extractShort(in.constData() + 2); + return QPair<int, int>(4, length); + } else if (in.at(0) == header1 && in.at(1) >= validProtocolIdStart && in.at(1) <= validProtocolIdEnd) { + // We recognise it but it's not a TCF message - emit it for any interested party to handle + const int length = trk::extractShort(in.constData() + 2); + if (4 + length <= in.size()) { + // We have all the data + QByteArray data(in.mid(4, length)); + emit unknownEvent(in.at(1), data); + in.remove(0, 4+length); + // and continue + } else { + // If we don't have all this packet, there can't be any data following it, so return now + // and wait for more data + return QPair<int, int>(-1, -1); + } + } else { + // Bad data - log it, remove it, and go round again + int nextHeader = in.indexOf(header1, 1); + QByteArray bad = in.mid(0, nextHeader); + qWarning("Bogus data received on serial line: %s\n" + "Frame Header at: %d", qPrintable(trk::stringFromArray(bad)), nextHeader); + in.remove(0, bad.length()); + // and continue + } + } + return QPair<int, int>(-1, -1); // No more data, or not enough for a complete header +} + +void CodaDevice::deviceReadyReadSerial() +{ + do { + // Extract message (pos,len) + const QPair<int, int> messagePos = findSerialHeader(d->m_readBuffer); + if (messagePos.first < 0) + break; + // Do we have the complete message? + const int messageEnd = messagePos.first + messagePos.second; + if (messageEnd > d->m_readBuffer.size()) + break; + processSerialMessage(d->m_readBuffer.mid(messagePos.first, messagePos.second)); + d->m_readBuffer.remove(0, messageEnd); + } while (!d->m_readBuffer.isEmpty()); + checkSendQueue(); // Send off further messages +} + +void CodaDevice::processSerialMessage(const QByteArray &message) +{ + if (debug > 1) + qDebug("Serial message: %s",qPrintable(trk::stringFromArray(message))); + if (message.isEmpty()) + return; + // Is thing a ping/pong response + const int size = message.size(); + if (message.startsWith(serialPongC)) { + const QString version = QString::fromLatin1(message.mid(sizeof(serialPongC) - 1)); + emitLogMessage(QString::fromLatin1("Serial connection from '%1'").arg(version)); + emit serialPong(version); + // Answer with locator. + if (!d->m_serialPingOnly) + writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC))); + return; + } + // Check for long message (see top, '0xfe #number, data' or '0x0 #number, data') + // TODO: This is currently untested. + const unsigned char *dataU = reinterpret_cast<const unsigned char *>(message.constData()); + const bool isLongMessageStart = size > SerialChunkHeaderSize + && *dataU == serialChunkingStart; + const bool isLongMessageContinuation = size > SerialChunkHeaderSize + && *dataU == serialChunkingContinuation; + if (isLongMessageStart || isLongMessageContinuation) { + const unsigned chunkNumber = *++dataU; + if (isLongMessageStart) { // Start new buffer + d->m_serialBuffer.clear(); + d->m_serialBuffer.reserve( (chunkNumber + 1) * serialChunkLength); + } + d->m_serialBuffer.append(message.mid(SerialChunkHeaderSize, size - SerialChunkHeaderSize)); + // Last chunk? - Process + if (!chunkNumber) { + processMessage(d->m_serialBuffer); + d->m_serialBuffer.clear(); + d->m_serialBuffer.squeeze(); + } + } else { + processMessage(message); // Normal, unchunked message + } +} + +void CodaDevice::deviceReadyReadTcp() +{ + // Take complete message off front of readbuffer. + do { + const int messageEndPos = d->m_readBuffer.indexOf(d->m_tcpMessageTerminator); + if (messageEndPos == -1) + break; + if (messageEndPos == 0) { + // TCF TRK 4.0.5 emits empty messages on errors. + emitLogMessage(QString::fromLatin1("An empty TCF TRK message has been received.")); + } else { + processMessage(d->m_readBuffer.left(messageEndPos)); + } + d->m_readBuffer.remove(0, messageEndPos + d->m_tcpMessageTerminator.size()); + } while (!d->m_readBuffer.isEmpty()); + checkSendQueue(); // Send off further messages +} + +void CodaDevice::processMessage(const QByteArray &message) +{ + if (debug) + qDebug("Read %d bytes:\n%s", message.size(), qPrintable(formatData(message))); + if (const int errorCode = parseMessage(message)) { + emitLogMessage(QString::fromLatin1("Parse error %1 : %2"). + arg(errorCode).arg(debugMessage(message))); + if (debug) + qDebug("Parse error %d for %d bytes:\n%s", errorCode, + message.size(), qPrintable(formatData(message))); + } +} + +// Split \0-terminated message into tokens, skipping the initial type character +static inline QVector<QByteArray> splitMessage(const QByteArray &message) +{ + QVector<QByteArray> tokens; + tokens.reserve(7); + const int messageSize = message.size(); + for (int pos = 2; pos < messageSize; ) { + const int nextPos = message.indexOf('\0', pos); + if (nextPos == -1) + break; + tokens.push_back(message.mid(pos, nextPos - pos)); + pos = nextPos + 1; + } + return tokens; +} + +int CodaDevice::parseMessage(const QByteArray &message) +{ + if (d->m_verbose) + emitLogMessage(debugMessage(message, "TCF ->")); + // Special JSON parse error message or protocol format error. + // The port is usually closed after receiving it. + // "\3\2{"Time":1276096098255,"Code":3,"Format": "Protocol format error"}" + if (message.startsWith("\003\002")) { + QByteArray text = message.mid(2); + const QString errorMessage = QString::fromLatin1("Parse error received: %1").arg(QString::fromAscii(text)); + emit error(errorMessage); + return 0; + } + if (message.size() < 4 || message.at(1) != '\0') + return 1; + // Split into tokens + const char type = message.at(0); + const QVector<QByteArray> tokens = splitMessage(message); + switch (type) { + case 'E': + return parseTcfEvent(tokens); + case 'R': // Command replies + case 'N': + case 'P': + return parseTcfCommandReply(type, tokens); + default: + emitLogMessage(QString::fromLatin1("Unhandled message type: %1").arg(debugMessage(message))); + return 756; + } + return 0; +} + +int CodaDevice::parseTcfCommandReply(char type, const QVector<QByteArray> &tokens) +{ + typedef CodaDevicePrivate::TokenWrittenMessageMap::iterator TokenWrittenMessageMapIterator; + // Find the corresponding entry in the written messages hash. + const int tokenCount = tokens.size(); + if (tokenCount < 1) + return 234; + bool tokenOk; + const int token = tokens.at(0).toInt(&tokenOk); + if (!tokenOk) + return 235; + const TokenWrittenMessageMapIterator it = d->m_writtenMessages.find(token); + if (it == d->m_writtenMessages.end()) { + qWarning("CodaDevice: Internal error: token %d not found for '%s'", + token, qPrintable(joinByteArrays(tokens))); + return 236; + } + // No callback: remove entry from map, happy + const unsigned specialHandling = it.value().specialHandling; + if (!it.value().callback && specialHandling == 0u) { + d->m_writtenMessages.erase(it); + return 0; + } + // Parse values into JSON + QVector<JsonValue> values; + values.reserve(tokenCount); + for (int i = 1; i < tokenCount; i++) { + if (!tokens.at(i).isEmpty()) { // Strange: Empty tokens occur. + const JsonValue value(tokens.at(i)); + if (value.isValid()) { + values.push_back(value); + } else { + qWarning("JSON parse error for reply to command token %d: #%d '%s'", + token, i, tokens.at(i).constData()); + d->m_writtenMessages.erase(it); + return -1; + } + } + } + // Construct result and invoke callback, remove entry from map. + CodaCommandResult result(type, it.value().service, it.value().data, + values, it.value().cookie); + + if (it.value().callback) + it.value().callback(result); + d->m_writtenMessages.erase(it); + return 0; +} + +int CodaDevice::parseTcfEvent(const QVector<QByteArray> &tokens) +{ + // Event: Ignore the periodical heartbeat event, answer 'Hello', + // emit signal for the rest + if (tokens.size() < 3) + return 433; + const Services service = serviceFromName(tokens.at(0).constData()); + if (service == LocatorService && tokens.at(1) == "peerHeartBeat") + return 0; + QVector<JsonValue> values; + for (int i = 2; i < tokens.size(); i++) { + const JsonValue value(tokens.at(i)); + if (!value.isValid()) + return 434; + values.push_back(value); + } + // Parse known events, emit signals + QScopedPointer<CodaEvent> knownEvent(CodaEvent::parseEvent(service, tokens.at(1), values)); + if (!knownEvent.isNull()) { + // Answer hello event (WLAN) + if (knownEvent->type() == CodaEvent::LocatorHello) + if (!d->m_serialFrame) + writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC))); + emit tcfEvent(*knownEvent); + } + emit genericTcfEvent(service, tokens.at(1), values); + + if (debug || d->m_verbose) { + QString msg; + QTextStream str(&msg); + if (knownEvent.isNull()) { + str << "Event: " << tokens.at(0) << ' ' << tokens.at(1) << '\n'; + foreach(const JsonValue &val, values) + str << " " << val.toString() << '\n'; + } else { + str << knownEvent->toString(); + } + emitLogMessage(msg); + } + + return 0; +} + +unsigned CodaDevice::verbose() const +{ + return d->m_verbose; +} + +bool CodaDevice::serialFrame() const +{ + return d->m_serialFrame; +} + +void CodaDevice::setSerialFrame(bool s) +{ + d->m_serialFrame = s; +} + +void CodaDevice::setVerbose(unsigned v) +{ + d->m_verbose = v; +} + +void CodaDevice::emitLogMessage(const QString &m) +{ + if (debug) + qWarning("%s", qPrintable(m)); + emit logMessage(m); +} + +bool CodaDevice::checkOpen() +{ + if (d->m_device.isNull()) { + emitLogMessage(QLatin1String("Internal error: No device set on CodaDevice.")); + return false; + } + if (!d->m_device->isOpen()) { + emitLogMessage(QLatin1String("Internal error: Device not open in CodaDevice.")); + return false; + } + return true; +} + +void CodaDevice::sendSerialPing(bool pingOnly) +{ + if (!checkOpen()) + return; + + d->m_serialPingOnly = pingOnly; + setSerialFrame(true); + writeMessage(QByteArray(serialPingC, qstrlen(serialPingC)), false); + if (d->m_verbose) + emitLogMessage(QLatin1String("Ping...")); +} + +void CodaDevice::sendCodaMessage(MessageType mt, Services service, const char *command, + const char *commandParameters, // may contain '\0' + int commandParametersLength, + const CodaCallback &callBack, + const QVariant &cookie) + +{ + if (!checkOpen()) + return; + // Format the message + const int token = d->m_token++; + QByteArray data; + data.reserve(30 + commandParametersLength); + data.append('C'); + data.append('\0'); + data.append(QByteArray::number(token)); + data.append('\0'); + data.append(serviceName(service)); + data.append('\0'); + data.append(command); + data.append('\0'); + if (commandParametersLength) + data.append(commandParameters, commandParametersLength); + const CodaSendQueueEntry entry(mt, token, service, data, callBack, cookie); + d->m_sendQueue.enqueue(entry); + checkSendQueue(); +} + +void CodaDevice::sendCodaMessage(MessageType mt, Services service, const char *command, + const QByteArray &commandParameters, + const CodaCallback &callBack, + const QVariant &cookie) +{ + sendCodaMessage(mt, service, command, commandParameters.constData(), commandParameters.size(), + callBack, cookie); +} + +// Enclose in message frame and write. +void CodaDevice::writeMessage(QByteArray data, bool ensureTerminating0) +{ + if (!checkOpen()) + return; + + if (d->m_serialFrame && data.size() > maxSerialMessageLength) { + qCritical("Attempt to send large message (%d bytes) exceeding the " + "limit of %d bytes over serial channel. Skipping.", + data.size(), maxSerialMessageLength); + return; + } + + if (d->m_verbose) + emitLogMessage(debugMessage(data, "TCF <-")); + + // Ensure \0-termination which easily gets lost in QByteArray CT. + if (ensureTerminating0 && !data.endsWith('\0')) + data.append('\0'); + if (d->m_serialFrame) { + data = encodeUsbSerialMessage(data); + } else { + data += d->m_tcpMessageTerminator; + } + + if (debug > 1) + qDebug("Writing:\n%s", qPrintable(formatData(data))); + + int result = d->m_device->write(data); + if (result < data.length()) + qWarning("Failed to write all data! result=%d", result); + if (QAbstractSocket *as = qobject_cast<QAbstractSocket *>(d->m_device.data())) + as->flush(); +} + +void CodaDevice::writeCustomData(char protocolId, const QByteArray &data) +{ + if (!checkOpen()) + return; + + if (!d->m_serialFrame) { + qWarning("Ignoring request to send data to non-serial CodaDevice"); + return; + } + if (data.length() > 0xFFFF) { + qWarning("Ignoring request to send too large packet, of size %d", data.length()); + return; + } + QByteArray framedData; + encodeSerialFrame(data, &framedData, protocolId); + device()->write(framedData); +} + +void CodaDevice::checkSendQueue() +{ + // Fire off messages or invoke noops until a message with reply is found + // and an entry to writtenMessages is made. + while (d->m_writtenMessages.empty()) { + if (d->m_sendQueue.isEmpty()) + break; + CodaSendQueueEntry entry = d->m_sendQueue.dequeue(); + switch (entry.messageType) { + case MessageWithReply: + d->m_writtenMessages.insert(entry.token, entry); + writeMessage(entry.data); + break; + case MessageWithoutReply: + writeMessage(entry.data); + break; + case NoopMessage: // Invoke the noop-callback for synchronization + if (entry.callback) { + CodaCommandResult noopResult(CodaCommandResult::SuccessReply); + noopResult.cookie = entry.cookie; + entry.callback(noopResult); + } + break; + } + } +} + +// Fix slashes +static inline QString fixFileName(QString in) +{ + in.replace(QLatin1Char('/'), QLatin1Char('\\')); + return in; +} + +// Start a process (consisting of a non-reply setSettings and start). +void CodaDevice::sendProcessStartCommand(const CodaCallback &callBack, + const QString &binaryIn, + unsigned uid, + QStringList arguments, + QString workingDirectory, + bool debugControl, + const QStringList &additionalLibraries, + const QVariant &cookie) +{ + // Obtain the bin directory, expand by c:/sys/bin if missing + const QChar backSlash('\\'); + int slashPos = binaryIn.lastIndexOf(QLatin1Char('/')); + if (slashPos == -1) + slashPos = binaryIn.lastIndexOf(backSlash); + const QString sysBin = QLatin1String("c:/sys/bin"); + const QString binaryFileName = slashPos == -1 ? binaryIn : binaryIn.mid(slashPos + 1); + + if (workingDirectory.isEmpty()) + workingDirectory = sysBin; + + // Format settings with empty dummy parameter + QByteArray setData; + JsonInputStream setStr(setData); + setStr << "" << '\0' + << '[' << "exeToLaunch" << ',' << "addExecutables" << ',' << "addLibraries" << ',' << "logUserTraces" << ']' + << '\0' << '[' + << binaryFileName << ',' + << '{' << binaryFileName << ':' << QString::number(uid, 16) << '}' << ',' + << additionalLibraries << ',' << true + << ']'; + sendCodaMessage( +#if 1 + MessageWithReply, // TCF TRK 4.0.5 onwards +#else + MessageWithoutReply, // TCF TRK 4.0.2 +#endif + SettingsService, "set", setData); + + QByteArray startData; + JsonInputStream startStr(startData); + startStr << "" //We don't really know the drive of the working dir + << '\0' << binaryFileName << '\0' << arguments << '\0' + << QStringList() << '\0' // Env is an array ["PATH=value"] (non-standard) + << debugControl; + sendCodaMessage(MessageWithReply, ProcessesService, "start", startData, callBack, cookie); +} + +void CodaDevice::sendRunProcessCommand(const CodaCallback &callBack, + const QString &processName, + QStringList arguments, + const QVariant &cookie) +{ + QByteArray startData; + JsonInputStream startStr(startData); + startStr << "" //We don't really know the drive of the working dir + << '\0' << processName << '\0' << arguments << '\0' + << QStringList() << '\0' // Env is an array ["PATH=value"] (non-standard) + << false; // Don't attach debugger + sendCodaMessage(MessageWithReply, ProcessesService, "start", startData, callBack, cookie); +} + +void CodaDevice::sendSettingsEnableLogCommand() +{ + + QByteArray setData; + JsonInputStream setStr(setData); + setStr << "" << '\0' + << '[' << "logUserTraces" << ']' + << '\0' << '[' + << true + << ']'; + sendCodaMessage( +#if 1 + MessageWithReply, // TCF TRK 4.0.5 onwards +#else + MessageWithoutReply, // TCF TRK 4.0.2 +#endif + SettingsService, "set", setData); +} + +void CodaDevice::sendProcessTerminateCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendCodaMessage(MessageWithReply, ProcessesService, "terminate", data, callBack, cookie); +} + +void CodaDevice::sendRunControlTerminateCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendCodaMessage(MessageWithReply, RunControlService, "terminate", data, callBack, cookie); +} + +// Non-standard: Remove executable from settings +void CodaDevice::sendSettingsRemoveExecutableCommand(const QString &binaryIn, + unsigned uid, + const QStringList &additionalLibraries, + const QVariant &cookie) +{ + QByteArray setData; + JsonInputStream setStr(setData); + setStr << "" << '\0' + << '[' << "removedExecutables" << ',' << "removedLibraries" << ']' + << '\0' << '[' + << '{' << QFileInfo(binaryIn).fileName() << ':' << QString::number(uid, 16) << '}' << ',' + << additionalLibraries + << ']'; + sendCodaMessage(MessageWithoutReply, SettingsService, "set", setData, CodaCallback(), cookie); +} + +void CodaDevice::sendRunControlResumeCommand(const CodaCallback &callBack, + const QByteArray &id, + RunControlResumeMode mode, + unsigned count, + quint64 rangeStart, + quint64 rangeEnd, + const QVariant &cookie) +{ + QByteArray resumeData; + JsonInputStream str(resumeData); + str << id << '\0' << int(mode) << '\0' << count; + switch (mode) { + case RM_STEP_OVER_RANGE: + case RM_STEP_INTO_RANGE: + case RM_REVERSE_STEP_OVER_RANGE: + case RM_REVERSE_STEP_INTO_RANGE: + str << '\0' << '{' << "RANGE_START" << ':' << rangeStart + << ',' << "RANGE_END" << ':' << rangeEnd << '}'; + break; + default: + break; + } + sendCodaMessage(MessageWithReply, RunControlService, "resume", resumeData, callBack, cookie); +} + +void CodaDevice::sendRunControlSuspendCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << id; + sendCodaMessage(MessageWithReply, RunControlService, "suspend", data, callBack, cookie); +} + +void CodaDevice::sendRunControlResumeCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + sendRunControlResumeCommand(callBack, id, RM_RESUME, 1, 0, 0, cookie); +} + +void CodaDevice::sendBreakpointsAddCommand(const CodaCallback &callBack, + const Breakpoint &bp, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << bp; + sendCodaMessage(MessageWithReply, BreakpointsService, "add", data, callBack, cookie); +} + +void CodaDevice::sendBreakpointsRemoveCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie) +{ + sendBreakpointsRemoveCommand(callBack, QVector<QByteArray>(1, id), cookie); +} + +void CodaDevice::sendBreakpointsRemoveCommand(const CodaCallback &callBack, + const QVector<QByteArray> &ids, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << ids; + sendCodaMessage(MessageWithReply, BreakpointsService, "remove", data, callBack, cookie); +} + +void CodaDevice::sendBreakpointsEnableCommand(const CodaCallback &callBack, + const QByteArray &id, + bool enable, + const QVariant &cookie) +{ + sendBreakpointsEnableCommand(callBack, QVector<QByteArray>(1, id), enable, cookie); +} + +void CodaDevice::sendBreakpointsEnableCommand(const CodaCallback &callBack, + const QVector<QByteArray> &ids, + bool enable, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << ids; + sendCodaMessage(MessageWithReply, BreakpointsService, + enable ? "enable" : "disable", + data, callBack, cookie); +} + +void CodaDevice::sendMemorySetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + quint64 start, const QByteArray& data, + const QVariant &cookie) +{ + QByteArray getData; + JsonInputStream str(getData); + // start/word size/mode. Mode should ideally be 1 (continue on error?) + str << contextId << '\0' << start << '\0' << 1 << '\0' << data.size() << '\0' << 1 + << '\0' << data.toBase64(); + sendCodaMessage(MessageWithReply, MemoryService, "set", getData, callBack, cookie); +} + +void CodaDevice::sendMemoryGetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + quint64 start, quint64 size, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + // start/word size/mode. Mode should ideally be 1 (continue on error?) + str << contextId << '\0' << start << '\0' << 1 << '\0' << size << '\0' << 1; + sendCodaMessage(MessageWithReply, MemoryService, "get", data, callBack, cookie); +} + +QByteArray CodaDevice::parseMemoryGet(const CodaCommandResult &r) +{ + if (r.type != CodaCommandResult::SuccessReply || r.values.size() < 1) + return QByteArray(); + const JsonValue &memoryV = r.values.front(); + + if (memoryV.type() != JsonValue::String || memoryV.data().size() < 2 + || !memoryV.data().endsWith('=')) + return QByteArray(); + // Catch errors reported as hash: + // R.4."TlVMTA==".{"Time":1276786871255,"Code":1,"AltCode":-38,"AltOrg":"POSIX","Format":"BadDescriptor"} + // Not sure what to make of it. + if (r.values.size() >= 2 && r.values.at(1).type() == JsonValue::Object) + qWarning("CodaDevice::parseMemoryGet(): Error retrieving memory: %s", r.values.at(1).toString(false).constData()); + // decode + const QByteArray memory = QByteArray::fromBase64(memoryV.data()); + if (memory.isEmpty()) + qWarning("Base64 decoding of %s failed.", memoryV.data().constData()); + if (debug) + qDebug("CodaDevice::parseMemoryGet: received %d bytes", memory.size()); + return memory; +} + +// Parse register children (array of names) +QVector<QByteArray> CodaDevice::parseRegisterGetChildren(const CodaCommandResult &r) +{ + QVector<QByteArray> rc; + if (!r || r.values.size() < 1 || r.values.front().type() != JsonValue::Array) + return rc; + const JsonValue &front = r.values.front(); + rc.reserve(front.childCount()); + foreach(const JsonValue &v, front.children()) + rc.push_back(v.data()); + return rc; +} + +CodaStatResponse CodaDevice::parseStat(const CodaCommandResult &r) +{ + CodaStatResponse rc; + if (!r || r.values.size() < 1 || r.values.front().type() != JsonValue::Object) + return rc; + foreach(const JsonValue &v, r.values.front().children()) { + if (v.name() == "Size") { + rc.size = v.data().toULongLong(); + } else if (v.name() == "ATime") { + if (const quint64 atime = v.data().toULongLong()) + rc.accessTime = CodaCommandResult::tcfTimeToQDateTime(atime); + } else if (v.name() == "MTime") { + if (const quint64 mtime = v.data().toULongLong()) + rc.modTime = CodaCommandResult::tcfTimeToQDateTime(mtime); + } + } + return rc; +} + +void CodaDevice::sendRegistersGetChildrenCommand(const CodaCallback &callBack, + const QByteArray &contextId, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << contextId; + sendCodaMessage(MessageWithReply, RegistersService, "getChildren", data, callBack, cookie); +} + +// Format id of register get request (needs contextId containing process and thread) +static inline QByteArray registerId(const QByteArray &contextId, QByteArray id) +{ + QByteArray completeId = contextId; + if (!completeId.isEmpty()) + completeId.append('.'); + completeId.append(id); + return completeId; +} + +// Format parameters of register get request +static inline QByteArray registerGetData(const QByteArray &contextId, QByteArray id) +{ + QByteArray data; + JsonInputStream str(data); + str << registerId(contextId, id); + return data; +} + +void CodaDevice::sendRegistersGetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + QByteArray id, + const QVariant &cookie) +{ + sendCodaMessage(MessageWithReply, RegistersService, "get", + registerGetData(contextId, id), callBack, cookie); +} + +void CodaDevice::sendRegistersGetMCommand(const CodaCallback &callBack, + const QByteArray &contextId, + const QVector<QByteArray> &ids, + const QVariant &cookie) +{ + // Format the register ids as a JSON list + QByteArray data; + JsonInputStream str(data); + str << '['; + const int count = ids.size(); + for (int r = 0; r < count; r++) { + if (r) + str << ','; + // TODO: When 8-byte floating-point registers are supported, query for register length based on register id + str << '[' << registerId(contextId, ids.at(r)) << ',' << '0' << ',' << '4' << ']'; + } + str << ']'; + sendCodaMessage(MessageWithReply, RegistersService, "getm", data, callBack, cookie); +} + +void CodaDevice::sendRegistersGetMRangeCommand(const CodaCallback &callBack, + const QByteArray &contextId, + unsigned start, unsigned count) +{ + const unsigned end = start + count; + if (end > (unsigned)d->m_registerNames.size()) { + qWarning("CodaDevice: No register name set for index %u (size: %d).", end, d->m_registerNames.size()); + return; + } + + QVector<QByteArray> ids; + ids.reserve(count); + for (unsigned i = start; i < end; ++i) + ids.push_back(d->m_registerNames.at(i)); + sendRegistersGetMCommand(callBack, contextId, ids, QVariant(start)); +} + +// Set register +void CodaDevice::sendRegistersSetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + QByteArray id, + const QByteArray &value, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + if (!contextId.isEmpty()) { + id.prepend('.'); + id.prepend(contextId); + } + str << id << '\0' << value.toBase64(); + sendCodaMessage(MessageWithReply, RegistersService, "set", data, callBack, cookie); +} + +// Set register +void CodaDevice::sendRegistersSetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + unsigned registerNumber, + const QByteArray &value, + const QVariant &cookie) +{ + if (registerNumber >= (unsigned)d->m_registerNames.size()) { + qWarning("CodaDevice: No register name set for index %u (size: %d).", registerNumber, d->m_registerNames.size()); + return; + } + sendRegistersSetCommand(callBack, contextId, + d->m_registerNames[registerNumber], + value, cookie); +} + +static const char outputListenerIDC[] = "ProgramOutputConsoleLogger"; + +void CodaDevice::sendLoggingAddListenerCommand(const CodaCallback &callBack, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << outputListenerIDC; + sendCodaMessage(MessageWithReply, LoggingService, "addListener", data, callBack, cookie); +} + +void CodaDevice::sendSymbianUninstallCommand(const Coda::CodaCallback &callBack, + const quint32 package, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + QString string = QString::number(package, 16); + str << string; + sendCodaMessage(MessageWithReply, SymbianInstallService, "uninstall", data, callBack, cookie); +} + +void CodaDevice::sendSymbianOsDataGetThreadsCommand(const CodaCallback &callBack, + const QVariant &cookie) +{ + QByteArray data; + sendCodaMessage(MessageWithReply, SymbianOSData, "getThreads", data, callBack, cookie); +} + +void CodaDevice::sendSymbianOsDataFindProcessesCommand(const CodaCallback &callBack, + const QByteArray &processName, + const QByteArray &uid, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << processName << '\0' << uid; + sendCodaMessage(MessageWithReply, SymbianOSData, "findRunningProcesses", data, callBack, cookie); +} + +void CodaDevice::sendSymbianOsDataGetQtVersionCommand(const CodaCallback &callBack, + const QVariant &cookie) +{ + sendCodaMessage(MessageWithReply, SymbianOSData, "getQtVersion", QByteArray(), callBack, cookie); +} + +void CodaDevice::sendSymbianOsDataGetRomInfoCommand(const CodaCallback &callBack, + const QVariant &cookie) +{ + sendCodaMessage(MessageWithReply, SymbianOSData, "getRomInfo", QByteArray(), callBack, cookie); +} + +void CodaDevice::sendSymbianOsDataGetHalInfoCommand(const CodaCallback &callBack, + const QStringList &keys, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << '['; + for (int i = 0; i < keys.count(); ++i) { + if (i) + str << ','; + str << keys[i]; + } + str << ']'; + sendCodaMessage(MessageWithReply, SymbianOSData, "getHalInfo", data, callBack, cookie); +} + +void Coda::CodaDevice::sendFileSystemOpenCommand(const Coda::CodaCallback &callBack, + const QByteArray &name, + unsigned flags, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << name << '\0' << flags << '\0' << '{' << '}'; + sendCodaMessage(MessageWithReply, FileSystemService, "open", data, callBack, cookie); +} + +void Coda::CodaDevice::sendFileSystemFstatCommand(const CodaCallback &callBack, + const QByteArray &handle, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << handle; + sendCodaMessage(MessageWithReply, FileSystemService, "fstat", data, callBack, cookie); +} + +void Coda::CodaDevice::sendFileSystemReadCommand(const Coda::CodaCallback &callBack, + const QByteArray &handle, + unsigned int offset, + unsigned int size, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << handle << '\0' << offset << '\0' << size; + sendCodaMessage(MessageWithReply, FileSystemService, "read", data, callBack, cookie); +} + +void Coda::CodaDevice::sendFileSystemWriteCommand(const Coda::CodaCallback &callBack, + const QByteArray &handle, + const QByteArray &dataIn, + unsigned offset, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << handle << '\0' << offset << '\0' << dataIn.toBase64(); + sendCodaMessage(MessageWithReply, FileSystemService, "write", data, callBack, cookie); +} + +void Coda::CodaDevice::sendFileSystemCloseCommand(const Coda::CodaCallback &callBack, + const QByteArray &handle, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << handle; + sendCodaMessage(MessageWithReply, FileSystemService, "close", data, callBack, cookie); +} + +void Coda::CodaDevice::sendSymbianInstallSilentInstallCommand(const Coda::CodaCallback &callBack, + const QByteArray &file, + const QByteArray &targetDrive, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << file << '\0' << targetDrive; + sendCodaMessage(MessageWithReply, SymbianInstallService, "install", data, callBack, cookie); +} + +void Coda::CodaDevice::sendSymbianInstallUIInstallCommand(const Coda::CodaCallback &callBack, + const QByteArray &file, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << file; + sendCodaMessage(MessageWithReply, SymbianInstallService, "installWithUI", data, callBack, cookie); +} + +void Coda::CodaDevice::sendSymbianInstallGetPackageInfoCommand(const Coda::CodaCallback &callBack, + const QList<quint32> &packages, + const QVariant &cookie) +{ + QByteArray data; + JsonInputStream str(data); + str << '['; + for (int i = 0; i < packages.count(); ++i) { + if (i) + str << ','; + QString pkgString; + pkgString.setNum(packages[i], 16); + str << pkgString; + } + str << ']'; + sendCodaMessage(MessageWithReply, SymbianInstallService, "getPackageInfo", data, callBack, cookie); +} + +void Coda::CodaDevice::sendDebugSessionControlSessionStartCommand(const Coda::CodaCallback &callBack, + const QVariant &cookie) +{ + sendCodaMessage(MessageWithReply, DebugSessionControl, "sessionStart", QByteArray(), callBack, cookie); +} + +void Coda::CodaDevice::sendDebugSessionControlSessionEndCommand(const Coda::CodaCallback &callBack, + const QVariant &cookie) +{ + sendCodaMessage(MessageWithReply, DebugSessionControl, "sessionEnd ", QByteArray(), callBack, cookie); +} + +} // namespace Coda diff --git a/tools/runonphone/symbianutils/codadevice.h b/tools/runonphone/symbianutils/codadevice.h new file mode 100644 index 0000000..253e8b2 --- /dev/null +++ b/tools/runonphone/symbianutils/codadevice.h @@ -0,0 +1,447 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CODAENGINE_H +#define CODAENGINE_H + +#include "symbianutils_global.h" +#include "codamessage.h" +#include "callback.h" +#include "json.h" + +#include <QtCore/QObject> +#include <QtCore/QSharedPointer> +#include <QtCore/QVector> +#include <QtCore/QVariant> +#include <QtCore/QStringList> +#include <QtCore/QDateTime> + +QT_BEGIN_NAMESPACE +class QIODevice; +class QTextStream; +QT_END_NAMESPACE + +namespace Coda { + +struct CodaDevicePrivate; +struct Breakpoint; + +/* Command error handling in TCF: + * 1) 'Severe' errors (JSON format, parameter format): Trk emits a + * nonstandard message (\3\2 error parameters) and closes the connection. + * 2) Protocol errors: 'N' without error message is returned. + * 3) Errors in command execution: 'R' with a TCF error hash is returned + * (see CodaCommandError). */ + +/* Error code return in 'R' reply to command + * (see top of 'Services' documentation). */ +struct SYMBIANUTILS_EXPORT CodaCommandError { + CodaCommandError(); + void clear(); + bool isError() const; + operator bool() const { return isError(); } + QString toString() const; + void write(QTextStream &str) const; + bool parse(const QVector<JsonValue> &values); + + quint64 timeMS; // Since 1.1.1970 + qint64 code; + QByteArray format; // message + // 'Alternative' meaning, like altOrg="POSIX"/altCode=<some errno> + QByteArray alternativeOrganization; + qint64 alternativeCode; +}; + +/* Answer to a Tcf command passed to the callback. */ +struct SYMBIANUTILS_EXPORT CodaCommandResult { + enum Type + { + SuccessReply, // 'R' and no error -> all happy. + CommandErrorReply, // 'R' with CodaCommandError received + ProgressReply, // 'P', progress indicator + FailReply // 'N' Protocol NAK, severe error + }; + + explicit CodaCommandResult(Type t = SuccessReply); + explicit CodaCommandResult(char typeChar, Services service, + const QByteArray &request, + const QVector<JsonValue> &values, + const QVariant &cookie); + + QString toString() const; + QString errorString() const; + operator bool() const { return type == SuccessReply || type == ProgressReply; } + + static QDateTime tcfTimeToQDateTime(quint64 tcfTimeMS); + + Type type; + Services service; + QByteArray request; + CodaCommandError commandError; + QVector<JsonValue> values; + QVariant cookie; +}; + +// Response to stat/fstat +struct SYMBIANUTILS_EXPORT CodaStatResponse +{ + CodaStatResponse(); + + quint64 size; + QDateTime modTime; + QDateTime accessTime; +}; + +typedef trk::Callback<const CodaCommandResult &> CodaCallback; + +/* CodaDevice: TCF communication helper using an asynchronous QIODevice + * implementing the TCF protocol according to: +http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Specification.html +http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services.html + * Commands can be sent along with callbacks that are passed a + * CodaCommandResult and an opaque QVariant cookie. In addition, events are emitted. + * + * CODA notes: + * - Commands are accepted only after receiving the Locator Hello event + * - Serial communication initiation sequence: + * Send serial ping from host sendSerialPing() -> receive pong response with + * version information -> Send Locator Hello Event -> Receive Locator Hello Event + * -> Commands are accepted. + * - WLAN communication initiation sequence: + * Receive Locator Hello Event from CODA -> Commands are accepted. + */ + +class SYMBIANUTILS_EXPORT CodaDevice : public QObject +{ + Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose) + Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame) + Q_OBJECT +public: + // Flags for FileSystem:open + enum FileSystemOpenFlags + { + FileSystem_TCF_O_READ = 0x00000001, + FileSystem_TCF_O_WRITE = 0x00000002, + FileSystem_TCF_O_APPEND = 0x00000004, + FileSystem_TCF_O_CREAT = 0x00000008, + FileSystem_TCF_O_TRUNC = 0x00000010, + FileSystem_TCF_O_EXCL = 0x00000020 + }; + + enum MessageType + { + MessageWithReply, + MessageWithoutReply, /* Non-standard: "Settings:set" command does not reply */ + NoopMessage + }; + + typedef QSharedPointer<QIODevice> IODevicePtr; + + explicit CodaDevice(QObject *parent = 0); + virtual ~CodaDevice(); + + unsigned verbose() const; + bool serialFrame() const; + void setSerialFrame(bool); + + // Mapping of register names to indices for multi-requests. + // Register names can be retrieved via 'Registers:getChildren' (requires + // context id to be stripped). + QVector<QByteArray> registerNames() const; + void setRegisterNames(const QVector<QByteArray>& n); + + IODevicePtr device() const; + IODevicePtr takeDevice(); + void setDevice(const IODevicePtr &dp); + + // Serial Only: Initiate communication. Will emit serialPong() signal with version. + void sendSerialPing(bool pingOnly = false); + + // Send with parameters from string (which may contain '\0'). + void sendCodaMessage(MessageType mt, Services service, const char *command, + const char *commandParameters, int commandParametersLength, + const CodaCallback &callBack = CodaCallback(), + const QVariant &cookie = QVariant()); + + void sendCodaMessage(MessageType mt, Services service, const char *command, + const QByteArray &commandParameters, + const CodaCallback &callBack = CodaCallback(), + const QVariant &cookie = QVariant()); + + // Convenience messages: Start a process + void sendProcessStartCommand(const CodaCallback &callBack, + const QString &binary, + unsigned uid, + QStringList arguments = QStringList(), + QString workingDirectory = QString(), + bool debugControl = true, + const QStringList &additionalLibraries = QStringList(), + const QVariant &cookie = QVariant()); + + // Just launch a process, don't attempt to attach the debugger to it + void sendRunProcessCommand(const CodaCallback &callBack, + const QString &processName, + QStringList arguments = QStringList(), + const QVariant &cookie = QVariant()); + + // Preferred over Processes:Terminate by TCF TRK. + void sendRunControlTerminateCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendProcessTerminateCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + // Non-standard: Remove executable from settings. + // Probably needs to be called after stopping. This command has no response. + void sendSettingsRemoveExecutableCommand(const QString &binaryIn, + unsigned uid, + const QStringList &additionalLibraries = QStringList(), + const QVariant &cookie = QVariant()); + + void sendRunControlSuspendCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + // Resume / Step (see RunControlResumeMode). + void sendRunControlResumeCommand(const CodaCallback &callBack, + const QByteArray &id, + RunControlResumeMode mode, + unsigned count /* = 1, currently ignored. */, + quint64 rangeStart, quint64 rangeEnd, + const QVariant &cookie = QVariant()); + + // Convenience to resume a suspended process + void sendRunControlResumeCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsAddCommand(const CodaCallback &callBack, + const Breakpoint &b, + const QVariant &cookie = QVariant()); + + void sendBreakpointsRemoveCommand(const CodaCallback &callBack, + const QByteArray &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsRemoveCommand(const CodaCallback &callBack, + const QVector<QByteArray> &id, + const QVariant &cookie = QVariant()); + + void sendBreakpointsEnableCommand(const CodaCallback &callBack, + const QByteArray &id, + bool enable, + const QVariant &cookie = QVariant()); + + void sendBreakpointsEnableCommand(const CodaCallback &callBack, + const QVector<QByteArray> &id, + bool enable, + const QVariant &cookie = QVariant()); + + + void sendMemoryGetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + quint64 start, quint64 size, + const QVariant &cookie = QVariant()); + + void sendMemorySetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + quint64 start, const QByteArray& data, + const QVariant &cookie = QVariant()); + + // Get register names (children of context). + // It is possible to recurse from thread id down to single registers. + void sendRegistersGetChildrenCommand(const CodaCallback &callBack, + const QByteArray &contextId, + const QVariant &cookie = QVariant()); + + // Register get + void sendRegistersGetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + QByteArray id, + const QVariant &cookie); + + void sendRegistersGetMCommand(const CodaCallback &callBack, + const QByteArray &contextId, + const QVector<QByteArray> &ids, + const QVariant &cookie = QVariant()); + + // Convenience to get a range of register "R0" .. "R<n>". + // Cookie will be an int containing "start". + void sendRegistersGetMRangeCommand(const CodaCallback &callBack, + const QByteArray &contextId, + unsigned start, unsigned count); + + // Set register + void sendRegistersSetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + QByteArray ids, + const QByteArray &value, // binary value + const QVariant &cookie = QVariant()); + // Set register + void sendRegistersSetCommand(const CodaCallback &callBack, + const QByteArray &contextId, + unsigned registerNumber, + const QByteArray &value, // binary value + const QVariant &cookie = QVariant()); + + // File System + void sendFileSystemOpenCommand(const CodaCallback &callBack, + const QByteArray &name, + unsigned flags = FileSystem_TCF_O_READ, + const QVariant &cookie = QVariant()); + + void sendFileSystemFstatCommand(const CodaCallback &callBack, + const QByteArray &handle, + const QVariant &cookie = QVariant()); + + void sendFileSystemReadCommand(const Coda::CodaCallback &callBack, + const QByteArray &handle, + unsigned int offset, + unsigned int size, + const QVariant &cookie = QVariant()); + + void sendFileSystemWriteCommand(const CodaCallback &callBack, + const QByteArray &handle, + const QByteArray &data, + unsigned offset = 0, + const QVariant &cookie = QVariant()); + + void sendFileSystemCloseCommand(const CodaCallback &callBack, + const QByteArray &handle, + const QVariant &cookie = QVariant()); + + // Symbian Install + void sendSymbianInstallSilentInstallCommand(const CodaCallback &callBack, + const QByteArray &file, + const QByteArray &targetDrive, + const QVariant &cookie = QVariant()); + + void sendSymbianInstallUIInstallCommand(const CodaCallback &callBack, + const QByteArray &file, + const QVariant &cookie = QVariant()); + + void sendSymbianInstallGetPackageInfoCommand(const Coda::CodaCallback &callBack, + const QList<quint32> &packages, + const QVariant &cookie = QVariant()); + + void sendLoggingAddListenerCommand(const CodaCallback &callBack, + const QVariant &cookie = QVariant()); + + void sendSymbianUninstallCommand(const Coda::CodaCallback &callBack, + const quint32 package, + const QVariant &cookie = QVariant()); + + // SymbianOs Data + void sendSymbianOsDataGetThreadsCommand(const CodaCallback &callBack, + const QVariant &cookie = QVariant()); + + void sendSymbianOsDataFindProcessesCommand(const CodaCallback &callBack, + const QByteArray &processName, + const QByteArray &uid, + const QVariant &cookie = QVariant()); + + void sendSymbianOsDataGetQtVersionCommand(const CodaCallback &callBack, + const QVariant &cookie = QVariant()); + + void sendSymbianOsDataGetRomInfoCommand(const CodaCallback &callBack, + const QVariant &cookie = QVariant()); + + void sendSymbianOsDataGetHalInfoCommand(const CodaCallback &callBack, + const QStringList &keys = QStringList(), + const QVariant &cookie = QVariant()); + + // DebugSessionControl + void sendDebugSessionControlSessionStartCommand(const CodaCallback &callBack, + const QVariant &cookie = QVariant()); + + void sendDebugSessionControlSessionEndCommand(const CodaCallback &callBack, + const QVariant &cookie = QVariant()); + + // Settings + void sendSettingsEnableLogCommand(); + + void writeCustomData(char protocolId, const QByteArray &aData); + + static QByteArray parseMemoryGet(const CodaCommandResult &r); + static QVector<QByteArray> parseRegisterGetChildren(const CodaCommandResult &r); + static CodaStatResponse parseStat(const CodaCommandResult &r); + +signals: + void genericTcfEvent(int service, const QByteArray &name, const QVector<JsonValue> &value); + void tcfEvent(const Coda::CodaEvent &knownEvent); + void unknownEvent(uchar protocolId, const QByteArray& data); + void serialPong(const QString &codaVersion); + + void logMessage(const QString &); + void error(const QString &); + +public slots: + void setVerbose(unsigned v); + +private slots: + void slotDeviceError(); + void slotDeviceSocketStateChanged(); + void slotDeviceReadyRead(); + +private: + void deviceReadyReadSerial(); + void deviceReadyReadTcp(); + + bool checkOpen(); + void checkSendQueue(); + void writeMessage(QByteArray data, bool ensureTerminating0 = true); + void emitLogMessage(const QString &); + inline int parseMessage(const QByteArray &); + void processMessage(const QByteArray &message); + inline void processSerialMessage(const QByteArray &message); + int parseTcfCommandReply(char type, const QVector<QByteArray> &tokens); + int parseTcfEvent(const QVector<QByteArray> &tokens); + +private: + QPair<int, int> findSerialHeader(QByteArray &in); + CodaDevicePrivate *d; +}; + +} // namespace Coda + +#endif // CODAENGINE_H diff --git a/tools/runonphone/symbianutils/tcftrkmessage.cpp b/tools/runonphone/symbianutils/codamessage.cpp index 9e9c16c..13fbcf2 100644 --- a/tools/runonphone/symbianutils/tcftrkmessage.cpp +++ b/tools/runonphone/symbianutils/codamessage.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "tcftrkmessage.h" +#include "codamessage.h" #include "json.h" #include <QtCore/QString> @@ -48,10 +48,11 @@ // Names matching the enum static const char *serviceNamesC[] = { "Locator", "RunControl", "Processes", "Memory", "Settings", "Breakpoints", - "Registers", "SimpleRegisters", + "Registers", "Logging", "FileSystem", "SymbianInstall", "SymbianOSData", + "DebugSessionControl", "UnknownService"}; -namespace tcftrk { +namespace Coda { SYMBIANUTILS_EXPORT QString joinByteArrays(const QVector<QByteArray> &a, char sep) { @@ -341,7 +342,7 @@ QString Breakpoint::toString() const JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b) { if (b.contextIds.isEmpty()) - qWarning("tcftrk::Breakpoint: No context ids specified"); + qWarning("Coda::Breakpoint: No context ids specified"); str << '{' << "ID" << ':' << QString::fromUtf8(b.id) << ',' << "BreakpointType" << ':' << breakPointTypesC[b.type] << ',' @@ -356,27 +357,27 @@ JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b) } // --- Events -TcfTrkEvent::TcfTrkEvent(Type type) : m_type(type) +CodaEvent::CodaEvent(Type type) : m_type(type) { } -TcfTrkEvent::~TcfTrkEvent() +CodaEvent::~CodaEvent() { } -TcfTrkEvent::Type TcfTrkEvent::type() const +CodaEvent::Type CodaEvent::type() const { return m_type; } -QString TcfTrkEvent::toString() const +QString CodaEvent::toString() const { return QString(); } static const char sharedLibrarySuspendReasonC[] = "Shared Library"; -TcfTrkEvent *TcfTrkEvent::parseEvent(Services s, const QByteArray &nameBA, const QVector<JsonValue> &values) +CodaEvent *CodaEvent::parseEvent(Services s, const QByteArray &nameBA, const QVector<JsonValue> &values) { switch (s) { case LocatorService: @@ -384,7 +385,7 @@ TcfTrkEvent *TcfTrkEvent::parseEvent(Services s, const QByteArray &nameBA, const QStringList services; foreach (const JsonValue &jv, values.front().children()) services.push_back(QString::fromUtf8(jv.data())); - return new TcfTrkLocatorHelloEvent(services); + return new CodaLocatorHelloEvent(services); } break; case RunControlService: @@ -395,67 +396,96 @@ TcfTrkEvent *TcfTrkEvent::parseEvent(Services s, const QByteArray &nameBA, const const QByteArray idBA = values.at(0).data(); const quint64 pc = values.at(1).data().toULongLong(); const QByteArray reasonBA = values.at(2).data(); + QByteArray messageBA; // Module load: Special if (reasonBA == sharedLibrarySuspendReasonC) { ModuleLoadEventInfo info; if (!info.parse(values.at(3))) return 0; - return new TcfTrkRunControlModuleLoadContextSuspendedEvent(idBA, reasonBA, pc, info); + return new CodaRunControlModuleLoadContextSuspendedEvent(idBA, reasonBA, pc, info); + } else { + // hash containing a 'message'-key with a verbose crash message. + if (values.at(3).type() == JsonValue::Object && values.at(3).childCount() + && values.at(3).children().at(0).type() == JsonValue::String) + messageBA = values.at(3).children().at(0).data(); } - return new TcfTrkRunControlContextSuspendedEvent(idBA, reasonBA, pc); + return new CodaRunControlContextSuspendedEvent(idBA, reasonBA, messageBA, pc); } // "contextSuspended" if (nameBA == "contextAdded") - return TcfTrkRunControlContextAddedEvent::parseEvent(values); + return CodaRunControlContextAddedEvent::parseEvent(values); if (nameBA == "contextRemoved" && values.front().type() == JsonValue::Array) { QVector<QByteArray> ids; foreach(const JsonValue &c, values.front().children()) ids.push_back(c.data()); - return new TcfTrkRunControlContextRemovedEvent(ids); + return new CodaRunControlContextRemovedEvent(ids); } break; + case LoggingService: + if ((nameBA == "writeln" || nameBA == "write" /*not yet used*/) && values.size() >= 2) + return new CodaLoggingWriteEvent(values.at(0).data(), values.at(1).data()); + break; + case ProcessesService: + if (nameBA == "exited" && values.size() >= 2) + return new CodaProcessExitedEvent(values.at(0).data()); + break; default: break; } return 0; } -// -------------- TcfTrkServiceHelloEvent -TcfTrkLocatorHelloEvent::TcfTrkLocatorHelloEvent(const QStringList &s) : - TcfTrkEvent(LocatorHello), +// -------------- CodaServiceHelloEvent +CodaLocatorHelloEvent::CodaLocatorHelloEvent(const QStringList &s) : + CodaEvent(LocatorHello), m_services(s) { } -QString TcfTrkLocatorHelloEvent::toString() const +QString CodaLocatorHelloEvent::toString() const { return QLatin1String("ServiceHello: ") + m_services.join(QLatin1String(", ")); } -// -------------- TcfTrkIdEvent -TcfTrkIdEvent::TcfTrkIdEvent(Type t, const QByteArray &id) : - TcfTrkEvent(t), m_id(id) +// -------------- Logging event + +CodaLoggingWriteEvent::CodaLoggingWriteEvent(const QByteArray &console, const QByteArray &message) : + CodaEvent(LoggingWriteEvent), m_console(console), m_message(message) +{ +} + +QString CodaLoggingWriteEvent::toString() const +{ + QByteArray msgBA = m_console; + msgBA += ": "; + msgBA += m_message; + return QString::fromUtf8(msgBA); +} + +// -------------- CodaIdEvent +CodaIdEvent::CodaIdEvent(Type t, const QByteArray &id) : + CodaEvent(t), m_id(id) { } -// ---------- TcfTrkIdsEvent -TcfTrkIdsEvent::TcfTrkIdsEvent(Type t, const QVector<QByteArray> &ids) : - TcfTrkEvent(t), m_ids(ids) +// ---------- CodaIdsEvent +CodaIdsEvent::CodaIdsEvent(Type t, const QVector<QByteArray> &ids) : + CodaEvent(t), m_ids(ids) { } -QString TcfTrkIdsEvent::joinedIdString(const char sep) const +QString CodaIdsEvent::joinedIdString(const char sep) const { return joinByteArrays(m_ids, sep); } -// ---------------- TcfTrkRunControlContextAddedEvent -TcfTrkRunControlContextAddedEvent::TcfTrkRunControlContextAddedEvent(const RunControlContexts &c) : - TcfTrkEvent(RunControlContextAdded), m_contexts(c) +// ---------------- CodaRunControlContextAddedEvent +CodaRunControlContextAddedEvent::CodaRunControlContextAddedEvent(const RunControlContexts &c) : + CodaEvent(RunControlContextAdded), m_contexts(c) { } -TcfTrkRunControlContextAddedEvent - *TcfTrkRunControlContextAddedEvent::parseEvent(const QVector<JsonValue> &values) +CodaRunControlContextAddedEvent + *CodaRunControlContextAddedEvent::parseEvent(const QVector<JsonValue> &values) { // Parse array of contexts if (values.size() < 1 || values.front().type() != JsonValue::Array) @@ -467,10 +497,10 @@ TcfTrkRunControlContextAddedEvent if (context.parse(v)) contexts.push_back(context); } - return new TcfTrkRunControlContextAddedEvent(contexts); + return new CodaRunControlContextAddedEvent(contexts); } -QString TcfTrkRunControlContextAddedEvent::toString() const +QString CodaRunControlContextAddedEvent::toString() const { QString rc; QTextStream str(&rc); @@ -484,42 +514,45 @@ QString TcfTrkRunControlContextAddedEvent::toString() const return rc; } -// --------------- TcfTrkRunControlContextRemovedEvent -TcfTrkRunControlContextRemovedEvent::TcfTrkRunControlContextRemovedEvent(const QVector<QByteArray> &ids) : - TcfTrkIdsEvent(RunControlContextRemoved, ids) +// --------------- CodaRunControlContextRemovedEvent +CodaRunControlContextRemovedEvent::CodaRunControlContextRemovedEvent(const QVector<QByteArray> &ids) : + CodaIdsEvent(RunControlContextRemoved, ids) { } -QString TcfTrkRunControlContextRemovedEvent::toString() const +QString CodaRunControlContextRemovedEvent::toString() const { return QLatin1String("RunControl: Removed contexts '") + joinedIdString() + ("'."); } -// --------------- TcfTrkRunControlContextSuspendedEvent -TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(const QByteArray &id, +// --------------- CodaRunControlContextSuspendedEvent +CodaRunControlContextSuspendedEvent::CodaRunControlContextSuspendedEvent(const QByteArray &id, const QByteArray &reason, + const QByteArray &message, quint64 pc) : - TcfTrkIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason) + CodaIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason), m_message(message) { } -TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(Type t, +CodaRunControlContextSuspendedEvent::CodaRunControlContextSuspendedEvent(Type t, const QByteArray &id, const QByteArray &reason, quint64 pc) : - TcfTrkIdEvent(t, id), m_pc(pc), m_reason(reason) + CodaIdEvent(t, id), m_pc(pc), m_reason(reason) { } -void TcfTrkRunControlContextSuspendedEvent::format(QTextStream &str) const +void CodaRunControlContextSuspendedEvent::format(QTextStream &str) const { str.setIntegerBase(16); str << "RunControl: '" << idString() << "' suspended at 0x" << m_pc << ": '" << m_reason << "'."; str.setIntegerBase(10); + if (!m_message.isEmpty()) + str << " (" <<m_message << ')'; } -QString TcfTrkRunControlContextSuspendedEvent::toString() const +QString CodaRunControlContextSuspendedEvent::toString() const { QString rc; QTextStream str(&rc); @@ -527,36 +560,46 @@ QString TcfTrkRunControlContextSuspendedEvent::toString() const return rc; } -TcfTrkRunControlContextSuspendedEvent::Reason TcfTrkRunControlContextSuspendedEvent::reason() const +CodaRunControlContextSuspendedEvent::Reason CodaRunControlContextSuspendedEvent::reason() const { if (m_reason == sharedLibrarySuspendReasonC) return ModuleLoad; if (m_reason == "Breakpoint") return BreakPoint; // 'Data abort exception'/'Thread has panicked' ... unfortunately somewhat unspecific. - if (m_reason.contains("exception") || m_reason.contains("panick")) + if (m_reason.contains("Exception") || m_reason.contains("panick")) return Crash; return Other; } -TcfTrkRunControlModuleLoadContextSuspendedEvent::TcfTrkRunControlModuleLoadContextSuspendedEvent(const QByteArray &id, +CodaRunControlModuleLoadContextSuspendedEvent::CodaRunControlModuleLoadContextSuspendedEvent(const QByteArray &id, const QByteArray &reason, quint64 pc, const ModuleLoadEventInfo &mi) : - TcfTrkRunControlContextSuspendedEvent(RunControlModuleLoadSuspended, id, reason, pc), + CodaRunControlContextSuspendedEvent(RunControlModuleLoadSuspended, id, reason, pc), m_mi(mi) { } -QString TcfTrkRunControlModuleLoadContextSuspendedEvent::toString() const +QString CodaRunControlModuleLoadContextSuspendedEvent::toString() const { QString rc; QTextStream str(&rc); - TcfTrkRunControlContextSuspendedEvent::format(str); + CodaRunControlContextSuspendedEvent::format(str); str << ' '; m_mi.format(str); return rc; } +// -------------- CodaIdEvent +CodaProcessExitedEvent::CodaProcessExitedEvent(const QByteArray &id) : + CodaEvent(ProcessExitedEvent), m_id(id) +{ +} + +QString CodaProcessExitedEvent::toString() const +{ + return QString("Process \"%1\" exited").arg(idString()); +} -} // namespace tcftrk +} // namespace Coda diff --git a/tools/runonphone/symbianutils/tcftrkmessage.h b/tools/runonphone/symbianutils/codamessage.h index cee8584..68347cb 100644 --- a/tools/runonphone/symbianutils/tcftrkmessage.h +++ b/tools/runonphone/symbianutils/codamessage.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef TRCFTRKMESSAGE_H -#define TRCFTRKMESSAGE_H +#ifndef CODAMESSAGE_H +#define CODAMESSAGE_H #include "symbianutils_global.h" @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE class QTextStream; QT_END_NAMESPACE -namespace tcftrk { +namespace Coda { class JsonValue; class JsonInputStream; @@ -61,10 +61,14 @@ enum Services { RunControlService, ProcessesService, MemoryService, - SettingsService, // non-standard, trk specific + SettingsService, // non-standard, CODA specific BreakpointsService, RegistersService, - SimpleRegistersService, // non-standard, trk specific + LoggingService, // non-standard, CODA specific + FileSystemService, + SymbianInstallService, // non-standard, CODA specific + SymbianOSData, // non-standard, CODA specific + DebugSessionControl, // non-standard, CODA specific UnknownService }; // Note: Check string array 'serviceNamesC' of same size when modifying this. @@ -138,7 +142,7 @@ struct SYMBIANUTILS_EXPORT ModuleLoadEventInfo { bool requireResume; }; -// Breakpoint as supported by TcfTrk source June 2010 +// Breakpoint as supported by Coda source June 2010 // TODO: Add watchpoints,etc once they are implemented struct SYMBIANUTILS_EXPORT Breakpoint { enum Type { Software, Hardware, Auto }; @@ -162,8 +166,8 @@ struct SYMBIANUTILS_EXPORT Breakpoint { SYMBIANUTILS_EXPORT JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b); // Event hierarchy -class SYMBIANUTILS_EXPORT TcfTrkEvent { - Q_DISABLE_COPY(TcfTrkEvent) +class SYMBIANUTILS_EXPORT CodaEvent { + Q_DISABLE_COPY(CodaEvent) public: enum Type { None, LocatorHello, @@ -172,40 +176,57 @@ public: RunControlSuspended, RunControlBreakpointSuspended, RunControlModuleLoadSuspended, - RunControlResumed + RunControlResumed, + LoggingWriteEvent, // Non-standard + ProcessExitedEvent // Non-standard }; - virtual ~TcfTrkEvent(); + virtual ~CodaEvent(); Type type() const; virtual QString toString() const; - static TcfTrkEvent *parseEvent(Services s, const QByteArray &name, const QVector<JsonValue> &val); + static CodaEvent *parseEvent(Services s, const QByteArray &name, const QVector<JsonValue> &val); protected: - explicit TcfTrkEvent(Type type = None); + explicit CodaEvent(Type type = None); private: const Type m_type; }; // ServiceHello -class SYMBIANUTILS_EXPORT TcfTrkLocatorHelloEvent : public TcfTrkEvent { +class SYMBIANUTILS_EXPORT CodaLocatorHelloEvent : public CodaEvent { public: - explicit TcfTrkLocatorHelloEvent(const QStringList &); + explicit CodaLocatorHelloEvent(const QStringList &); - const QStringList &services() { return m_services; } + const QStringList &services() const { return m_services; } virtual QString toString() const; private: QStringList m_services; }; +// Logging event (non-standard, CODA specific) +class SYMBIANUTILS_EXPORT CodaLoggingWriteEvent : public CodaEvent { +public: + explicit CodaLoggingWriteEvent(const QByteArray &console, const QByteArray &message); + + QByteArray message() const { return m_message; } + QByteArray console() const { return m_console; } + + virtual QString toString() const; + +private: + const QByteArray m_console; + const QByteArray m_message; +}; + // Base for events that just have one id as parameter // (simple suspend) -class SYMBIANUTILS_EXPORT TcfTrkIdEvent : public TcfTrkEvent { +class SYMBIANUTILS_EXPORT CodaIdEvent : public CodaEvent { protected: - explicit TcfTrkIdEvent(Type t, const QByteArray &id); + explicit CodaIdEvent(Type t, const QByteArray &id); public: QByteArray id() const { return m_id; } QString idString() const { return QString::fromUtf8(m_id); } @@ -216,9 +237,9 @@ private: // Base for events that just have some ids as parameter // (context removed) -class SYMBIANUTILS_EXPORT TcfTrkIdsEvent : public TcfTrkEvent { +class SYMBIANUTILS_EXPORT CodaIdsEvent : public CodaEvent { protected: - explicit TcfTrkIdsEvent(Type t, const QVector<QByteArray> &ids); + explicit CodaIdsEvent(Type t, const QVector<QByteArray> &ids); public: QVector<QByteArray> ids() const { return m_ids; } @@ -229,44 +250,46 @@ private: }; // RunControlContextAdded -class SYMBIANUTILS_EXPORT TcfTrkRunControlContextAddedEvent : public TcfTrkEvent { +class SYMBIANUTILS_EXPORT CodaRunControlContextAddedEvent : public CodaEvent { public: typedef QVector<RunControlContext> RunControlContexts; - explicit TcfTrkRunControlContextAddedEvent(const RunControlContexts &c); + explicit CodaRunControlContextAddedEvent(const RunControlContexts &c); const RunControlContexts &contexts() const { return m_contexts; } virtual QString toString() const; - static TcfTrkRunControlContextAddedEvent *parseEvent(const QVector<JsonValue> &val); + static CodaRunControlContextAddedEvent *parseEvent(const QVector<JsonValue> &val); private: const RunControlContexts m_contexts; }; // RunControlContextRemoved -class SYMBIANUTILS_EXPORT TcfTrkRunControlContextRemovedEvent : public TcfTrkIdsEvent { +class SYMBIANUTILS_EXPORT CodaRunControlContextRemovedEvent : public CodaIdsEvent { public: - explicit TcfTrkRunControlContextRemovedEvent(const QVector<QByteArray> &id); + explicit CodaRunControlContextRemovedEvent(const QVector<QByteArray> &id); virtual QString toString() const; }; // Simple RunControlContextSuspended (process/thread) -class SYMBIANUTILS_EXPORT TcfTrkRunControlContextSuspendedEvent : public TcfTrkIdEvent { +class SYMBIANUTILS_EXPORT CodaRunControlContextSuspendedEvent : public CodaIdEvent { public: enum Reason { BreakPoint, ModuleLoad, Crash, Other } ; - explicit TcfTrkRunControlContextSuspendedEvent(const QByteArray &id, + explicit CodaRunControlContextSuspendedEvent(const QByteArray &id, const QByteArray &reason, + const QByteArray &message, quint64 pc = 0); virtual QString toString() const; quint64 pc() const { return m_pc; } QByteArray reasonID() const { return m_reason; } Reason reason() const; + QByteArray message() const { return m_message; } protected: - explicit TcfTrkRunControlContextSuspendedEvent(Type t, + explicit CodaRunControlContextSuspendedEvent(Type t, const QByteArray &id, const QByteArray &reason, quint64 pc = 0); @@ -275,12 +298,13 @@ protected: private: const quint64 m_pc; const QByteArray m_reason; + const QByteArray m_message; }; // RunControlContextSuspended due to module load -class SYMBIANUTILS_EXPORT TcfTrkRunControlModuleLoadContextSuspendedEvent : public TcfTrkRunControlContextSuspendedEvent { +class SYMBIANUTILS_EXPORT CodaRunControlModuleLoadContextSuspendedEvent : public CodaRunControlContextSuspendedEvent { public: - explicit TcfTrkRunControlModuleLoadContextSuspendedEvent(const QByteArray &id, + explicit CodaRunControlModuleLoadContextSuspendedEvent(const QByteArray &id, const QByteArray &reason, quint64 pc, const ModuleLoadEventInfo &mi); @@ -292,5 +316,18 @@ private: const ModuleLoadEventInfo m_mi; }; -} // namespace tcftrk -#endif // TRCFTRKMESSAGE_H +// Process exited event +class SYMBIANUTILS_EXPORT CodaProcessExitedEvent : public CodaEvent { +public: + explicit CodaProcessExitedEvent(const QByteArray &id); + + QByteArray id() const { return m_id; } + QString idString() const { return QString::fromUtf8(m_id); } + virtual QString toString() const; + +private: + const QByteArray m_id; +}; + +} // namespace Coda +#endif // CODAMESSAGE_H diff --git a/tools/runonphone/symbianutils/json.cpp b/tools/runonphone/symbianutils/json.cpp index a2d53ce..93f9395 100644 --- a/tools/runonphone/symbianutils/json.cpp +++ b/tools/runonphone/symbianutils/json.cpp @@ -49,6 +49,7 @@ #include <QtCore/QTextStream> #include <QtCore/QDebug> #include <QtCore/QStringList> +#include <QtCore/QVariant> #include <ctype.h> @@ -59,7 +60,7 @@ #define JDEBUG(s) #endif -namespace tcftrk { +namespace Coda { static void skipSpaces(const char *&from, const char *to) { @@ -100,6 +101,7 @@ QByteArray JsonValue::parseNumber(const char *&from, const char *to) QByteArray JsonValue::parseCString(const char *&from, const char *to) { QByteArray result; + const char * const fromSaved = from; JDEBUG("parseCString: " << QByteArray(from, to - from)); if (*from != '"') { qDebug() << "JSON Parse Error, double quote expected"; @@ -117,7 +119,8 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to) if (*ptr == '\\') { ++ptr; if (ptr == to) { - qDebug() << "JSON Parse Error, unterminated backslash escape"; + qWarning("JSON Parse Error, unterminated backslash escape in '%s'", + QByteArray(fromSaved, to - fromSaved).constData()); from = ptr; // So we don't hang return QByteArray(); } @@ -142,8 +145,24 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to) case 'v': *dst++ = '\v'; break; case '"': *dst++ = '"'; break; case '\\': *dst++ = '\\'; break; - default: - { + case 'u': { // 4 digit hex escape as in '\u000a' + if (end - src < 4) { + qWarning("JSON Parse Error, too few hex digits in \\u-escape in '%s' obtained from '%s'", + result.constData(), QByteArray(fromSaved, to - fromSaved).constData()); + return QByteArray(); + } + bool ok; + const uchar prod = QByteArray(src, 4).toUInt(&ok, 16); + if (!ok) { + qWarning("JSON Parse Error, invalid hex digits in \\u-escape in '%s' obtained from '%s'", + result.constData(), QByteArray(fromSaved, to - fromSaved).constData()); + return QByteArray(); + } + *dst++ = prod; + src += 4; + } + break; + default: { // Up to 3 decimal digits: Not sure if this is supported in JSON? int chars = 0; uchar prod = 0; forever { @@ -157,7 +176,8 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to) c = *src++; } if (!chars) { - qDebug() << "JSON Parse Error, unrecognized backslash escape"; + qWarning("JSON Parse Error, unrecognized backslash escape in string '%s' obtained from '%s'", + result.constData(), QByteArray(fromSaved, to - fromSaved).constData()); return QByteArray(); } *dst++ = prod; @@ -360,7 +380,7 @@ QByteArray JsonValue::toString(bool multiline, int indent) const break; case String: if (!m_name.isEmpty()) - result += m_name + "="; + result += m_name + '='; result += '"' + escapeCString(m_data) + '"'; break; case Number: @@ -380,30 +400,69 @@ QByteArray JsonValue::toString(bool multiline, int indent) const if (multiline) { result += "{\n"; dumpChildren(&result, multiline, indent + 1); - result += '\n' + ind(indent) + "}"; + result += '\n' + ind(indent) + '}'; } else { - result += "{"; + result += '{'; dumpChildren(&result, multiline, indent + 1); - result += "}"; + result += '}'; } break; case Array: if (!m_name.isEmpty()) - result += m_name + "="; + result += m_name + '='; if (multiline) { result += "[\n"; dumpChildren(&result, multiline, indent + 1); - result += '\n' + ind(indent) + "]"; + result += '\n' + ind(indent) + ']'; } else { - result += "["; + result += '['; dumpChildren(&result, multiline, indent + 1); - result += "]"; + result += ']'; } break; } return result; } + +QVariant JsonValue::toVariant() const +{ + switch (m_type) { + case String: + return QString(m_data); + case Number: { + bool ok; + qint64 val = QString(m_data).toLongLong(&ok); + if (ok) + return val; + return QVariant(); + } + case Object: { + QHash<QString, QVariant> hash; + for (int i = 0; i < m_children.size(); ++i) { + QString name(m_children[i].name()); + QVariant val = m_children[i].toVariant(); + hash.insert(name, val); + } + return hash; + } + case Array: { + QList<QVariant> list; + for (int i = 0; i < m_children.size(); ++i) { + list.append(m_children[i].toVariant()); + } + return list; + } + case Boolean: + return data() == QByteArray("true"); + case Invalid: + case NullObject: + default: + return QVariant(); + } +} + + void JsonValue::fromString(const QByteArray &ba) { const char *from = ba.constBegin(); @@ -486,5 +545,5 @@ JsonInputStream &JsonInputStream::operator<<(bool b) return *this; } -} // namespace tcftrk +} // namespace Coda diff --git a/tools/runonphone/symbianutils/json.h b/tools/runonphone/symbianutils/json.h index ca9aebf..11273e0 100644 --- a/tools/runonphone/symbianutils/json.h +++ b/tools/runonphone/symbianutils/json.h @@ -48,7 +48,7 @@ #include <QtCore/QStringList> #include <QtCore/QVector> -namespace tcftrk { +namespace Coda { class SYMBIANUTILS_EXPORT JsonValue { @@ -67,7 +67,7 @@ public: Boolean, Object, NullObject, - Array, + Array }; Type m_type; @@ -95,6 +95,8 @@ public: void fromString(const QByteArray &str); void setStreamOutput(const QByteArray &name, const QByteArray &content); + QVariant toVariant() const; + private: static QByteArray parseCString(const char *&from, const char *to); static QByteArray parseNumber(const char *&from, const char *to); @@ -144,6 +146,6 @@ private: QByteArray &m_target; }; -} // namespace tcftrk +} // namespace Coda #endif // SYMBIANUTILS_JSON_H diff --git a/tools/runonphone/symbianutils/launcher.cpp b/tools/runonphone/symbianutils/launcher.cpp index e52cf28..ff67881 100644 --- a/tools/runonphone/symbianutils/launcher.cpp +++ b/tools/runonphone/symbianutils/launcher.cpp @@ -52,6 +52,7 @@ #include <QtCore/QDebug> #include <QtCore/QQueue> #include <QtCore/QFile> +#include <QtCore/QFileInfo> #include <QtCore/QScopedPointer> #include <cstdio> @@ -86,15 +87,24 @@ void CrashReportState::clear() } struct LauncherPrivate { - struct CopyState { - QString sourceFileName; - QString destinationFileName; + struct TransferState { + int currentFileName; uint copyFileHandle; QScopedPointer<QByteArray> data; qint64 position; QScopedPointer<QFile> localFile; }; + struct CopyState : public TransferState { + QStringList sourceFileNames; + QStringList destinationFileNames; + }; + + struct DownloadState : public TransferState { + QString sourceFileName; + QString destinationFileName; + }; + explicit LauncherPrivate(const TrkDevicePtr &d); TrkDevicePtr m_device; @@ -106,21 +116,28 @@ struct LauncherPrivate { Session m_session; // global-ish data (process id, target information) CopyState m_copyState; - CopyState m_downloadState; + DownloadState m_downloadState; QString m_fileName; - QStringList m_commandLineArgs; - QString m_installFileName; + QString m_commandLineArgs; + QStringList m_installFileNames; + int m_currentInstallFileName; int m_verbose; Launcher::Actions m_startupActions; bool m_closeDevice; CrashReportState m_crashReportState; + Launcher::InstallationMode m_installationMode; + Launcher::InstallationMode m_currentInstallationStep; + char m_installationDrive; }; LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) : m_device(d), m_state(Launcher::Disconnected), m_verbose(0), - m_closeDevice(true) + m_closeDevice(true), + m_installationMode(Launcher::InstallationModeSilentAndUser), + m_currentInstallationStep(Launcher::InstallationModeSilent), + m_installationDrive('C') { if (m_device.isNull()) m_device = TrkDevicePtr(new TrkDevice); @@ -159,6 +176,16 @@ void Launcher::setState(State s) } } +void Launcher::setInstallationMode(InstallationMode installation) +{ + d->m_installationMode = installation; +} + +void Launcher::setInstallationDrive(char drive) +{ + d->m_installationDrive = drive; +} + void Launcher::addStartupActions(trk::Launcher::Actions startupActions) { d->m_startupActions = Actions(d->m_startupActions | startupActions); @@ -184,10 +211,11 @@ void Launcher::setFileName(const QString &name) d->m_fileName = name; } -void Launcher::setCopyFileName(const QString &srcName, const QString &dstName) +void Launcher::setCopyFileNames(const QStringList &srcNames, const QStringList &dstNames) { - d->m_copyState.sourceFileName = srcName; - d->m_copyState.destinationFileName = dstName; + d->m_copyState.sourceFileNames = srcNames; + d->m_copyState.destinationFileNames = dstNames; + d->m_copyState.currentFileName = 0; } void Launcher::setDownloadFileName(const QString &srcName, const QString &dstName) @@ -196,12 +224,13 @@ void Launcher::setDownloadFileName(const QString &srcName, const QString &dstNam d->m_downloadState.destinationFileName = dstName; } -void Launcher::setInstallFileName(const QString &name) +void Launcher::setInstallFileNames(const QStringList &names) { - d->m_installFileName = name; + d->m_installFileNames = names; + d->m_currentInstallFileName = 0; } -void Launcher::setCommandLineArgs(const QStringList &args) +void Launcher::setCommandLineArgs(const QString &args) { d->m_commandLineArgs = args; } @@ -227,6 +256,16 @@ void Launcher::setCloseDevice(bool c) d->m_closeDevice = c; } +Launcher::InstallationMode Launcher::installationMode() const +{ + return d->m_installationMode; +} + +char Launcher::installationDrive() const +{ + return d->m_installationDrive; +} + bool Launcher::startServer(QString *errorMessage) { errorMessage->clear(); @@ -241,29 +280,30 @@ bool Launcher::startServer(QString *errorMessage) if (!d->m_fileName.isEmpty()) str << " Executable=" << d->m_fileName; if (!d->m_commandLineArgs.isEmpty()) - str << " Arguments= " << d->m_commandLineArgs.join(QString(QLatin1Char(' '))); - if (!d->m_copyState.sourceFileName.isEmpty()) - str << " Package/Source=" << d->m_copyState.sourceFileName; - if (!d->m_copyState.destinationFileName.isEmpty()) - str << " Remote Package/Destination=" << d->m_copyState.destinationFileName; + str << " Arguments= " << d->m_commandLineArgs; + for (int i = 0; i < d->m_copyState.sourceFileNames.size(); ++i) { + str << " Package/Source=" << d->m_copyState.sourceFileNames.at(i); + str << " Remote Package/Destination=" << d->m_copyState.destinationFileNames.at(i); + } if (!d->m_downloadState.sourceFileName.isEmpty()) str << " Source=" << d->m_downloadState.sourceFileName; if (!d->m_downloadState.destinationFileName.isEmpty()) str << " Destination=" << d->m_downloadState.destinationFileName; - if (!d->m_installFileName.isEmpty()) - str << " Install file=" << d->m_installFileName; + if (!d->m_installFileNames.isEmpty()) + foreach (const QString &installFileName, d->m_installFileNames) + str << " Install file=" << installFileName; logMessage(msg); } if (d->m_startupActions & ActionCopy) { - if (d->m_copyState.sourceFileName.isEmpty()) { + if (d->m_copyState.sourceFileNames.isEmpty()) { qWarning("No local filename given for copying package."); return false; - } else if (d->m_copyState.destinationFileName.isEmpty()) { + } else if (d->m_copyState.destinationFileNames.isEmpty()) { qWarning("No remote filename given for copying package."); return false; } } - if (d->m_startupActions & ActionInstall && d->m_installFileName.isEmpty()) { + if (d->m_startupActions & ActionInstall && d->m_installFileNames.isEmpty()) { qWarning("No package name given for installing."); return false; } @@ -303,7 +343,7 @@ void Launcher::handleConnect(const TrkResult &result) if (d->m_startupActions & ActionCopy) copyFileToRemote(); else if (d->m_startupActions & ActionInstall) - installRemotePackageSilently(); + installRemotePackage(); else if (d->m_startupActions & ActionRun) startInferiorIfNeeded(); else if (d->m_startupActions & ActionDownload) @@ -416,9 +456,9 @@ void Launcher::handleResult(const TrkResult &result) case TrkNotifyAck: break; case TrkNotifyNak: { // NAK - logMessage(prefix + "NAK: " + str); + logMessage(prefix + QLatin1String("NAK: ") + str); //logMessage(prefix << "TOKEN: " << result.token); - logMessage(prefix + "ERROR: " + errorMessage(result.data.at(0))); + logMessage(prefix + QLatin1String("ERROR: ") + errorMessage(result.data.at(0))); break; } case TrkNotifyStopped: { // Notified Stopped @@ -433,12 +473,12 @@ void Launcher::handleResult(const TrkResult &result) break; } case TrkNotifyException: { // Notify Exception (obsolete) - logMessage(prefix + "NOTE: EXCEPTION " + str); + logMessage(prefix + QLatin1String("NOTE: EXCEPTION ") + str); d->m_device->sendTrkAck(result.token); break; } case TrkNotifyInternalError: { // - logMessage(prefix + "NOTE: INTERNAL ERROR: " + str); + logMessage(prefix + QLatin1String("NOTE: INTERNAL ERROR: ") + str); d->m_device->sendTrkAck(result.token); break; } @@ -497,22 +537,22 @@ void Launcher::handleResult(const TrkResult &result) break; } case TrkNotifyProcessorStarted: { // NotifyProcessorStarted - logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str); + logMessage(prefix + QLatin1String("NOTE: PROCESSOR STARTED: ") + str); d->m_device->sendTrkAck(result.token); break; } case TrkNotifyProcessorStandBy: { // NotifyProcessorStandby - logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str); + logMessage(prefix + QLatin1String("NOTE: PROCESSOR STANDBY: ") + str); d->m_device->sendTrkAck(result.token); break; } case TrkNotifyProcessorReset: { // NotifyProcessorReset - logMessage(prefix + "NOTE: PROCESSOR RESET: " + str); + logMessage(prefix + QLatin1String("NOTE: PROCESSOR RESET: ") + str); d->m_device->sendTrkAck(result.token); break; } default: { - logMessage(prefix + "INVALID: " + str); + logMessage(prefix + QLatin1String("INVALID: ") + str); break; } } @@ -560,15 +600,15 @@ static inline QString msgCannotOpenLocalFile(const QString &fileName, const QStr void Launcher::handleFileCreation(const TrkResult &result) { if (result.errorCode() || result.data.size() < 6) { - const QString msg = msgCannotOpenRemoteFile(d->m_copyState.destinationFileName, result.errorString()); + const QString msg = msgCannotOpenRemoteFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString()); logMessage(msg); - emit canNotCreateFile(d->m_copyState.destinationFileName, msg); + emit canNotCreateFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), msg); disconnectTrk(); return; } const char *data = result.data.data(); d->m_copyState.copyFileHandle = extractInt(data + 2); - const QString localFileName = d->m_copyState.sourceFileName; + const QString localFileName = d->m_copyState.sourceFileNames.at(d->m_copyState.currentFileName); QFile file(localFileName); d->m_copyState.position = 0; if (!file.open(QIODevice::ReadOnly)) { @@ -644,7 +684,7 @@ void Launcher::handleCopy(const TrkResult &result) { if (result.errorCode() || result.data.size() < 4) { closeRemoteFile(true); - emit canNotWriteFile(d->m_copyState.destinationFileName, result.errorString()); + emit canNotWriteFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString()); disconnectTrk(); } else { continueCopying(extractShort(result.data.data() + 2)); @@ -680,7 +720,7 @@ void Launcher::closeRemoteFile(bool failed) d->m_device->sendTrkMessage(TrkCloseFile, failed ? TrkCallback() : TrkCallback(this, &Launcher::handleFileCopied), ba); - d->m_copyState.data.reset(); + d->m_copyState.data.reset(0); d->m_copyState.copyFileHandle = 0; d->m_copyState.position = 0; } @@ -688,15 +728,21 @@ void Launcher::closeRemoteFile(bool failed) void Launcher::handleFileCopied(const TrkResult &result) { if (result.errorCode()) - emit canNotCloseFile(d->m_copyState.destinationFileName, result.errorString()); - if (d->m_startupActions & ActionInstall) - installRemotePackageSilently(); - else if (d->m_startupActions & ActionRun) + emit canNotCloseFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString()); + + ++d->m_copyState.currentFileName; + + if (d->m_startupActions & ActionInstall && d->m_copyState.currentFileName < d->m_copyState.sourceFileNames.size()) { + copyFileToRemote(); + } else if (d->m_startupActions & ActionInstall) { + installRemotePackage(); + } else if (d->m_startupActions & ActionRun) { startInferiorIfNeeded(); - else if (d->m_startupActions & ActionDownload) + } else if (d->m_startupActions & ActionDownload) { copyFileFromRemote(); - else + } else { disconnectTrk(); + } } void Launcher::handleCpuType(const TrkResult &result) @@ -840,16 +886,18 @@ void Launcher::disconnectTrk() void Launcher::copyFileToRemote() { - emit copyingStarted(); + QFileInfo fileInfo(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName)); + emit copyingStarted(fileInfo.fileName()); QByteArray ba; ba.append(char(10)); //kDSFileOpenWrite | kDSFileOpenBinary - appendString(&ba, d->m_copyState.destinationFileName.toLocal8Bit(), TargetByteOrder, false); + appendString(&ba, d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName).toLocal8Bit(), TargetByteOrder, false); d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileCreation), ba); } void Launcher::copyFileFromRemote() { - emit copyingStarted(); + QFileInfo fileInfo(d->m_downloadState.sourceFileName); + emit copyingStarted(fileInfo.fileName()); QByteArray ba; ba.append(char(9)); //kDSFileOpenRead | kDSFileOpenBinary appendString(&ba, d->m_downloadState.sourceFileName.toLocal8Bit(), TargetByteOrder, false); @@ -858,23 +906,59 @@ void Launcher::copyFileFromRemote() void Launcher::installRemotePackageSilently() { - emit installingStarted(); + emit installingStarted(d->m_installFileNames.at(d->m_currentInstallFileName)); + d->m_currentInstallationStep = InstallationModeSilent; QByteArray ba; - ba.append('C'); - appendString(&ba, d->m_installFileName.toLocal8Bit(), TargetByteOrder, false); + ba.append(static_cast<char>(QChar::toUpper((ushort)d->m_installationDrive))); + appendString(&ba, d->m_installFileNames.at(d->m_currentInstallFileName).toLocal8Bit(), TargetByteOrder, false); d->m_device->sendTrkMessage(TrkInstallFile, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba); } +void Launcher::installRemotePackageByUser() +{ + emit installingStarted(d->m_installFileNames.at(d->m_currentInstallFileName)); + d->m_currentInstallationStep = InstallationModeUser; + QByteArray ba; + appendString(&ba, d->m_installFileNames.at(d->m_currentInstallFileName).toLocal8Bit(), TargetByteOrder, false); + d->m_device->sendTrkMessage(TrkInstallFile2, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba); +} + +void Launcher::installRemotePackage() +{ + switch (installationMode()) { + case InstallationModeSilent: + case InstallationModeSilentAndUser: + installRemotePackageSilently(); + break; + case InstallationModeUser: + installRemotePackageByUser(); + break; + default: + break; + } +} + void Launcher::handleInstallPackageFinished(const TrkResult &result) { if (result.errorCode()) { - emit canNotInstall(d->m_installFileName, result.errorString()); + if (installationMode() == InstallationModeSilentAndUser + && d->m_currentInstallationStep & InstallationModeSilent) { + installRemotePackageByUser(); + return; + } + emit canNotInstall(d->m_installFileNames.at(d->m_currentInstallFileName), result.errorString()); disconnectTrk(); return; - } else { - emit installingFinished(); } - if (d->m_startupActions & ActionRun) { + + ++d->m_currentInstallFileName; + + if (d->m_currentInstallFileName == d->m_installFileNames.size()) + emit installingFinished(); + + if (d->m_startupActions & ActionInstall && d->m_currentInstallFileName < d->m_installFileNames.size()) { + installRemotePackage(); + } else if (d->m_startupActions & ActionRun) { startInferiorIfNeeded(); } else if (d->m_startupActions & ActionDownload) { copyFileFromRemote(); @@ -884,7 +968,7 @@ void Launcher::handleInstallPackageFinished(const TrkResult &result) } QByteArray Launcher::startProcessMessage(const QString &executable, - const QStringList &arguments) + const QString &arguments) { // It's not started yet QByteArray ba; @@ -894,7 +978,7 @@ QByteArray Launcher::startProcessMessage(const QString &executable, QByteArray commandLineBa = executable.toLocal8Bit(); commandLineBa.append(char(0)); if (!arguments.isEmpty()) - commandLineBa.append(arguments.join(QString(QLatin1Char(' '))).toLocal8Bit()); + commandLineBa.append(arguments.toLocal8Bit()); appendString(&ba, commandLineBa, TargetByteOrder, true); return ba; } @@ -930,6 +1014,7 @@ void Launcher::startInferiorIfNeeded() logMessage("Process already 'started'"); return; } + d->m_device->sendTrkMessage(TrkCreateItem, TrkCallback(this, &Launcher::handleCreateProcess), startProcessMessage(d->m_fileName, d->m_commandLineArgs)); // Create Item } @@ -950,7 +1035,10 @@ Launcher *Launcher::acquireFromDeviceManager(const QString &serverName, SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance(); const QSharedPointer<trk::TrkDevice> device = sdm->acquireDevice(serverName); if (device.isNull()) { - *errorMessage = tr("Unable to acquire a device for port '%1'. It appears to be in use.").arg(serverName); + if (serverName.isEmpty()) + *errorMessage = tr("No device is connected. Please connect a device and try again."); + else + *errorMessage = tr("Unable to acquire a device for port '%1'. It appears to be in use.").arg(serverName); return 0; } // Wire release signal. @@ -964,6 +1052,8 @@ Launcher *Launcher::acquireFromDeviceManager(const QString &serverName, // Preliminary release of device, disconnecting the signal. void Launcher::releaseToDeviceManager(Launcher *launcher) { + Q_ASSERT(launcher); + SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance(); // Disentangle launcher and its device, remove connection from destroyed launcher->setCloseDevice(false); diff --git a/tools/runonphone/symbianutils/launcher.h b/tools/runonphone/symbianutils/launcher.h index 63189f1..2f674af 100644 --- a/tools/runonphone/symbianutils/launcher.h +++ b/tools/runonphone/symbianutils/launcher.h @@ -64,6 +64,13 @@ class SYMBIANUTILS_EXPORT Launcher : public QObject public: typedef void (Launcher::*TrkCallBack)(const TrkResult &); + enum InstallationMode { + InstallationModeSilent = 0x1, + InstallationModeUser = 0x2, + InstallationModeSilentAndUser = InstallationModeSilent|InstallationModeUser + //first attempt is silent and if it fails then the user installation is launched + }; + enum Actions { ActionPingOnly = 0x0, ActionCopy = 0x1, @@ -95,13 +102,19 @@ public: void setTrkServerName(const QString &name); QString trkServerName() const; void setFileName(const QString &name); - void setCopyFileName(const QString &srcName, const QString &dstName); + void setCopyFileNames(const QStringList &srcName, const QStringList &dstName); void setDownloadFileName(const QString &srcName, const QString &dstName); - void setInstallFileName(const QString &name); - void setCommandLineArgs(const QStringList &args); + void setInstallFileNames(const QStringList &names); + void setCommandLineArgs(const QString &args); bool startServer(QString *errorMessage); + void setInstallationMode(InstallationMode installation); + void setInstallationDrive(char drive); void setVerbose(int v); void setSerialFrame(bool b); + + InstallationMode installationMode() const; + char installationDrive() const; + bool serialFrame() const; // Close device or leave it open bool closeDevice() const; @@ -122,7 +135,7 @@ public: // Create Trk message to start a process. static QByteArray startProcessMessage(const QString &executable, - const QStringList &arguments); + const QString &arguments); // Create Trk message to read memory static QByteArray readMemoryMessage(uint pid, uint tid, uint from, uint len); static QByteArray readRegistersMessage(uint pid, uint tid); @@ -135,14 +148,14 @@ public: signals: void deviceDescriptionReceived(const QString &port, const QString &description); - void copyingStarted(); + void copyingStarted(const QString &fileName); void canNotConnect(const QString &errorMessage); void canNotCreateFile(const QString &filename, const QString &errorMessage); void canNotOpenFile(const QString &filename, const QString &errorMessage); void canNotOpenLocalFile(const QString &filename, const QString &errorMessage); void canNotWriteFile(const QString &filename, const QString &errorMessage); void canNotCloseFile(const QString &filename, const QString &errorMessage); - void installingStarted(); + void installingStarted(const QString &packageName); void canNotInstall(const QString &packageFilename, const QString &errorMessage); void installingFinished(); void startingApplication(); @@ -152,7 +165,7 @@ signals: void applicationOutputReceived(const QString &output); void copyProgress(int percent); void stateChanged(int); - void processStopped(uint pc, uint pid, uint tid, const QString& reason); + void processStopped(uint pc, uint pid, uint tid, const QString &reason); void processResumed(uint pid, uint tid); void libraryLoaded(const trk::Library &lib); void libraryUnloaded(const trk::Library &lib); @@ -198,6 +211,8 @@ private: void copyFileToRemote(); void copyFileFromRemote(); void installRemotePackageSilently(); + void installRemotePackageByUser(); + void installRemotePackage(); void startInferiorIfNeeded(); void handleFinished(); diff --git a/tools/runonphone/symbianutils/symbiandevicemanager.cpp b/tools/runonphone/symbianutils/symbiandevicemanager.cpp index 02727d7..23f5348 100644 --- a/tools/runonphone/symbianutils/symbiandevicemanager.cpp +++ b/tools/runonphone/symbianutils/symbiandevicemanager.cpp @@ -41,7 +41,11 @@ #include "symbiandevicemanager.h" #include "trkdevice.h" +#include "codadevice.h" +#include "virtualserialdevice.h" +#include <QtCore/QCoreApplication> +#include <QtCore/QEvent> #include <QtCore/QSettings> #include <QtCore/QStringList> #include <QtCore/QFileInfo> @@ -50,6 +54,9 @@ #include <QtCore/QSharedData> #include <QtCore/QScopedPointer> #include <QtCore/QSignalMapper> +#include <QtCore/QThread> +#include <QtCore/QWaitCondition> +#include <QtCore/QTimer> namespace SymbianUtils { @@ -66,7 +73,7 @@ public: SymbianDeviceData(); ~SymbianDeviceData(); - inline bool isOpen() const { return !device.isNull() && device->isOpen(); } + bool isOpen() const; void forcedClose(); QString portName; @@ -77,15 +84,25 @@ public: DeviceCommunicationType type; QSharedPointer<trk::TrkDevice> device; - bool deviceAcquired; + QSharedPointer<Coda::CodaDevice> codaDevice; + int deviceAcquired; }; SymbianDeviceData::SymbianDeviceData() : type(SerialPortCommunication), - deviceAcquired(false) + deviceAcquired(0) { } +bool SymbianDeviceData::isOpen() const +{ + if (device) + return device->isOpen(); + if (codaDevice) + return codaDevice->device()->isOpen(); + return false; +} + SymbianDeviceData::~SymbianDeviceData() { forcedClose(); @@ -101,7 +118,10 @@ void SymbianDeviceData::forcedClose() if (deviceAcquired) qWarning("Device on '%s' unplugged while an operation is in progress.", qPrintable(portName)); - device->close(); + if (device) + device->close(); + else + codaDevice->device()->close(); } } @@ -167,7 +187,7 @@ SymbianDevice::TrkDevicePtr SymbianDevice::acquireDevice() m_data->device->setPort(m_data->portName); m_data->device->setSerialFrame(m_data->type == SerialPortCommunication); } - m_data->deviceAcquired = true; + m_data->deviceAcquired = 1; return m_data->device; } @@ -184,7 +204,7 @@ void SymbianDevice::releaseDevice(TrkDevicePtr *ptr /* = 0 */) ptr->data()->disconnect(); *ptr = TrkDevicePtr(); } - m_data->deviceAcquired = false; + m_data->deviceAcquired = 0; } else { qWarning("Internal error: Attempt to release device that is not acquired."); } @@ -255,17 +275,34 @@ SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDevice &cd) // ------------- SymbianDeviceManagerPrivate struct SymbianDeviceManagerPrivate { - SymbianDeviceManagerPrivate() : m_initialized(false), m_destroyReleaseMapper(0) {} + SymbianDeviceManagerPrivate() : m_initialized(false), m_devicesLock(QMutex::Recursive) {} bool m_initialized; SymbianDeviceManager::SymbianDeviceList m_devices; - QSignalMapper *m_destroyReleaseMapper; + QMutex m_devicesLock; // Used for protecting access to m_devices and serialising getCodaDevice/delayedClosePort + // The following 2 variables are needed to manage requests for a TCF port not coming from the main thread + int m_constructTcfPortEventType; + QMutex m_codaPortWaitMutex; +}; + +class QConstructTcfPortEvent : public QEvent +{ +public: + QConstructTcfPortEvent(QEvent::Type eventId, const QString &portName, CodaDevicePtr *device, QWaitCondition *waiter) : + QEvent(eventId), m_portName(portName), m_device(device), m_waiter(waiter) + {} + + QString m_portName; + CodaDevicePtr* m_device; + QWaitCondition *m_waiter; }; + SymbianDeviceManager::SymbianDeviceManager(QObject *parent) : QObject(parent), d(new SymbianDeviceManagerPrivate) { + d->m_constructTcfPortEventType = QEvent::registerEventType(); } SymbianDeviceManager::~SymbianDeviceManager() @@ -276,11 +313,13 @@ SymbianDeviceManager::~SymbianDeviceManager() SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::devices() const { ensureInitialized(); + QMutexLocker lock(&d->m_devicesLock); return d->m_devices; } QString SymbianDeviceManager::toString() const { + QMutexLocker lock(&d->m_devicesLock); QString rc; QTextStream str(&rc); str << d->m_devices.size() << " devices:\n"; @@ -305,6 +344,7 @@ int SymbianDeviceManager::findByPortName(const QString &p) const QString SymbianDeviceManager::friendlyNameForPort(const QString &port) const { + QMutexLocker lock(&d->m_devicesLock); const int idx = findByPortName(port); return idx == -1 ? QString() : d->m_devices.at(idx).friendlyName(); } @@ -326,6 +366,106 @@ SymbianDeviceManager::TrkDevicePtr return rc; } +CodaDevicePtr SymbianDeviceManager::getCodaDevice(const QString &port) +{ + ensureInitialized(); + QMutexLocker lock(&d->m_devicesLock); + const int idx = findByPortName(port); + if (idx == -1) { + qWarning("Attempt to acquire device '%s' that does not exist.", qPrintable(port)); + if (debug) + qDebug() << *this; + return CodaDevicePtr(); + } + SymbianDevice& device = d->m_devices[idx]; + if (device.m_data->device && device.m_data->device.data()->isOpen()) { + qWarning("Attempting to open a port '%s' that is configured for TRK!", qPrintable(port)); + return CodaDevicePtr(); + } + CodaDevicePtr& devicePtr = device.m_data->codaDevice; + if (devicePtr.isNull() || !devicePtr->device()->isOpen()) { + // Check we instanciate in the correct thread - we can't afford to create the CodaDevice (and more specifically, open the VirtualSerialDevice) in a thread that isn't guaranteed to be long-lived. + // Therefore, if we're not in SymbianDeviceManager's thread, rejig things so it's opened in the main thread + if (QThread::currentThread() != thread()) { + // SymbianDeviceManager is owned by the main thread + d->m_codaPortWaitMutex.lock(); + QWaitCondition waiter; + QCoreApplication::postEvent(this, new QConstructTcfPortEvent((QEvent::Type)d->m_constructTcfPortEventType, port, &devicePtr, &waiter)); + waiter.wait(&d->m_codaPortWaitMutex); + // When the wait returns (due to the wakeAll in SymbianDeviceManager::customEvent), the CodaDevice will be fully set up + d->m_codaPortWaitMutex.unlock(); + } else { + // We're in the main thread, just set it up directly + constructCodaPort(devicePtr, port); + } + // We still carry on in the case we failed to open so the client can access the IODevice's errorString() + } + if (devicePtr->device()->isOpen()) + device.m_data->deviceAcquired++; + return devicePtr; +} + +void SymbianDeviceManager::constructCodaPort(CodaDevicePtr& device, const QString& portName) +{ + QMutexLocker locker(&d->m_codaPortWaitMutex); + if (device.isNull()) { + device = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice); + const QSharedPointer<SymbianUtils::VirtualSerialDevice> serialDevice(new SymbianUtils::VirtualSerialDevice(portName)); + device->setSerialFrame(true); + device->setDevice(serialDevice); + } + if (!device->device()->isOpen()) { + bool ok = device->device().staticCast<SymbianUtils::VirtualSerialDevice>()->open(QIODevice::ReadWrite); + if (!ok && debug) { + qDebug("SymbianDeviceManager: Failed to open port %s", qPrintable(portName)); + } + } +} + +void SymbianDeviceManager::customEvent(QEvent *event) +{ + if (event->type() == d->m_constructTcfPortEventType) { + QConstructTcfPortEvent* constructEvent = static_cast<QConstructTcfPortEvent*>(event); + constructCodaPort(*constructEvent->m_device, constructEvent->m_portName); + constructEvent->m_waiter->wakeAll(); // Should only ever be one thing waiting on this + } +} + +void SymbianDeviceManager::releaseCodaDevice(CodaDevicePtr &port) +{ + if (port) { + QMutexLocker(&d->m_devicesLock); + // Check if this was the last reference to the port, if so close it after a short delay + foreach (const SymbianDevice& device, d->m_devices) { + if (device.m_data->codaDevice.data() == port.data()) { + if (device.m_data->deviceAcquired > 0) + device.m_data->deviceAcquired--; + if (device.m_data->deviceAcquired == 0) { + if (debug) + qDebug("Starting timer to close port %s", qPrintable(device.m_data->portName)); + QTimer::singleShot(1000, this, SLOT(delayedClosePort())); + } + break; + } + } + port.clear(); + } +} + +void SymbianDeviceManager::delayedClosePort() +{ + // Find any coda ports that are still open but have a reference count of zero, and delete them + QMutexLocker(&d->m_devicesLock); + foreach (const SymbianDevice& device, d->m_devices) { + Coda::CodaDevice* codaDevice = device.m_data->codaDevice.data(); + if (codaDevice && device.m_data->deviceAcquired == 0 && codaDevice->device()->isOpen()) { + if (debug) + qDebug("Closing device %s", qPrintable(device.m_data->portName)); + device.m_data->codaDevice->device()->close(); + } + } +} + void SymbianDeviceManager::update() { update(true); @@ -336,11 +476,10 @@ void SymbianDeviceManager::releaseDevice(const QString &port) const int idx = findByPortName(port); if (debug) qDebug() << "SymbianDeviceManager::releaseDevice" << port << idx << sender(); - if (idx != -1) { + if (idx != -1) d->m_devices[idx].releaseDevice(); - } else { + else qWarning("Attempt to release non-existing device %s.", qPrintable(port)); - } } void SymbianDeviceManager::setAdditionalInformation(const QString &port, const QString &ai) @@ -358,6 +497,8 @@ void SymbianDeviceManager::ensureInitialized() const void SymbianDeviceManager::update(bool emitSignals) { + QMutexLocker lock(&d->m_devicesLock); + static int n = 0; typedef SymbianDeviceList::iterator SymbianDeviceListIterator; @@ -377,6 +518,7 @@ void SymbianDeviceManager::update(bool emitSignals) } // Merge the lists and emit the respective added/removed signals, assuming // no one can plug a different device on the same port at the speed of lightning + SymbianDeviceList removedDevices; if (!d->m_devices.isEmpty()) { // Find deleted devices for (SymbianDeviceListIterator oldIt = d->m_devices.begin(); oldIt != d->m_devices.end(); ) { @@ -386,25 +528,33 @@ void SymbianDeviceManager::update(bool emitSignals) SymbianDevice toBeDeleted = *oldIt; toBeDeleted.forcedClose(); oldIt = d->m_devices.erase(oldIt); - if (emitSignals) - emit deviceRemoved(toBeDeleted); + removedDevices.append(toBeDeleted); } } } + SymbianDeviceList addedDevices; if (!newDevices.isEmpty()) { // Find new devices and insert in order foreach(const SymbianDevice &newDevice, newDevices) { if (!d->m_devices.contains(newDevice)) { d->m_devices.append(newDevice); - if (emitSignals) - emit deviceAdded(newDevice); + addedDevices.append(newDevice); } } if (d->m_devices.size() > 1) qStableSort(d->m_devices.begin(), d->m_devices.end()); } - if (emitSignals) + + lock.unlock(); + if (emitSignals) { + foreach (const SymbianDevice &device, removedDevices) { + emit deviceRemoved(device); + } + foreach (const SymbianDevice &device, addedDevices) { + emit deviceAdded(device); + } emit updated(); + } if (debug) qDebug("<SerialDeviceLister::update\n%s\n", qPrintable(toString())); @@ -457,7 +607,9 @@ SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::blueToothDevices() } // New kernel versions support /dev/ttyUSB0, /dev/ttyUSB1. Trk responds // on the latter (usually), try first. - static const char *usbTtyDevices[] = { "/dev/ttyUSB1", "/dev/ttyUSB0" }; + static const char *usbTtyDevices[] = { + "/dev/ttyUSB3", "/dev/ttyUSB2", "/dev/ttyUSB1", "/dev/ttyUSB0", + "/dev/ttyACM3", "/dev/ttyACM2", "/dev/ttyACM1", "/dev/ttyACM0"}; const int usbTtyCount = sizeof(usbTtyDevices)/sizeof(const char *); for (int d = 0; d < usbTtyCount; d++) { const QString ttyUSBDevice = QLatin1String(usbTtyDevices[d]); @@ -486,4 +638,106 @@ SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &sdm) return d; } -} // namespace SymbianUtilsInternal +OstChannel *SymbianDeviceManager::getOstChannel(const QString &port, uchar channelId) +{ + CodaDevicePtr coda = getCodaDevice(port); + if (coda.isNull() || !coda->device()->isOpen()) + return 0; + return new OstChannel(coda, channelId); +} + +struct OstChannelPrivate +{ + CodaDevicePtr m_codaPtr; + QByteArray m_dataBuffer; + uchar m_channelId; + bool m_hasReceivedData; +}; + +OstChannel::OstChannel(const CodaDevicePtr &codaPtr, uchar channelId) + : d(new OstChannelPrivate) +{ + d->m_codaPtr = codaPtr; + d->m_channelId = channelId; + d->m_hasReceivedData = false; + connect(codaPtr.data(), SIGNAL(unknownEvent(uchar, QByteArray)), this, SLOT(ostDataReceived(uchar,QByteArray))); + connect(codaPtr->device().data(), SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose())); + QIODevice::open(ReadWrite|Unbuffered); +} + +void OstChannel::close() +{ + QIODevice::close(); + if (d && d->m_codaPtr.data()) { + disconnect(d->m_codaPtr.data(), 0, this, 0); + SymbianDeviceManager::instance()->releaseCodaDevice(d->m_codaPtr); + } +} + +OstChannel::~OstChannel() +{ + close(); + delete d; +} + +void OstChannel::flush() +{ + //TODO d->m_codaPtr->device()- +} + +qint64 OstChannel::bytesAvailable() const +{ + return d->m_dataBuffer.size(); +} + +bool OstChannel::isSequential() const +{ + return true; +} + +qint64 OstChannel::readData(char *data, qint64 maxSize) +{ + qint64 amount = qMin(maxSize, (qint64)d->m_dataBuffer.size()); + qMemCopy(data, d->m_dataBuffer.constData(), amount); + d->m_dataBuffer.remove(0, amount); + return amount; +} + +qint64 OstChannel::writeData(const char *data, qint64 maxSize) +{ + static const qint64 KMaxOstPayload = 1024; + // If necessary, split the packet up + while (maxSize) { + QByteArray dataBuf = QByteArray::fromRawData(data, qMin(KMaxOstPayload, maxSize)); + d->m_codaPtr->writeCustomData(d->m_channelId, dataBuf); + data += dataBuf.length(); + maxSize -= dataBuf.length(); + } + return maxSize; +} + +void OstChannel::ostDataReceived(uchar channelId, const QByteArray &aData) +{ + if (channelId == d->m_channelId) { + d->m_hasReceivedData = true; + d->m_dataBuffer.append(aData); + emit readyRead(); + } +} + +Coda::CodaDevice& OstChannel::codaDevice() const +{ + return *d->m_codaPtr; +} + +bool OstChannel::hasReceivedData() const +{ + return isOpen() && d->m_hasReceivedData; +} + +void OstChannel::deviceAboutToClose() +{ + close(); +} + +} // namespace SymbianUtils diff --git a/tools/runonphone/symbianutils/symbiandevicemanager.h b/tools/runonphone/symbianutils/symbiandevicemanager.h index d65b5b0..366963c 100644 --- a/tools/runonphone/symbianutils/symbiandevicemanager.h +++ b/tools/runonphone/symbianutils/symbiandevicemanager.h @@ -44,7 +44,7 @@ #include "symbianutils_global.h" -#include <QtCore/QObject> +#include <QtCore/QIODevice> #include <QtCore/QExplicitlySharedDataPointer> #include <QtCore/QSharedPointer> @@ -56,17 +56,23 @@ QT_END_NAMESPACE namespace trk { class TrkDevice; } +namespace Coda { + class CodaDevice; +} namespace SymbianUtils { struct SymbianDeviceManagerPrivate; class SymbianDeviceData; +class OstChannel; enum DeviceCommunicationType { SerialPortCommunication = 0, BlueToothCommunication = 1 }; +typedef QSharedPointer<Coda::CodaDevice> CodaDevicePtr; + // SymbianDevice: Explicitly shared device data and a TrkDevice // instance that can be acquired (exclusively) for use. // A device removal from the manager will result in the @@ -90,13 +96,6 @@ public: QString additionalInformation() const; void setAdditionalInformation(const QString &); - // Acquire: Mark the device as 'out' and return a shared pointer - // unless it is already in use by another owner. The result should not - // be passed on further. - TrkDevicePtr acquireDevice(); - // Give back a device and mark it as 'free'. - void releaseDevice(TrkDevicePtr *ptr = 0); - bool isOpen() const; // Windows only. @@ -107,6 +106,14 @@ public: QString toString() const; private: + // Acquire: Mark the device as 'out' and return a shared pointer + // unless it is already in use by another owner. The result should not + // be passed on further. + // TRK only + TrkDevicePtr acquireDevice(); + // Give back a device and mark it as 'free'. TRK only. + void releaseDevice(TrkDevicePtr *ptr = 0); + void forcedClose(); QExplicitlySharedDataPointer<SymbianDeviceData> m_data; @@ -145,9 +152,25 @@ public: SymbianDeviceList devices() const; QString toString() const; - // Acquire a device for use. See releaseDevice(). + // Acquire a TRK device for use. Assuming the port is found, equivalent to devices()[findByPortName(port)].acquireDevice(). See also releaseDevice(). TrkDevicePtr acquireDevice(const QString &port); + //// The TCF code prefers to set up the CodaDevice object itself, so we let it and just handle opening the underlying QIODevice and keeping track of the CodaDevice + //// Returns true if port was opened successfully. + + // Gets the CodaDevice, which may or may not be open depending on what other clients have already acquired it. + // Therefore once clients have set up any signals and slots they required, they should check CodaDevice::device()->isOpen() + // and if false, the open failed and they should check device()->errorString() if required. + // Caller should call releaseCodaDevice if they want the port to auto-close itself + CodaDevicePtr getCodaDevice(const QString &port); + + // Note this function makes no guarantee that someone else isn't already listening on this channel id, or that there is anything on the other end + // Returns NULL if the port couldn't be opened + OstChannel *getOstChannel(const QString &port, uchar channelId); + + // Caller is responsible for disconnecting any signals from aPort - do not assume the CodaDevice will be deleted as a result of this call. On return aPort will be clear()ed. + void releaseCodaDevice(CodaDevicePtr &aPort); + int findByPortName(const QString &p) const; QString friendlyNameForPort(const QString &port) const; @@ -162,17 +185,54 @@ signals: void deviceAdded(const SymbianUtils::SymbianDevice &d); void updated(); +private slots: + void delayedClosePort(); + private: void ensureInitialized() const; void update(bool emitSignals); SymbianDeviceList serialPorts() const; SymbianDeviceList blueToothDevices() const; + void customEvent(QEvent *event); + void constructCodaPort(CodaDevicePtr& device, const QString& portName); SymbianDeviceManagerPrivate *d; }; SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &); +struct OstChannelPrivate; + +class SYMBIANUTILS_EXPORT OstChannel : public QIODevice +{ + Q_OBJECT + +public: + void close(); + ~OstChannel(); + void flush(); + + qint64 bytesAvailable() const; + bool isSequential() const; + bool hasReceivedData() const; + + Coda::CodaDevice &codaDevice() const; + +private slots: + void ostDataReceived(uchar channelId, const QByteArray &aData); + void deviceAboutToClose(); + +private: + OstChannel(const CodaDevicePtr &codaPtr, uchar channelId); + Q_DISABLE_COPY(OstChannel) + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private: + OstChannelPrivate *d; + friend class SymbianDeviceManager; +}; + } // namespace SymbianUtils #endif // SYMBIANDEVICEMANAGER_H diff --git a/tools/runonphone/symbianutils/symbianutils.pri b/tools/runonphone/symbianutils/symbianutils.pri index f07e494..2d32680 100644 --- a/tools/runonphone/symbianutils/symbianutils.pri +++ b/tools/runonphone/symbianutils/symbianutils.pri @@ -12,9 +12,10 @@ HEADERS += $$PWD/symbianutils_global.h \ $$PWD/bluetoothlistener.h \ $$PWD/communicationstarter.h \ $$PWD/symbiandevicemanager.h \ - $$PWD/tcftrkdevice.h \ - $$PWD/tcftrkmessage.h \ - $$PWD/json.h + $$PWD/codadevice.h \ + $$PWD/codamessage.h \ + $$PWD/json.h \ + $$PWD/virtualserialdevice.h SOURCES += $$PWD/trkutils.cpp \ $$PWD/trkdevice.cpp \ @@ -22,9 +23,14 @@ SOURCES += $$PWD/trkutils.cpp \ $$PWD/bluetoothlistener.cpp \ $$PWD/communicationstarter.cpp \ $$PWD/symbiandevicemanager.cpp \ - $$PWD/tcftrkdevice.cpp \ - $$PWD/tcftrkmessage.cpp \ - $$PWD/json.cpp + $$PWD/codadevice.cpp \ + $$PWD/codamessage.cpp \ + $$PWD/json.cpp \ + $$PWD/virtualserialdevice.cpp + +DEFINES += HAS_SERIALPORT +win32:SOURCES += $$PWD/virtualserialdevice_win.cpp +unix:SOURCES += $$PWD/virtualserialdevice_posix.cpp # Tests/trklauncher is a console application contains(QT, gui) { diff --git a/tools/runonphone/symbianutils/tcftrkdevice.cpp b/tools/runonphone/symbianutils/tcftrkdevice.cpp deleted file mode 100644 index 219f673..0000000 --- a/tools/runonphone/symbianutils/tcftrkdevice.cpp +++ /dev/null @@ -1,929 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "tcftrkdevice.h" -#include "json.h" - -#include <QtNetwork/QAbstractSocket> -#include <QtCore/QDebug> -#include <QtCore/QVector> -#include <QtCore/QQueue> -#include <QtCore/QTextStream> -#include <QtCore/QDateTime> -#include <QtCore/QFileInfo> - -enum { debug = 0 }; - -static const char messageTerminatorC[] = "\003\001"; - -namespace tcftrk { -// ------------- TcfTrkCommandError - -TcfTrkCommandError::TcfTrkCommandError() : timeMS(0), code(0), alternativeCode(0) -{ -} - -void TcfTrkCommandError::clear() -{ - timeMS = 0; - code = alternativeCode = 0; - format.clear(); - alternativeOrganization.clear(); -} - -void TcfTrkCommandError::write(QTextStream &str) const -{ - if (timeMS) { - const QDateTime time(QDate(1970, 1, 1)); - str << time.addMSecs(timeMS).toString(Qt::ISODate) << ": Error code: " << code - << " '" << format << '\''; - if (!alternativeOrganization.isEmpty()) - str << " ('" << alternativeOrganization << "', code: " << alternativeCode << ')'; - } else{ - str << "<No error>"; - } -} - -QString TcfTrkCommandError::toString() const -{ - QString rc; - QTextStream str(&rc); - write(str); - return rc; -} - -/* {"Time":1277459762255,"Code":1,"AltCode":-6,"AltOrg":"POSIX","Format":"Unknown error: -6"} */ -bool TcfTrkCommandError::parse(const QVector<JsonValue> &values) -{ - // Parse an arbitrary hash (that could as well be a command response) - // and check for error elements. - unsigned errorKeyCount = 0; - clear(); - do { - if (values.isEmpty() || values.front().type() != JsonValue::Object) - break; - foreach (const JsonValue &c, values.front().children()) { - if (c.name() == "Time") { - timeMS = c.data().toULongLong(); - errorKeyCount++; - } else if (c.name() == "Code") { - code = c.data().toInt(); - errorKeyCount++; - } else if (c.name() == "Format") { - format = c.data(); - errorKeyCount++; - } else if (c.name() == "AltCode") { - alternativeCode = c.data().toInt(); - errorKeyCount++; - } else if (c.name() == "AltOrg") { - alternativeOrganization = c.data(); - errorKeyCount++; - } - } - } while (false); - const bool errorFound = errorKeyCount >= 2u; // Should be at least 'Time', 'Code'. - if (!errorFound) - clear(); - if (debug) { - qDebug() << "TcfTrkCommandError::parse: Found error: " << errorFound; - if (!values.isEmpty()) - qDebug() << values.front().toString(); - } - return errorFound; -} - -// ------------ TcfTrkCommandResult - -TcfTrkCommandResult::TcfTrkCommandResult(Type t) : - type(t), service(LocatorService) -{ -} - -TcfTrkCommandResult::TcfTrkCommandResult(char typeChar, Services s, - const QByteArray &r, - const QVector<JsonValue> &v, - const QVariant &ck) : - type(FailReply), service(s), request(r), values(v), cookie(ck) -{ - switch (typeChar) { - case 'N': - type = FailReply; - break; - case 'P': - type = ProgressReply; - break; - case 'R': - type = commandError.parse(values) ? CommandErrorReply : SuccessReply; - break; - default: - qWarning("Unknown TCF reply type '%c'", typeChar); - } -} - -QString TcfTrkCommandResult::errorString() const -{ - QString rc; - QTextStream str(&rc); - - switch (type) { - case SuccessReply: - case ProgressReply: - str << "<No error>"; - return rc; - case FailReply: - str << "NAK"; - case CommandErrorReply: - commandError.write(str); - break; - } - // Append the failed command for reference - str << " (Command was: '"; - QByteArray printableRequest = request; - printableRequest.replace('\0', '|'); - str << printableRequest << "')"; - return rc; -} - -QString TcfTrkCommandResult::toString() const -{ - QString rc; - QTextStream str(&rc); - str << "Command answer "; - switch (type) { - case SuccessReply: - str << "[success]"; - break; - case CommandErrorReply: - str << "[command error]"; - break; - case FailReply: - str << "[fail (NAK)]"; - break; - case ProgressReply: - str << "[progress]"; - break; - } - str << ", " << values.size() << " values(s) to request: '"; - QByteArray printableRequest = request; - printableRequest.replace('\0', '|'); - str << printableRequest << "' "; - if (cookie.isValid()) - str << " cookie: " << cookie.toString(); - str << '\n'; - for (int i = 0, count = values.size(); i < count; i++) - str << '#' << i << ' ' << values.at(i).toString() << '\n'; - if (type == CommandErrorReply) - str << "Error: " << errorString(); - return rc; -} - -struct TcfTrkSendQueueEntry -{ - typedef TcfTrkDevice::MessageType MessageType; - - explicit TcfTrkSendQueueEntry(MessageType mt, - int tok, - Services s, - const QByteArray &d, - const TcfTrkCallback &cb= TcfTrkCallback(), - const QVariant &ck = QVariant()) : - messageType(mt), service(s), data(d), token(tok), cookie(ck), callback(cb) {} - - MessageType messageType; - Services service; - QByteArray data; - int token; - QVariant cookie; - TcfTrkCallback callback; -}; - -struct TcfTrkDevicePrivate { - typedef TcfTrkDevice::IODevicePtr IODevicePtr; - typedef QHash<int, TcfTrkSendQueueEntry> TokenWrittenMessageMap; - - TcfTrkDevicePrivate(); - - const QByteArray m_messageTerminator; - - IODevicePtr m_device; - unsigned m_verbose; - QByteArray m_readBuffer; - int m_token; - QQueue<TcfTrkSendQueueEntry> m_sendQueue; - TokenWrittenMessageMap m_writtenMessages; - QVector<QByteArray> m_registerNames; -}; - -TcfTrkDevicePrivate::TcfTrkDevicePrivate() : - m_messageTerminator(messageTerminatorC), - m_verbose(0), m_token(0) -{ -} - -TcfTrkDevice::TcfTrkDevice(QObject *parent) : - QObject(parent), d(new TcfTrkDevicePrivate) -{ -} - -TcfTrkDevice::~TcfTrkDevice() -{ - delete d; -} - -QVector<QByteArray> TcfTrkDevice::registerNames() const -{ - return d->m_registerNames; -} - -void TcfTrkDevice::setRegisterNames(const QVector<QByteArray>& n) -{ - d->m_registerNames = n; - if (d->m_verbose) { - QString msg; - QTextStream str(&msg); - const int count = n.size(); - str << "Registers (" << count << "): "; - for (int i = 0; i < count; i++) - str << '#' << i << '=' << n.at(i) << ' '; - emitLogMessage(msg); - } -} - -TcfTrkDevice::IODevicePtr TcfTrkDevice::device() const -{ - return d->m_device; -} - -TcfTrkDevice::IODevicePtr TcfTrkDevice::takeDevice() -{ - const IODevicePtr old = d->m_device; - if (!old.isNull()) { - old.data()->disconnect(this); - d->m_device = IODevicePtr(); - } - d->m_readBuffer.clear(); - d->m_token = 0; - d->m_sendQueue.clear(); - return old; -} - -void TcfTrkDevice::setDevice(const IODevicePtr &dp) -{ - if (dp.data() == d->m_device.data()) - return; - if (dp.isNull()) { - emitLogMessage(QLatin1String("Internal error: Attempt to set NULL device.")); - return; - } - takeDevice(); - d->m_device = dp; - connect(dp.data(), SIGNAL(readyRead()), this, SLOT(slotDeviceReadyRead())); - if (QAbstractSocket *s = qobject_cast<QAbstractSocket *>(dp.data())) { - connect(s, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotDeviceError())); - connect(s, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(slotDeviceSocketStateChanged())); - } -} - -void TcfTrkDevice::slotDeviceError() -{ - const QString message = d->m_device->errorString(); - emitLogMessage(message); - emit error(message); -} - -void TcfTrkDevice::slotDeviceSocketStateChanged() -{ - if (const QAbstractSocket *s = qobject_cast<const QAbstractSocket *>(d->m_device.data())) { - const QAbstractSocket::SocketState st = s->state(); - switch (st) { - case QAbstractSocket::UnconnectedState: - emitLogMessage(QLatin1String("Unconnected")); - break; - case QAbstractSocket::HostLookupState: - emitLogMessage(QLatin1String("HostLookupState")); - break; - case QAbstractSocket::ConnectingState: - emitLogMessage(QLatin1String("Connecting")); - break; - case QAbstractSocket::ConnectedState: - emitLogMessage(QLatin1String("Connected")); - break; - case QAbstractSocket::ClosingState: - emitLogMessage(QLatin1String("Closing")); - break; - default: - emitLogMessage(QString::fromLatin1("State %1").arg(st)); - break; - } - } -} - -static inline QString debugMessage(QByteArray message, const char *prefix = 0) -{ - message.replace('\0', '|'); - const QString messageS = QString::fromLatin1(message); - return prefix ? - (QLatin1String(prefix) + messageS) : messageS; -} - -void TcfTrkDevice::slotDeviceReadyRead() -{ - d->m_readBuffer += d->m_device->readAll(); - // Take complete message off front of readbuffer. - do { - const int messageEndPos = d->m_readBuffer.indexOf(d->m_messageTerminator); - if (messageEndPos == -1) - break; - const QByteArray message = d->m_readBuffer.left(messageEndPos); - if (debug) - qDebug("Read:\n%s", qPrintable(formatData(message))); - if (const int errorCode = parseMessage(message)) { - emitLogMessage(QString::fromLatin1("Parse error %1 for: %2").arg(errorCode).arg(debugMessage(message))); - } - d->m_readBuffer.remove(0, messageEndPos + d->m_messageTerminator.size()); - } while (!d->m_readBuffer.isEmpty()); - checkSendQueue(); // Send off further message -} - -// Split \0-terminated message into tokens, skipping the initial type character -static inline QVector<QByteArray> splitMessage(const QByteArray &message) -{ - QVector<QByteArray> tokens; - tokens.reserve(7); - const int messageSize = message.size(); - for (int pos = 2; pos < messageSize; ) { - const int nextPos = message.indexOf('\0', pos); - if (nextPos == -1) - break; - tokens.push_back(message.mid(pos, nextPos - pos)); - pos = nextPos + 1; - } - return tokens; -} - -int TcfTrkDevice::parseMessage(const QByteArray &message) -{ - if (d->m_verbose) - emitLogMessage(debugMessage(message, "TCF ->")); - // Special JSON parse error message or protocol format error. - // The port is usually closed after receiving it. - // "\3\2{"Time":1276096098255,"Code":3,"Format": "Protocol format error"}" - if (message.startsWith("\003\002")) { - QByteArray text = message.mid(2); - const QString errorMessage = QString::fromLatin1("Parse error received: %1").arg(QString::fromAscii(text)); - emit error(errorMessage); - return 0; - } - if (message.size() < 4 || message.at(1) != '\0') - return 1; - // Split into tokens - const char type = message.at(0); - const QVector<QByteArray> tokens = splitMessage(message); - switch (type) { - case 'E': - return parseTcfEvent(tokens); - case 'R': // Command replies - case 'N': - case 'P': - return parseTcfCommandReply(type, tokens); - default: - emitLogMessage(QString::fromLatin1("Unhandled message type: %1").arg(debugMessage(message))); - return 756; - } - return 0; -} - -int TcfTrkDevice::parseTcfCommandReply(char type, const QVector<QByteArray> &tokens) -{ - typedef TcfTrkDevicePrivate::TokenWrittenMessageMap::iterator TokenWrittenMessageMapIterator; - // Find the corresponding entry in the written messages hash. - const int tokenCount = tokens.size(); - if (tokenCount < 1) - return 234; - bool tokenOk; - const int token = tokens.at(0).toInt(&tokenOk); - if (!tokenOk) - return 235; - const TokenWrittenMessageMapIterator it = d->m_writtenMessages.find(token); - if (it == d->m_writtenMessages.end()) { - qWarning("TcfTrkDevice: Internal error: token %d not found for '%s'", - token, qPrintable(joinByteArrays(tokens))); - return 236; - } - // No callback: remove entry from map, happy - if (!it.value().callback) { - d->m_writtenMessages.erase(it); - return 0; - } - // Parse values into JSON - QVector<JsonValue> values; - values.reserve(tokenCount); - for (int i = 1; i < tokenCount; i++) { - if (!tokens.at(i).isEmpty()) { // Strange: Empty tokens occur. - const JsonValue value(tokens.at(i)); - if (value.isValid()) { - values.push_back(value); - } else { - qWarning("JSON parse error for reply to command token %d: #%d '%s'", - token, i, tokens.at(i).constData()); - d->m_writtenMessages.erase(it); - return -1; - } - } - } - - // Construct result and invoke callback, remove entry from map. - TcfTrkCallback callback = it.value().callback; - TcfTrkCommandResult result(type, it.value().service, it.value().data, - values, it.value().cookie); - d->m_writtenMessages.erase(it); - callback(result); - return 0; -} - -static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]"; - -int TcfTrkDevice::parseTcfEvent(const QVector<QByteArray> &tokens) -{ - // Event: Ignore the periodical heartbeat event, answer 'Hello', - // emit signal for the rest - if (tokens.size() < 3) - return 433; - const Services service = serviceFromName(tokens.at(0).constData()); - if (service == LocatorService && tokens.at(1) == "peerHeartBeat") - return 0; - QVector<JsonValue> values; - for (int i = 2; i < tokens.size(); i++) { - const JsonValue value(tokens.at(i)); - if (!value.isValid()) - return 434; - values.push_back(value); - } - // Parse known events, emit signals - QScopedPointer<TcfTrkEvent> knownEvent(TcfTrkEvent::parseEvent(service, tokens.at(1), values)); - if (!knownEvent.isNull()) { - // Answer hello event. - if (knownEvent->type() == TcfTrkEvent::LocatorHello) - writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC))); - emit tcfEvent(*knownEvent); - } - emit genericTcfEvent(service, tokens.at(1), values); - - if (debug || d->m_verbose) { - QString msg; - QTextStream str(&msg); - if (knownEvent.isNull()) { - str << "Event: " << tokens.at(0) << ' ' << tokens.at(1) << '\n'; - foreach(const JsonValue &val, values) - str << " " << val.toString() << '\n'; - } else { - str << knownEvent->toString(); - } - emitLogMessage(msg); - } - - return 0; -} - -unsigned TcfTrkDevice::verbose() const -{ - return d->m_verbose; -} - -void TcfTrkDevice::setVerbose(unsigned v) -{ - d->m_verbose = v; -} - -void TcfTrkDevice::emitLogMessage(const QString &m) -{ - if (debug) - qWarning("%s", qPrintable(m)); - emit logMessage(m); -} - -bool TcfTrkDevice::checkOpen() -{ - if (d->m_device.isNull()) { - emitLogMessage(QLatin1String("Internal error: No device set on TcfTrkDevice.")); - return false; - } - if (!d->m_device->isOpen()) { - emitLogMessage(QLatin1String("Internal error: Device not open in TcfTrkDevice.")); - return false; - } - return true; -} - -void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command, - const char *commandParameters, int commandParametersLength, - const TcfTrkCallback &callBack, - const QVariant &cookie) - -{ - if (!checkOpen()) - return; - // Format the message - const int token = d->m_token++; - QByteArray data; - data.reserve(30 + commandParametersLength); - data.append('C'); - data.append('\0'); - data.append(QByteArray::number(token)); - data.append('\0'); - data.append(serviceName(service)); - data.append('\0'); - data.append(command); - data.append('\0'); - if (commandParametersLength) - data.append(commandParameters, commandParametersLength); - const TcfTrkSendQueueEntry entry(mt, token, service, data, callBack, cookie); - d->m_sendQueue.enqueue(entry); - checkSendQueue(); -} - -void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command, - const QByteArray &commandParameters, - const TcfTrkCallback &callBack, - const QVariant &cookie) -{ - sendTcfTrkMessage(mt, service, command, commandParameters.constData(), commandParameters.size(), - callBack, cookie); -} - -// Enclose in message frame and write. -void TcfTrkDevice::writeMessage(QByteArray data) -{ - if (!checkOpen()) - return; - - if (d->m_verbose) - emitLogMessage(debugMessage(data, "TCF <-")); - - // Ensure \0-termination which easily gets lost in QByteArray CT. - if (!data.endsWith('\0')) - data.append('\0'); - data += d->m_messageTerminator; - - if (debug > 1) - qDebug("Writing:\n%s", qPrintable(formatData(data))); - - d->m_device->write(data); - if (QAbstractSocket *as = qobject_cast<QAbstractSocket *>(d->m_device.data())) - as->flush(); -} - -void TcfTrkDevice::checkSendQueue() -{ - // Fire off messages or invoke noops until a message with reply is found - // and an entry to writtenMessages is made. - while (d->m_writtenMessages.empty()) { - if (d->m_sendQueue.isEmpty()) - break; - TcfTrkSendQueueEntry entry = d->m_sendQueue.dequeue(); - switch (entry.messageType) { - case MessageWithReply: - d->m_writtenMessages.insert(entry.token, entry); - writeMessage(entry.data); - break; - case MessageWithoutReply: - writeMessage(entry.data); - break; - case NoopMessage: // Invoke the noop-callback for synchronization - if (entry.callback) { - TcfTrkCommandResult noopResult(TcfTrkCommandResult::SuccessReply); - noopResult.cookie = entry.cookie; - entry.callback(noopResult); - } - break; - } - } -} - -// Fix slashes -static inline QString fixFileName(QString in) -{ - in.replace(QLatin1Char('/'), QLatin1Char('\\')); - return in; -} - -// Start a process (consisting of a non-reply setSettings and start). -void TcfTrkDevice::sendProcessStartCommand(const TcfTrkCallback &callBack, - const QString &binaryIn, - unsigned uid, - QStringList arguments, - QString workingDirectory, - bool debugControl, - const QStringList &additionalLibraries, - const QVariant &cookie) -{ - // Obtain the bin directory, expand by c:/sys/bin if missing - const QChar backSlash('\\'); - int slashPos = binaryIn.lastIndexOf(QLatin1Char('/')); - if (slashPos == -1) - slashPos = binaryIn.lastIndexOf(backSlash); - const QString sysBin = QLatin1String("c:/sys/bin"); - const QString binaryFileName = slashPos == -1 ? binaryIn : binaryIn.mid(slashPos + 1); - const QString binaryDirectory = slashPos == -1 ? sysBin : binaryIn.left(slashPos); - const QString binary = fixFileName(binaryDirectory + QLatin1Char('/') + binaryFileName); - - // Fixup: Does argv[0] convention exist on Symbian? - arguments.push_front(binary); - if (workingDirectory.isEmpty()) - workingDirectory = sysBin; - - // Format settings with empty dummy parameter - QByteArray setData; - JsonInputStream setStr(setData); - setStr << "" << '\0' - << '[' << "exeToLaunch" << ',' << "addExecutables" << ',' << "addLibraries" << ']' - << '\0' << '[' - << binary << ',' - << '{' << binaryFileName << ':' << QString::number(uid, 16) << '}' << ',' - << additionalLibraries - << ']'; - sendTcfTrkMessage(MessageWithoutReply, SettingsService, "set", setData); - - QByteArray startData; - JsonInputStream startStr(startData); - startStr << fixFileName(workingDirectory) - << '\0' << binary << '\0' << arguments << '\0' - << QStringList() << '\0' // Env is an array ["PATH=value"] (non-standard) - << debugControl; - sendTcfTrkMessage(MessageWithReply, ProcessesService, "start", startData, callBack, cookie); -} - -void TcfTrkDevice::sendProcessTerminateCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie) -{ - QByteArray data; - JsonInputStream str(data); - str << id; - sendTcfTrkMessage(MessageWithReply, ProcessesService, "terminate", data, callBack, cookie); -} - -void TcfTrkDevice::sendRunControlTerminateCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie) -{ - QByteArray data; - JsonInputStream str(data); - str << id; - sendTcfTrkMessage(MessageWithReply, RunControlService, "terminate", data, callBack, cookie); -} - -// Non-standard: Remove executable from settings -void TcfTrkDevice::sendSettingsRemoveExecutableCommand(const QString &binaryIn, - unsigned uid, - const QStringList &additionalLibraries, - const QVariant &cookie) -{ - QByteArray setData; - JsonInputStream setStr(setData); - setStr << "" << '\0' - << '[' << "removedExecutables" << ',' << "removedLibraries" << ']' - << '\0' << '[' - << '{' << QFileInfo(binaryIn).fileName() << ':' << QString::number(uid, 16) << '}' << ',' - << additionalLibraries - << ']'; - sendTcfTrkMessage(MessageWithoutReply, SettingsService, "set", setData, TcfTrkCallback(), cookie); -} - -void TcfTrkDevice::sendRunControlResumeCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - RunControlResumeMode mode, - unsigned count, - quint64 rangeStart, - quint64 rangeEnd, - const QVariant &cookie) -{ - QByteArray resumeData; - JsonInputStream str(resumeData); - str << id << '\0' << int(mode) << '\0' << count; - switch (mode) { - case RM_STEP_OVER_RANGE: - case RM_STEP_INTO_RANGE: - case RM_REVERSE_STEP_OVER_RANGE: - case RM_REVERSE_STEP_INTO_RANGE: - str << '\0' << '{' << "RANGE_START" << ':' << rangeStart - << ',' << "RANGE_END" << ':' << rangeEnd << '}'; - break; - default: - break; - } - sendTcfTrkMessage(MessageWithReply, RunControlService, "resume", resumeData, callBack, cookie); -} - -void TcfTrkDevice::sendRunControlSuspendCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie) -{ - QByteArray data; - JsonInputStream str(data); - str << id; - sendTcfTrkMessage(MessageWithReply, RunControlService, "suspend", data, callBack, cookie); -} - -void TcfTrkDevice::sendRunControlResumeCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie) -{ - sendRunControlResumeCommand(callBack, id, RM_RESUME, 1, 0, 0, cookie); -} - -void TcfTrkDevice::sendBreakpointsAddCommand(const TcfTrkCallback &callBack, - const Breakpoint &bp, - const QVariant &cookie) -{ - QByteArray data; - JsonInputStream str(data); - str << bp; - sendTcfTrkMessage(MessageWithReply, BreakpointsService, "add", data, callBack, cookie); -} - -void TcfTrkDevice::sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie) -{ - sendBreakpointsRemoveCommand(callBack, QVector<QByteArray>(1, id), cookie); -} - -void TcfTrkDevice::sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, - const QVector<QByteArray> &ids, - const QVariant &cookie) -{ - QByteArray data; - JsonInputStream str(data); - str << ids; - sendTcfTrkMessage(MessageWithReply, BreakpointsService, "remove", data, callBack, cookie); -} - -void TcfTrkDevice::sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - bool enable, - const QVariant &cookie) -{ - sendBreakpointsEnableCommand(callBack, QVector<QByteArray>(1, id), enable, cookie); -} - -void TcfTrkDevice::sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, - const QVector<QByteArray> &ids, - bool enable, - const QVariant &cookie) -{ - QByteArray data; - JsonInputStream str(data); - str << ids; - sendTcfTrkMessage(MessageWithReply, BreakpointsService, - enable ? "enable" : "disable", - data, callBack, cookie); -} - -void TcfTrkDevice::sendMemorySetCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - quint64 start, const QByteArray& data, - const QVariant &cookie) -{ - QByteArray getData; - JsonInputStream str(getData); - // start/word size/mode. Mode should ideally be 1 (continue on error?) - str << contextId << '\0' << start << '\0' << 1 << '\0' << data.size() << '\0' << 1 - << '\0' << data.toBase64(); - sendTcfTrkMessage(MessageWithReply, MemoryService, "set", getData, callBack, cookie); -} - -void TcfTrkDevice::sendMemoryGetCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - quint64 start, quint64 size, - const QVariant &cookie) -{ - QByteArray data; - JsonInputStream str(data); - // start/word size/mode. Mode should ideally be 1 (continue on error?) - str << contextId << '\0' << start << '\0' << 1 << '\0' << size << '\0' << 1; - sendTcfTrkMessage(MessageWithReply, MemoryService, "get", data, callBack, cookie); -} - -QByteArray TcfTrkDevice::parseMemoryGet(const TcfTrkCommandResult &r) -{ - if (r.type != TcfTrkCommandResult::SuccessReply || r.values.size() < 1) - return QByteArray(); - const JsonValue &memoryV = r.values.front(); - - if (memoryV.type() != JsonValue::String || memoryV.data().size() < 2 - || !memoryV.data().endsWith('=')) - return QByteArray(); - // Catch errors reported as hash: - // R.4."TlVMTA==".{"Time":1276786871255,"Code":1,"AltCode":-38,"AltOrg":"POSIX","Format":"BadDescriptor"} - // Not sure what to make of it. - if (r.values.size() >= 2 && r.values.at(1).type() == JsonValue::Object) - qWarning("Error retrieving memory: %s", r.values.at(1).toString(false).constData()); - // decode - const QByteArray memory = QByteArray::fromBase64(memoryV.data()); - if (memory.isEmpty()) - qWarning("Base64 decoding of %s failed.", memoryV.data().constData()); - if (debug) - qDebug("TcfTrkDevice::parseMemoryGet: received %d bytes", memory.size()); - return memory; -} - -void TcfTrkDevice::sendRegistersGetMCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - const QVector<QByteArray> &ids, - const QVariant &cookie) -{ - // TODO: use "Registers" (which uses base64-encoded values) - QByteArray data; - JsonInputStream str(data); - str << contextId << '\0' << ids; - sendTcfTrkMessage(MessageWithReply, SimpleRegistersService, "get", data, callBack, cookie); -} - -void TcfTrkDevice::sendRegistersGetMRangeCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - unsigned start, unsigned count) -{ - const unsigned end = start + count; - if (end > (unsigned)d->m_registerNames.size()) { - qWarning("TcfTrkDevice: No register name set for index %u (size: %d).", end, d->m_registerNames.size()); - return; - } - - QVector<QByteArray> ids; - ids.reserve(count); - for (unsigned i = start; i < end; i++) - ids.push_back(d->m_registerNames.at(i)); - sendRegistersGetMCommand(callBack, contextId, ids, QVariant(start)); -} - -// Set register -void TcfTrkDevice::sendRegistersSetCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - const QByteArray &id, - unsigned value, - const QVariant &cookie) -{ - // TODO: use "Registers" (which uses base64-encoded values) - QByteArray data; - JsonInputStream str(data); - str << contextId << '\0' << QVector<QByteArray>(1, id) - << '\0' << QVector<QByteArray>(1, QByteArray::number(value, 16)); - sendTcfTrkMessage(MessageWithReply, SimpleRegistersService, "set", data, callBack, cookie); -} - -// Set register -void TcfTrkDevice::sendRegistersSetCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - unsigned registerNumber, - unsigned value, - const QVariant &cookie) -{ - if (registerNumber >= (unsigned)d->m_registerNames.size()) { - qWarning("TcfTrkDevice: No register name set for index %u (size: %d).", registerNumber, d->m_registerNames.size()); - return; - } - sendRegistersSetCommand(callBack, contextId, - d->m_registerNames[registerNumber], - value, cookie); -} - -} // namespace tcftrk diff --git a/tools/runonphone/symbianutils/tcftrkdevice.h b/tools/runonphone/symbianutils/tcftrkdevice.h deleted file mode 100644 index 8f754e8..0000000 --- a/tools/runonphone/symbianutils/tcftrkdevice.h +++ /dev/null @@ -1,295 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TCFTRKENGINE_H -#define TCFTRKENGINE_H - -#include "symbianutils_global.h" -#include "tcftrkmessage.h" -#include "callback.h" -#include "json.h" - -#include <QtCore/QObject> -#include <QtCore/QSharedPointer> -#include <QtCore/QVector> -#include <QtCore/QVariant> -#include <QtCore/QStringList> - -QT_BEGIN_NAMESPACE -class QIODevice; -class QTextStream; -QT_END_NAMESPACE - -namespace tcftrk { - -struct TcfTrkDevicePrivate; -struct Breakpoint; - -/* Command error handling in TCF: - * 1) 'Severe' errors (JSON format, parameter format): Trk emits a - * nonstandard message (\3\2 error parameters) and closes the connection. - * 2) Protocol errors: 'N' without error message is returned. - * 3) Errors in command execution: 'R' with a TCF error hash is returned - * (see TcfTrkCommandError). */ - -/* Error code return in 'R' reply to command - * (see top of 'Services' documentation). */ -struct SYMBIANUTILS_EXPORT TcfTrkCommandError { - TcfTrkCommandError(); - void clear(); - operator bool() const { return timeMS != 0; } - QString toString() const; - void write(QTextStream &str) const; - bool parse(const QVector<JsonValue> &values); - - quint64 timeMS; // Since 1.1.1970 - int code; - QByteArray format; // message - // 'Alternative' meaning, like altOrg="POSIX"/altCode=<some errno> - QByteArray alternativeOrganization; - int alternativeCode; -}; - -/* Answer to a Tcf command passed to the callback. */ -struct SYMBIANUTILS_EXPORT TcfTrkCommandResult { - enum Type { - SuccessReply, // 'R' and no error -> all happy. - CommandErrorReply, // 'R' with TcfTrkCommandError received - ProgressReply, // 'P', progress indicator - FailReply // 'N' Protocol NAK, severe error - }; - - explicit TcfTrkCommandResult(Type t = SuccessReply); - explicit TcfTrkCommandResult(char typeChar, Services service, - const QByteArray &request, - const QVector<JsonValue> &values, - const QVariant &cookie); - - QString toString() const; - QString errorString() const; - operator bool() const { return type == SuccessReply || type == ProgressReply; } - - Type type; - Services service; - QByteArray request; - TcfTrkCommandError commandError; - QVector<JsonValue> values; - QVariant cookie; -}; - -typedef trk::Callback<const TcfTrkCommandResult &> TcfTrkCallback; - -/* TcfTrkDevice: TCF communication helper using an asynchronous QIODevice - * implementing the TCF protocol according to: -http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Specification.html -http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services.html - * Commands can be sent along with callbacks that are passed a - * TcfTrkCommandResult and an opaque QVariant cookie. In addition, events are emitted. -*/ - -class SYMBIANUTILS_EXPORT TcfTrkDevice : public QObject -{ - Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose) - Q_OBJECT -public: - enum MessageType { MessageWithReply, - MessageWithoutReply, /* Non-standard: "Settings:set" command does not reply */ - NoopMessage }; - - typedef QSharedPointer<QIODevice> IODevicePtr; - - explicit TcfTrkDevice(QObject *parent = 0); - virtual ~TcfTrkDevice(); - - unsigned verbose() const; - - // Mapping of register names for indices - QVector<QByteArray> registerNames() const; - void setRegisterNames(const QVector<QByteArray>& n); - - IODevicePtr device() const; - IODevicePtr takeDevice(); - void setDevice(const IODevicePtr &dp); - - void sendTcfTrkMessage(MessageType mt, Services service, - const char *command, - const char *commandParameters, int commandParametersLength, - const TcfTrkCallback &callBack = TcfTrkCallback(), - const QVariant &cookie = QVariant()); - - void sendTcfTrkMessage(MessageType mt, Services service, const char *command, - const QByteArray &commandParameters, - const TcfTrkCallback &callBack = TcfTrkCallback(), - const QVariant &cookie = QVariant()); - - // Convenience messages: Start a process - void sendProcessStartCommand(const TcfTrkCallback &callBack, - const QString &binary, - unsigned uid, - QStringList arguments = QStringList(), - QString workingDirectory = QString(), - bool debugControl = true, - const QStringList &additionalLibraries = QStringList(), - const QVariant &cookie = QVariant()); - - // Preferred over Processes:Terminate by TCF TRK. - void sendRunControlTerminateCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie = QVariant()); - - void sendProcessTerminateCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie = QVariant()); - - // Non-standard: Remove executable from settings. - // Probably needs to be called after stopping. This command has no response. - void sendSettingsRemoveExecutableCommand(const QString &binaryIn, - unsigned uid, - const QStringList &additionalLibraries = QStringList(), - const QVariant &cookie = QVariant()); - - void sendRunControlSuspendCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie = QVariant()); - - // Resume / Step (see RunControlResumeMode). - void sendRunControlResumeCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - RunControlResumeMode mode, - unsigned count /* = 1, currently ignored. */, - quint64 rangeStart, quint64 rangeEnd, - const QVariant &cookie = QVariant()); - - // Convenience to resume a suspended process - void sendRunControlResumeCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie = QVariant()); - - void sendBreakpointsAddCommand(const TcfTrkCallback &callBack, - const Breakpoint &b, - const QVariant &cookie = QVariant()); - - void sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - const QVariant &cookie = QVariant()); - - void sendBreakpointsRemoveCommand(const TcfTrkCallback &callBack, - const QVector<QByteArray> &id, - const QVariant &cookie = QVariant()); - - void sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, - const QByteArray &id, - bool enable, - const QVariant &cookie = QVariant()); - - void sendBreakpointsEnableCommand(const TcfTrkCallback &callBack, - const QVector<QByteArray> &id, - bool enable, - const QVariant &cookie = QVariant()); - - - void sendMemoryGetCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - quint64 start, quint64 size, - const QVariant &cookie = QVariant()); - - void sendMemorySetCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - quint64 start, const QByteArray& data, - const QVariant &cookie = QVariant()); - - // Reply is an array of hexvalues - void sendRegistersGetMCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - const QVector<QByteArray> &ids, - const QVariant &cookie = QVariant()); - - // Convenience to get a range of register "R0" .. "R<n>". - // Cookie will be an int containing "start". - void sendRegistersGetMRangeCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - unsigned start, unsigned count); - - // Set register - void sendRegistersSetCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - const QByteArray &ids, - unsigned value, - const QVariant &cookie = QVariant()); - // Set register - void sendRegistersSetCommand(const TcfTrkCallback &callBack, - const QByteArray &contextId, - unsigned registerNumber, - unsigned value, - const QVariant &cookie = QVariant()); - - static QByteArray parseMemoryGet(const TcfTrkCommandResult &r); - -signals: - void genericTcfEvent(int service, const QByteArray &name, const QVector<tcftrk::JsonValue> &value); - void tcfEvent(const tcftrk::TcfTrkEvent &knownEvent); - - void logMessage(const QString &); - void error(const QString &); - -public slots: - void setVerbose(unsigned v); - -private slots: - void slotDeviceError(); - void slotDeviceSocketStateChanged(); - void slotDeviceReadyRead(); - -private: - bool checkOpen(); - void checkSendQueue(); - void writeMessage(QByteArray data); - void emitLogMessage(const QString &); - int parseMessage(const QByteArray &); - int parseTcfCommandReply(char type, const QVector<QByteArray> &tokens); - int parseTcfEvent(const QVector<QByteArray> &tokens); - - TcfTrkDevicePrivate *d; -}; - -} // namespace tcftrk - -#endif // TCFTRKENGINE_H diff --git a/tools/runonphone/symbianutils/trkdevice.cpp b/tools/runonphone/symbianutils/trkdevice.cpp index c6dc0a4..e28e70e 100644 --- a/tools/runonphone/symbianutils/trkdevice.cpp +++ b/tools/runonphone/symbianutils/trkdevice.cpp @@ -694,7 +694,7 @@ public slots: void terminate(); private: - enum Handles { FileHandle, TerminateEventHandle, HandleCount }; + enum Handles { TerminateEventHandle, FileHandle, HandleCount }; inline int tryRead(); @@ -727,7 +727,7 @@ int WinReaderThread::tryRead() const DWORD bytesToRead = qMax(DWORD(1), qMin(comStat.cbInQue, DWORD(BufSize))); // Trigger read DWORD bytesRead = 0; - if (ReadFile(m_context->device, &buffer, bytesToRead, &bytesRead, &m_context->readOverlapped)) { + if (ReadFile(m_context->device, &buffer, bytesToRead, &bytesRead, &m_context->readOverlapped) && bytesRead > 0) { if (bytesRead == 1) { processData(buffer[0]); } else { @@ -736,7 +736,7 @@ int WinReaderThread::tryRead() return 0; } const DWORD readError = GetLastError(); - if (readError != ERROR_IO_PENDING) { + if (readError != ERROR_IO_PENDING && readError != 0) { emit error(QString::fromLatin1("Read error: %1").arg(winErrorMessage(readError))); return -1; } diff --git a/tools/runonphone/symbianutils/trkutils.h b/tools/runonphone/symbianutils/trkutils.h index 663dc38..a4f5453 100644 --- a/tools/runonphone/symbianutils/trkutils.h +++ b/tools/runonphone/symbianutils/trkutils.h @@ -145,7 +145,7 @@ enum DSOSItemTypes { kDSOSProcAttachItem = 0x0005, kDSOSThreadAttachItem = 0x0006, kDSOSProcAttach2Item = 0x0007, - kDSOSProcRunItem = 0x0008, + kDSOSProcRunItem = 0x0008 /* 0x0009 - 0x00ff reserved for general expansion */ /* 0x0100 - 0xffff available for target-specific use */ }; @@ -170,7 +170,7 @@ enum Endianness { LittleEndian, BigEndian, - TargetByteOrder = BigEndian, + TargetByteOrder = BigEndian }; SYMBIANUTILS_EXPORT void appendShort(QByteArray *ba, ushort s, Endianness = TargetByteOrder); diff --git a/tools/runonphone/symbianutils/virtualserialdevice.cpp b/tools/runonphone/symbianutils/virtualserialdevice.cpp new file mode 100644 index 0000000..4a8b354 --- /dev/null +++ b/tools/runonphone/symbianutils/virtualserialdevice.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "virtualserialdevice.h" +#include <QtCore/QThread> +#include <QtCore/QWaitCondition> + +namespace SymbianUtils { + +bool VirtualSerialDevice::isSequential() const +{ + return true; +} + +VirtualSerialDevice::VirtualSerialDevice(const QString &aPortName, QObject *parent) : + QIODevice(parent), portName(aPortName), lock(QMutex::NonRecursive), emittingBytesWritten(false), waiterForBytesWritten(NULL) +{ + platInit(); +} + +const QString& VirtualSerialDevice::getPortName() const +{ + return portName; +} + +void VirtualSerialDevice::close() +{ + if (isOpen()) { + QMutexLocker locker(&lock); + delete waiterForBytesWritten; + waiterForBytesWritten = NULL; + QIODevice::close(); + platClose(); + } +} + +void VirtualSerialDevice::emitBytesWrittenIfNeeded(QMutexLocker& locker, qint64 len) +{ + if (waiterForBytesWritten) { + waiterForBytesWritten->wakeAll(); + } + if (!emittingBytesWritten) { + emittingBytesWritten = true; + locker.unlock(); + emit bytesWritten(len); + locker.relock(); + emittingBytesWritten = false; + } +} + +} // namespace SymbianUtils diff --git a/tools/runonphone/symbianutils/virtualserialdevice.h b/tools/runonphone/symbianutils/virtualserialdevice.h new file mode 100644 index 0000000..9b65eef --- /dev/null +++ b/tools/runonphone/symbianutils/virtualserialdevice.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VIRTUALSERIALPORT_H +#define VIRTUALSERIALPORT_H + +#include <QtCore/QIODevice> +#include <QtCore/QString> +#include <QtCore/QMutex> + +QT_BEGIN_NAMESPACE +class QWaitCondition; +QT_END_NAMESPACE + +#include "symbianutils_global.h" + +namespace SymbianUtils { + +class VirtualSerialDevicePrivate; + +class SYMBIANUTILS_EXPORT VirtualSerialDevice : public QIODevice +{ + Q_OBJECT +public: + explicit VirtualSerialDevice(const QString &name, QObject *parent = 0); + ~VirtualSerialDevice(); + + bool open(OpenMode mode); + void close(); + const QString &getPortName() const; + void flush(); + + qint64 bytesAvailable() const; + bool isSequential() const; + bool waitForBytesWritten(int msecs); + bool waitForReadyRead(int msecs); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private: + Q_DISABLE_COPY(VirtualSerialDevice) + void platInit(); + void platClose(); + void emitBytesWrittenIfNeeded(QMutexLocker &locker, qint64 len); + +private: + QString portName; + mutable QMutex lock; + QList<QByteArray> pendingWrites; + bool emittingBytesWritten; + QWaitCondition* waiterForBytesWritten; + VirtualSerialDevicePrivate *d; + +// Platform-specific stuff +#ifdef Q_OS_WIN +private: + qint64 writeNextBuffer(QMutexLocker &locker); + void doWriteCompleted(QMutexLocker &locker); +private slots: + void writeCompleted(); + void commEventOccurred(); +#endif + +#ifdef Q_OS_UNIX +private: + bool tryWrite(const char *data, qint64 maxSize, qint64 &bytesWritten); + enum FlushPendingOption { + NothingSpecial = 0, + StopAfterWritingOneBuffer = 1, + EmitBytesWrittenAsync = 2, // Needed so we don't emit bytesWritten signal directly from writeBytes + }; + Q_DECLARE_FLAGS(FlushPendingOptions, FlushPendingOption) + bool tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags = NothingSpecial); + +private slots: + void writeHasUnblocked(int fileHandle); + +signals: + void AsyncCall_emitBytesWrittenIfNeeded(qint64 len); + +#endif + +}; + +} // namespace SymbianUtils + +#endif // VIRTUALSERIALPORT_H diff --git a/tools/runonphone/symbianutils/virtualserialdevice_posix.cpp b/tools/runonphone/symbianutils/virtualserialdevice_posix.cpp new file mode 100644 index 0000000..4e389fc --- /dev/null +++ b/tools/runonphone/symbianutils/virtualserialdevice_posix.cpp @@ -0,0 +1,344 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <termios.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <QtCore/QSocketNotifier> +#include <QtCore/QTimer> +#include <QtCore/QThread> +#include <QtCore/QWaitCondition> +#include "virtualserialdevice.h" + +namespace SymbianUtils { + +class VirtualSerialDevicePrivate +{ +public: + int portHandle; + QSocketNotifier* readNotifier; + QSocketNotifier* writeUnblockedNotifier; +}; + +void VirtualSerialDevice::platInit() +{ + d = new VirtualSerialDevicePrivate; + d->portHandle = -1; + d->readNotifier = NULL; + d->writeUnblockedNotifier = NULL; + connect(this, SIGNAL(AsyncCall_emitBytesWrittenIfNeeded(qint64)), this, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection); +} + +bool VirtualSerialDevice::open(OpenMode mode) +{ + if (isOpen()) return true; + + d->portHandle = ::open(portName.toAscii().constData(), O_RDWR | O_NONBLOCK | O_NOCTTY); + if (d->portHandle == -1) { + setErrorString(tr("The port %1 could not be opened: %2 (POSIX error %3)"). + arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno)); + return false; + } + + struct termios termInfo; + if (tcgetattr(d->portHandle, &termInfo) < 0) { + setErrorString(tr("Unable to retrieve terminal settings of port %1: %2 (POSIX error %3)"). + arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno)); + close(); + return false; + } + cfmakeraw(&termInfo); + // Turn off terminal echo as not get messages back, among other things + termInfo.c_cflag |= CREAD|CLOCAL; + termInfo.c_cc[VTIME] = 0; + termInfo.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); + termInfo.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY|IXON|IXOFF)); + termInfo.c_oflag &= (~OPOST); + termInfo.c_cc[VMIN] = 0; + termInfo.c_cc[VINTR] = _POSIX_VDISABLE; + termInfo.c_cc[VQUIT] = _POSIX_VDISABLE; + termInfo.c_cc[VSTART] = _POSIX_VDISABLE; + termInfo.c_cc[VSTOP] = _POSIX_VDISABLE; + termInfo.c_cc[VSUSP] = _POSIX_VDISABLE; + + if (tcsetattr(d->portHandle, TCSAFLUSH, &termInfo) < 0) { + setErrorString(tr("Unable to apply terminal settings to port %1: %2 (POSIX error %3)"). + arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno)); + close(); + return false; + } + + d->readNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Read); + connect(d->readNotifier, SIGNAL(activated(int)), this, SIGNAL(readyRead())); + + d->writeUnblockedNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Write); + d->writeUnblockedNotifier->setEnabled(false); + connect(d->writeUnblockedNotifier, SIGNAL(activated(int)), this, SLOT(writeHasUnblocked(int))); + + bool ok = QIODevice::open(mode | QIODevice::Unbuffered); + if (!ok) close(); + return ok; +} + +void VirtualSerialDevice::platClose() +{ + delete d->readNotifier; + d->readNotifier = NULL; + + delete d->writeUnblockedNotifier; + d->writeUnblockedNotifier = NULL; + + ::close(d->portHandle); + d->portHandle = -1; +} + +VirtualSerialDevice::~VirtualSerialDevice() +{ + close(); + delete d; +} + +qint64 VirtualSerialDevice::bytesAvailable() const +{ + QMutexLocker locker(&lock); + if (!isOpen()) return 0; + + int avail = 0; + if (ioctl(d->portHandle, FIONREAD, &avail) == -1) { + return 0; + } + return (qint64)avail + QIODevice::bytesAvailable(); +} + +qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize) +{ + QMutexLocker locker(&lock); + int result = ::read(d->portHandle, data, maxSize); + if (result == -1 && errno == EAGAIN) + result = 0; // To Qt, 0 here means nothing ready right now, and -1 is reserved for permanent errors + return result; +} + +qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize) +{ + QMutexLocker locker(&lock); + qint64 bytesWritten; + bool needToWait = tryFlushPendingBuffers(locker, EmitBytesWrittenAsync); + if (!needToWait) { + needToWait = tryWrite(data, maxSize, bytesWritten); + if (needToWait && bytesWritten > 0) { + // Wrote some of the buffer, adjust pointers to point to the remainder that needs queueing + data += bytesWritten; + maxSize -= bytesWritten; + } + } + + if (needToWait) { + pendingWrites.append(QByteArray(data, maxSize)); + d->writeUnblockedNotifier->setEnabled(true); + // Now wait for the writeUnblocked signal or for a call to waitForBytesWritten + return bytesWritten + maxSize; + } else { + //emitBytesWrittenIfNeeded(locker, bytesWritten); + // Can't emit bytesWritten directly from writeData - means clients end up recursing + emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten); + return bytesWritten; + } +} + +/* Returns true if EAGAIN encountered. + * if error occurred (other than EAGAIN) returns -1 in bytesWritten + * lock must be held. Doesn't emit signals or set notifiers. + */ +bool VirtualSerialDevice::tryWrite(const char *data, qint64 maxSize, qint64& bytesWritten) +{ + // Must be locked + bytesWritten = 0; + while (maxSize > 0) { + int result = ::write(d->portHandle, data, maxSize); + if (result == -1) { + if (errno == EAGAIN) + return true; // Need to wait + setErrorString(tr("Cannot write to port %1: %2 (POSIX error %3)"). + arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno)); + + bytesWritten = -1; + return false; + } else { + if (result == 0) + qWarning("%s: Zero bytes written to port %s!", Q_FUNC_INFO, qPrintable(portName)); + bytesWritten += result; + maxSize -= result; + data += result; + } + } + return false; // If we reach here we've successfully written all the data without blocking +} + +/* Returns true if EAGAIN encountered. Emits (or queues) bytesWritten for any buffers written. + * If stopAfterWritingOneBuffer is true, return immediately if a single buffer is written, rather than + * attempting to drain the whole queue. + * Doesn't modify notifier. + */ +bool VirtualSerialDevice::tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags) +{ + while (pendingWrites.count() > 0) { + // Try writing everything we've got, until we hit EAGAIN + const QByteArray& data = pendingWrites[0]; + qint64 bytesWritten; + bool needToWait = tryWrite(data.constData(), data.size(), bytesWritten); + if (needToWait) { + if (bytesWritten > 0) { + // We wrote some of the data, update the pending queue + QByteArray remainder = data.mid(bytesWritten); + pendingWrites.removeFirst(); + pendingWrites.insert(0, remainder); + } + return needToWait; + } else { + pendingWrites.removeFirst(); + if (flags & EmitBytesWrittenAsync) { + emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten); + } else { + emitBytesWrittenIfNeeded(locker, bytesWritten); + } + if (flags & StopAfterWritingOneBuffer) return false; + // Otherwise go round loop again + } + } + return false; // no EAGAIN encountered +} + +void VirtualSerialDevice::writeHasUnblocked(int fileHandle) +{ + Q_ASSERT(fileHandle == d->portHandle); + (void)fileHandle; // Compiler shutter-upper + d->writeUnblockedNotifier->setEnabled(false); + + QMutexLocker locker(&lock); + bool needToWait = tryFlushPendingBuffers(locker); + if (needToWait) d->writeUnblockedNotifier->setEnabled(true); +} + +// Copy of qt_safe_select from /qt/src/corelib/kernel/qeventdispatcher_unix.cpp +// But without the timeout correction +int safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, + const struct timeval *orig_timeout) +{ + if (!orig_timeout) { + // no timeout -> block forever + register int ret; + do { + ret = select(nfds, fdread, fdwrite, fdexcept, 0); + } while (ret == -1 && errno == EINTR); + return ret; + } + + timeval timeout = *orig_timeout; + + int ret; + forever { + ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout); + if (ret != -1 || errno != EINTR) + return ret; + } +} + +bool VirtualSerialDevice::waitForBytesWritten(int msecs) +{ + QMutexLocker locker(&lock); + if (pendingWrites.count() == 0) return false; + + if (QThread::currentThread() != thread()) { + // Wait for signal from main thread + unsigned long timeout = msecs; + if (msecs == -1) timeout = ULONG_MAX; + if (waiterForBytesWritten == NULL) + waiterForBytesWritten = new QWaitCondition; + return waiterForBytesWritten->wait(&lock, timeout); + } + + d->writeUnblockedNotifier->setEnabled(false); + forever { + fd_set writeSet; + FD_ZERO(&writeSet); + FD_SET(d->portHandle, &writeSet); + + struct timeval timeout; + if (msecs != -1) { + timeout.tv_sec = msecs / 1000; + timeout.tv_usec = (msecs % 1000) * 1000; + } + int ret = safe_select(d->portHandle+1, NULL, &writeSet, NULL, msecs == -1 ? NULL : &timeout); + + if (ret == 0) { + // Timeout + return false; + } else if (ret < 0) { + setErrorString(tr("The function select() returned an error on port %1: %2 (POSIX error %3)"). + arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno)); + return false; + } else { + bool needToWait = tryFlushPendingBuffers(locker, StopAfterWritingOneBuffer); + if (needToWait) { + // go round the select again + } else { + return true; + } + } + } +} + +void VirtualSerialDevice::flush() +{ + while (waitForBytesWritten(-1)) { /* loop */ } + tcflush(d->portHandle, TCIOFLUSH); +} + +bool VirtualSerialDevice::waitForReadyRead(int msecs) +{ + return QIODevice::waitForReadyRead(msecs); //TODO +} + +} // namespace SymbianUtils diff --git a/tools/runonphone/symbianutils/virtualserialdevice_win.cpp b/tools/runonphone/symbianutils/virtualserialdevice_win.cpp new file mode 100644 index 0000000..d9f4588 --- /dev/null +++ b/tools/runonphone/symbianutils/virtualserialdevice_win.cpp @@ -0,0 +1,369 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "virtualserialdevice.h" +#include <windows.h> +#include <QtCore/private/qwineventnotifier_p.h> +#include <QtCore/QThread> +#include <QtCore/QWaitCondition> + +namespace SymbianUtils { + +class VirtualSerialDevicePrivate +{ +public: + HANDLE portHandle; + OVERLAPPED writeOverlapped; + OVERLAPPED commEventOverlapped; + DWORD commEventMask; + QWinEventNotifier *writeCompleteNotifier; + QWinEventNotifier *commEventNotifier; +}; + +void VirtualSerialDevice::platInit() +{ + d = new VirtualSerialDevicePrivate; + d->portHandle = INVALID_HANDLE_VALUE; + d->writeCompleteNotifier = NULL; + memset(&d->writeOverlapped, 0, sizeof(OVERLAPPED)); + d->commEventNotifier = NULL; + memset(&d->commEventOverlapped, 0, sizeof(OVERLAPPED)); +} + +QString windowsPortName(const QString& port) +{ + // Add the \\.\ to the name if it's a COM port and doesn't already have it + QString winPortName(port); + if (winPortName.startsWith(QLatin1String("COM"))) { + winPortName.prepend("\\\\.\\"); + } + return winPortName; +} + +// Copied from \creator\src\libs\utils\winutils.cpp +QString winErrorMessage(unsigned long error) +{ + // Some of the windows error messages are a bit too obscure + switch (error) + { + case ERROR_FILE_NOT_FOUND: + case ERROR_NOT_FOUND: + return VirtualSerialDevice::tr("Port not found"); + break; + case ERROR_ACCESS_DENIED: + return VirtualSerialDevice::tr("Port in use"); + case ERROR_SEM_TIMEOUT: // Bluetooth ports sometimes return this + return VirtualSerialDevice::tr("Timed out"); + case ERROR_NETWORK_UNREACHABLE: + return VirtualSerialDevice::tr("Port unreachable"); // I don't know what this error indicates... from observation, that the windows Bluetooth stack has got itself into a state and needs resetting + default: + break; + } + + QString rc = QString::fromLatin1("#%1: ").arg(error); + ushort *lpMsgBuf; + + const int len = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL); + if (len) { + rc = QString::fromUtf16(lpMsgBuf, len); + LocalFree(lpMsgBuf); + } else { + rc += QString::fromLatin1("<unknown error>"); + } + return rc.trimmed(); +} + +bool VirtualSerialDevice::open(OpenMode mode) +{ + Q_ASSERT(QThread::currentThread() == thread()); + if (isOpen()) return true; + + d->portHandle = CreateFileA(windowsPortName(portName).toAscii(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (d->portHandle == INVALID_HANDLE_VALUE) { + setErrorString(tr("The port %1 could not be opened: %2"). + arg(portName, winErrorMessage(GetLastError()))); + return false; + } + + DCB commState; + memset(&commState, 0, sizeof(DCB)); + commState.DCBlength = sizeof(DCB); + bool ok = GetCommState(d->portHandle, &commState); + if (ok) { + commState.BaudRate = CBR_115200; + commState.fBinary = TRUE; + commState.fParity = FALSE; + commState.fOutxCtsFlow = FALSE; + commState.fOutxDsrFlow = FALSE; + commState.fInX = FALSE; + commState.fOutX = FALSE; + commState.fNull = FALSE; + commState.fAbortOnError = FALSE; + commState.fDsrSensitivity = FALSE; + commState.fDtrControl = DTR_CONTROL_DISABLE; + commState.ByteSize = 8; + commState.Parity = NOPARITY; + commState.StopBits = ONESTOPBIT; + ok = SetCommState(d->portHandle, &commState); + } + if (!ok) { + qWarning("%s setting comm state", qPrintable(winErrorMessage(GetLastError()))); + } + + // http://msdn.microsoft.com/en-us/library/aa363190(v=vs.85).aspx says this means + // "the read operation is to return immediately with the bytes that have already been received, even if no bytes have been received" + COMMTIMEOUTS timeouts; + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + SetCommTimeouts(d->portHandle, &timeouts); + + d->writeOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + d->writeCompleteNotifier = new QWinEventNotifier(d->writeOverlapped.hEvent, this); + connect(d->writeCompleteNotifier, SIGNAL(activated(HANDLE)), this, SLOT(writeCompleted())); + + // This is how we implement readyRead notifications + d->commEventOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + d->commEventNotifier = new QWinEventNotifier(d->commEventOverlapped.hEvent, this); + connect(d->commEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(commEventOccurred())); + + if (!SetCommMask(d->portHandle, EV_RXCHAR)) { + // What to do? + qWarning("%s: Could not set comm mask, err=%d", Q_FUNC_INFO, (int)GetLastError()); + } + bool result = WaitCommEvent(d->portHandle, &d->commEventMask, &d->commEventOverlapped); + Q_ASSERT(result == false); // Can't see how it would make sense to be anything else... + (void)result; // For release build + if (GetLastError() != ERROR_IO_PENDING) { + setErrorString(tr("An error occurred while waiting for read notifications from %1: %2"). + arg(portName, winErrorMessage(GetLastError()))); + close(); + return false; + } + + ok = QIODevice::open(mode); + if (!ok) close(); + return ok; +} + +void VirtualSerialDevice::platClose() +{ + delete d->writeCompleteNotifier; + d->writeCompleteNotifier = NULL; + CloseHandle(d->writeOverlapped.hEvent); + d->writeOverlapped.hEvent = INVALID_HANDLE_VALUE; + + delete d->commEventNotifier; + d->commEventNotifier = NULL; + d->commEventOverlapped.hEvent = INVALID_HANDLE_VALUE; + + CloseHandle(d->portHandle); + d->portHandle = INVALID_HANDLE_VALUE; +} + +VirtualSerialDevice::~VirtualSerialDevice() +{ + close(); + delete d; +} + +qint64 VirtualSerialDevice::bytesAvailable() const +{ + QMutexLocker locker(&lock); + if (!isOpen()) return 0; + + qint64 avail = 0; + COMSTAT Status; + if (ClearCommError(d->portHandle, NULL, &Status)) { + avail = Status.cbInQue; + } + return avail + QIODevice::bytesAvailable(); +} + +void VirtualSerialDevice::commEventOccurred() +{ + DWORD event = d->commEventMask; + if (event & EV_RXCHAR) { + emit readyRead(); + } + ResetEvent(d->commEventOverlapped.hEvent); + WaitCommEvent(d->portHandle, &d->commEventMask, &d->commEventOverlapped); +} + +qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize) +{ + QMutexLocker locker(&lock); + // We do our reads synchronously + OVERLAPPED readOverlapped; + memset(&readOverlapped, 0, sizeof(OVERLAPPED)); + DWORD bytesRead; + BOOL done = ReadFile(d->portHandle, data, maxSize, &bytesRead, &readOverlapped); + if (done) return (qint64)bytesRead; + + if (GetLastError() == ERROR_IO_PENDING) { + // Note the TRUE to wait for the read to complete + done = GetOverlappedResult(d->portHandle, &readOverlapped, &bytesRead, TRUE); + if (done) return (qint64)bytesRead; + } + + // If we reach here an error has occurred + setErrorString(tr("An error occurred while reading from %1: %2"). + arg(portName, winErrorMessage(GetLastError()))); + return -1; +} + + +qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize) +{ + QMutexLocker locker(&lock); + + pendingWrites.append(QByteArray(data, maxSize)); // Can't see a way of doing async io safely without having to copy here... + if (pendingWrites.count() == 1) { + return writeNextBuffer(locker); + } else { + return maxSize; + } +} + +qint64 VirtualSerialDevice::writeNextBuffer(QMutexLocker& locker) +{ + Q_UNUSED(locker) + // Must be locked on entry + qint64 bufLen = pendingWrites[0].length(); + BOOL ok = WriteFile(d->portHandle, pendingWrites[0].constData(), bufLen, NULL, &d->writeOverlapped); + if (ok || GetLastError() == ERROR_IO_PENDING) { + // Apparently it can return true for a small asynchronous write... + // Hopefully it still gets signalled in the same way! + + // Wait for signal via writeCompleted + return bufLen; + } + else { + setErrorString(tr("An error occurred while writing to %1: %2"). + arg(portName, winErrorMessage(GetLastError()))); + pendingWrites.removeFirst(); + return -1; + } +} + +void VirtualSerialDevice::writeCompleted() +{ + QMutexLocker locker(&lock); + if (pendingWrites.count() == 0) { + qWarning("%s: writeCompleted called when there are no pending writes on %s!", + Q_FUNC_INFO, qPrintable(portName)); + return; + } + + doWriteCompleted(locker); +} + +void VirtualSerialDevice::doWriteCompleted(QMutexLocker &locker) +{ + // Must be locked on entry + ResetEvent(d->writeOverlapped.hEvent); + + qint64 len = pendingWrites.first().length(); + pendingWrites.removeFirst(); + + if (pendingWrites.count() > 0) { + // Get the next write started before notifying in case client calls waitForBytesWritten in their slot + writeNextBuffer(locker); + } + + emitBytesWrittenIfNeeded(locker, len); +} + +bool VirtualSerialDevice::waitForBytesWritten(int msecs) +{ + QMutexLocker locker(&lock); + if (pendingWrites.count() == 0) return false; + + if (QThread::currentThread() != thread()) { + // Wait for signal from main thread + unsigned long timeout = msecs; + if (msecs == -1) timeout = ULONG_MAX; + if (waiterForBytesWritten == NULL) + waiterForBytesWritten = new QWaitCondition; + return waiterForBytesWritten->wait(&lock, timeout); + } + + DWORD waitTime = msecs; + if (msecs == -1) waitTime = INFINITE; // Ok these are probably bitwise the same, but just to prove I've thought about it... + DWORD result = WaitForSingleObject(d->writeOverlapped.hEvent, waitTime); // Do I need WaitForSingleObjectEx and worry about alertable states? + if (result == WAIT_TIMEOUT) { + return false; + } + else if (result == WAIT_OBJECT_0) { + DWORD bytesWritten; + BOOL ok = GetOverlappedResult(d->portHandle, &d->writeOverlapped, &bytesWritten, TRUE); + if (!ok) { + setErrorString(tr("An error occurred while syncing on waitForBytesWritten for %1: %2"). + arg(portName, winErrorMessage(GetLastError()))); + return false; + } + Q_ASSERT(bytesWritten == (DWORD)pendingWrites.first().length()); + + doWriteCompleted(locker); + return true; + } + else { + setErrorString(QString("An error occurred in waitForBytesWritten() for %1: %2"). + arg(portName, winErrorMessage(GetLastError()))); + return false; + } +} + +void VirtualSerialDevice::flush() +{ + while (waitForBytesWritten(-1)) { /* loop */ } +} + +bool VirtualSerialDevice::waitForReadyRead(int msecs) +{ + return QIODevice::waitForReadyRead(msecs); //TODO +} + +} // namespace SymbianUtils diff --git a/tools/runonphone/trksignalhandler.cpp b/tools/runonphone/trksignalhandler.cpp index 062501a..52de3c8 100644 --- a/tools/runonphone/trksignalhandler.cpp +++ b/tools/runonphone/trksignalhandler.cpp @@ -77,10 +77,10 @@ private: bool terminateNeeded; }; -void TrkSignalHandler::copyingStarted() +void TrkSignalHandler::copyingStarted(const QString &fileName) { if (d->loglevel > 0) - d->out << "Copying..." << endl; + d->out << "Copying " << fileName << "..." << endl; } void TrkSignalHandler::canNotConnect(const QString &errorMessage) @@ -103,10 +103,10 @@ void TrkSignalHandler::canNotCloseFile(const QString &filename, const QString &e d->err << "Cannot close file (" << filename << ") - " << errorMessage << endl; } -void TrkSignalHandler::installingStarted() +void TrkSignalHandler::installingStarted(const QString &packageName) { if (d->loglevel > 0) - d->out << "Installing..." << endl; + d->out << "Installing " << packageName << "..." << endl; } void TrkSignalHandler::canNotInstall(const QString &packageFilename, const QString &errorMessage) diff --git a/tools/runonphone/trksignalhandler.h b/tools/runonphone/trksignalhandler.h index 5c76b19..e551c34 100644 --- a/tools/runonphone/trksignalhandler.h +++ b/tools/runonphone/trksignalhandler.h @@ -50,12 +50,12 @@ class TrkSignalHandler : public QObject { Q_OBJECT public slots: - void copyingStarted(); + void copyingStarted(const QString &fileName); void canNotConnect(const QString &errorMessage); void canNotCreateFile(const QString &filename, const QString &errorMessage); void canNotWriteFile(const QString &filename, const QString &errorMessage); void canNotCloseFile(const QString &filename, const QString &errorMessage); - void installingStarted(); + void installingStarted(const QString &packageName); void canNotInstall(const QString &packageFilename, const QString &errorMessage); void installingFinished(); void startingApplication(); diff --git a/tools/shared/qtpropertybrowser/qtpropertybrowserutils.pri b/tools/shared/qtpropertybrowser/qtpropertybrowserutils.pri new file mode 100644 index 0000000..1755448 --- /dev/null +++ b/tools/shared/qtpropertybrowser/qtpropertybrowserutils.pri @@ -0,0 +1,4 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +SOURCES += $$PWD/qtpropertybrowserutils.cpp +HEADERS += $$PWD/qtpropertybrowserutils_p.h diff --git a/tools/shared/qtpropertybrowser/qtvariantproperty.cpp b/tools/shared/qtpropertybrowser/qtvariantproperty.cpp index 7a17e34..c9626c3 100644 --- a/tools/shared/qtpropertybrowser/qtvariantproperty.cpp +++ b/tools/shared/qtpropertybrowser/qtvariantproperty.cpp @@ -549,7 +549,7 @@ void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, con void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QKeySequence &val) { QVariant v; - qVariantSetValue(v, val); + v.setValue(val); valueChanged(property, v); } @@ -636,7 +636,7 @@ void QtVariantPropertyManagerPrivate::slotEnumIconsChanged(QtProperty *property, { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { QVariant v; - qVariantSetValue(v, enumIcons); + v.setValue(enumIcons); emit q_ptr->attributeChanged(varProp, m_enumIconsAttribute, v); } } @@ -1488,7 +1488,7 @@ QVariant QtVariantPropertyManager::attributeValue(const QtProperty *property, co return enumManager->enumNames(internProp); if (attribute == d_ptr->m_enumIconsAttribute) { QVariant v; - qVariantSetValue(v, enumManager->enumIcons(internProp)); + v.setValue(enumManager->enumIcons(internProp)); return v; } return QVariant(); @@ -1568,73 +1568,73 @@ void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &va QtAbstractPropertyManager *manager = internProp->propertyManager(); if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) { - intManager->setValue(internProp, qVariantValue<int>(val)); + intManager->setValue(internProp, qvariant_cast<int>(val)); return; } else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) { - doubleManager->setValue(internProp, qVariantValue<double>(val)); + doubleManager->setValue(internProp, qvariant_cast<double>(val)); return; } else if (QtBoolPropertyManager *boolManager = qobject_cast<QtBoolPropertyManager *>(manager)) { - boolManager->setValue(internProp, qVariantValue<bool>(val)); + boolManager->setValue(internProp, qvariant_cast<bool>(val)); return; } else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) { - stringManager->setValue(internProp, qVariantValue<QString>(val)); + stringManager->setValue(internProp, qvariant_cast<QString>(val)); return; } else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) { - dateManager->setValue(internProp, qVariantValue<QDate>(val)); + dateManager->setValue(internProp, qvariant_cast<QDate>(val)); return; } else if (QtTimePropertyManager *timeManager = qobject_cast<QtTimePropertyManager *>(manager)) { - timeManager->setValue(internProp, qVariantValue<QTime>(val)); + timeManager->setValue(internProp, qvariant_cast<QTime>(val)); return; } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast<QtDateTimePropertyManager *>(manager)) { - dateTimeManager->setValue(internProp, qVariantValue<QDateTime>(val)); + dateTimeManager->setValue(internProp, qvariant_cast<QDateTime>(val)); return; } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast<QtKeySequencePropertyManager *>(manager)) { - keySequenceManager->setValue(internProp, qVariantValue<QKeySequence>(val)); + keySequenceManager->setValue(internProp, qvariant_cast<QKeySequence>(val)); return; } else if (QtCharPropertyManager *charManager = qobject_cast<QtCharPropertyManager *>(manager)) { - charManager->setValue(internProp, qVariantValue<QChar>(val)); + charManager->setValue(internProp, qvariant_cast<QChar>(val)); return; } else if (QtLocalePropertyManager *localeManager = qobject_cast<QtLocalePropertyManager *>(manager)) { - localeManager->setValue(internProp, qVariantValue<QLocale>(val)); + localeManager->setValue(internProp, qvariant_cast<QLocale>(val)); return; } else if (QtPointPropertyManager *pointManager = qobject_cast<QtPointPropertyManager *>(manager)) { - pointManager->setValue(internProp, qVariantValue<QPoint>(val)); + pointManager->setValue(internProp, qvariant_cast<QPoint>(val)); return; } else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) { - pointFManager->setValue(internProp, qVariantValue<QPointF>(val)); + pointFManager->setValue(internProp, qvariant_cast<QPointF>(val)); return; } else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) { - sizeManager->setValue(internProp, qVariantValue<QSize>(val)); + sizeManager->setValue(internProp, qvariant_cast<QSize>(val)); return; } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) { - sizeFManager->setValue(internProp, qVariantValue<QSizeF>(val)); + sizeFManager->setValue(internProp, qvariant_cast<QSizeF>(val)); return; } else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) { - rectManager->setValue(internProp, qVariantValue<QRect>(val)); + rectManager->setValue(internProp, qvariant_cast<QRect>(val)); return; } else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) { - rectFManager->setValue(internProp, qVariantValue<QRectF>(val)); + rectFManager->setValue(internProp, qvariant_cast<QRectF>(val)); return; } else if (QtColorPropertyManager *colorManager = qobject_cast<QtColorPropertyManager *>(manager)) { - colorManager->setValue(internProp, qVariantValue<QColor>(val)); + colorManager->setValue(internProp, qvariant_cast<QColor>(val)); return; } else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) { - enumManager->setValue(internProp, qVariantValue<int>(val)); + enumManager->setValue(internProp, qvariant_cast<int>(val)); return; } else if (QtSizePolicyPropertyManager *sizePolicyManager = qobject_cast<QtSizePolicyPropertyManager *>(manager)) { - sizePolicyManager->setValue(internProp, qVariantValue<QSizePolicy>(val)); + sizePolicyManager->setValue(internProp, qvariant_cast<QSizePolicy>(val)); return; } else if (QtFontPropertyManager *fontManager = qobject_cast<QtFontPropertyManager *>(manager)) { - fontManager->setValue(internProp, qVariantValue<QFont>(val)); + fontManager->setValue(internProp, qvariant_cast<QFont>(val)); return; #ifndef QT_NO_CURSOR } else if (QtCursorPropertyManager *cursorManager = qobject_cast<QtCursorPropertyManager *>(manager)) { - cursorManager->setValue(internProp, qVariantValue<QCursor>(val)); + cursorManager->setValue(internProp, qvariant_cast<QCursor>(val)); return; #endif } else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) { - flagManager->setValue(internProp, qVariantValue<int>(val)); + flagManager->setValue(internProp, qvariant_cast<int>(val)); return; } } @@ -1672,69 +1672,69 @@ void QtVariantPropertyManager::setAttribute(QtProperty *property, QtAbstractPropertyManager *manager = internProp->propertyManager(); if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - intManager->setMaximum(internProp, qVariantValue<int>(value)); + intManager->setMaximum(internProp, qvariant_cast<int>(value)); else if (attribute == d_ptr->m_minimumAttribute) - intManager->setMinimum(internProp, qVariantValue<int>(value)); + intManager->setMinimum(internProp, qvariant_cast<int>(value)); else if (attribute == d_ptr->m_singleStepAttribute) - intManager->setSingleStep(internProp, qVariantValue<int>(value)); + intManager->setSingleStep(internProp, qvariant_cast<int>(value)); return; } else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - doubleManager->setMaximum(internProp, qVariantValue<double>(value)); + doubleManager->setMaximum(internProp, qvariant_cast<double>(value)); if (attribute == d_ptr->m_minimumAttribute) - doubleManager->setMinimum(internProp, qVariantValue<double>(value)); + doubleManager->setMinimum(internProp, qvariant_cast<double>(value)); if (attribute == d_ptr->m_singleStepAttribute) - doubleManager->setSingleStep(internProp, qVariantValue<double>(value)); + doubleManager->setSingleStep(internProp, qvariant_cast<double>(value)); if (attribute == d_ptr->m_decimalsAttribute) - doubleManager->setDecimals(internProp, qVariantValue<int>(value)); + doubleManager->setDecimals(internProp, qvariant_cast<int>(value)); return; } else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) { if (attribute == d_ptr->m_regExpAttribute) - stringManager->setRegExp(internProp, qVariantValue<QRegExp>(value)); + stringManager->setRegExp(internProp, qvariant_cast<QRegExp>(value)); return; } else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - dateManager->setMaximum(internProp, qVariantValue<QDate>(value)); + dateManager->setMaximum(internProp, qvariant_cast<QDate>(value)); if (attribute == d_ptr->m_minimumAttribute) - dateManager->setMinimum(internProp, qVariantValue<QDate>(value)); + dateManager->setMinimum(internProp, qvariant_cast<QDate>(value)); return; } else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) { if (attribute == d_ptr->m_decimalsAttribute) - pointFManager->setDecimals(internProp, qVariantValue<int>(value)); + pointFManager->setDecimals(internProp, qvariant_cast<int>(value)); return; } else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - sizeManager->setMaximum(internProp, qVariantValue<QSize>(value)); + sizeManager->setMaximum(internProp, qvariant_cast<QSize>(value)); if (attribute == d_ptr->m_minimumAttribute) - sizeManager->setMinimum(internProp, qVariantValue<QSize>(value)); + sizeManager->setMinimum(internProp, qvariant_cast<QSize>(value)); return; } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) { if (attribute == d_ptr->m_maximumAttribute) - sizeFManager->setMaximum(internProp, qVariantValue<QSizeF>(value)); + sizeFManager->setMaximum(internProp, qvariant_cast<QSizeF>(value)); if (attribute == d_ptr->m_minimumAttribute) - sizeFManager->setMinimum(internProp, qVariantValue<QSizeF>(value)); + sizeFManager->setMinimum(internProp, qvariant_cast<QSizeF>(value)); if (attribute == d_ptr->m_decimalsAttribute) - sizeFManager->setDecimals(internProp, qVariantValue<int>(value)); + sizeFManager->setDecimals(internProp, qvariant_cast<int>(value)); return; } else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) { if (attribute == d_ptr->m_constraintAttribute) - rectManager->setConstraint(internProp, qVariantValue<QRect>(value)); + rectManager->setConstraint(internProp, qvariant_cast<QRect>(value)); return; } else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) { if (attribute == d_ptr->m_constraintAttribute) - rectFManager->setConstraint(internProp, qVariantValue<QRectF>(value)); + rectFManager->setConstraint(internProp, qvariant_cast<QRectF>(value)); if (attribute == d_ptr->m_decimalsAttribute) - rectFManager->setDecimals(internProp, qVariantValue<int>(value)); + rectFManager->setDecimals(internProp, qvariant_cast<int>(value)); return; } else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) { if (attribute == d_ptr->m_enumNamesAttribute) - enumManager->setEnumNames(internProp, qVariantValue<QStringList>(value)); + enumManager->setEnumNames(internProp, qvariant_cast<QStringList>(value)); if (attribute == d_ptr->m_enumIconsAttribute) - enumManager->setEnumIcons(internProp, qVariantValue<QtIconMap>(value)); + enumManager->setEnumIcons(internProp, qvariant_cast<QtIconMap>(value)); return; } else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) { if (attribute == d_ptr->m_flagNamesAttribute) - flagManager->setFlagNames(internProp, qVariantValue<QStringList>(value)); + flagManager->setFlagNames(internProp, qvariant_cast<QStringList>(value)); return; } } @@ -1997,87 +1997,87 @@ QtVariantEditorFactory::~QtVariantEditorFactory() */ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager) { - QList<QtIntPropertyManager *> intPropertyManagers = qFindChildren<QtIntPropertyManager *>(manager); + QList<QtIntPropertyManager *> intPropertyManagers = manager->findChildren<QtIntPropertyManager *>(); QListIterator<QtIntPropertyManager *> itInt(intPropertyManagers); while (itInt.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itInt.next()); - QList<QtDoublePropertyManager *> doublePropertyManagers = qFindChildren<QtDoublePropertyManager *>(manager); + QList<QtDoublePropertyManager *> doublePropertyManagers = manager->findChildren<QtDoublePropertyManager *>(); QListIterator<QtDoublePropertyManager *> itDouble(doublePropertyManagers); while (itDouble.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itDouble.next()); - QList<QtBoolPropertyManager *> boolPropertyManagers = qFindChildren<QtBoolPropertyManager *>(manager); + QList<QtBoolPropertyManager *> boolPropertyManagers = manager->findChildren<QtBoolPropertyManager *>(); QListIterator<QtBoolPropertyManager *> itBool(boolPropertyManagers); while (itBool.hasNext()) d_ptr->m_checkBoxFactory->addPropertyManager(itBool.next()); - QList<QtStringPropertyManager *> stringPropertyManagers = qFindChildren<QtStringPropertyManager *>(manager); + QList<QtStringPropertyManager *> stringPropertyManagers = manager->findChildren<QtStringPropertyManager *>(); QListIterator<QtStringPropertyManager *> itString(stringPropertyManagers); while (itString.hasNext()) d_ptr->m_lineEditFactory->addPropertyManager(itString.next()); - QList<QtDatePropertyManager *> datePropertyManagers = qFindChildren<QtDatePropertyManager *>(manager); + QList<QtDatePropertyManager *> datePropertyManagers = manager->findChildren<QtDatePropertyManager *>(); QListIterator<QtDatePropertyManager *> itDate(datePropertyManagers); while (itDate.hasNext()) d_ptr->m_dateEditFactory->addPropertyManager(itDate.next()); - QList<QtTimePropertyManager *> timePropertyManagers = qFindChildren<QtTimePropertyManager *>(manager); + QList<QtTimePropertyManager *> timePropertyManagers = manager->findChildren<QtTimePropertyManager *>(); QListIterator<QtTimePropertyManager *> itTime(timePropertyManagers); while (itTime.hasNext()) d_ptr->m_timeEditFactory->addPropertyManager(itTime.next()); - QList<QtDateTimePropertyManager *> dateTimePropertyManagers = qFindChildren<QtDateTimePropertyManager *>(manager); + QList<QtDateTimePropertyManager *> dateTimePropertyManagers = manager->findChildren<QtDateTimePropertyManager *>(); QListIterator<QtDateTimePropertyManager *> itDateTime(dateTimePropertyManagers); while (itDateTime.hasNext()) d_ptr->m_dateTimeEditFactory->addPropertyManager(itDateTime.next()); - QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = qFindChildren<QtKeySequencePropertyManager *>(manager); + QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = manager->findChildren<QtKeySequencePropertyManager *>(); QListIterator<QtKeySequencePropertyManager *> itKeySequence(keySequencePropertyManagers); while (itKeySequence.hasNext()) d_ptr->m_keySequenceEditorFactory->addPropertyManager(itKeySequence.next()); - QList<QtCharPropertyManager *> charPropertyManagers = qFindChildren<QtCharPropertyManager *>(manager); + QList<QtCharPropertyManager *> charPropertyManagers = manager->findChildren<QtCharPropertyManager *>(); QListIterator<QtCharPropertyManager *> itChar(charPropertyManagers); while (itChar.hasNext()) d_ptr->m_charEditorFactory->addPropertyManager(itChar.next()); - QList<QtLocalePropertyManager *> localePropertyManagers = qFindChildren<QtLocalePropertyManager *>(manager); + QList<QtLocalePropertyManager *> localePropertyManagers = manager->findChildren<QtLocalePropertyManager *>(); QListIterator<QtLocalePropertyManager *> itLocale(localePropertyManagers); while (itLocale.hasNext()) d_ptr->m_comboBoxFactory->addPropertyManager(itLocale.next()->subEnumPropertyManager()); - QList<QtPointPropertyManager *> pointPropertyManagers = qFindChildren<QtPointPropertyManager *>(manager); + QList<QtPointPropertyManager *> pointPropertyManagers = manager->findChildren<QtPointPropertyManager *>(); QListIterator<QtPointPropertyManager *> itPoint(pointPropertyManagers); while (itPoint.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itPoint.next()->subIntPropertyManager()); - QList<QtPointFPropertyManager *> pointFPropertyManagers = qFindChildren<QtPointFPropertyManager *>(manager); + QList<QtPointFPropertyManager *> pointFPropertyManagers = manager->findChildren<QtPointFPropertyManager *>(); QListIterator<QtPointFPropertyManager *> itPointF(pointFPropertyManagers); while (itPointF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itPointF.next()->subDoublePropertyManager()); - QList<QtSizePropertyManager *> sizePropertyManagers = qFindChildren<QtSizePropertyManager *>(manager); + QList<QtSizePropertyManager *> sizePropertyManagers = manager->findChildren<QtSizePropertyManager *>(); QListIterator<QtSizePropertyManager *> itSize(sizePropertyManagers); while (itSize.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itSize.next()->subIntPropertyManager()); - QList<QtSizeFPropertyManager *> sizeFPropertyManagers = qFindChildren<QtSizeFPropertyManager *>(manager); + QList<QtSizeFPropertyManager *> sizeFPropertyManagers = manager->findChildren<QtSizeFPropertyManager *>(); QListIterator<QtSizeFPropertyManager *> itSizeF(sizeFPropertyManagers); while (itSizeF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itSizeF.next()->subDoublePropertyManager()); - QList<QtRectPropertyManager *> rectPropertyManagers = qFindChildren<QtRectPropertyManager *>(manager); + QList<QtRectPropertyManager *> rectPropertyManagers = manager->findChildren<QtRectPropertyManager *>(); QListIterator<QtRectPropertyManager *> itRect(rectPropertyManagers); while (itRect.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itRect.next()->subIntPropertyManager()); - QList<QtRectFPropertyManager *> rectFPropertyManagers = qFindChildren<QtRectFPropertyManager *>(manager); + QList<QtRectFPropertyManager *> rectFPropertyManagers = manager->findChildren<QtRectFPropertyManager *>(); QListIterator<QtRectFPropertyManager *> itRectF(rectFPropertyManagers); while (itRectF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itRectF.next()->subDoublePropertyManager()); - QList<QtColorPropertyManager *> colorPropertyManagers = qFindChildren<QtColorPropertyManager *>(manager); + QList<QtColorPropertyManager *> colorPropertyManagers = manager->findChildren<QtColorPropertyManager *>(); QListIterator<QtColorPropertyManager *> itColor(colorPropertyManagers); while (itColor.hasNext()) { QtColorPropertyManager *manager = itColor.next(); @@ -2085,12 +2085,12 @@ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *ma d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); } - QList<QtEnumPropertyManager *> enumPropertyManagers = qFindChildren<QtEnumPropertyManager *>(manager); + QList<QtEnumPropertyManager *> enumPropertyManagers = manager->findChildren<QtEnumPropertyManager *>(); QListIterator<QtEnumPropertyManager *> itEnum(enumPropertyManagers); while (itEnum.hasNext()) d_ptr->m_comboBoxFactory->addPropertyManager(itEnum.next()); - QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = qFindChildren<QtSizePolicyPropertyManager *>(manager); + QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = manager->findChildren<QtSizePolicyPropertyManager *>(); QListIterator<QtSizePolicyPropertyManager *> itSizePolicy(sizePolicyPropertyManagers); while (itSizePolicy.hasNext()) { QtSizePolicyPropertyManager *manager = itSizePolicy.next(); @@ -2098,7 +2098,7 @@ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *ma d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager()); } - QList<QtFontPropertyManager *> fontPropertyManagers = qFindChildren<QtFontPropertyManager *>(manager); + QList<QtFontPropertyManager *> fontPropertyManagers = manager->findChildren<QtFontPropertyManager *>(); QListIterator<QtFontPropertyManager *> itFont(fontPropertyManagers); while (itFont.hasNext()) { QtFontPropertyManager *manager = itFont.next(); @@ -2108,12 +2108,12 @@ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *ma d_ptr->m_checkBoxFactory->addPropertyManager(manager->subBoolPropertyManager()); } - QList<QtCursorPropertyManager *> cursorPropertyManagers = qFindChildren<QtCursorPropertyManager *>(manager); + QList<QtCursorPropertyManager *> cursorPropertyManagers = manager->findChildren<QtCursorPropertyManager *>(); QListIterator<QtCursorPropertyManager *> itCursor(cursorPropertyManagers); while (itCursor.hasNext()) d_ptr->m_cursorEditorFactory->addPropertyManager(itCursor.next()); - QList<QtFlagPropertyManager *> flagPropertyManagers = qFindChildren<QtFlagPropertyManager *>(manager); + QList<QtFlagPropertyManager *> flagPropertyManagers = manager->findChildren<QtFlagPropertyManager *>(); QListIterator<QtFlagPropertyManager *> itFlag(flagPropertyManagers); while (itFlag.hasNext()) d_ptr->m_checkBoxFactory->addPropertyManager(itFlag.next()->subBoolPropertyManager()); @@ -2141,87 +2141,87 @@ QWidget *QtVariantEditorFactory::createEditor(QtVariantPropertyManager *manager, */ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager) { - QList<QtIntPropertyManager *> intPropertyManagers = qFindChildren<QtIntPropertyManager *>(manager); + QList<QtIntPropertyManager *> intPropertyManagers = manager->findChildren<QtIntPropertyManager *>(); QListIterator<QtIntPropertyManager *> itInt(intPropertyManagers); while (itInt.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itInt.next()); - QList<QtDoublePropertyManager *> doublePropertyManagers = qFindChildren<QtDoublePropertyManager *>(manager); + QList<QtDoublePropertyManager *> doublePropertyManagers = manager->findChildren<QtDoublePropertyManager *>(); QListIterator<QtDoublePropertyManager *> itDouble(doublePropertyManagers); while (itDouble.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itDouble.next()); - QList<QtBoolPropertyManager *> boolPropertyManagers = qFindChildren<QtBoolPropertyManager *>(manager); + QList<QtBoolPropertyManager *> boolPropertyManagers = manager->findChildren<QtBoolPropertyManager *>(); QListIterator<QtBoolPropertyManager *> itBool(boolPropertyManagers); while (itBool.hasNext()) d_ptr->m_checkBoxFactory->removePropertyManager(itBool.next()); - QList<QtStringPropertyManager *> stringPropertyManagers = qFindChildren<QtStringPropertyManager *>(manager); + QList<QtStringPropertyManager *> stringPropertyManagers = manager->findChildren<QtStringPropertyManager *>(); QListIterator<QtStringPropertyManager *> itString(stringPropertyManagers); while (itString.hasNext()) d_ptr->m_lineEditFactory->removePropertyManager(itString.next()); - QList<QtDatePropertyManager *> datePropertyManagers = qFindChildren<QtDatePropertyManager *>(manager); + QList<QtDatePropertyManager *> datePropertyManagers = manager->findChildren<QtDatePropertyManager *>(); QListIterator<QtDatePropertyManager *> itDate(datePropertyManagers); while (itDate.hasNext()) d_ptr->m_dateEditFactory->removePropertyManager(itDate.next()); - QList<QtTimePropertyManager *> timePropertyManagers = qFindChildren<QtTimePropertyManager *>(manager); + QList<QtTimePropertyManager *> timePropertyManagers = manager->findChildren<QtTimePropertyManager *>(); QListIterator<QtTimePropertyManager *> itTime(timePropertyManagers); while (itTime.hasNext()) d_ptr->m_timeEditFactory->removePropertyManager(itTime.next()); - QList<QtDateTimePropertyManager *> dateTimePropertyManagers = qFindChildren<QtDateTimePropertyManager *>(manager); + QList<QtDateTimePropertyManager *> dateTimePropertyManagers = manager->findChildren<QtDateTimePropertyManager *>(); QListIterator<QtDateTimePropertyManager *> itDateTime(dateTimePropertyManagers); while (itDateTime.hasNext()) d_ptr->m_dateTimeEditFactory->removePropertyManager(itDateTime.next()); - QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = qFindChildren<QtKeySequencePropertyManager *>(manager); + QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = manager->findChildren<QtKeySequencePropertyManager *>(); QListIterator<QtKeySequencePropertyManager *> itKeySequence(keySequencePropertyManagers); while (itKeySequence.hasNext()) d_ptr->m_keySequenceEditorFactory->removePropertyManager(itKeySequence.next()); - QList<QtCharPropertyManager *> charPropertyManagers = qFindChildren<QtCharPropertyManager *>(manager); + QList<QtCharPropertyManager *> charPropertyManagers = manager->findChildren<QtCharPropertyManager *>(); QListIterator<QtCharPropertyManager *> itChar(charPropertyManagers); while (itChar.hasNext()) d_ptr->m_charEditorFactory->removePropertyManager(itChar.next()); - QList<QtLocalePropertyManager *> localePropertyManagers = qFindChildren<QtLocalePropertyManager *>(manager); + QList<QtLocalePropertyManager *> localePropertyManagers = manager->findChildren<QtLocalePropertyManager *>(); QListIterator<QtLocalePropertyManager *> itLocale(localePropertyManagers); while (itLocale.hasNext()) d_ptr->m_comboBoxFactory->removePropertyManager(itLocale.next()->subEnumPropertyManager()); - QList<QtPointPropertyManager *> pointPropertyManagers = qFindChildren<QtPointPropertyManager *>(manager); + QList<QtPointPropertyManager *> pointPropertyManagers = manager->findChildren<QtPointPropertyManager *>(); QListIterator<QtPointPropertyManager *> itPoint(pointPropertyManagers); while (itPoint.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itPoint.next()->subIntPropertyManager()); - QList<QtPointFPropertyManager *> pointFPropertyManagers = qFindChildren<QtPointFPropertyManager *>(manager); + QList<QtPointFPropertyManager *> pointFPropertyManagers = manager->findChildren<QtPointFPropertyManager *>(); QListIterator<QtPointFPropertyManager *> itPointF(pointFPropertyManagers); while (itPointF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itPointF.next()->subDoublePropertyManager()); - QList<QtSizePropertyManager *> sizePropertyManagers = qFindChildren<QtSizePropertyManager *>(manager); + QList<QtSizePropertyManager *> sizePropertyManagers = manager->findChildren<QtSizePropertyManager *>(); QListIterator<QtSizePropertyManager *> itSize(sizePropertyManagers); while (itSize.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itSize.next()->subIntPropertyManager()); - QList<QtSizeFPropertyManager *> sizeFPropertyManagers = qFindChildren<QtSizeFPropertyManager *>(manager); + QList<QtSizeFPropertyManager *> sizeFPropertyManagers = manager->findChildren<QtSizeFPropertyManager *>(); QListIterator<QtSizeFPropertyManager *> itSizeF(sizeFPropertyManagers); while (itSizeF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itSizeF.next()->subDoublePropertyManager()); - QList<QtRectPropertyManager *> rectPropertyManagers = qFindChildren<QtRectPropertyManager *>(manager); + QList<QtRectPropertyManager *> rectPropertyManagers = manager->findChildren<QtRectPropertyManager *>(); QListIterator<QtRectPropertyManager *> itRect(rectPropertyManagers); while (itRect.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itRect.next()->subIntPropertyManager()); - QList<QtRectFPropertyManager *> rectFPropertyManagers = qFindChildren<QtRectFPropertyManager *>(manager); + QList<QtRectFPropertyManager *> rectFPropertyManagers = manager->findChildren<QtRectFPropertyManager *>(); QListIterator<QtRectFPropertyManager *> itRectF(rectFPropertyManagers); while (itRectF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itRectF.next()->subDoublePropertyManager()); - QList<QtColorPropertyManager *> colorPropertyManagers = qFindChildren<QtColorPropertyManager *>(manager); + QList<QtColorPropertyManager *> colorPropertyManagers = manager->findChildren<QtColorPropertyManager *>(); QListIterator<QtColorPropertyManager *> itColor(colorPropertyManagers); while (itColor.hasNext()) { QtColorPropertyManager *manager = itColor.next(); @@ -2229,12 +2229,12 @@ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); } - QList<QtEnumPropertyManager *> enumPropertyManagers = qFindChildren<QtEnumPropertyManager *>(manager); + QList<QtEnumPropertyManager *> enumPropertyManagers = manager->findChildren<QtEnumPropertyManager *>(); QListIterator<QtEnumPropertyManager *> itEnum(enumPropertyManagers); while (itEnum.hasNext()) d_ptr->m_comboBoxFactory->removePropertyManager(itEnum.next()); - QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = qFindChildren<QtSizePolicyPropertyManager *>(manager); + QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = manager->findChildren<QtSizePolicyPropertyManager *>(); QListIterator<QtSizePolicyPropertyManager *> itSizePolicy(sizePolicyPropertyManagers); while (itSizePolicy.hasNext()) { QtSizePolicyPropertyManager *manager = itSizePolicy.next(); @@ -2242,7 +2242,7 @@ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager()); } - QList<QtFontPropertyManager *> fontPropertyManagers = qFindChildren<QtFontPropertyManager *>(manager); + QList<QtFontPropertyManager *> fontPropertyManagers = manager->findChildren<QtFontPropertyManager *>(); QListIterator<QtFontPropertyManager *> itFont(fontPropertyManagers); while (itFont.hasNext()) { QtFontPropertyManager *manager = itFont.next(); @@ -2252,12 +2252,12 @@ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager d_ptr->m_checkBoxFactory->removePropertyManager(manager->subBoolPropertyManager()); } - QList<QtCursorPropertyManager *> cursorPropertyManagers = qFindChildren<QtCursorPropertyManager *>(manager); + QList<QtCursorPropertyManager *> cursorPropertyManagers = manager->findChildren<QtCursorPropertyManager *>(); QListIterator<QtCursorPropertyManager *> itCursor(cursorPropertyManagers); while (itCursor.hasNext()) d_ptr->m_cursorEditorFactory->removePropertyManager(itCursor.next()); - QList<QtFlagPropertyManager *> flagPropertyManagers = qFindChildren<QtFlagPropertyManager *>(manager); + QList<QtFlagPropertyManager *> flagPropertyManagers = manager->findChildren<QtFlagPropertyManager *>(); QListIterator<QtFlagPropertyManager *> itFlag(flagPropertyManagers); while (itFlag.hasNext()) d_ptr->m_checkBoxFactory->removePropertyManager(itFlag.next()->subBoolPropertyManager()); diff --git a/tools/tools.pro b/tools/tools.pro index 8f23fe4..b23df4b 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -20,10 +20,13 @@ TEMPLATE = subdirs SUBDIRS += designer } } - unix:!mac:!embedded:contains(QT_CONFIG, qt3support):SUBDIRS += qtconfig - win32:!wince*:SUBDIRS += activeqt + unix:!symbian:!mac:!embedded:!qpa:SUBDIRS += qtconfig + win32:!wince*:!win32-g++*:SUBDIRS += activeqt + } + contains(QT_CONFIG, declarative) { + SUBDIRS += qml + !symbian: SUBDIRS += qmlplugindump } - contains(QT_CONFIG, declarative):SUBDIRS += qml } !wince*:!symbian:SUBDIRS += linguist diff --git a/tools/xmlpatterns/main.cpp b/tools/xmlpatterns/main.cpp index 4619ac1..d9ccf21 100644 --- a/tools/xmlpatterns/main.cpp +++ b/tools/xmlpatterns/main.cpp @@ -145,14 +145,14 @@ protected: } /* The value.isNull() check ensures we can bind variables whose value is an empty string. */ - return qVariantFromValue(Parameter(name, value.isNull() ? QString(QLatin1String("")) : value )); + return QVariant::fromValue(Parameter(name, value.isNull() ? QString(QLatin1String("")) : value )); } else if(arg.name() == QLatin1String("output")) { QFile *const f = new QFile(input); if(f->open(QIODevice::WriteOnly)) - return qVariantFromValue(static_cast<QIODevice *>(f)); + return QVariant::fromValue(static_cast<QIODevice *>(f)); else { message(QXmlPatternistCLI::tr("Failed to open file %1 for writing: %2").arg(f->fileName(), f->errorString())); @@ -168,7 +168,7 @@ protected: return QVariant(); } else - return qVariantFromValue(name); + return QVariant::fromValue(name); } else return QApplicationArgumentParser::convertToValue(arg, input); @@ -200,7 +200,7 @@ protected: out->open(stdout, QIODevice::WriteOnly); #endif - return qVariantFromValue(static_cast<QIODevice *>(out)); + return QVariant::fromValue(static_cast<QIODevice *>(out)); } else return QApplicationArgumentParser::defaultValue(argument); @@ -317,7 +317,7 @@ int main(int argc, char **argv) QXmlQuery query(lang, namePool); - query.setInitialTemplateName(qVariantValue<QXmlName>(parser.value(initialTemplateName))); + query.setInitialTemplateName(qvariant_cast<QXmlName>(parser.value(initialTemplateName))); /* Bind external variables. */ { @@ -329,7 +329,7 @@ int main(int argc, char **argv) for(int i = 0; i < len; ++i) { - const Parameter p(qVariantValue<Parameter>(parameters.at(i))); + const Parameter p(qvariant_cast<Parameter>(parameters.at(i))); if(usedParameters.contains(p.first)) { @@ -359,7 +359,7 @@ int main(int argc, char **argv) query.setQuery(effectiveURI); - const QPatternist::AutoPtr<QIODevice> outDevice(qVariantValue<QIODevice *>(parser.value(output))); + const QPatternist::AutoPtr<QIODevice> outDevice(qvariant_cast<QIODevice *>(parser.value(output))); Q_ASSERT(outDevice); Q_ASSERT(outDevice->isWritable()); |