diff options
author | axis <qt-info@nokia.com> | 2010-02-16 11:53:07 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2010-02-16 11:53:07 (GMT) |
commit | 15b08dffc1354bc816b04901a7442679382b0935 (patch) | |
tree | 783af85b75f9de3ab10902c5ba66cf5e22b2fe61 /tools | |
parent | 9f5b02406f38fe02a27de7843b9f8a11232d2064 (diff) | |
parent | 9d174f13e48730ac06aa429e0f011a02b333025e (diff) | |
download | Qt-15b08dffc1354bc816b04901a7442679382b0935.zip Qt-15b08dffc1354bc816b04901a7442679382b0935.tar.gz Qt-15b08dffc1354bc816b04901a7442679382b0935.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-s60-public
Conflicts:
configure
mkspecs/common/symbian/symbian.conf
mkspecs/features/symbian/application_icon.prf
qmake/generators/makefile.cpp
qmake/generators/symbian/initprojectdeploy_symbian.cpp
qmake/generators/symbian/symmake.cpp
tools/assistant/tools/assistant/assistant.pro
Diffstat (limited to 'tools')
214 files changed, 14692 insertions, 11500 deletions
diff --git a/tools/assistant/assistant.pro b/tools/assistant/assistant.pro index 08d0d4b..97196b2 100644 --- a/tools/assistant/assistant.pro +++ b/tools/assistant/assistant.pro @@ -3,6 +3,4 @@ CONFIG += ordered SUBDIRS += lib/fulltextsearch \ lib \ - tools \ - compat \ - compat/lib \
\ No newline at end of file + tools diff --git a/tools/assistant/compat/Info_mac.plist b/tools/assistant/compat/Info_mac.plist deleted file mode 100644 index b1e6336..0000000 --- a/tools/assistant/compat/Info_mac.plist +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd"> -<plist version="0.9"> -<dict> - <key>CFBundleIconFile</key> - <string>@ICON@</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>????</string> - <key>CFBundleIdentifier</key> - <string>com.trolltech.assistant-compat</string> - <key>CFBundleExecutable</key> - <string>@EXECUTABLE@</string> -</dict> -</plist> diff --git a/tools/assistant/compat/assistant.icns b/tools/assistant/compat/assistant.icns Binary files differdeleted file mode 100644 index 6291dd3..0000000 --- a/tools/assistant/compat/assistant.icns +++ /dev/null diff --git a/tools/assistant/compat/assistant.ico b/tools/assistant/compat/assistant.ico Binary files differdeleted file mode 100644 index 9e1b83f..0000000 --- a/tools/assistant/compat/assistant.ico +++ /dev/null diff --git a/tools/assistant/compat/assistant.pro b/tools/assistant/compat/assistant.pro deleted file mode 100644 index e865d6b..0000000 --- a/tools/assistant/compat/assistant.pro +++ /dev/null @@ -1,84 +0,0 @@ -include($$QT_SOURCE_TREE/tools/shared/fontpanel/fontpanel.pri) - -TEMPLATE = app -LANGUAGE = C++ -TARGET = assistant_adp - -CONFIG += qt warn_on - -unix:contains(QT_CONFIG, dbus):QT += dbus - -build_all:!build_pass { - CONFIG -= build_all - CONFIG += release -} -QT += xml network - -PROJECTNAME = Assistant -DESTDIR = ../../../bin - -FORMS += helpdialog.ui \ - mainwindow.ui \ - tabbedbrowser.ui \ - topicchooser.ui - -SOURCES += main.cpp \ - helpwindow.cpp \ - topicchooser.cpp \ - docuparser.cpp \ - index.cpp \ - profile.cpp \ - config.cpp \ - helpdialog.cpp \ - mainwindow.cpp \ - tabbedbrowser.cpp \ - fontsettingsdialog.cpp - -HEADERS += helpwindow.h \ - topicchooser.h \ - docuparser.h \ - index.h \ - profile.h \ - helpdialog.h \ - mainwindow.h \ - tabbedbrowser.h \ - config.h \ - fontsettingsdialog.h - -RESOURCES += assistant.qrc - -contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE -DEFINES += QT_KEYWORDS -#DEFINES += QT_PALMTOPCENTER_DOCS - -win32 { - !wince*:LIBS += -lshell32 - RC_FILE = assistant.rc -} - -mac { - ICON = assistant.icns - TARGET = Assistant_adp - QMAKE_INFO_PLIST = Info_mac.plist -} - -target.path=$$[QT_INSTALL_BINS] -INSTALLS += target - -TRANSLATIONS = assistant_de.ts - -unix:!contains(QT_CONFIG, zlib):LIBS += -lz - -contains(CONFIG, static): { - win32 { - exists($$[QT_INSTALL_PLUGINS]/imageformats/qjpeg.lib) { - QTPLUGIN += qjpeg - DEFINES += USE_STATIC_JPEG_PLUGIN - } - } else { - exists($$[QT_INSTALL_PLUGINS]/imageformats/qjpeg.a) { - QTPLUGIN += qjpeg - DEFINES += USE_STATIC_JPEG_PLUGIN - } - } -} diff --git a/tools/assistant/compat/assistant.qrc b/tools/assistant/compat/assistant.qrc deleted file mode 100644 index dae1f48..0000000 --- a/tools/assistant/compat/assistant.qrc +++ /dev/null @@ -1,37 +0,0 @@ -<RCC> - <qresource prefix="/trolltech/assistant" > - <file>images/assistant-128.png</file> - <file>images/assistant.png</file> - <file>images/close.png</file> - <file>images/designer.png</file> - <file>images/linguist.png</file> - <file>images/mac/addtab.png</file> - <file>images/mac/book.png</file> - <file>images/mac/closetab.png</file> - <file>images/mac/editcopy.png</file> - <file>images/mac/find.png</file> - <file>images/mac/home.png</file> - <file>images/mac/next.png</file> - <file>images/mac/prev.png</file> - <file>images/mac/print.png</file> - <file>images/mac/synctoc.png</file> - <file>images/mac/whatsthis.png</file> - <file>images/mac/zoomin.png</file> - <file>images/mac/zoomout.png</file> - <file>images/qt.png</file> - <file>images/win/addtab.png</file> - <file>images/win/book.png</file> - <file>images/win/closetab.png</file> - <file>images/win/editcopy.png</file> - <file>images/win/find.png</file> - <file>images/win/home.png</file> - <file>images/win/next.png</file> - <file>images/win/previous.png</file> - <file>images/win/print.png</file> - <file>images/win/synctoc.png</file> - <file>images/win/whatsthis.png</file> - <file>images/win/zoomin.png</file> - <file>images/win/zoomout.png</file> - <file>images/wrap.png</file> - </qresource> -</RCC> diff --git a/tools/assistant/compat/assistant.rc b/tools/assistant/compat/assistant.rc deleted file mode 100644 index b4786ce..0000000 --- a/tools/assistant/compat/assistant.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "assistant.ico" diff --git a/tools/assistant/compat/compat.pro b/tools/assistant/compat/compat.pro deleted file mode 100644 index 1086f4c..0000000 --- a/tools/assistant/compat/compat.pro +++ /dev/null @@ -1,84 +0,0 @@ -include($$QT_SOURCE_TREE/tools/shared/fontpanel/fontpanel.pri) - -TEMPLATE = app -LANGUAGE = C++ -TARGET = assistant_adp - -CONFIG += qt warn_on - -unix:contains(QT_CONFIG, dbus):QT += dbus - -build_all:!build_pass { - CONFIG -= build_all - CONFIG += release -} -QT += xml network - -PROJECTNAME = Assistant -DESTDIR = ../../../bin - -FORMS += helpdialog.ui \ - mainwindow.ui \ - tabbedbrowser.ui \ - topicchooser.ui - -SOURCES += main.cpp \ - helpwindow.cpp \ - topicchooser.cpp \ - docuparser.cpp \ - index.cpp \ - profile.cpp \ - config.cpp \ - helpdialog.cpp \ - mainwindow.cpp \ - tabbedbrowser.cpp \ - fontsettingsdialog.cpp - -HEADERS += helpwindow.h \ - topicchooser.h \ - docuparser.h \ - index.h \ - profile.h \ - helpdialog.h \ - mainwindow.h \ - tabbedbrowser.h \ - config.h \ - fontsettingsdialog.h - -RESOURCES += assistant.qrc - -contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE -DEFINES += QT_KEYWORDS -#DEFINES += QT_PALMTOPCENTER_DOCS - -win32 { - LIBS += -lshell32 - RC_FILE = assistant.rc -} - -mac { - ICON = assistant.icns - TARGET = Assistant_adp -# QMAKE_INFO_PLIST = Info_mac.plist -} - -target.path=$$[QT_INSTALL_BINS] -INSTALLS += target - -TRANSLATIONS = assistant_de.ts - -unix:!contains(QT_CONFIG, zlib):LIBS += -lz - -contains(CONFIG, static): { - win32 { - exists($$[QT_INSTALL_PLUGINS]/imageformats/qjpeg.lib) { - QTPLUGIN += qjpeg - DEFINES += USE_STATIC_JPEG_PLUGIN - } - } else { - exists($$[QT_INSTALL_PLUGINS]/imageformats/qjpeg.a) { - QTPLUGIN += qjpeg - DEFINES += USE_STATIC_JPEG_PLUGIN - } - } -} diff --git a/tools/assistant/compat/config.cpp b/tools/assistant/compat/config.cpp deleted file mode 100644 index 1faef42..0000000 --- a/tools/assistant/compat/config.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "config.h" -#include "profile.h" -#include "docuparser.h" - -#include <QApplication> -#include <QDesktopWidget> -#include <QLibraryInfo> -#include <QFont> -#include <QFontInfo> -#include <QDir> -#include <QFile> -#include <QFileInfo> -#include <QSettings> -#include <QList> - -QT_BEGIN_NAMESPACE - -static Config *static_configuration = 0; - -inline QString getVersionString() -{ - return QString::number( (QT_VERSION >> 16) & 0xff ) - + QLatin1String(".") + QString::number( (QT_VERSION >> 8) & 0xff ); -} - -Config::Config() - : profil( 0 ), hideSidebar( false ), rebuildDocs(true) -{ - if( !static_configuration ) { - static_configuration = this; - } else { - qWarning( "Multiple configurations not allowed!" ); - } -} - -Config *Config::loadConfig(const QString &profileFileName) -{ - Config *config = new Config(); - - if (profileFileName.isEmpty()) { // no profile - if (!config->defaultProfileExists()) { - config->profil = Profile::createDefaultProfile(); - config->saveProfile(config->profil); - } else { - config->profil = new Profile(); - } - config->loadDefaultProfile(); - config->load(); - return config; - } - - QFile file(profileFileName); - if (!file.exists()) { - qWarning( "File does not exist: %s", qPrintable(profileFileName) ); - return 0; - } - DocuParser *parser = DocuParser::createParser( profileFileName ); - if (!parser) { - qWarning( "Failed to create parser for file: %s", qPrintable(profileFileName) ); - return 0; - } - if (parser->parserVersion() < DocuParser::Qt320) { - qWarning( "File does not contain profile information" ); - return 0; - } - DocuParser320 *profileParser = static_cast<DocuParser320*>(parser); - parser->parse(&file); - config->profil = profileParser->profile(); - if (!config->profil) { - qWarning( "Config::loadConfig(), no profile in: %s", qPrintable(profileFileName) ); - return 0; - } - config->profil->setProfileType(Profile::UserProfile); - config->profil->setDocuParser(profileParser); - config->load(); - return config; -} - -Config *Config::configuration() -{ - Q_ASSERT( static_configuration ); - return static_configuration; -} - -void Config::load() -{ - const QString key = getVersionString() + QLatin1String("/"); - - bool isDefaultProfile = profil->props[QLatin1String("name")] == QLatin1String("default"); - const QString pKey = isDefaultProfile ? QString::fromLatin1(QT_VERSION_STR) - : getVersionString(); - - const QString profkey = pKey + QLatin1String("/Profile/") + profil->props[QLatin1String("name")] + QLatin1String("/"); - - QSettings settings; - - home = profil->props[QLatin1String("startpage")];; - if (home.isEmpty() && isDefaultProfile) - home = QLibraryInfo::location(QLibraryInfo::DocumentationPath) + QLatin1String("/html/index.html"); - src = settings.value( profkey + QLatin1String("Source") ).toStringList(); - sideBar = settings.value( key + QLatin1String("SideBarPage") ).toInt(); - if (qApp->type() != QApplication::Tty) - winGeometry = settings.value(key + QLatin1String("windowGeometry")).toByteArray(); - - mainWinState = settings.value(key + QLatin1String("MainWindowState")).toByteArray(); - pointFntSize = settings.value(key + QLatin1String("FontSize"), qApp->font().pointSizeF()).toDouble(); - rebuildDocs = settings.value( key + QLatin1String("RebuildDocDB"), true ).toBool(); - - profileNames = settings.value( key + QLatin1String("Profile") ).toStringList(); - - m_fontSettings.windowFont = qVariantValue<QFont>(settings.value(key + QLatin1String("windowfont"), qApp->font())); - m_fontSettings.browserFont = qVariantValue<QFont>(settings.value(key + QLatin1String("browserfont"), qApp->font())); - m_fontSettings.useWindowFont = settings.value(key + QLatin1String("usewindowfont"), false).toBool(); - m_fontSettings.useBrowserFont = settings.value(key + QLatin1String("usebrowserfont"), false).toBool(); - m_fontSettings.windowWritingSystem = static_cast<QFontDatabase::WritingSystem>( - settings.value(key + QLatin1String("windowwritingsystem"), QFontDatabase::Latin).toInt()); - m_fontSettings.browserWritingSystem = static_cast<QFontDatabase::WritingSystem>( - settings.value(key + QLatin1String("browserwritingsystem"), QFontDatabase::Latin).toInt()); - - m_fontSettings.browserFont.setPointSizeF(pointFntSize); -} - -void Config::save() -{ - saveSettings(); - saveProfile( profil ); -} - -void Config::saveSettings() -{ - const QString key = getVersionString() + QLatin1String("/"); - - const QString pKey = (profil->props[QLatin1String("name")] == QLatin1String("default")) - ? QString::fromLatin1(QT_VERSION_STR) - : getVersionString(); - - const QString profkey = pKey + QLatin1String("/Profile/") + profil->props[QLatin1String("name")] + QLatin1String("/"); - - QSettings settings; - - settings.setValue( profkey + QLatin1String("Source"), src ); - settings.setValue( key + QLatin1String("SideBarPage"), sideBarPage() ); - if (qApp->type() != QApplication::Tty) - settings.setValue(key + QLatin1String("windowGeometry"), winGeometry); - - settings.setValue( key + QLatin1String("MainWindowState"), mainWinState ); - settings.setValue( key + QLatin1String("FontSize"), pointFntSize); - settings.setValue( key + QLatin1String("RebuildDocDB"), rebuildDocs ); - - settings.setValue(key + QLatin1String("windowfont"), m_fontSettings.windowFont); - settings.setValue(key + QLatin1String("browserfont"), m_fontSettings.browserFont); - settings.setValue(key + QLatin1String("usewindowfont"), m_fontSettings.useWindowFont); - settings.setValue(key + QLatin1String("usebrowserfont"), m_fontSettings.useBrowserFont); - settings.setValue(key + QLatin1String("windowwritingsystem"), m_fontSettings.windowWritingSystem); - settings.setValue(key + QLatin1String("browserwritingsystem"), m_fontSettings.browserWritingSystem); -} - -#ifdef ASSISTANT_DEBUG -static void dumpmap( const QMap<QString,QString> &m, const QString &header ) -{ - qDebug( header ); - QMap<QString,QString>::ConstIterator it = m.begin(); - while (it != m.end()) { - qDebug( " " + it.key() + ":\t\t" + *it ); - ++it; - } -} -#endif - -bool Config::defaultProfileExists() -{ - QSettings settings; - const QString profKey = QLatin1String(QT_VERSION_STR) + QLatin1String("/Profile/default/"); - - if (settings.contains(profKey + QLatin1String("DocFiles")) - && settings.contains(profKey + QLatin1String("Titles")) - && settings.contains(profKey + QLatin1String("ImageDirs"))) { - QStringList dcfs = settings.value(profKey + QLatin1String("DocFiles") ).toStringList(); - foreach (QString file, dcfs) { - if (file == Profile::storableFilePath(file)) - return true; - } - } - return false; -} - -void Config::loadDefaultProfile() -{ - QSettings settings; - const QString profKey = QLatin1String(QT_VERSION_STR) + QLatin1String("/Profile/default/"); - - if (!defaultProfileExists()) - return; - - // Override the defaults with settings in registry. - profil->icons.clear(); - profil->indexPages.clear(); - profil->imageDirs.clear(); - profil->docs.clear(); - profil->dcfTitles.clear(); - - QStringList titles = settings.value( profKey + QLatin1String("Titles") ).toStringList(); - QStringList iconLst = settings.value( profKey + QLatin1String("DocIcons") ).toStringList(); - QStringList indexLst = settings.value( profKey + QLatin1String("IndexPages") ).toStringList(); - QStringList imgDirLst = settings.value( profKey + QLatin1String("ImageDirs") ).toStringList(); - QStringList dcfs = settings.value( profKey + QLatin1String("DocFiles") ).toStringList(); - profil->props[QLatin1String("name")] = QLatin1String("default"); - - QString filePath; - QStringList::ConstIterator it = titles.constBegin(); - QStringList::ConstIterator iconIt = iconLst.constBegin(); - QStringList::ConstIterator indexIt = indexLst.constBegin(); - QStringList::ConstIterator imageIt = imgDirLst.constBegin(); - QStringList::ConstIterator dcfIt = dcfs.constBegin(); - while((it != titles.constEnd()) - && (iconIt != iconLst.constEnd()) - && (indexIt != indexLst.constEnd()) - && (imageIt != imgDirLst.constEnd()) - && (dcfIt != dcfs.constEnd())) { - profil->addDCFIcon( *it, *iconIt ); - profil->addDCFIndexPage(*it, Profile::loadableFilePath(*indexIt)); - profil->addDCFImageDir( *it, *imageIt ); - profil->addDCFTitle(Profile::loadableFilePath(*dcfIt), *it); - ++it, ++iconIt, ++indexIt, ++imageIt, ++dcfIt; - } -#if ASSISTANT_DEBUG - dumpmap( profil->icons, QLatin1String("Icons") ); - dumpmap( profil->indexPages, QLatin1String("IndexPages") ); - dumpmap( profil->imageDirs, QLatin1String("ImageDirs") ); - dumpmap( profil->dcfTitles, QLatin1String("dcfTitles") ); - qDebug( "Docfiles: \n " + profil->docs.join( "\n " ) ); -#endif -} - -void Config::saveProfile( Profile *profile ) -{ - if (profil->profileType() == Profile::UserProfile) - return; - - const QString key = (profile->props[QLatin1String("name")] == QLatin1String("default")) - ? QString::fromLatin1(QT_VERSION_STR) - : getVersionString(); - - const QString profKey = key + QLatin1String("/Profile/") + profile->props[QLatin1String("name")] + QLatin1String("/"); - - QString path = QLibraryInfo::location(QLibraryInfo::DocumentationPath).replace(QLatin1String("\\"), QLatin1String("/")); - QStringList indexes, icons, imgDirs, dcfs; - QStringList titles = profile->dcfTitles.keys(); - QStringList::ConstIterator it = titles.constBegin(); - QString filePath; - for ( ; it != titles.constEnd(); ++it ) { - - indexes << Profile::storableFilePath(profile->indexPages[*it]); - icons << profile->icons[*it]; - imgDirs << profile->imageDirs[*it]; - dcfs << Profile::storableFilePath(profile->dcfTitles[*it]); - } - - QSettings settings; - settings.setValue( profKey + QLatin1String("Titles"), titles ); - settings.setValue( profKey + QLatin1String("DocFiles"), dcfs ); - settings.setValue( profKey + QLatin1String("IndexPages"), indexes ); - settings.setValue( profKey + QLatin1String("DocIcons"), icons ); - settings.setValue( profKey + QLatin1String("ImageDirs"), imgDirs ); - -#if ASSISTANT_DEBUG - qDebug() << "Titles:\n - " << ((QStringList*)&titles)->join("\n - "); - qDebug() << "Docfiles:\n - " << dcfs.join("\n - " ); - qDebug() << "IndexPages:\n - " << indexes.join("\n - "); - qDebug() << "DocIcons:\n - " << icons.join("\n - " ); - qDebug() << "ImageDirs:\n - " << imgDirs.join("\n - " ); -#endif -} - -QStringList Config::mimePaths() -{ - static QStringList lst; - - if( lst.count() > 0 ) - return lst; - - for (QMap<QString,QString>::ConstIterator it = profil->dcfTitles.constBegin(); - it != profil->dcfTitles.constEnd(); ++it ) { - - // Mime source for .dcf file path - QFileInfo info( *it ); - QString dcfPath = info.absolutePath(); - if (!lst.contains(dcfPath)) - lst << dcfPath; - - // Image dir for .dcf - QString imgDir = QDir::toNativeSeparators( dcfPath + QDir::separator() - + profil->imageDirs[it.key()] ); - if (!lst.contains(imgDir)) - lst << imgDir; - } - return lst; -} - -QStringList Config::profiles() const -{ - return profileNames; -} - -QString Config::title() const -{ - QString s = profil->props[QLatin1String("title")]; - if (s.isEmpty()) - s = QObject::tr("Qt Assistant by Nokia"); - return s; -} - -QString Config::aboutApplicationMenuText() const -{ - return profil->props[QLatin1String("aboutmenutext")]; -} - -QString Config::aboutURL() const -{ - return profil->props[QLatin1String("abouturl")]; -} - -QString Config::homePage() const -{ - return home.isEmpty() ? profil->props[QLatin1String("startpage")] : home; -} - -QStringList Config::source() const -{ - return src.size() == 0 ? QStringList(profil->props[QLatin1String("startpage")]) : src; -} - -QStringList Config::docFiles() const -{ - return profil->docs; -} - -QPixmap Config::docIcon( const QString &title ) const -{ - // ### To allow qdoc generated dcf files to reference the doc icons from qmake_image_col - QString name = profil->icons[title]; - QString resName = QLatin1String(":/trolltech/assistant/images/") + name; - - if (QFile::exists(resName)) - return QPixmap(resName); - - if (name.startsWith(QLatin1String("file:"))) - name = name.mid(5); - return QPixmap(name); -} - -QPixmap Config::applicationIcon() const -{ - QString name = profil->props[QLatin1String("applicationicon")]; - QString resName = QLatin1String(":/trolltech/assistant/images/") + name; - - if (QFile::exists(resName)) - return QPixmap(resName); - - if (name.startsWith(QLatin1String("file:"))) - name = name.mid(5); - return QPixmap(name); -} - -QStringList Config::docTitles() const -{ - return QStringList(profil->indexPages.keys()); -} - -QString Config::docImageDir( const QString &docfile ) const -{ - return profil->imageDirs[docfile]; -} - -QString Config::indexPage( const QString &title ) const -{ - return profil->indexPages[title]; -} - -void Config::hideSideBar( bool b ) -{ - hideSidebar = b; -} - -bool Config::sideBarHidden() const -{ - return hideSidebar; -} - -QString Config::assistantDocPath() const -{ - return profil->props[QLatin1String("assistantdocs")].isEmpty() - ? QLibraryInfo::location(QLibraryInfo::DocumentationPath) + QLatin1String("/html") - : profil->props[QLatin1String("assistantdocs")]; -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/config.h b/tools/assistant/compat/config.h deleted file mode 100644 index 498e6bb..0000000 --- a/tools/assistant/compat/config.h +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CONFIG_H -#define CONFIG_H - -#include "profile.h" - -#include <QString> -#include <QStringList> -#include <QPixmap> -#include <QMap> - -#include <QtGui/QFont> -#include <QtGui/QFontDatabase> - -QT_BEGIN_NAMESPACE - -class Profile; - -struct FontSettings -{ - FontSettings() : useWindowFont(false), useBrowserFont(false), - windowWritingSystem(QFontDatabase::Latin), browserWritingSystem(QFontDatabase::Latin) - { } - - QFont windowFont; - QFont browserFont; - - bool useWindowFont; - bool useBrowserFont; - - QFontDatabase::WritingSystem windowWritingSystem; - QFontDatabase::WritingSystem browserWritingSystem; -}; - -class Config -{ -public: - - Config(); - - void load(); - void save(); - Profile *profile() const { return profil; } - QString profileName() const { return profil->props[QLatin1String("name")]; } - bool validProfileName() const; - void hideSideBar( bool b ); - bool sideBarHidden() const; - QStringList mimePaths(); - - // From profile, read only - QStringList docFiles() const; - QStringList docTitles() const; - QString indexPage( const QString &title ) const; - QString docImageDir( const QString &title ) const; - QPixmap docIcon( const QString &title ) const; - - QStringList profiles() const; - QString title() const; - QString aboutApplicationMenuText() const; - QString aboutURL() const; - QPixmap applicationIcon() const; - - // From QSettings, read / write - QString homePage() const; - void setHomePage( const QString &hom ) { home = hom; } - - QStringList source() const; - void setSource( const QStringList &s ) { src = s; } - - int sideBarPage() const { return sideBar; } - void setSideBarPage( int sbp ) { sideBar = sbp; } - - QByteArray windowGeometry() const { return winGeometry; } - void setWindowGeometry( const QByteArray &geometry ) { winGeometry = geometry; } - - QByteArray mainWindowState() const { return mainWinState; } - void setMainWindowState( const QByteArray &state ) { mainWinState = state; } - - qreal fontPointSize() const { return pointFntSize; } - void setFontPointSize(qreal size) - { - pointFntSize = size; - m_fontSettings.useBrowserFont = true; - m_fontSettings.browserFont.setPointSizeF(size); - } - - FontSettings fontSettings() { return m_fontSettings; } - void setFontSettings(const FontSettings &settings) { m_fontSettings = settings; } - - QString assistantDocPath() const; - - bool docRebuild() const { return rebuildDocs; } - void setDocRebuild( bool rb ) { rebuildDocs = rb; } - - void saveProfile( Profile *profile ); - void loadDefaultProfile(); - bool defaultProfileExists(); - - static Config *configuration(); - static Config *loadConfig(const QString &profileFileName); - -private: - Config( const Config &c ); - Config& operator=( const Config &c ); - - void saveSettings(); - -private: - Profile *profil; - - QStringList profileNames; - QString home; - QStringList src; - QByteArray mainWinState; - QByteArray winGeometry; - qreal pointFntSize; - int sideBar; - bool hideSidebar; - bool rebuildDocs; - FontSettings m_fontSettings; -}; - -QT_END_NAMESPACE - -#endif // CONFIG_H diff --git a/tools/assistant/compat/docuparser.cpp b/tools/assistant/compat/docuparser.cpp deleted file mode 100644 index db2f824..0000000 --- a/tools/assistant/compat/docuparser.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "docuparser.h" -#include "profile.h" - -#include <QDir> -#include <QFile> -#include <QFileInfo> -#include <QRegExp> -#include <QString> -#include <QDataStream> - -QT_BEGIN_NAMESPACE - -QDataStream &operator>>(QDataStream &s, ContentItem &ci) -{ - s >> ci.title; - s >> ci.reference; - s >> ci.depth; - return s; -} - -QDataStream &operator<<(QDataStream &s, const ContentItem &ci) -{ - s << ci.title; - s << ci.reference; - s << ci.depth; - return s; -} - -const QString DocuParser::DocumentKey = QLatin1String("/Qt Assistant/") + QLatin1String(QT_VERSION_STR) + QLatin1String("/"); - -DocuParser *DocuParser::createParser(const QString &fileName) -{ - QFile file(fileName); - if(!file.open(QFile::ReadOnly)) { - return 0; - } - - QString str; - int maxlen = 1024; - int majVer = 0, minVer = 0, serVer = 0; - static QRegExp re(QLatin1String("assistantconfig +version=\"(\\d)\\.(\\d)\\.(\\d)\""), Qt::CaseInsensitive); - Q_ASSERT(re.isValid()); - while(!(str = QLatin1String(file.readLine(maxlen))).isEmpty()) { - if(re.indexIn(str) >= 0) { - majVer = re.cap(1).toInt(); - minVer = re.cap(2).toInt(); - serVer = re.cap(3).toInt(); - break; - } - } - - if (majVer < 3 || (majVer == 3 && minVer < 2)) { - return new DocuParser310; - } - - return new DocuParser320; -} - - -bool DocuParser::parse(QFile *file) -{ - QXmlInputSource source(file); - QXmlSimpleReader reader; - reader.setContentHandler(this); - reader.setErrorHandler(this); - setFileName(QFileInfo(*file).absoluteFilePath()); - return reader.parse(source); -} - - -QString DocuParser::errorProtocol() const -{ - return errorProt; -} - - -QList<ContentItem> DocuParser::getContentItems() -{ - return contentList; -} - - -QList<IndexItem*> DocuParser::getIndexItems() -{ - return indexList; -} - -QString DocuParser::absolutify(const QString &name, bool makeUrl) const -{ - if (!name.isEmpty()) { - QString s = name; - s.replace(QLatin1String("\\"), QLatin1String("/")); - QFileInfo orgPath(name); - if(orgPath.isRelative()) - s = QFileInfo(fname).path() + QLatin1Char('/') + name; - if (makeUrl) - s.prepend(QLatin1String("file:")); - return s; - } - return name; -} - - -void DocuParser310::addTo(Profile *p) -{ - p->addDCFTitle(fname, docTitle); - p->addDCFIcon(docTitle, iconName); - p->addDCFIndexPage(docTitle, conURL); -} - - -bool DocuParser310::startDocument() -{ - state = StateInit; - errorProt = QLatin1String(""); - - contentRef = QLatin1String(""); - indexRef = QLatin1String(""); - depth = 0; - - contentList.clear(); - qDeleteAll(indexList); - indexList.clear(); - - return true; -} - - -bool DocuParser310::startElement(const QString &, const QString &, - const QString &qname, - const QXmlAttributes &attr) -{ - if (qname == QLatin1String("DCF") && state == StateInit) { - state = StateContent; - contentRef = absolutify(attr.value(QLatin1String("ref")), false); - conURL = contentRef; - docTitle = attr.value(QLatin1String("title")); - iconName = absolutify(attr.value(QLatin1String("icon")), false); - contentList.append(ContentItem(docTitle, absolutify(contentRef), depth)); - } else if (qname == QLatin1String("section") && (state == StateContent || state == StateSect)) { - state = StateSect; - contentRef = absolutify(attr.value(QLatin1String("ref"))); - title = attr.value(QLatin1String("title")); - depth++; - contentList.append(ContentItem(title, contentRef, depth)); - } else if (qname == QLatin1String("keyword") && state == StateSect) { - state = StateKeyword; - indexRef = absolutify(attr.value(QLatin1String("ref"))); - } else - return false; - return true; -} - -bool DocuParser310::endElement(const QString &nameSpace, const QString &localName, - const QString &qName) -{ - Q_UNUSED(nameSpace); - Q_UNUSED(localName); - Q_UNUSED(qName); - - switch(state) { - case StateInit: - break; - case StateContent: - state = StateInit; - break; - case StateSect: - state = --depth ? StateSect : StateContent; - break; - case StateKeyword: - state = StateSect; - break; - default: - break; - } - return true; -} - - -bool DocuParser310::characters(const QString& ch) -{ - QString str = ch.simplified(); - if (str.isEmpty()) - return true; - - switch (state) { - case StateInit: - case StateContent: - case StateSect: - return false; - break; - case StateKeyword: - indexList.append(new IndexItem(str, indexRef)); - break; - default: - return false; - } - return true; -} - - -bool DocuParser310::fatalError(const QXmlParseException& exception) -{ - errorProt += QString::fromLatin1("fatal parsing error: %1 in line %2, column %3\n") - .arg(exception.message()) - .arg(exception.lineNumber()) - .arg(exception.columnNumber()); - - return QXmlDefaultHandler::fatalError(exception); -} - - -DocuParser320::DocuParser320() - : prof(new Profile) -{ -} - - -void DocuParser320::addTo(Profile *p) -{ - QMap<QString,QString>::ConstIterator it; - - for (it = prof->dcfTitles.constBegin(); it != prof->dcfTitles.constEnd(); ++it) - p->dcfTitles[it.key()] = *it; - - for (it = prof->icons.constBegin(); it != prof->icons.constEnd(); ++it) - p->icons[it.key()] = *it; - - for (it = prof->indexPages.constBegin(); it != prof->indexPages.constEnd(); ++it) - p->indexPages[it.key()] = *it; -} - - -bool DocuParser320::startDocument() -{ - state = StateInit; - errorProt = QLatin1String(""); - - contentRef = QLatin1String(""); - indexRef = QLatin1String(""); - depth = 0; - contentList.clear(); - indexList.clear(); - - prof->addDCF(fname); - - return true; -} - -bool DocuParser320::startElement(const QString &, const QString &, - const QString &qname, - const QXmlAttributes &attr) -{ - QString lower = qname.toLower(); - - switch(state) { - - case StateInit: - if(lower == QLatin1String("assistantconfig")) - state = StateDocRoot; - break; - - case StateDocRoot: - if(lower == QLatin1String("dcf")) { - state = StateContent; - contentRef = absolutify(attr.value(QLatin1String("ref"))); - conURL = contentRef; - docTitle = attr.value(QLatin1String("title")); - iconName = absolutify(attr.value(QLatin1String("icon"))); - contentList.append(ContentItem(docTitle, contentRef, depth)); - } else if(lower == QLatin1String("profile")) { - state = StateProfile; - } - break; - - case StateSect: - if (lower == QLatin1String("keyword") && state == StateSect) { - state = StateKeyword; - indexRef = absolutify(attr.value(QLatin1String("ref"))); - break; - } // else if (lower == "section") - case StateContent: - if(lower == QLatin1String("section")) { - state = StateSect; - contentRef = absolutify(attr.value(QLatin1String("ref"))); - title = attr.value(QLatin1String("title")); - depth++; - contentList.append(ContentItem(title, contentRef, depth)); - } - break; - - case StateProfile: - if(lower == QLatin1String("property")) { - state = StateProperty; - propertyName = attr.value(QLatin1String("name")); - } - break; - - case StateProperty: - break; - - default: - break; - } - - return true; -} - -bool DocuParser320::endElement(const QString &nameSpace, - const QString &localName, - const QString &qName) -{ - Q_UNUSED(nameSpace); - Q_UNUSED(localName); - Q_UNUSED(qName); - - switch(state) { - case StateInit: - break; - case StateDocRoot: - state = StateInit; - break; - case StateProfile: - state = StateDocRoot; - break; - case StateProperty: - state = StateProfile; - if(propertyName.isEmpty() || propertyValue.isEmpty()) - return false; - { - static const QStringList lst = QStringList() - << QLatin1String("startpage") << QLatin1String("abouturl") - << QLatin1String("applicationicon") << QLatin1String("assistantdocs"); - - if (lst.contains(propertyName)) - propertyValue = absolutify(propertyValue); - } - prof->addProperty(propertyName, propertyValue); - break; - case StateContent: - if(!iconName.isEmpty()) - prof->addDCFIcon(docTitle, iconName); - if(contentRef.isEmpty()) - return false; - prof->addDCFIndexPage(docTitle, conURL); - prof->addDCFTitle(fname, docTitle); - state = StateDocRoot; - break; - case StateSect: - state = --depth ? StateSect : StateContent; - break; - case StateKeyword: - state = StateSect; - break; - } - return true; -} - -bool DocuParser320::characters(const QString& ch) -{ - QString str = ch.simplified(); - if (str.isEmpty()) - return true; - - switch (state) { - case StateInit: - case StateContent: - case StateSect: - return false; - break; - case StateKeyword: - indexList.append(new IndexItem(str, indexRef)); - break; - case StateProperty: - propertyValue = ch; - break; - default: - return false; - } - return true; -} - -bool DocuParser320::fatalError(const QXmlParseException& exception) -{ - errorProt += QString::fromLatin1("fatal parsing error: %1 in line %2, column %3\n") - .arg(exception.message()) - .arg(exception.lineNumber()) - .arg(exception.columnNumber()); - return QXmlDefaultHandler::fatalError(exception); -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/docuparser.h b/tools/assistant/compat/docuparser.h deleted file mode 100644 index 7c7692e..0000000 --- a/tools/assistant/compat/docuparser.h +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DOCUPARSER_H -#define DOCUPARSER_H - -#include <QList> -#include <QMap> -#include <QXmlDefaultHandler> -#include <QXmlAttributes> -#include <QXmlParseException> - -QT_BEGIN_NAMESPACE - -class Profile; - -struct ContentItem { - ContentItem() - : title( QString() ), reference( QString() ), depth( 0 ) {} - ContentItem( const QString &t, const QString &r, int d ) - : title( t ), reference( r ), depth( d ) {} - QString title; - QString reference; - int depth; - Q_DUMMY_COMPARISON_OPERATOR(ContentItem) -}; - -QDataStream &operator>>( QDataStream &s, ContentItem &ci ); -QDataStream &operator<<( QDataStream &s, const ContentItem &ci ); - -struct IndexItem { - IndexItem( const QString &k, const QString &r ) - : keyword( k ), reference( r ) {} - QString keyword; - QString reference; -}; - - - -class DocuParser : public QXmlDefaultHandler -{ -public: - enum ParserVersion { Qt310, Qt320 }; - // Since We don't want problems with documentation - // from version to version, this string stores the correct - // version string to save documents. - static const QString DocumentKey; - - static DocuParser *createParser( const QString &fileName ); - - virtual bool parse( QFile *file ); - - QList<ContentItem> getContentItems(); - QList<IndexItem*> getIndexItems(); - - QString errorProtocol() const; - QString contentsURL() const { return conURL; } - - virtual ParserVersion parserVersion() const = 0; - virtual void addTo( Profile *p ) = 0; - - QString fileName() const { return fname; } - void setFileName( const QString &file ) { fname = file; } - -protected: - QString absolutify( const QString &input, bool makeUrl = true ) const; - - QString contentRef, indexRef, errorProt, conURL; - QString docTitle, title, iconName; - QList<ContentItem> contentList; - QList<IndexItem*> indexList; - QString fname; -}; - - -class DocuParser310 : public DocuParser -{ -public: - enum States{ StateInit, StateContent, StateSect, StateKeyword }; - - bool startDocument(); - bool startElement( const QString&, const QString&, const QString& , - const QXmlAttributes& ); - bool endElement( const QString&, const QString&, const QString& ); - bool characters( const QString & ); - bool fatalError( const QXmlParseException& exception ); - - virtual ParserVersion parserVersion() const { return Qt310; } - virtual void addTo( Profile *p ); - -private: - States state; - int depth; -}; - - -class DocuParser320 : public DocuParser -{ -public: - enum States { StateInit, StateDocRoot, StateProfile, StateProperty, - StateContent, StateSect, StateKeyword }; - - DocuParser320(); - - bool startDocument(); - bool startElement( const QString&, const QString&, const QString& , - const QXmlAttributes& ); - bool endElement( const QString&, const QString&, const QString& ); - bool characters( const QString & ); - bool fatalError( const QXmlParseException& exception ); - - virtual ParserVersion parserVersion() const { return Qt320; } - virtual void addTo( Profile *p ); - Profile *profile() const { return prof; } - -private: - - States state; - int depth; - int docfileCounter; - QString propertyValue; - QString propertyName; - Profile *prof; -}; - -QT_END_NAMESPACE - -#endif // DOCUPARSER_H diff --git a/tools/assistant/compat/fontsettingsdialog.cpp b/tools/assistant/compat/fontsettingsdialog.cpp deleted file mode 100644 index 31a3241..0000000 --- a/tools/assistant/compat/fontsettingsdialog.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "fontsettingsdialog.h" -#include "fontpanel.h" -#include "config.h" - -#include <QtGui/QLabel> -#include <QtGui/QComboBox> -#include <QtGui/QHBoxLayout> -#include <QtGui/QVBoxLayout> -#include <QtGui/QApplication> -#include <QtGui/QStackedWidget> -#include <QtGui/QDialogButtonBox> - -QT_BEGIN_NAMESPACE - -FontSettingsDialog::FontSettingsDialog(QWidget *parent) - : QDialog(parent) - , m_windowFontPanel(new FontPanel(this)) - , m_browserFontPanel(new FontPanel(this)) - , m_dialogButtonBox(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel)) -{ - setModal(true); - setWindowTitle(tr("Font Settings")); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - - QVBoxLayout *mainVLayout = new QVBoxLayout(this); - QHBoxLayout *hboxLayout = new QHBoxLayout; - mainVLayout->addLayout(hboxLayout); - - QLabel *label = new QLabel(tr("Font settings for:"), this); - label->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); - hboxLayout->addWidget(label); - QComboBox *comboBox = new QComboBox(this); - comboBox->addItem(tr("Browser")); - comboBox->addItem(tr("Application")); - hboxLayout->addWidget(comboBox); - - m_windowFontPanel->setCheckable(true); - m_browserFontPanel->setCheckable(true); - - const QString customSettings(tr("Use custom settings")); - m_windowFontPanel->setTitle(customSettings); - m_browserFontPanel->setTitle(customSettings); - - QStackedWidget *stackWidget = new QStackedWidget(this); - stackWidget->addWidget(m_browserFontPanel); - stackWidget->addWidget(m_windowFontPanel); - - mainVLayout->addWidget(stackWidget); - mainVLayout->addWidget(m_dialogButtonBox); - - connect(m_dialogButtonBox , SIGNAL(rejected()), this, SLOT(reject())); - connect(m_dialogButtonBox , SIGNAL(accepted()), this, SLOT(accept())); - connect(comboBox, SIGNAL(activated(int)), stackWidget, SLOT(setCurrentIndex(int))); -} - -FontSettingsDialog::~FontSettingsDialog() -{ - // nothing todo -} - -bool FontSettingsDialog::showDialog(FontSettings *settings) -{ - setupFontSettingsDialog(settings); - - if (exec() != Accepted) - return false; - - updateFontSettings(settings); - return true; -} - -void FontSettingsDialog::updateFontSettings(FontSettings *settings) -{ - settings->useWindowFont = m_windowFontPanel->isChecked(); - settings->useBrowserFont = m_browserFontPanel->isChecked(); - - settings->windowFont = settings->useWindowFont ? m_windowFontPanel->selectedFont() : qApp->font(); - settings->browserFont = settings->useBrowserFont ? m_browserFontPanel->selectedFont() : qApp->font(); - - settings->windowWritingSystem = settings->useWindowFont ? m_windowFontPanel->writingSystem() : QFontDatabase::Latin; - settings->browserWritingSystem = settings->useBrowserFont ? m_browserFontPanel->writingSystem() : QFontDatabase::Latin; -} - -void FontSettingsDialog::setupFontSettingsDialog(const FontSettings *settings) -{ - m_windowFontPanel->setSelectedFont(settings->windowFont); - m_browserFontPanel->setSelectedFont(settings->browserFont); - - m_windowFontPanel->setWritingSystem(settings->windowWritingSystem); - m_browserFontPanel->setWritingSystem(settings->browserWritingSystem); - - m_windowFontPanel->setChecked(settings->useWindowFont); - m_browserFontPanel->setChecked(settings->useBrowserFont); -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/helpdialog.cpp b/tools/assistant/compat/helpdialog.cpp deleted file mode 100644 index 23c1bfc..0000000 --- a/tools/assistant/compat/helpdialog.cpp +++ /dev/null @@ -1,1331 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "helpdialog.h" -#include "helpwindow.h" -#include "topicchooser.h" -#include "docuparser.h" -#include "mainwindow.h" -#include "config.h" -#include "tabbedbrowser.h" - -#include <QtGui> -#include <QtDebug> -#include <QtCore/QVarLengthArray> - -#include <stdlib.h> -#include <limits.h> - -QT_BEGIN_NAMESPACE - -enum -{ - LinkRole = Qt::UserRole + 1000 -}; - -static bool verifyDirectory(const QString &str) -{ - QFileInfo dirInfo(str); - if (!dirInfo.exists()) - return QDir().mkdir(str); - if (!dirInfo.isDir()) { - qWarning("'%s' exists but is not a directory", str.toLatin1().constData()); - return false; - } - return true; -} - -struct IndexKeyword { - IndexKeyword(const QString &kw, const QString &l) - : keyword(kw), link(l) {} - IndexKeyword() : keyword(QString()), link(QString()) {} - bool operator<(const IndexKeyword &ik) const { - return keyword.toLower() < ik.keyword.toLower(); - } - bool operator<=(const IndexKeyword &ik) const { - return keyword.toLower() <= ik.keyword.toLower(); - } - bool operator>(const IndexKeyword &ik) const { - return keyword.toLower() > ik.keyword.toLower(); - } - Q_DUMMY_COMPARISON_OPERATOR(IndexKeyword) - QString keyword; - QString link; -}; - -QDataStream &operator>>(QDataStream &s, IndexKeyword &ik) -{ - s >> ik.keyword; - s >> ik.link; - return s; -} - -QDataStream &operator<<(QDataStream &s, const IndexKeyword &ik) -{ - s << ik.keyword; - s << ik.link; - return s; -} - -QValidator::State SearchValidator::validate(QString &str, int &) const -{ - for (int i = 0; i < (int) str.length(); ++i) { - QChar c = str[i]; - if (!c.isLetterOrNumber() && c != QLatin1Char('\'') && c != QLatin1Char('`') - && c != QLatin1Char('\"') && c != QLatin1Char(' ') && c != QLatin1Char('-') && c != QLatin1Char('_') - && c!= QLatin1Char('*')) - return QValidator::Invalid; - } - return QValidator::Acceptable; -} - -class IndexListModel: public QStringListModel -{ -public: - IndexListModel(QObject *parent = 0) - : QStringListModel(parent) {} - - void clear() { contents.clear(); setStringList(QStringList()); } - - QString description(int index) const { return stringList().at(index); } - QStringList links(int index) const { return contents.values(stringList().at(index)); } - void addLink(const QString &description, const QString &link) { contents.insert(description, link); } - - void publish() { filter(QString(), QString()); } - - QModelIndex filter(const QString &s, const QString &real); - - virtual Qt::ItemFlags flags(const QModelIndex &index) const - { return QStringListModel::flags(index) & ~Qt::ItemIsEditable; } - -private: - QMultiMap<QString, QString> contents; -}; - -bool caseInsensitiveLessThan(const QString &as, const QString &bs) -{ - const QChar *a = as.unicode(); - const QChar *b = bs.unicode(); - if (a == 0) - return true; - if (b == 0) - return false; - if (a == b) - return false; - int l=qMin(as.length(),bs.length()); - while (l-- && QChar::toLower(a->unicode()) == QChar::toLower(b->unicode())) - a++,b++; - if (l==-1) - return (as.length() < bs.length()); - return QChar::toLower(a->unicode()) < QChar::toLower(b->unicode()); -} - -/** - * \a real is kinda a hack for the smart search, need a way to match a regexp to an item - * How would you say the best match for Q.*Wiget is QWidget? - */ -QModelIndex IndexListModel::filter(const QString &s, const QString &real) -{ - QStringList list; - - int goodMatch = -1; - int perfectMatch = -1; - if (s.isEmpty()) - perfectMatch = 0; - - const QRegExp regExp(s, Qt::CaseInsensitive); - QMultiMap<QString, QString>::iterator it = contents.begin(); - QString lastKey; - for (; it != contents.end(); ++it) { - if (it.key() == lastKey) - continue; - lastKey = it.key(); - const QString key = it.key(); - if (key.contains(regExp) || key.contains(s, Qt::CaseInsensitive)) { - list.append(key); - if (perfectMatch == -1 && (key.startsWith(real, Qt::CaseInsensitive))) { - if (goodMatch == -1) - goodMatch = list.count() - 1; - if (real.length() == key.length()){ - perfectMatch = list.count() - 1; - } - } else if (perfectMatch > -1 && s == key) { - perfectMatch = list.count() - 1; - } - } - } - - int bestMatch = perfectMatch; - if (bestMatch == -1) - bestMatch = goodMatch; - bestMatch = qMax(0, bestMatch); - - // sort the new list - QString match; - if (bestMatch >= 0 && list.count() > bestMatch) - match = list[bestMatch]; - qSort(list.begin(), list.end(), caseInsensitiveLessThan); - setStringList(list); - for (int i = 0; i < list.size(); ++i) { - if (list.at(i) == match){ - bestMatch = i; - break; - } - } - return index(bestMatch, 0, QModelIndex()); -} - -HelpNavigationListItem::HelpNavigationListItem(QListWidget *ls, const QString &txt) - : QListWidgetItem(txt, ls) -{ -} - -void HelpNavigationListItem::addLink(const QString &link) -{ - QString lnk = HelpDialog::removeAnchorFromLink(link); - if (linkList.filter(lnk, Qt::CaseInsensitive).count() > 0) - return; - linkList << link; -} - -HelpDialog::HelpDialog(QWidget *parent, MainWindow *h) - : QWidget(parent), lwClosed(false), help(h) -{ - ui.setupUi(this); - ui.listContents->setUniformRowHeights(true); - ui.listContents->header()->setStretchLastSection(false); - ui.listContents->header()->setResizeMode(QHeaderView::ResizeToContents); - ui.listBookmarks->setUniformRowHeights(true); - ui.listBookmarks->header()->setStretchLastSection(false); - ui.listBookmarks->header()->setResizeMode(QHeaderView::ResizeToContents); - - indexModel = new IndexListModel(this); - ui.listIndex->setModel(indexModel); - ui.listIndex->setLayoutMode(QListView::Batched); - ui.listBookmarks->setItemHidden(ui.listBookmarks->headerItem(), true); - ui.listContents->setItemHidden(ui.listContents->headerItem(), true); - ui.searchButton->setShortcut(QKeySequence(Qt::ALT|Qt::SHIFT|Qt::Key_S)); -} - -void HelpDialog::initialize() -{ - connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); - - connect(ui.listContents, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(showTopic(QTreeWidgetItem*))); - connect(ui.listContents, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showTreeItemMenu(QPoint))); - ui.listContents->viewport()->installEventFilter(this); - - connect(ui.editIndex, SIGNAL(returnPressed()), this, SLOT(showTopic())); - connect(ui.editIndex, SIGNAL(textEdited(QString)), this, SLOT(searchInIndex(QString))); - - connect(ui.listIndex, SIGNAL(activated(QModelIndex)), this, SLOT(showTopic())); - connect(ui.listIndex, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showIndexItemMenu(QPoint))); - - connect(ui.listBookmarks, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(showTopic(QTreeWidgetItem*))); - connect(ui.listBookmarks, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showTreeItemMenu(QPoint))); - - connect(ui.termsEdit, SIGNAL(textChanged(QString)), this, SLOT(updateSearchButton(QString))); - - connect(ui.resultBox, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showListItemMenu(QPoint))); - - cacheFilesPath = QDir::homePath() + QLatin1String("/.assistant"); //### Find a better location for the dbs - - ui.editIndex->installEventFilter(this); - - ui.framePrepare->hide(); - connect(qApp, SIGNAL(lastWindowClosed()), SLOT(lastWinClosed())); - - ui.termsEdit->setValidator(new SearchValidator(ui.termsEdit)); - - actionOpenCurrentTab = new QAction(this); - actionOpenCurrentTab->setText(tr("Open Link in Current Tab")); - - actionOpenLinkInNewWindow = new QAction(this); - actionOpenLinkInNewWindow->setText(tr("Open Link in New Window")); - - actionOpenLinkInNewTab = new QAction(this); - actionOpenLinkInNewTab->setText(tr("Open Link in New Tab")); - - itemPopup = new QMenu(this); - itemPopup->addAction(actionOpenCurrentTab); - itemPopup->addAction(actionOpenLinkInNewWindow); - itemPopup->addAction(actionOpenLinkInNewTab); - - ui.tabWidget->setElideMode(Qt::ElideNone); - - contentList.clear(); - - initDoneMsgShown = false; - fullTextIndex = 0; - indexDone = false; - titleMapDone = false; - contentsInserted = false; - bookmarksInserted = false; - setupTitleMap(); - -} - -void HelpDialog::processEvents() -{ - qApp->processEvents(QEventLoop::ExcludeUserInputEvents); -} - - -void HelpDialog::lastWinClosed() -{ - lwClosed = true; -} - -void HelpDialog::removeOldCacheFiles(bool onlyFulltextSearchIndex) -{ - if (!verifyDirectory(cacheFilesPath)) { - qWarning("Failed to created assistant directory"); - return; - } - QString pname = QLatin1String(".") + Config::configuration()->profileName(); - - QStringList fileList; - fileList << QLatin1String("indexdb40.dict") - << QLatin1String("indexdb40.doc"); - - if (!onlyFulltextSearchIndex) - fileList << QLatin1String("indexdb40") << QLatin1String("contentdb40"); - - QStringList::iterator it = fileList.begin(); - for (; it != fileList.end(); ++it) { - if (QFile::exists(cacheFilesPath + QDir::separator() + *it + pname)) { - QFile f(cacheFilesPath + QDir::separator() + *it + pname); - f.remove(); - } - } -} - -void HelpDialog::timerEvent(QTimerEvent *e) -{ - Q_UNUSED(e); - static int opacity = 255; - help->setWindowOpacity((opacity-=4)/255.0); - if (opacity<=0) - qApp->quit(); -} - - -void HelpDialog::loadIndexFile() -{ - if (indexDone) - return; - - setCursor(Qt::WaitCursor); - indexDone = true; - ui.labelPrepare->setText(tr("Prepare...")); - ui.framePrepare->show(); - processEvents(); - - QProgressBar *bar = ui.progressPrepare; - bar->setMaximum(100); - bar->setValue(0); - - keywordDocuments.clear(); - QList<IndexKeyword> lst; - QFile indexFile(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.") + - Config::configuration()->profileName()); - if (!indexFile.open(QFile::ReadOnly)) { - buildKeywordDB(); - processEvents(); - if (lwClosed) - return; - if (!indexFile.open(QFile::ReadOnly)) { - QMessageBox::warning(help, tr("Qt Assistant"), tr("Failed to load keyword index file\n" - "Assistant will not work!")); -#if defined Q_WS_WIN || defined Q_WS_MACX - startTimer(50); -#endif - return; - } - } - - QDataStream ds(&indexFile); - quint32 fileAges; - ds >> fileAges; - if (fileAges != getFileAges()) { - indexFile.close(); - buildKeywordDB(); - if (!indexFile.open(QFile::ReadOnly)) { - QMessageBox::warning(help, tr("Qt Assistant"), - tr("Cannot open the index file %1").arg(QFileInfo(indexFile).absoluteFilePath())); - return; - } - ds.setDevice(&indexFile); - ds >> fileAges; - } - ds >> lst; - indexFile.close(); - - bar->setValue(bar->maximum()); - processEvents(); - - for (int i=0; i<lst.count(); ++i) { - const IndexKeyword &idx = lst.at(i); - indexModel->addLink(idx.keyword, idx.link); - - keywordDocuments << HelpDialog::removeAnchorFromLink(idx.link); - } - - indexModel->publish(); - - ui.framePrepare->hide(); - showInitDoneMessage(); - setCursor(Qt::ArrowCursor); -} - -quint32 HelpDialog::getFileAges() -{ - QStringList addDocuFiles = Config::configuration()->docFiles(); - QStringList::const_iterator i = addDocuFiles.constBegin(); - - quint32 fileAges = 0; - for (; i != addDocuFiles.constEnd(); ++i) { - QFileInfo fi(*i); - if (fi.exists()) - fileAges += fi.lastModified().toTime_t(); - } - - return fileAges; -} - -void HelpDialog::buildKeywordDB() -{ - QStringList addDocuFiles = Config::configuration()->docFiles(); - QStringList::iterator i = addDocuFiles.begin(); - - // Set up an indeterminate progress bar. - ui.labelPrepare->setText(tr("Prepare...")); - ui.progressPrepare->setMaximum(0); - ui.progressPrepare->setMinimum(0); - ui.progressPrepare->setValue(0); - processEvents(); - - QList<IndexKeyword> lst; - quint32 fileAges = 0; - for (i = addDocuFiles.begin(); i != addDocuFiles.end(); ++i) { - QFile file(*i); - if (!file.exists()) { - QMessageBox::warning(this, tr("Warning"), - tr("Documentation file %1 does not exist!\n" - "Skipping file.").arg(QFileInfo(file).absoluteFilePath())); - continue; - } - fileAges += QFileInfo(file).lastModified().toTime_t(); - DocuParser *handler = DocuParser::createParser(*i); - bool ok = handler->parse(&file); - file.close(); - if (!ok){ - QString msg = QString::fromLatin1("In file %1:\n%2") - .arg(QFileInfo(file).absoluteFilePath()) - .arg(handler->errorProtocol()); - QMessageBox::critical(this, tr("Parse Error"), tr(msg.toUtf8())); - delete handler; - continue; - } - - QList<IndexItem*> indLst = handler->getIndexItems(); - int counter = 0; - foreach (IndexItem *indItem, indLst) { - QFileInfo fi(indItem->reference); - lst.append(IndexKeyword(indItem->keyword, indItem->reference)); - - if (++counter%100 == 0) { - if (ui.progressPrepare) - ui.progressPrepare->setValue(counter); - processEvents(); - if (lwClosed) { - return; - } - } - } - delete handler; - } - if (!lst.isEmpty()) - qSort(lst); - - QFile indexout(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.") - + Config::configuration()->profileName()); - if (verifyDirectory(cacheFilesPath) && indexout.open(QFile::WriteOnly)) { - QDataStream s(&indexout); - s << fileAges; - s << lst; - indexout.close(); - } -} - -void HelpDialog::setupTitleMap() -{ - if (titleMapDone) - return; - - bool needRebuild = false; - if (Config::configuration()->profileName() == QLatin1String("default")) { - const QStringList docuFiles = Config::configuration()->docFiles(); - for (QStringList::ConstIterator it = docuFiles.begin(); it != docuFiles.end(); ++it) { - if (!QFile::exists(*it)) { - Config::configuration()->saveProfile(Profile::createDefaultProfile()); - Config::configuration()->loadDefaultProfile(); - needRebuild = true; - break; - } - } - } - - if (Config::configuration()->docRebuild() || needRebuild) { - removeOldCacheFiles(); - Config::configuration()->setDocRebuild(false); - Config::configuration()->saveProfile(Config::configuration()->profile()); - } - if (contentList.isEmpty()) - getAllContents(); - - titleMapDone = true; - titleMap.clear(); - for (QList<QPair<QString, ContentList> >::Iterator it = contentList.begin(); it != contentList.end(); ++it) { - ContentList lst = (*it).second; - foreach (ContentItem item, lst) { - titleMap[item.reference] = item.title.trimmed(); - } - } - processEvents(); -} - -void HelpDialog::getAllContents() -{ - QFile contentFile(cacheFilesPath + QDir::separator() + QLatin1String("contentdb40.") - + Config::configuration()->profileName()); - contentList.clear(); - if (!contentFile.open(QFile::ReadOnly)) { - buildContentDict(); - return; - } - - QDataStream ds(&contentFile); - quint32 fileAges; - ds >> fileAges; - if (fileAges != getFileAges()) { - contentFile.close(); - removeOldCacheFiles(true); - buildContentDict(); - return; - } - QString key; - QList<ContentItem> lst; - while (!ds.atEnd()) { - ds >> key; - ds >> lst; - contentList += qMakePair(key, QList<ContentItem>(lst)); - } - contentFile.close(); - processEvents(); - -} - -void HelpDialog::buildContentDict() -{ - QStringList docuFiles = Config::configuration()->docFiles(); - - quint32 fileAges = 0; - for (QStringList::iterator it = docuFiles.begin(); it != docuFiles.end(); ++it) { - QFile file(*it); - if (!file.exists()) { - QMessageBox::warning(this, tr("Warning"), - tr("Documentation file %1 does not exist!\n" - "Skipping file.").arg(QFileInfo(file).absoluteFilePath())); - continue; - } - fileAges += QFileInfo(file).lastModified().toTime_t(); - DocuParser *handler = DocuParser::createParser(*it); - if (!handler) { - QMessageBox::warning(this, tr("Warning"), - tr("Documentation file %1 is not compatible!\n" - "Skipping file.").arg(QFileInfo(file).absoluteFilePath())); - continue; - } - bool ok = handler->parse(&file); - file.close(); - if (ok) { - contentList += qMakePair(*it, QList<ContentItem>(handler->getContentItems())); - delete handler; - } else { - QString msg = QString::fromLatin1("In file %1:\n%2") - .arg(QFileInfo(file).absoluteFilePath()) - .arg(handler->errorProtocol()); - QMessageBox::critical(this, tr("Parse Error"), tr(msg.toUtf8())); - continue; - } - } - - QFile contentOut(cacheFilesPath + QDir::separator() + QLatin1String("contentdb40.") - + Config::configuration()->profileName()); - if (contentOut.open(QFile::WriteOnly)) { - QDataStream s(&contentOut); - s << fileAges; - for (QList<QPair<QString, ContentList> >::Iterator it = contentList.begin(); it != contentList.end(); ++it) { - s << *it; - } - contentOut.close(); - } -} - -void HelpDialog::currentTabChanged(int index) -{ - QString s = ui.tabWidget->widget(index)->objectName(); - if (s == QLatin1String("indexPage")) - QTimer::singleShot(0, this, SLOT(loadIndexFile())); - else if (s == QLatin1String("bookmarkPage")) - insertBookmarks(); - else if (s == QLatin1String("contentPage")) - QTimer::singleShot(0, this, SLOT(insertContents())); - else if (s == QLatin1String("searchPage")) - QTimer::singleShot(0, this, SLOT(setupFullTextIndex())); -} - -void HelpDialog::showInitDoneMessage() -{ - if (initDoneMsgShown) - return; - initDoneMsgShown = true; - help->statusBar()->showMessage(tr("Done"), 3000); -} - -void HelpDialog::showTopic(QTreeWidgetItem *item) -{ - if (item) - showTopic(); -} - -void HelpDialog::showTopic() -{ - QString tabName = ui.tabWidget->currentWidget()->objectName(); - - if (tabName == QLatin1String("indexPage")) - showIndexTopic(); - else if (tabName == QLatin1String("bookmarkPage")) - showBookmarkTopic(); - else if (tabName == QLatin1String("contentPage")) - showContentsTopic(); -} - -void HelpDialog::showIndexTopic() -{ - int row = ui.listIndex->currentIndex().row(); - if (row == -1 || row >= indexModel->rowCount()) - return; - - QString description = indexModel->description(row); - QStringList links = indexModel->links(row); - - bool blocked = ui.editIndex->blockSignals(true); - ui.editIndex->setText(description); - ui.editIndex->blockSignals(blocked); - - if (links.count() == 1) { - emit showLink(links.first()); - } else { - qSort(links); - QStringList::Iterator it = links.begin(); - QStringList linkList; - QStringList linkNames; - for (; it != links.end(); ++it) { - linkList << *it; - linkNames << titleOfLink(*it); - } - QString link = TopicChooser::getLink(this, linkNames, linkList, description); - if (!link.isEmpty()) - emit showLink(link); - } - - ui.listIndex->setCurrentIndex(indexModel->index(indexModel->stringList().indexOf(description))); - ui.listIndex->scrollTo(ui.listIndex->currentIndex(), QAbstractItemView::PositionAtTop); -} - -void HelpDialog::searchInIndex(const QString &searchString) -{ - QRegExp atoz(QLatin1String("[A-Z]")); - int matches = searchString.count(atoz); - if (matches > 0 && !searchString.contains(QLatin1String(".*"))) - { - int start = 0; - QString newSearch; - for (; matches > 0; --matches) { - int match = searchString.indexOf(atoz, start+1); - if (match <= start) - continue; - newSearch += searchString.mid(start, match-start); - newSearch += QLatin1String(".*"); - start = match; - } - newSearch += searchString.mid(start); - ui.listIndex->setCurrentIndex(indexModel->filter(newSearch, searchString)); - } - else - ui.listIndex->setCurrentIndex(indexModel->filter(searchString, searchString)); -} - -QString HelpDialog::titleOfLink(const QString &link) -{ - QString s = HelpDialog::removeAnchorFromLink(link); - s = titleMap[s]; - if (s.isEmpty()) - return link; - return s; -} - -bool HelpDialog::eventFilter(QObject * o, QEvent * e) -{ - if (o == ui.editIndex && e->type() == QEvent::KeyPress) { - switch (static_cast<QKeyEvent*>(e)->key()) { - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_PageDown: - case Qt::Key_PageUp: - QApplication::sendEvent(ui.listIndex, e); - break; - - default: - break; - } - } else if (o == ui.listContents->viewport()) { - if (e->type() == QEvent::MouseButtonRelease) { - QMouseEvent *me = static_cast<QMouseEvent*>(e); - if (me->button() == Qt::LeftButton) { - QTreeWidgetItem *item = ui.listContents->itemAt(me->pos()); - QRect vRect = ui.listContents->visualItemRect(item); - - // only show topic if we clicked an item - if (item && vRect.contains(me->pos())) - showTopic(item); - } - } - } - - return QWidget::eventFilter(o, e); -} - -void HelpDialog::addBookmark() -{ - if (!bookmarksInserted) - insertBookmarks(); - QString link = help->browsers()->currentBrowser()->source().toString(); - QString title = help->browsers()->currentBrowser()->documentTitle(); - if (title.isEmpty()) - title = titleOfLink(link); - - QTreeWidgetItem *i = new QTreeWidgetItem(ui.listBookmarks, 0); - i->setText(0, title); - i->setData(0, LinkRole, link); - ui.buttonRemove->setEnabled(true); - saveBookmarks(); - help->updateBookmarkMenu(); -} - -void HelpDialog::on_buttonAdd_clicked() -{ - addBookmark(); -} - -void HelpDialog::on_buttonRemove_clicked() -{ - if (!ui.listBookmarks->currentItem()) - return; - - delete ui.listBookmarks->currentItem(); - saveBookmarks(); - if (ui.listBookmarks->topLevelItemCount() != 0) { - ui.listBookmarks->setCurrentItem(ui.listBookmarks->topLevelItem(0)); - } - ui.buttonRemove->setEnabled(ui.listBookmarks->topLevelItemCount() > 0); - help->updateBookmarkMenu(); -} - -void HelpDialog::insertBookmarks() -{ - if (bookmarksInserted) - return; - bookmarksInserted = true; - ui.listBookmarks->clear(); - QFile f(cacheFilesPath + QDir::separator() + QLatin1String("bookmarks.") - + Config::configuration()->profileName()); - if (!f.open(QFile::ReadOnly)) - return; - QTextStream ts(&f); - while (!ts.atEnd()) { - QTreeWidgetItem *i = new QTreeWidgetItem(ui.listBookmarks, 0); - i->setText(0, ts.readLine()); - i->setData(0, LinkRole, ts.readLine()); - } - ui.buttonRemove->setEnabled(ui.listBookmarks->topLevelItemCount() > 0); - help->updateBookmarkMenu(); - showInitDoneMessage(); -} - -void HelpDialog::showBookmarkTopic() -{ - if (!ui.listBookmarks->currentItem()) - return; - - QTreeWidgetItem *i = (QTreeWidgetItem*)ui.listBookmarks->currentItem(); - emit showLink(i->data(0, LinkRole).toString()); -} - -static void store(QTreeWidgetItem *i, QTextStream &ts) -{ - ts << i->text(0) << endl; - ts << i->data(0, LinkRole).toString() << endl; - - for (int index = 0; index < i->childCount(); ++index) - store(i->child(index), ts); -} - -static void store(QTreeWidget *tw, QTextStream &ts) -{ - for (int index = 0; index < tw->topLevelItemCount(); ++index) - store(tw->topLevelItem(index), ts); -} - -void HelpDialog::saveBookmarks() -{ - QFile f(cacheFilesPath + QDir::separator() + QLatin1String("bookmarks.") - + Config::configuration()->profileName()); - if (!f.open(QFile::WriteOnly)) - return; - - QTextStream ts(&f); - store(ui.listBookmarks, ts); - f.close(); -} - -void HelpDialog::insertContents() -{ -#ifdef Q_WS_MAC - static const QLatin1String IconPath(":/trolltech/assistant/images/mac/book.png"); -#else - static const QLatin1String IconPath(":/trolltech/assistant/images/win/book.png"); -#endif - if (contentsInserted) - return; - - if (contentList.isEmpty()) - getAllContents(); - - contentsInserted = true; - ui.listContents->clear(); - setCursor(Qt::WaitCursor); - if (!titleMapDone) - setupTitleMap(); - -#if 0 // ### port me - ui.listContents->setSorting(-1); -#endif - - for (QList<QPair<QString, ContentList> >::Iterator it = contentList.begin(); it != contentList.end(); ++it) { - QTreeWidgetItem *newEntry = 0; - - QTreeWidgetItem *contentEntry = 0; - QStack<QTreeWidgetItem*> stack; - stack.clear(); - int depth = 0; - bool root = false; - - const int depthSize = 32; - QVarLengthArray<QTreeWidgetItem*, depthSize> lastItem(depthSize); - - ContentList lst = (*it).second; - for (ContentList::ConstIterator it = lst.constBegin(); it != lst.constEnd(); ++it) { - ContentItem item = *it; - if (item.depth == 0) { - lastItem[0] = 0; - newEntry = new QTreeWidgetItem(ui.listContents, 0); - newEntry->setIcon(0, QIcon(IconPath)); - newEntry->setText(0, item.title); - newEntry->setData(0, LinkRole, item.reference); - stack.push(newEntry); - depth = 1; - root = true; - } - else{ - if ((item.depth > depth) && root) { - depth = item.depth; - stack.push(contentEntry); - } - if (item.depth == depth) { - if (lastItem.capacity() == depth) - lastItem.resize(depth + depthSize); - contentEntry = new QTreeWidgetItem(stack.top(), lastItem[ depth ]); - lastItem[ depth ] = contentEntry; - contentEntry->setText(0, item.title); - contentEntry->setData(0, LinkRole, item.reference); - } - else if (item.depth < depth) { - stack.pop(); - depth--; - item = *(--it); - } - } - } - processEvents(); - } - setCursor(Qt::ArrowCursor); - showInitDoneMessage(); -} - -void HelpDialog::showContentsTopic() -{ - QTreeWidgetItem *i = (QTreeWidgetItem*)ui.listContents->currentItem(); - if (!i) - return; - emit showLink(i->data(0, LinkRole).toString()); -} - -QTreeWidgetItem * HelpDialog::locateLink(QTreeWidgetItem *item, const QString &link) -{ - QTreeWidgetItem *child = 0; -#ifdef Q_OS_WIN - Qt::CaseSensitivity checkCase = Qt::CaseInsensitive; -#else - Qt::CaseSensitivity checkCase = Qt::CaseSensitive; -#endif - for (int i = 0, childCount = item->childCount(); i<childCount; i++) { - child = item->child(i); - ///check whether it is this item - if (link.startsWith(child->data(0, LinkRole).toString(), checkCase)) - break; - //check if the link is a child of this item - else if (child->childCount()) { - child = locateLink(child, link); - if (child) - break; - } - child = 0; - } - return child; -} - -void HelpDialog::locateContents(const QString &link) -{ - //ensure the TOC is filled - if (!contentsInserted) - insertContents(); -#ifdef Q_OS_WIN - Qt::CaseSensitivity checkCase = Qt::CaseInsensitive; -#else - Qt::CaseSensitivity checkCase = Qt::CaseSensitive; -#endif - QString findLink(link); - //Installations on a windows local drive will give the 'link' as <file:///C:/xxx> - //and the contents in the TOC will be <file:C:/xxx>. - //But on others the 'link' of format <file:///root/xxx> - //and the contents in the TOC will be <file:/root/xxx>. - if (findLink.contains(QLatin1String("file:///"))) { - if (findLink[9] == QLatin1Char(':')) //on windows drives - findLink.replace(0, 8, QLatin1String("file:")); - else - findLink.replace(0, 8, QLatin1String("file:/")); - } - - bool topLevel = false; - QTreeWidgetItem *item = 0; - int totalItems = ui.listContents->topLevelItemCount(); - - for (int i = 0; i < totalItems; i++ ) { - // first see if we are one of the top level items - item = (QTreeWidgetItem*)ui.listContents->topLevelItem(i); - if (findLink.startsWith(item->data(0, LinkRole).toString(), checkCase)) { - topLevel = true; - break; - } - } - - if (!topLevel) { - // now try to find it in the sublevel items - for (int n = 0; n < totalItems; ++n) { - item = (QTreeWidgetItem*)ui.listContents->topLevelItem(n); - item = locateLink(item, findLink); - if (item) - break; - } - } - - //remove the old selection - QList<QTreeWidgetItem *> selected = ui.listContents->selectedItems(); - foreach(QTreeWidgetItem *sel, selected) - ui.listContents->setItemSelected(sel, false); - - //set the TOC item and show - ui.listContents->setCurrentItem(item); - ui.listContents->setItemSelected(item, true); - ui.listContents->scrollToItem(item); -} - -void HelpDialog::toggleContents() -{ - if (!isVisible() || ui.tabWidget->currentIndex() != 0) { - ui.tabWidget->setCurrentIndex(0); - parentWidget()->show(); - } - else - parentWidget()->hide(); -} - -void HelpDialog::toggleIndex() -{ - if (!isVisible() || ui.tabWidget->currentIndex() != 1 || !ui.editIndex->hasFocus()) { - ui.tabWidget->setCurrentIndex(1); - parentWidget()->show(); - ui.editIndex->setFocus(); - } - else - parentWidget()->hide(); -} - -void HelpDialog::toggleBookmarks() -{ - if (!isVisible() || ui.tabWidget->currentIndex() != 2) { - ui.tabWidget->setCurrentIndex(2); - parentWidget()->show(); - } - else - parentWidget()->hide(); -} - -void HelpDialog::toggleSearch() -{ - if (!isVisible() || ui.tabWidget->currentIndex() != 3) { - ui.tabWidget->setCurrentIndex(3); - parentWidget()->show(); - } - else - parentWidget()->hide(); -} - -void HelpDialog::setupFullTextIndex() -{ - if (fullTextIndex) - return; - - QString pname = Config::configuration()->profileName(); - fullTextIndex = new Index(QStringList(), QDir::homePath()); // ### Is this correct ? - if (!verifyDirectory(cacheFilesPath)) { - QMessageBox::warning(help, tr("Qt Assistant"), - tr("Failed to save fulltext search index\n" - "Assistant will not work!")); - return; - } - fullTextIndex->setDictionaryFile(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.dict.") + pname); - fullTextIndex->setDocListFile(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.doc.") + pname); - processEvents(); - - connect(fullTextIndex, SIGNAL(indexingProgress(int)), - this, SLOT(setIndexingProgress(int))); - QFile f(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.dict.") + pname); - if (!f.exists()) { - QString doc; - QSet<QString> documentSet; - QMap<QString, QString>::ConstIterator it = titleMap.constBegin(); - for (; it != titleMap.constEnd(); ++it) { - doc = HelpDialog::removeAnchorFromLink(it.key()); - if (!doc.isEmpty()) - documentSet.insert(doc); - } - loadIndexFile(); - for ( QStringList::Iterator it = keywordDocuments.begin(); it != keywordDocuments.end(); ++it ) { - if (!(*it).isEmpty()) - documentSet.insert(*it); - } - fullTextIndex->setDocList( documentSet.toList() ); - - help->statusBar()->clearMessage(); - setCursor(Qt::WaitCursor); - ui.labelPrepare->setText(tr("Indexing files...")); - ui.progressPrepare->setMaximum(100); - ui.progressPrepare->reset(); - ui.progressPrepare->show(); - ui.framePrepare->show(); - processEvents(); - if (fullTextIndex->makeIndex() == -1) - return; - fullTextIndex->writeDict(); - ui.progressPrepare->setValue(100); - ui.framePrepare->hide(); - setCursor(Qt::ArrowCursor); - showInitDoneMessage(); - } else { - setCursor(Qt::WaitCursor); - help->statusBar()->showMessage(tr("Reading dictionary...")); - processEvents(); - fullTextIndex->readDict(); - help->statusBar()->showMessage(tr("Done"), 3000); - setCursor(Qt::ArrowCursor); - } - keywordDocuments.clear(); -} - -void HelpDialog::setIndexingProgress(int prog) -{ - ui.progressPrepare->setValue(prog); - processEvents(); -} - -void HelpDialog::startSearch() -{ - QString str = ui.termsEdit->text(); - str = str.simplified(); - str = str.replace(QLatin1String("\'"), QLatin1String("\"")); - str = str.replace(QLatin1String("`"), QLatin1String("\"")); - QString buf = str; - str = str.replace(QLatin1String("-"), QLatin1String(" ")); - str = str.replace(QRegExp(QLatin1String("\\s[\\S]?\\s")), QLatin1String(" ")); - terms = str.split(QLatin1Char(' ')); - QStringList termSeq; - QStringList seqWords; - QStringList::iterator it = terms.begin(); - for (; it != terms.end(); ++it) { - (*it) = (*it).simplified(); - (*it) = (*it).toLower(); - (*it) = (*it).replace(QLatin1String("\""), QLatin1String("")); - } - if (str.contains(QLatin1Char('\"'))) { - if ((str.count(QLatin1Char('\"')))%2 == 0) { - int beg = 0; - int end = 0; - QString s; - beg = str.indexOf(QLatin1Char('\"'), beg); - while (beg != -1) { - beg++; - end = str.indexOf(QLatin1Char('\"'), beg); - s = str.mid(beg, end - beg); - s = s.toLower(); - s = s.simplified(); - if (s.contains(QLatin1Char('*'))) { - QMessageBox::warning(this, tr("Full Text Search"), - tr("Using a wildcard within phrases is not allowed.")); - return; - } - seqWords += s.split(QLatin1Char(' ')); - termSeq << s; - beg = str.indexOf(QLatin1Char('\"'), end + 1); - } - } else { - QMessageBox::warning(this, tr("Full Text Search"), - tr("The closing quotation mark is missing.")); - return; - } - } - setCursor(Qt::WaitCursor); - foundDocs.clear(); - foundDocs = fullTextIndex->query(terms, termSeq, seqWords); - QString msg = tr("%n document(s) found.", "", foundDocs.count()); - help->statusBar()->showMessage(tr(msg.toUtf8()), 3000); - ui.resultBox->clear(); - for (it = foundDocs.begin(); it != foundDocs.end(); ++it) - ui.resultBox->addItem(fullTextIndex->getDocumentTitle(*it)); - - terms.clear(); - bool isPhrase = false; - QString s; - for (int i = 0; i < (int)buf.length(); ++i) { - if (buf[i] == QLatin1Char('\"')) { - isPhrase = !isPhrase; - s = s.simplified(); - if (!s.isEmpty()) - terms << s; - s = QLatin1String(""); - } else if (buf[i] == QLatin1Char(' ') && !isPhrase) { - s = s.simplified(); - if (!s.isEmpty()) - terms << s; - s = QLatin1String(""); - } else - s += buf[i]; - } - if (!s.isEmpty()) - terms << s; - - setCursor(Qt::ArrowCursor); -} - -void HelpDialog::on_helpButton_clicked() -{ - emit showLink(MainWindow::urlifyFileName( - Config::configuration()->assistantDocPath() + - QLatin1String("/assistant-manual.html#full-text-searching"))); -} - -void HelpDialog::on_resultBox_itemActivated(QListWidgetItem *item) -{ - showResultPage(item); -} - -void HelpDialog::showResultPage(QListWidgetItem *item) -{ - if (item) - emit showSearchLink(foundDocs[ui.resultBox->row(item)], terms); -} - -void HelpDialog::showIndexItemMenu(const QPoint &pos) -{ - QListView *listView = qobject_cast<QListView*>(sender()); - if (!listView) - return; - - QModelIndex idx = listView->indexAt(pos); - if (!idx.isValid()) - return; - - QAction *action = itemPopup->exec(listView->viewport()->mapToGlobal(pos)); - if (action == actionOpenCurrentTab) { - showTopic(); - } else if (action) { - HelpWindow *hw = help->browsers()->currentBrowser(); - QString itemName = idx.data().toString(); - ui.editIndex->setText(itemName); - QStringList links = indexModel->links(idx.row()); - if (links.count() == 1) { - if (action == actionOpenLinkInNewWindow) - hw->openLinkInNewWindow(links.first()); - else - hw->openLinkInNewPage(links.first()); - } else { - QStringList::Iterator it = links.begin(); - QStringList linkList; - QStringList linkNames; - for (; it != links.end(); ++it) { - linkList << *it; - linkNames << titleOfLink(*it); - } - QString link = TopicChooser::getLink(this, linkNames, linkList, itemName); - if (!link.isEmpty()) { - if (action == actionOpenLinkInNewWindow) - hw->openLinkInNewWindow(link); - else - hw->openLinkInNewPage(link); - } - } - } -} - -void HelpDialog::showListItemMenu(const QPoint &pos) -{ - QListWidget *listWidget = qobject_cast<QListWidget*>(sender()); - if (!listWidget) - return; - QListWidgetItem *item = listWidget->itemAt(pos); - if (!item) - return; - - QAction *action = itemPopup->exec(listWidget->viewport()->mapToGlobal(pos)); - if (action == actionOpenCurrentTab) { - showResultPage(item); - } else if (action) { - HelpWindow *hw = help->browsers()->currentBrowser(); - QString link = foundDocs[ui.resultBox->row(item)]; - if (action == actionOpenLinkInNewWindow) - hw->openLinkInNewWindow(link); - else - hw->openLinkInNewPage(link); - } -} - -void HelpDialog::showTreeItemMenu(const QPoint &pos) -{ - QTreeWidget *treeWidget = qobject_cast<QTreeWidget*>(sender()); - - if (!treeWidget) - return; - - QTreeWidgetItem *item = treeWidget->itemAt(pos); - - if (!item) - return; - - QAction *action = itemPopup->exec(treeWidget->viewport()->mapToGlobal(pos)); - if (action == actionOpenCurrentTab) { - if (ui.tabWidget->currentWidget()->objectName() == QLatin1String("contentPage")) - showContentsTopic(); - else - showBookmarkTopic(); - } else if (action) { - QTreeWidgetItem *i = (QTreeWidgetItem*)item; - if (action == actionOpenLinkInNewWindow) - help->browsers()->currentBrowser()->openLinkInNewWindow(i->data(0, LinkRole).toString()); - else - help->browsers()->currentBrowser()->openLinkInNewPage(i->data(0, LinkRole).toString()); - } -} - -void HelpDialog::on_termsEdit_returnPressed() -{ - startSearch(); -} - -void HelpDialog::updateSearchButton(const QString &txt) -{ - ui.searchButton->setDisabled(txt.isEmpty()); -} - -void HelpDialog::on_searchButton_clicked() -{ - startSearch(); -} - -QString HelpDialog::removeAnchorFromLink(const QString &link) -{ - int i = link.length(); - int j = link.lastIndexOf(QLatin1Char('/')); - int l = link.lastIndexOf(QDir::separator()); - if (l > j) - j = l; - if (j > -1) { - QString fileName = link.mid(j+1); - int k = fileName.lastIndexOf(QLatin1Char('#')); - if (k > -1) - i = j + k + 1; - } - return link.left(i); -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/helpdialog.h b/tools/assistant/compat/helpdialog.h deleted file mode 100644 index 4e1bac2..0000000 --- a/tools/assistant/compat/helpdialog.h +++ /dev/null @@ -1,184 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HELPDIALOG_H -#define HELPDIALOG_H - -#include "ui_helpdialog.h" -#include "index.h" -#include "helpwindow.h" -#include "docuparser.h" - -#include <QList> -#include <QPair> -#include <QListWidget> -#include <QTreeWidget> -#include <QMap> -#include <QStringList> -#include <QValidator> -#include <qmenu.h> -#include <QHash> - -QT_BEGIN_NAMESPACE - -class QProgressBar; -class MainWindow; -class QTextBrowser; -class IndexListModel; - -class HelpNavigationListItem : public QListWidgetItem -{ -public: - HelpNavigationListItem(QListWidget *ls, const QString &txt); - - void addLink(const QString &link); - QStringList links() const { return linkList; } -private: - QStringList linkList; - -}; - -class SearchValidator : public QValidator -{ - Q_OBJECT -public: - SearchValidator(QObject *parent) - : QValidator(parent) {} - ~SearchValidator() {} - QValidator::State validate(QString &str, int &) const; -}; - -class HelpDialog : public QWidget -{ - Q_OBJECT -public: - HelpDialog(QWidget *parent, MainWindow *h); - - inline QTabWidget *tabWidget() const - { return ui.tabWidget; } - - QString titleOfLink(const QString &link); - bool eventFilter(QObject *, QEvent *); - bool lastWindowClosed() { return lwClosed; } - - void timerEvent(QTimerEvent *e); - static QString removeAnchorFromLink(const QString &link); - -signals: - void showLink(const QString &s); - void showSearchLink(const QString &s, const QStringList &terms); - -public slots: - void initialize(); - void startSearch(); - void addBookmark(); - void currentTabChanged(int index); - void locateContents(const QString &link); - -private slots: - void on_buttonAdd_clicked(); - void on_buttonRemove_clicked(); - void on_termsEdit_returnPressed(); - void on_helpButton_clicked(); - void on_searchButton_clicked(); - void on_resultBox_itemActivated(QListWidgetItem*); - void updateSearchButton(const QString &txt); - - void showResultPage(QListWidgetItem *); - - void showTopic(QTreeWidgetItem *); - void loadIndexFile(); - void insertContents(); - void setupFullTextIndex(); - void showTopic(); - void searchInIndex(const QString &s); - void toggleContents(); - void toggleIndex(); - void toggleBookmarks(); - void toggleSearch(); - void lastWinClosed(); - void setIndexingProgress(int prog); - void showListItemMenu(const QPoint &pos); - void showIndexItemMenu(const QPoint &pos); - void showTreeItemMenu(const QPoint &pos); - void insertBookmarks(); - void processEvents(); - -private: - typedef QList<ContentItem> ContentList; - void removeOldCacheFiles(bool onlyFulltextSearchIndex = false); - void buildKeywordDB(); - quint32 getFileAges(); - void showIndexTopic(); - void showBookmarkTopic(); - void setupTitleMap(); - void saveBookmarks(); - void showContentsTopic(); - void showInitDoneMessage(); - void buildContentDict(); - QTreeWidgetItem * locateLink(QTreeWidgetItem *item, const QString &link); - -private: - Ui::HelpDialog ui; - - IndexListModel *indexModel; - QMap<QString, QString> titleMap; - bool indexDone, bookmarksInserted, titleMapDone, contentsInserted; - bool lwClosed; - MainWindow *help; - QString documentationPath; - Index *fullTextIndex; - QStringList terms, foundDocs; - bool initDoneMsgShown; - void getAllContents(); - QList<QPair<QString, ContentList> > contentList; - QMenu *itemPopup; - QString cacheFilesPath; - QStringList keywordDocuments; - - QAction *actionOpenCurrentTab; - QAction *actionOpenLinkInNewWindow; - QAction *actionOpenLinkInNewTab; -}; - -QT_END_NAMESPACE - -#endif // HELPDIALOG_H diff --git a/tools/assistant/compat/helpdialog.ui b/tools/assistant/compat/helpdialog.ui deleted file mode 100644 index 0fc8817..0000000 --- a/tools/assistant/compat/helpdialog.ui +++ /dev/null @@ -1,404 +0,0 @@ -<ui version="4.0" > - <author></author> - <comment>********************************************************************* -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -*********************************************************************</comment> - <exportmacro></exportmacro> - <class>HelpDialog</class> - <widget class="QWidget" name="HelpDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>274</width> - <height>417</height> - </rect> - </property> - <property name="windowTitle" > - <string>Help</string> - </property> - <property name="whatsThis" > - <string><b>Help</b><p>Choose the topic you want help on from the contents list, or search the index for keywords.</p></string> - </property> - <layout class="QVBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QTabWidget" name="tabWidget" > - <property name="whatsThis" > - <string>Displays help topics organized by category, index or bookmarks. Another tab inherits the full text search.</string> - </property> - <widget class="QWidget" name="contentPage" > - <attribute name="title" > - <string>Con&tents</string> - </attribute> - <layout class="QVBoxLayout" > - <property name="margin" > - <number>5</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QTreeWidget" name="listContents" > - <property name="contextMenuPolicy" > - <enum>Qt::CustomContextMenu</enum> - </property> - <property name="whatsThis" > - <string><b>Help topics organized by category.</b><p>Double-click an item to see the topics in that category. To view a topic, just double-click it.</p></string> - </property> - <property name="rootIsDecorated" > - <bool>true</bool> - </property> - <property name="uniformRowHeights" > - <bool>true</bool> - </property> - <column> - <property name="text" > - <string>column 1</string> - </property> - </column> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="indexPage" > - <attribute name="title" > - <string>&Index</string> - </attribute> - <layout class="QVBoxLayout" > - <property name="margin" > - <number>5</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QLabel" name="TextLabel1" > - <property name="text" > - <string>&Look For:</string> - </property> - <property name="buddy" > - <cstring>editIndex</cstring> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="editIndex" > - <property name="toolTip" > - <string>Enter keyword</string> - </property> - <property name="whatsThis" > - <string><b>Enter a keyword.</b><p>The list will select an item that matches the entered string best.</p></string> - </property> - </widget> - </item> - <item> - <widget class="QListView" name="listIndex" > - <property name="contextMenuPolicy" > - <enum>Qt::CustomContextMenu</enum> - </property> - <property name="whatsThis" > - <string><b>List of available help topics.</b><p>Double-click on an item to open its help page. If more than one is found, you must specify which page you want.</p></string> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="bookmarkPage" > - <attribute name="title" > - <string>&Bookmarks</string> - </attribute> - <layout class="QVBoxLayout" > - <property name="margin" > - <number>5</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QTreeWidget" name="listBookmarks" > - <property name="contextMenuPolicy" > - <enum>Qt::CustomContextMenu</enum> - </property> - <property name="whatsThis" > - <string>Displays the list of bookmarks.</string> - </property> - <property name="uniformRowHeights" > - <bool>true</bool> - </property> - <column> - <property name="text" > - <string>column 1</string> - </property> - </column> - </widget> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType" > - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="buttonAdd" > - <property name="toolTip" > - <string>Add new bookmark</string> - </property> - <property name="whatsThis" > - <string>Add the currently displayed page as a new bookmark.</string> - </property> - <property name="text" > - <string>&New</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="buttonRemove" > - <property name="toolTip" > - <string>Delete bookmark</string> - </property> - <property name="whatsThis" > - <string>Delete the selected bookmark.</string> - </property> - <property name="text" > - <string>&Delete</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QWidget" name="searchPage" > - <attribute name="title" > - <string>&Search</string> - </attribute> - <layout class="QGridLayout" > - <property name="margin" > - <number>5</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item row="3" column="0" > - <spacer> - <property name="orientation" > - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType" > - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0" > - <widget class="QLabel" name="TextLabel1_2" > - <property name="text" > - <string>Searching f&or:</string> - </property> - <property name="buddy" > - <cstring>termsEdit</cstring> - </property> - </widget> - </item> - <item row="1" column="0" > - <widget class="QLineEdit" name="termsEdit" > - <property name="toolTip" > - <string>Enter searchword(s)</string> - </property> - <property name="whatsThis" > - <string><b>Enter search word(s).</b><p>Enter here the word(s) you are looking for. The words may contain wildcards (*). For a sequence of words quote them.</p></string> - </property> - </widget> - </item> - <item row="5" column="0" > - <widget class="QListWidget" name="resultBox" > - <property name="contextMenuPolicy" > - <enum>Qt::CustomContextMenu</enum> - </property> - <property name="whatsThis" > - <string><b>Found documents</b><p>This list contains all found documents from the last search. The documents are ordered, i.e. the first document has the most matches.</p></string> - </property> - </widget> - </item> - <item row="4" column="0" > - <widget class="QLabel" name="TextLabel2" > - <property name="text" > - <string>Found &Documents:</string> - </property> - <property name="buddy" > - <cstring>resultBox</cstring> - </property> - </widget> - </item> - <item row="2" column="0" > - <layout class="QHBoxLayout" > - <property name="margin" > - <number>1</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QPushButton" name="helpButton" > - <property name="toolTip" > - <string>Display the help page</string> - </property> - <property name="whatsThis" > - <string>Display the help page for the full text search.</string> - </property> - <property name="text" > - <string>He&lp</string> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType" > - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" > - <size> - <width>61</width> - <height>21</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="searchButton" > - <property name="toolTip" > - <string>Start searching</string> - </property> - <property name="whatsThis" > - <string>Pressing this button starts the search.</string> - </property> - <property name="text" > - <string>&Search</string> - </property> - <property name="enabled" > - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - <item> - <widget class="QFrame" name="framePrepare" > - <property name="frameShape" > - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow" > - <enum>QFrame::Raised</enum> - </property> - <layout class="QHBoxLayout" > - <property name="margin" > - <number>3</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QLabel" name="labelPrepare" > - <property name="text" > - <string>Preparing...</string> - </property> - </widget> - </item> - <item> - <widget class="QProgressBar" name="progressPrepare" /> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <pixmapfunction></pixmapfunction> - <tabstops> - <tabstop>tabWidget</tabstop> - <tabstop>listContents</tabstop> - <tabstop>editIndex</tabstop> - <tabstop>listIndex</tabstop> - <tabstop>listBookmarks</tabstop> - <tabstop>buttonAdd</tabstop> - <tabstop>buttonRemove</tabstop> - <tabstop>termsEdit</tabstop> - <tabstop>searchButton</tabstop> - <tabstop>helpButton</tabstop> - <tabstop>resultBox</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/tools/assistant/compat/helpwindow.cpp b/tools/assistant/compat/helpwindow.cpp deleted file mode 100644 index 6674342..0000000 --- a/tools/assistant/compat/helpwindow.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "helpwindow.h" -#include "mainwindow.h" -#include "tabbedbrowser.h" -#include "helpdialog.h" -#include "config.h" - -#include <QApplication> -#include <QClipboard> -#include <QUrl> -#include <QMessageBox> -#include <QDir> -#include <QFile> -#include <QProcess> -#include <QAction> -#include <QFileInfo> -#include <QFont> -#include <QtEvents> -#include <QTextStream> -#include <QTextCodec> -#include <QStatusBar> -#include <QTextCursor> -#include <QTextObject> -#include <QTextLayout> -#include <QtDebug> -#include <qdesktopservices.h> - -#include <QtGui/QClipboard> -#include <QtGui/QApplication> - -#if defined(Q_OS_WIN32) -# include <windows.h> -#endif - -QT_BEGIN_NAMESPACE - -HelpWindow::HelpWindow(MainWindow *w, QWidget *parent) - : QTextBrowser(parent) - , mw(w) - , blockScroll(false) - , shiftPressed(false) - , newWindow(false) -{ - FontSettings settings = Config::configuration()->fontSettings(); - setFont(settings.browserFont); - - connect(this, SIGNAL(copyAvailable(bool)), w, SLOT(copyAvailable(bool))); -} - -void HelpWindow::setSource(const QUrl &name) -{ - if (name.isValid()) { - if (name.scheme() == QLatin1String("http") || name.scheme() == QLatin1String("ftp") - || name.scheme() == QLatin1String("mailto") || name.path().endsWith(QLatin1String("pdf"))) { - bool launched = QDesktopServices::openUrl(name); - if (!launched) { - QMessageBox::information(mw, tr("Help"), - tr("Unable to launch web browser.\n"), - tr("OK")); - } - return; - } - - QFileInfo fi(name.toLocalFile()); - if (name.scheme() == QLatin1String("file") && fi.exists()) { - if (newWindow || (shiftPressed && hasFocus())) { - shiftPressed = false; - mw->saveSettings(); - MainWindow *nmw = new MainWindow; - nmw->move(mw->geometry().topLeft()); - nmw->show(); - - if (mw->isMaximized()) - nmw->showMaximized(); - - nmw->setup(); - nmw->showLink(name.toString()); - } else { - QTextBrowser::setSource(name); - QTextBrowser::scrollToAnchor(name.fragment()); - } - return; - } - } - - mw->statusBar()->showMessage(tr("Failed to open link: '%1'").arg(name.toString()), 5000); - setHtml(tr("<div align=\"center\"><h1>The page could not be found</h1><br>" - "<h3>'%1'</h3></div>").arg(name.toString())); - mw->browsers()->updateTitle(tr("Error...")); -} - -void HelpWindow::openLinkInNewWindow() -{ - if (lastAnchor.isEmpty()) - return; - newWindow = true; - setSource(lastAnchor); - newWindow = false; -} - -void HelpWindow::openLinkInNewWindow(const QString &link) -{ - lastAnchor = link; - openLinkInNewWindow(); -} - -void HelpWindow::openLinkInNewPage() -{ - if(lastAnchor.isEmpty()) - return; - mw->browsers()->newTab(lastAnchor); - lastAnchor.clear(); -} - -void HelpWindow::openLinkInNewPage(const QString &link) -{ - lastAnchor = link; - openLinkInNewPage(); -} - -bool HelpWindow::hasAnchorAt(const QPoint& pos) -{ - lastAnchor = anchorAt(pos); - if (lastAnchor.isEmpty()) - 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; - } - return true; -} - -void HelpWindow::contextMenuEvent(QContextMenuEvent *e) -{ - QMenu menu(QLatin1String(""), 0); - - 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()); - - menu.addAction(tr("Open Link in New Tab"), - this, SLOT(openLinkInNewPage())); - menu.addAction(tr("Open Link in New Window\tShift+LMB"), - this, SLOT(openLinkInNewWindow())); - } - mw->setupPopupMenu(&menu); - QAction *action = menu.exec(e->globalPos()); - if (action == copyAnchorAction) - QApplication::clipboard()->setText(link.toString()); -} - -void HelpWindow::mouseReleaseEvent(QMouseEvent *e) -{ - if (e->button() == Qt::XButton1) { - QTextBrowser::backward(); - return; - } - - if (e->button() == Qt::XButton2) { - QTextBrowser::forward(); - return; - } - - if (e->button() == Qt::MidButton && hasAnchorAt(e->pos())) { - openLinkInNewPage(); - return; - } - QTextBrowser::mouseReleaseEvent(e); -} - -void HelpWindow::blockScrolling(bool b) -{ - blockScroll = b; -} - -void HelpWindow::ensureCursorVisible() -{ - if (!blockScroll) - QTextBrowser::ensureCursorVisible(); -} - -void HelpWindow::mousePressEvent(QMouseEvent *e) -{ - shiftPressed = e->modifiers() & Qt::ShiftModifier; - if (!(shiftPressed && hasAnchorAt(e->pos()))) - QTextBrowser::mousePressEvent(e); -} - -void HelpWindow::keyPressEvent(QKeyEvent *e) -{ - shiftPressed = e->modifiers() & Qt::ShiftModifier; - QTextBrowser::keyPressEvent(e); -} - -bool HelpWindow::isKDERunning() const -{ - return !qgetenv("KDE_FULL_SESSION").isEmpty(); -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/images/assistant-128.png b/tools/assistant/compat/images/assistant-128.png Binary files differdeleted file mode 100644 index f05949f..0000000 --- a/tools/assistant/compat/images/assistant-128.png +++ /dev/null diff --git a/tools/assistant/compat/images/assistant.png b/tools/assistant/compat/images/assistant.png Binary files differdeleted file mode 100644 index ea4d1e7..0000000 --- a/tools/assistant/compat/images/assistant.png +++ /dev/null diff --git a/tools/assistant/compat/images/close.png b/tools/assistant/compat/images/close.png Binary files differdeleted file mode 100644 index 540694e..0000000 --- a/tools/assistant/compat/images/close.png +++ /dev/null diff --git a/tools/assistant/compat/images/designer.png b/tools/assistant/compat/images/designer.png Binary files differdeleted file mode 100644 index 72c42e7..0000000 --- a/tools/assistant/compat/images/designer.png +++ /dev/null diff --git a/tools/assistant/compat/images/linguist.png b/tools/assistant/compat/images/linguist.png Binary files differdeleted file mode 100644 index d388cbd..0000000 --- a/tools/assistant/compat/images/linguist.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/addtab.png b/tools/assistant/compat/images/mac/addtab.png Binary files differdeleted file mode 100644 index 20928fb..0000000 --- a/tools/assistant/compat/images/mac/addtab.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/book.png b/tools/assistant/compat/images/mac/book.png Binary files differdeleted file mode 100644 index 7a3204c..0000000 --- a/tools/assistant/compat/images/mac/book.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/closetab.png b/tools/assistant/compat/images/mac/closetab.png Binary files differdeleted file mode 100644 index ab9d669..0000000 --- a/tools/assistant/compat/images/mac/closetab.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/editcopy.png b/tools/assistant/compat/images/mac/editcopy.png Binary files differdeleted file mode 100644 index f551364..0000000 --- a/tools/assistant/compat/images/mac/editcopy.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/find.png b/tools/assistant/compat/images/mac/find.png Binary files differdeleted file mode 100644 index 3561745..0000000 --- a/tools/assistant/compat/images/mac/find.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/home.png b/tools/assistant/compat/images/mac/home.png Binary files differdeleted file mode 100644 index 78d94da..0000000 --- a/tools/assistant/compat/images/mac/home.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/next.png b/tools/assistant/compat/images/mac/next.png Binary files differdeleted file mode 100644 index a585cab..0000000 --- a/tools/assistant/compat/images/mac/next.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/prev.png b/tools/assistant/compat/images/mac/prev.png Binary files differdeleted file mode 100644 index 612fb34..0000000 --- a/tools/assistant/compat/images/mac/prev.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/print.png b/tools/assistant/compat/images/mac/print.png Binary files differdeleted file mode 100644 index 10ca56c..0000000 --- a/tools/assistant/compat/images/mac/print.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/synctoc.png b/tools/assistant/compat/images/mac/synctoc.png Binary files differdeleted file mode 100644 index 067fa94..0000000 --- a/tools/assistant/compat/images/mac/synctoc.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/whatsthis.png b/tools/assistant/compat/images/mac/whatsthis.png Binary files differdeleted file mode 100644 index 5b7078f..0000000 --- a/tools/assistant/compat/images/mac/whatsthis.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/zoomin.png b/tools/assistant/compat/images/mac/zoomin.png Binary files differdeleted file mode 100644 index d46f5af..0000000 --- a/tools/assistant/compat/images/mac/zoomin.png +++ /dev/null diff --git a/tools/assistant/compat/images/mac/zoomout.png b/tools/assistant/compat/images/mac/zoomout.png Binary files differdeleted file mode 100644 index 4632656..0000000 --- a/tools/assistant/compat/images/mac/zoomout.png +++ /dev/null diff --git a/tools/assistant/compat/images/qt.png b/tools/assistant/compat/images/qt.png Binary files differdeleted file mode 100644 index 2dc6716..0000000 --- a/tools/assistant/compat/images/qt.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/addtab.png b/tools/assistant/compat/images/win/addtab.png Binary files differdeleted file mode 100644 index 4bb0feb..0000000 --- a/tools/assistant/compat/images/win/addtab.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/book.png b/tools/assistant/compat/images/win/book.png Binary files differdeleted file mode 100644 index 09ec4d3..0000000 --- a/tools/assistant/compat/images/win/book.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/closetab.png b/tools/assistant/compat/images/win/closetab.png Binary files differdeleted file mode 100644 index ef9e020..0000000 --- a/tools/assistant/compat/images/win/closetab.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/editcopy.png b/tools/assistant/compat/images/win/editcopy.png Binary files differdeleted file mode 100644 index 1121b47..0000000 --- a/tools/assistant/compat/images/win/editcopy.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/find.png b/tools/assistant/compat/images/win/find.png Binary files differdeleted file mode 100644 index 6ea35e9..0000000 --- a/tools/assistant/compat/images/win/find.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/home.png b/tools/assistant/compat/images/win/home.png Binary files differdeleted file mode 100644 index b1c6ae1..0000000 --- a/tools/assistant/compat/images/win/home.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/next.png b/tools/assistant/compat/images/win/next.png Binary files differdeleted file mode 100644 index 8df4127..0000000 --- a/tools/assistant/compat/images/win/next.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/previous.png b/tools/assistant/compat/images/win/previous.png Binary files differdeleted file mode 100644 index 0780bc2..0000000 --- a/tools/assistant/compat/images/win/previous.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/print.png b/tools/assistant/compat/images/win/print.png Binary files differdeleted file mode 100644 index ba7c02d..0000000 --- a/tools/assistant/compat/images/win/print.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/synctoc.png b/tools/assistant/compat/images/win/synctoc.png Binary files differdeleted file mode 100644 index da301bc..0000000 --- a/tools/assistant/compat/images/win/synctoc.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/whatsthis.png b/tools/assistant/compat/images/win/whatsthis.png Binary files differdeleted file mode 100644 index 623cad6..0000000 --- a/tools/assistant/compat/images/win/whatsthis.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/zoomin.png b/tools/assistant/compat/images/win/zoomin.png Binary files differdeleted file mode 100644 index 2e586fc..0000000 --- a/tools/assistant/compat/images/win/zoomin.png +++ /dev/null diff --git a/tools/assistant/compat/images/win/zoomout.png b/tools/assistant/compat/images/win/zoomout.png Binary files differdeleted file mode 100644 index a736d39..0000000 --- a/tools/assistant/compat/images/win/zoomout.png +++ /dev/null diff --git a/tools/assistant/compat/images/wrap.png b/tools/assistant/compat/images/wrap.png Binary files differdeleted file mode 100644 index 90f18d9..0000000 --- a/tools/assistant/compat/images/wrap.png +++ /dev/null diff --git a/tools/assistant/compat/index.cpp b/tools/assistant/compat/index.cpp deleted file mode 100644 index ff54626..0000000 --- a/tools/assistant/compat/index.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "index.h" - -#include <QFile> -#include <QDir> -#include <QStringList> -#include <QApplication> -#include <QByteArray> -#include <QTextStream> -#include <QtAlgorithms> -#include <QUrl> -#include <QTextCodec> -#include <ctype.h> -#include <QTextDocument> - -QT_BEGIN_NAMESPACE - -struct Term { - Term() : frequency(-1) {} - Term( const QString &t, int f, QVector<Document> l ) : term( t ), frequency( f ), documents( l ) {} - QString term; - int frequency; - QVector<Document>documents; - bool operator<( const Term &i2 ) const { return frequency < i2.frequency; } -}; - -QDataStream &operator>>( QDataStream &s, Document &l ) -{ - s >> l.docNumber; - s >> l.frequency; - return s; -} - -QDataStream &operator<<( QDataStream &s, const Document &l ) -{ - s << (qint16)l.docNumber; - s << (qint16)l.frequency; - return s; -} - -Index::Index( const QString &dp, const QString &hp ) - : QObject( 0 ), docPath( dp ) -{ - Q_UNUSED(hp); - - alreadyHaveDocList = false; - lastWindowClosed = false; - connect( qApp, SIGNAL(lastWindowClosed()), - this, SLOT(setLastWinClosed()) ); -} - -Index::Index( const QStringList &dl, const QString &hp ) - : QObject( 0 ) -{ - Q_UNUSED(hp); - docList = dl; - alreadyHaveDocList = true; - lastWindowClosed = false; - connect( qApp, SIGNAL(lastWindowClosed()), - this, SLOT(setLastWinClosed()) ); -} - -void Index::setLastWinClosed() -{ - lastWindowClosed = true; -} - -void Index::setDictionaryFile( const QString &f ) -{ - dictFile = f; -} - -void Index::setDocListFile( const QString &f ) -{ - docListFile = f; -} - -void Index::setDocList( const QStringList &lst ) -{ - docList = lst; -} - -int Index::makeIndex() -{ - if ( !alreadyHaveDocList ) - setupDocumentList(); - if ( docList.isEmpty() ) - return 1; - QStringList::Iterator it = docList.begin(); - int steps = docList.count() / 100; - if ( !steps ) - steps++; - int prog = 0; - for ( int i = 0; it != docList.end(); ++it, ++i ) { - if ( lastWindowClosed ) { - return -1; - } - QUrl url(*it); - parseDocument( url.toLocalFile(), i ); - if ( i%steps == 0 ) { - prog++; - emit indexingProgress( prog ); - } - } - return 0; -} - -void Index::setupDocumentList() -{ - QDir d( docPath ); - QStringList filters; - filters.append(QLatin1String("*.html")); - QStringList lst = d.entryList(filters); - QStringList::ConstIterator it = lst.constBegin(); - for ( ; it != lst.constEnd(); ++it ) - docList.append( QLatin1String("file:") + docPath + QLatin1String("/") + *it ); -} - -void Index::insertInDict( const QString &str, int docNum ) -{ - if ( str == QLatin1String("amp") || str == QLatin1String("nbsp")) - return; - Entry *e = 0; - if ( dict.count() ) - e = dict[ str ]; - - if ( e ) { - if ( e->documents.last().docNumber != docNum ) - e->documents.append( Document(docNum, 1 ) ); - else - e->documents.last().frequency++; - } else { - dict.insert( str, new Entry( docNum ) ); - } -} - -QString Index::getCharsetForDocument(QFile *file) -{ - QTextStream s(file); - QString contents = s.readAll(); - - QString encoding; - int start = contents.indexOf(QLatin1String("<meta"), 0, Qt::CaseInsensitive); - if (start > 0) { - int end = contents.indexOf(QLatin1String(">"), start); - QString meta = contents.mid(start+5, end-start); - meta = meta.toLower(); - QRegExp r(QLatin1String("charset=([^\"\\s]+)")); - if (r.indexIn(meta) != -1) { - encoding = r.cap(1); - } - } - - file->seek(0); - if (encoding.isEmpty()) - return QLatin1String("utf-8"); - return encoding; -} - -void Index::parseDocument( const QString &filename, int docNum ) -{ - QFile file( filename ); - if ( !file.open(QFile::ReadOnly) ) { - qWarning( "can not open file %s", qPrintable(filename) ); - return; - } - - QTextStream s(&file); - QString en = getCharsetForDocument(&file); - s.setCodec(QTextCodec::codecForName(en.toLatin1().constData())); - - QString text = s.readAll(); - if (text.isNull()) - return; - - bool valid = true; - const QChar *buf = text.unicode(); - QChar str[64]; - QChar c = buf[0]; - int j = 0; - int i = 0; - while ( j < text.length() ) { - if ( c == QLatin1Char('<') || c == QLatin1Char('&') ) { - valid = false; - if ( i > 1 ) - insertInDict( QString(str,i), docNum ); - i = 0; - c = buf[++j]; - continue; - } - if ( ( c == QLatin1Char('>') || c == QLatin1Char(';') ) && !valid ) { - valid = true; - c = buf[++j]; - continue; - } - if ( !valid ) { - c = buf[++j]; - continue; - } - if ( ( c.isLetterOrNumber() || c == QLatin1Char('_') ) && i < 63 ) { - str[i] = c.toLower(); - ++i; - } else { - if ( i > 1 ) - insertInDict( QString(str,i), docNum ); - i = 0; - } - c = buf[++j]; - } - if ( i > 1 ) - insertInDict( QString(str,i), docNum ); - file.close(); -} - -void Index::writeDict() -{ - QFile f( dictFile ); - if ( !f.open(QFile::WriteOnly ) ) - return; - QDataStream s( &f ); - for(QHash<QString, Entry *>::Iterator it = dict.begin(); it != dict.end(); ++it) { - s << it.key(); - s << it.value()->documents.count(); - s << it.value()->documents; - } - f.close(); - writeDocumentList(); -} - -void Index::writeDocumentList() -{ - QFile f( docListFile ); - if ( !f.open(QFile::WriteOnly ) ) - return; - QDataStream s( &f ); - s << docList; -} - -void Index::readDict() -{ - QFile f( dictFile ); - if ( !f.open(QFile::ReadOnly ) ) - return; - - dict.clear(); - QDataStream s( &f ); - QString key; - int numOfDocs; - QVector<Document> docs; - while ( !s.atEnd() ) { - s >> key; - s >> numOfDocs; - docs.resize(numOfDocs); - s >> docs; - dict.insert( key, new Entry( docs ) ); - } - f.close(); - readDocumentList(); -} - -void Index::readDocumentList() -{ - QFile f( docListFile ); - if ( !f.open(QFile::ReadOnly ) ) - return; - QDataStream s( &f ); - s >> docList; -} - -QStringList Index::query( const QStringList &terms, const QStringList &termSeq, const QStringList &seqWords ) -{ - QList<Term> termList; - for (QStringList::ConstIterator it = terms.begin(); it != terms.end(); ++it ) { - Entry *e = 0; - if ( (*it).contains(QLatin1Char('*')) ) { - QVector<Document> wcts = setupDummyTerm( getWildcardTerms( *it ) ); - termList.append( Term(QLatin1String("dummy"), wcts.count(), wcts ) ); - } else if ( dict[ *it ] ) { - e = dict[ *it ]; - termList.append( Term( *it, e->documents.count(), e->documents ) ); - } else { - return QStringList(); - } - } - if ( !termList.count() ) - return QStringList(); - qSort(termList); - - QVector<Document> minDocs = termList.takeFirst().documents; - for(QList<Term>::Iterator it = termList.begin(); it != termList.end(); ++it) { - Term *t = &(*it); - QVector<Document> docs = t->documents; - for(QVector<Document>::Iterator minDoc_it = minDocs.begin(); minDoc_it != minDocs.end(); ) { - bool found = false; - for (QVector<Document>::ConstIterator doc_it = docs.constBegin(); doc_it != docs.constEnd(); ++doc_it ) { - if ( (*minDoc_it).docNumber == (*doc_it).docNumber ) { - (*minDoc_it).frequency += (*doc_it).frequency; - found = true; - break; - } - } - if ( !found ) - minDoc_it = minDocs.erase( minDoc_it ); - else - ++minDoc_it; - } - } - - QStringList results; - qSort( minDocs ); - if ( termSeq.isEmpty() ) { - for(QVector<Document>::Iterator it = minDocs.begin(); it != minDocs.end(); ++it) - results << docList.at((int)(*it).docNumber); - return results; - } - - QString fileName; - for(QVector<Document>::Iterator it = minDocs.begin(); it != minDocs.end(); ++it) { - fileName = docList[ (int)(*it).docNumber ]; - if ( searchForPattern( termSeq, seqWords, fileName ) ) - results << fileName; - } - return results; -} - -QString Index::getDocumentTitle( const QString &fullFileName ) -{ - QUrl url(fullFileName); - QString fileName = url.toLocalFile(); - - if (documentTitleCache.contains(fileName)) - return documentTitleCache.value(fileName); - - QFile file( fileName ); - if ( !file.open( QFile::ReadOnly ) ) { - qWarning( "cannot open file %s", qPrintable(fileName) ); - return fileName; - } - QTextStream s( &file ); - QString text = s.readAll(); - - int start = text.indexOf(QLatin1String("<title>"), 0, Qt::CaseInsensitive) + 7; - int end = text.indexOf(QLatin1String("</title>"), 0, Qt::CaseInsensitive); - - QString title = tr("Untitled"); - if (end - start > 0) { - title = text.mid(start, end - start); - if (Qt::mightBeRichText(title)) { - QTextDocument doc; - doc.setHtml(title); - title = doc.toPlainText(); - } - } - documentTitleCache.insert(fileName, title); - return title; -} - -QStringList Index::getWildcardTerms( const QString &term ) -{ - QStringList lst; - QStringList terms = split( term ); - QStringList::Iterator iter; - - for(QHash<QString, Entry*>::Iterator it = dict.begin(); it != dict.end(); ++it) { - int index = 0; - bool found = false; - QString text( it.key() ); - for ( iter = terms.begin(); iter != terms.end(); ++iter ) { - if ( *iter == QLatin1String("*") ) { - found = true; - continue; - } - if ( iter == terms.begin() && (*iter)[0] != text[0] ) { - found = false; - break; - } - index = text.indexOf( *iter, index ); - if ( *iter == terms.last() && index != (int)text.length()-1 ) { - index = text.lastIndexOf( *iter ); - if ( index != (int)text.length() - (int)(*iter).length() ) { - found = false; - break; - } - } - if ( index != -1 ) { - found = true; - index += (*iter).length(); - continue; - } else { - found = false; - break; - } - } - if ( found ) - lst << text; - } - - return lst; -} - -QStringList Index::split( const QString &str ) -{ - QStringList lst; - int j = 0; - int i = str.indexOf(QLatin1Char('*'), j ); - - if (str.startsWith(QLatin1String("*"))) - lst << QLatin1String("*"); - - while ( i != -1 ) { - if ( i > j && i <= (int)str.length() ) { - lst << str.mid( j, i - j ); - lst << QLatin1String("*"); - } - j = i + 1; - i = str.indexOf(QLatin1Char('*'), j ); - } - - int l = str.length() - 1; - if ( str.mid( j, l - j + 1 ).length() > 0 ) - lst << str.mid( j, l - j + 1 ); - - return lst; -} - -QVector<Document> Index::setupDummyTerm( const QStringList &terms ) -{ - QList<Term> termList; - for (QStringList::ConstIterator it = terms.begin(); it != terms.end(); ++it) { - Entry *e = 0; - if ( dict[ *it ] ) { - e = dict[ *it ]; - termList.append( Term( *it, e->documents.count(), e->documents ) ); - } - } - QVector<Document> maxList(0); - if ( !termList.count() ) - return maxList; - qSort(termList); - - maxList = termList.takeLast().documents; - for(QList<Term>::Iterator it = termList.begin(); it != termList.end(); ++it) { - Term *t = &(*it); - QVector<Document> docs = t->documents; - for (QVector<Document>::iterator docIt = docs.begin(); docIt != docs.end(); ++docIt ) { - if ( maxList.indexOf( *docIt ) == -1 ) - maxList.append( *docIt ); - } - } - return maxList; -} - -void Index::buildMiniDict( const QString &str ) -{ - if ( miniDict[ str ] ) - miniDict[ str ]->positions.append( wordNum ); - ++wordNum; -} - -bool Index::searchForPattern( const QStringList &patterns, const QStringList &words, const QString &fileName ) -{ - QUrl url(fileName); - QString fName = url.toLocalFile(); - QFile file( fName ); - if ( !file.open( QFile::ReadOnly ) ) { - qWarning( "cannot open file %s", qPrintable(fName) ); - return false; - } - - wordNum = 3; - miniDict.clear(); - QStringList::ConstIterator cIt = words.begin(); - for ( ; cIt != words.end(); ++cIt ) - miniDict.insert( *cIt, new PosEntry( 0 ) ); - - QTextStream s( &file ); - QString text = s.readAll(); - bool valid = true; - const QChar *buf = text.unicode(); - QChar str[64]; - QChar c = buf[0]; - int j = 0; - int i = 0; - while ( j < text.length() ) { - if ( c == QLatin1Char('<') || c == QLatin1Char('&') ) { - valid = false; - if ( i > 1 ) - buildMiniDict( QString(str,i) ); - i = 0; - c = buf[++j]; - continue; - } - if ( ( c == QLatin1Char('>') || c == QLatin1Char(';') ) && !valid ) { - valid = true; - c = buf[++j]; - continue; - } - if ( !valid ) { - c = buf[++j]; - continue; - } - if ( ( c.isLetterOrNumber() || c == QLatin1Char('_') ) && i < 63 ) { - str[i] = c.toLower(); - ++i; - } else { - if ( i > 1 ) - buildMiniDict( QString(str,i) ); - i = 0; - } - c = buf[++j]; - } - if ( i > 1 ) - buildMiniDict( QString(str,i) ); - file.close(); - - QStringList::ConstIterator patIt = patterns.begin(); - QStringList wordLst; - QList<uint> a, b; - QList<uint>::iterator aIt; - for ( ; patIt != patterns.end(); ++patIt ) { - wordLst = (*patIt).split(QLatin1Char(' ')); - a = miniDict[ wordLst[0] ]->positions; - for ( int j = 1; j < (int)wordLst.count(); ++j ) { - b = miniDict[ wordLst[j] ]->positions; - aIt = a.begin(); - while ( aIt != a.end() ) { - if ( b.contains( *aIt + 1 )) { - (*aIt)++; - ++aIt; - } else { - aIt = a.erase( aIt ); - } - } - } - } - if ( a.count() ) - return true; - return false; -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/index.h b/tools/assistant/compat/index.h deleted file mode 100644 index 9dd6d54..0000000 --- a/tools/assistant/compat/index.h +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef INDEX_H -#define INDEX_H - -#include <QStringList> -#include <QHash> -#include <QDataStream> -#include <QObject> -#include <QList> -#include <QFile> -#include <QVector> - -QT_BEGIN_NAMESPACE - -struct Document { - Document( int d, int f ) : docNumber( d ), frequency( f ) {} - Document() : docNumber( -1 ), frequency( 0 ) {} - bool operator==( const Document &doc ) const { - return docNumber == doc.docNumber; - } - bool operator<( const Document &doc ) const { - return frequency > doc.frequency; - } - bool operator<=( const Document &doc ) const { - return frequency >= doc.frequency; - } - bool operator>( const Document &doc ) const { - return frequency < doc.frequency; - } - qint16 docNumber; - qint16 frequency; -}; - -QDataStream &operator>>( QDataStream &s, Document &l ); -QDataStream &operator<<( QDataStream &s, const Document &l ); - -class Index : public QObject -{ - Q_OBJECT -public: - struct Entry { - Entry( int d ) { documents.append( Document( d, 1 ) ); } - Entry( QVector<Document> l ) : documents( l ) {} - QVector<Document> documents; - }; - struct PosEntry { - PosEntry( int p ) { positions.append( p ); } - QList<uint> positions; - }; - - Index( const QString &dp, const QString &hp ); - Index( const QStringList &dl, const QString &hp ); - void writeDict(); - void readDict(); - int makeIndex(); - QStringList query( const QStringList&, const QStringList&, const QStringList& ); - QString getDocumentTitle( const QString& ); - void setDictionaryFile( const QString& ); - void setDocListFile( const QString& ); - void setDocList( const QStringList & ); - -signals: - void indexingProgress( int ); - -private slots: - void setLastWinClosed(); - -private: - void setupDocumentList(); - void parseDocument( const QString&, int ); - void insertInDict( const QString&, int ); - void writeDocumentList(); - void readDocumentList(); - QStringList getWildcardTerms( const QString& ); - QStringList split( const QString& ); - QVector<Document> setupDummyTerm( const QStringList& ); - bool searchForPattern( const QStringList&, const QStringList&, const QString& ); - void buildMiniDict( const QString& ); - QString getCharsetForDocument(QFile *); - QStringList docList; - QHash<QString, Entry*> dict; - QHash<QString, PosEntry*> miniDict; - uint wordNum; - QString docPath; - QString dictFile, docListFile; - bool alreadyHaveDocList; - bool lastWindowClosed; - QHash<QString, QString> documentTitleCache; -}; - -#endif - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/lib/lib.pro b/tools/assistant/compat/lib/lib.pro deleted file mode 100644 index e50d470..0000000 --- a/tools/assistant/compat/lib/lib.pro +++ /dev/null @@ -1,78 +0,0 @@ -TEMPLATE = lib -QT += network -TARGET = QtAssistantClient -isEmpty(QT_MAJOR_VERSION) { - VERSION=4.3.0 -} else { - VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} -} - -CONFIG += qt warn_on -mac|win32:CONFIG += debug_and_release -mac:unix:CONFIG += explicitlib -CONFIG -= dll - -HEADERS = qassistantclient.h \ - qassistantclient_global.h -SOURCES = qassistantclient.cpp - -DESTDIR = ../../../../lib -DLLDESTDIR = ../../../../bin - -unix { - QMAKE_CFLAGS += $$QMAKE_CFLAGS_SHLIB - QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_SHLIB -} - -DEFINES += QT_ASSISTANT_CLIENT_LIBRARY -contains(CONFIG, static) { - DEFINES += QT_ASSISTANT_CLIENT_STATIC -} - -#load up the headers info -CONFIG += qt_install_headers -HEADERS_PRI = $$QT_BUILD_TREE/include/QtAssistant/headers.pri -include($$HEADERS_PRI, "", true)|clear(HEADERS_PRI) - -#mac frameworks -mac:!static:contains(QT_CONFIG, qt_framework) { - TARGET = QtAssistant # Change the name to match the headers - QMAKE_FRAMEWORK_BUNDLE_NAME = $$TARGET - CONFIG += lib_bundle qt_no_framework_direct_includes qt_framework - CONFIG(debug, debug|release) { - !build_pass:CONFIG += build_all - } else { #release - !debug_and_release|build_pass { - CONFIG -= qt_install_headers #no need to install these as well - FRAMEWORK_HEADERS.version = Versions - FRAMEWORK_HEADERS.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES - FRAMEWORK_HEADERS.path = Headers - } - QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS - } -} - -TARGET = $$qtLibraryTarget($$TARGET$$QT_LIBINFIX) #done towards the end - -target.path=$$[QT_INSTALL_LIBS] -INSTALLS += target -win32 { - dlltarget.path=$$[QT_INSTALL_BINS] - INSTALLS += dlltarget -} - -qt_install_headers { - assistant_headers.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES - assistant_headers.path = $$[QT_INSTALL_HEADERS]/QtAssistant - INSTALLS += assistant_headers -} - -unix { - CONFIG += create_pc - QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS] - QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/QtAssistant - QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS] - QMAKE_PKGCONFIG_DESTDIR = pkgconfig - QMAKE_PKGCONFIG_REQUIRES += QtNetwork -} - diff --git a/tools/assistant/compat/lib/qassistantclient.cpp b/tools/assistant/compat/lib/qassistantclient.cpp deleted file mode 100644 index 72d0a92..0000000 --- a/tools/assistant/compat/lib/qassistantclient.cpp +++ /dev/null @@ -1,446 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qassistantclient.h" - -#include <qtcpsocket.h> -#include <qtextstream.h> -#include <qtimer.h> -#include <qfileinfo.h> -#include <qmap.h> - -QT_BEGIN_NAMESPACE - -class QAssistantClientPrivate -{ - friend class QAssistantClient; - QStringList arguments; -}; - -static QMap<const QAssistantClient*,QAssistantClientPrivate*> *dpointers = 0; - -static QAssistantClientPrivate *data( const QAssistantClient *client, bool create=false ) -{ - if( !dpointers ) - dpointers = new QMap<const QAssistantClient*,QAssistantClientPrivate*>; - QAssistantClientPrivate *d = (*dpointers)[client]; - if( !d && create ) { - d = new QAssistantClientPrivate; - dpointers->insert( client, d ); - } - return d; -} - -/*! - \class QAssistantClient - \obsolete - \brief The QAssistantClient class provides a means of using Qt - Assistant as an application's help tool. - - \ingroup helpsystem - - \bold{Note:} \e{This class is obsolete and only required when using - the old Qt Assistant, now called assistant_adp. If you want to use - the new Qt Assistant as a remote help viewer, simple create a - QProcess instance and specify \tt{assistant} as its executable. - The following code shows how to start Qt Assistant and request a - certain page to be shown:} - - \snippet doc/src/snippets/code/tools_assistant_compat_lib_qassistantclient.cpp 0 - - \e{For a complete example using the Qt Assistant remotely, see the \l - {help/remotecontrol}{Remote Control} example.} - - In order to make Qt Assistant act as a customized help tool for - your application, you must provide your application with a - QAssistantClient object in addition to a \l - {assistant-manual.html} {Qt Assistant Document Profile} (\c .adp - file) and the associated documentation. - - Note that the QAssistantClient class is not included in the Qt - library. To use it you must add the following line to your pro - file: - - \snippet doc/src/snippets/code/tools_assistant_compat_lib_qassistantclient.cpp 1 - - A QAssistantClient instance can open or close Qt Assistant - whenever it is required. - - Once you have created a QAssistantClient instance, specifying the - path to the Qt Assistant executable, using Qt Assistant is - simple: You can either call the openAssistant() slot to show the - defined start page of the documentation, or you can call the - showPage() slot to show a particular help page. When you call - openAssistant() and showPage(), Qt Assistant will be launched if - it isn't already running. When Qt Assistant is running, the - isOpen() function returns true. - - When calling showPage() the Qt Assistant instance will also be - brought to the foreground if its hidden. The showPage() slot can - be called multiple times, while calling openAssistant() several - times without closing the application in between, will have no - effect. - - You can close Qt Assistant at any time using the closeAssistant() - slot. When you call openAssistant(), or you call showPage() - without a previous call to openAssistant(), the assistantOpened() - signal is emitted. Similarly when closeAssistant() is called, - assistantClosed() is emitted. In either case, if an error occurs, - error() is emitted. - - One QAssistantClient instance interacts with one Qt Assistant - instance, so every time you call openAssistant(), showPage() or - closeAssistant() they are applied to the particular Qt Assistant - instance associated with the QAssistantClient. - - Qt Assistant's documentation set can be altered using the command - line arguments that are passed to the application when it is - launched. When started without any options, Qt Assistant displays - a default set of documentation. When Qt is installed, the default - documentation set in Qt Assistant contains the Qt reference - documentation as well as the tools that come with Qt, such as \QD - and \c qmake. - - Use the setArguments() function to specify the command line - arguments. You can add or remove documentation from Qt Assistant - by adding and removing the relevant content files: The command - line arguments are \c {-addContentFile file.dcf} and \c - {-removeContentFile file.dcf} respectively. You can make Qt - Assistant run customized documentation sets that are separate from - the Qt documentation, by specifying a profile: \c {-profile - myapplication.adp}. The profile format can also be used to alter - several of Qt Assistant's properties such as its title and - startpage. - - The Documentation Content File (\c .dcf) and Qt Assistant - Documentation Profile (\c .adp) formats are documented in the \l - {assistant-manual.html}{Qt Assistant Manual}. - - For a complete example using the QAssistantClient class, see the - \e{Simple Text Viewer} example. The example shows how you can make - Qt Assistant act as a customized help tool for your application - using the QAssistantClient class combined with a Qt Assistant - Document Profile. - - \sa {Qt Assistant Manual}, {Simple Text Viewer Example} -*/ - -/*! - \fn void QAssistantClient::assistantOpened() - - This signal is emitted when Qt Assistant is opened and the - client-server communication is set up. - - \sa openAssistant(), showPage() -*/ - -/*! - \fn void QAssistantClient::assistantClosed() - - This signal is emitted when the connection to Qt Assistant is - closed. This happens when the user exits Qt Assistant, if an - error in the server or client occurs, or if closeAssistant() is - called. - - \sa closeAssistant() -*/ - -/*! - \fn void QAssistantClient::error( const QString &message ) - - This signal is emitted if Qt Assistant cannot be started, or if an - error occurs during the initialization of the connection between - Qt Assistant and the calling application. The \a message provides an - explanation of the error. -*/ - -/*! - Constructs an assistant client with the specified \a parent. For - systems other than Mac OS, \a path specifies the path to the Qt - Assistant executable. For Mac OS, \a path specifies a directory - containing a valid assistant.app bundle. If \a path is the empty - string, the system path (\c{%PATH%} or \c $PATH) is used. -*/ -QAssistantClient::QAssistantClient( const QString &path, QObject *parent ) - : QObject( parent ), host ( QLatin1String("localhost") ) -{ -#if defined(Q_OS_MAC) - const QString assistant = QLatin1String("Assistant_adp"); -#else - const QString assistant = QLatin1String("assistant_adp"); -#endif - - if ( path.isEmpty() ) - assistantCommand = assistant; - else { - QFileInfo fi( path ); - if ( fi.isDir() ) - assistantCommand = path + QLatin1String("/") + assistant; - else - assistantCommand = path; - } - -#if defined(Q_OS_MAC) - assistantCommand += QLatin1String(".app/Contents/MacOS/Assistant_adp"); -#endif - - socket = new QTcpSocket( this ); - connect( socket, SIGNAL(connected()), - SLOT(socketConnected()) ); - connect( socket, SIGNAL(disconnected()), - SLOT(socketConnectionClosed()) ); - connect( socket, SIGNAL(error(QAbstractSocket::SocketError)), - SLOT(socketError()) ); - opened = false; - proc = new QProcess( this ); - port = 0; - pageBuffer = QLatin1String(""); - connect( proc, SIGNAL(readyReadStandardError()), - this, SLOT(readStdError()) ); - connect( proc, SIGNAL(error(QProcess::ProcessError)), - this, SLOT(procError(QProcess::ProcessError)) ); -} - -/*! - Destroys the assistant client object. -*/ -QAssistantClient::~QAssistantClient() -{ - if ( proc->state() == QProcess::Running ) - proc->terminate(); - - if( dpointers ) { - QAssistantClientPrivate *d = (*dpointers)[ this ]; - if ( d ) { - dpointers->remove(this); - delete d; - if( dpointers->isEmpty() ) { - delete dpointers; - dpointers = 0; - } - } - } -} - -/*! - Opens Qt Assistant, i.e. sets up the client-server communication - between the application and Qt Assistant, and shows the start page - specified by the current \l {assistant-manual.html} - {Qt Assistant Document Profile}. If there is no specfied profile, - and Qt is installed, the default start page is the Qt Reference - Documentation's index page. - - If the connection is already established, this function does - nothing. Use the showPage() function to show another page. If an - error occurs, the error() signal is emitted. - - \sa showPage(), assistantOpened() -*/ -void QAssistantClient::openAssistant() -{ - if ( proc->state() == QProcess::Running ) - return; - - QStringList args; - args.append(QLatin1String("-server")); - if( !pageBuffer.isEmpty() ) { - args.append( QLatin1String("-file") ); - args.append( pageBuffer ); - } - - QAssistantClientPrivate *d = data( this ); - if( d ) { - QStringList::ConstIterator it = d->arguments.constBegin(); - while( it!=d->arguments.constEnd() ) { - args.append( *it ); - ++it; - } - } - - connect( proc, SIGNAL(readyReadStandardOutput()), - this, SLOT(readPort()) ); - - proc->start(assistantCommand, args); -} - -void QAssistantClient::procError(QProcess::ProcessError err) -{ - switch (err) - { - case QProcess::FailedToStart: - emit error( tr( "Failed to start Qt Assistant." ) ); - break; - case QProcess::Crashed: - emit error( tr( "Qt Assistant crashed." ) ); - break; - default: - emit error( tr( "Error while running Qt Assistant." ) ); - } -} - -void QAssistantClient::readPort() -{ - QString p(QString::fromLatin1(proc->readAllStandardOutput())); - quint16 port = p.toUShort(); - if ( port == 0 ) { - emit error( tr( "Cannot connect to Qt Assistant." ) ); - return; - } - socket->connectToHost( host, port ); - disconnect( proc, SIGNAL(readyReadStandardOutput()), - this, SLOT(readPort()) ); -} - -/*! - Closes the Qt Assistant instance. - - \sa openAssistant(), assistantClosed() -*/ -void QAssistantClient::closeAssistant() -{ - if ( !opened ) - return; - - bool blocked = proc->blockSignals(true); - proc->terminate(); - if (!proc->waitForFinished(2000)) { - // If the process hasn't died after 2 seconds, - // we kill it, causing it to exit immediately. - proc->kill(); - } - proc->blockSignals(blocked); -} - -/*! - Brings Qt Assistant to the foreground showing the given \a page. - The \a page parameter is a path to an HTML file - (e.g., QLatin1String("/home/pasquale/superproduct/docs/html/intro.html")). - - If Qt Assistant hasn't been opened yet, this function will call - the openAssistant() slot with the specified page as the start - page. - - \note The first time Qt Assistant is started, its window will open - in front of the application's windows. Subsequent calls to this function - will only load the specified pages in Qt Assistant and will not display - its window in front of the application's windows. - - \sa openAssistant() -*/ -void QAssistantClient::showPage( const QString &page ) -{ - if (opened) { - QTextStream os( socket ); - os << page << QLatin1String("\n"); - } else { - pageBuffer = page; - - if (proc->state() == QProcess::NotRunning) { - openAssistant(); - pageBuffer.clear(); - return; - } - } -} - -/*! - \property QAssistantClient::open - \brief whether Qt Assistant is open - -*/ -bool QAssistantClient::isOpen() const -{ - return opened; -} - -void QAssistantClient::socketConnected() -{ - opened = true; - if ( !pageBuffer.isEmpty() ) - showPage( pageBuffer ); - emit assistantOpened(); -} - -void QAssistantClient::socketConnectionClosed() -{ - opened = false; - emit assistantClosed(); -} - -void QAssistantClient::socketError() -{ - QAbstractSocket::SocketError err = socket->error(); - if (err == QTcpSocket::ConnectionRefusedError) - emit error( tr( "Could not connect to Assistant: Connection refused" ) ); - else if (err == QTcpSocket::HostNotFoundError) - emit error( tr( "Could not connect to Assistant: Host not found" ) ); - else if (err != QTcpSocket::RemoteHostClosedError) - emit error( tr( "Communication error" ) ); -} - -void QAssistantClient::readStdError() -{ - QString errmsg = QString::fromLatin1(proc->readAllStandardError()); - - if (!errmsg.isEmpty()) - emit error( errmsg.simplified() ); -} - -/*! - \fn void QAssistantClient::setArguments(const QStringList &arguments) - - Sets the command line \a arguments that are passed to Qt Assistant - when it is launched. - - The command line arguments can be used to alter Qt Assistant's - documentation set. When started without any options, Qt Assistant - displays a default set of documentation. When Qt is installed, the - default documentation set in Qt Assistant contains the Qt - reference documentation as well as the tools that come with Qt, - such as Qt Designer and qmake. -*/ -void QAssistantClient::setArguments( const QStringList &args ) -{ - QAssistantClientPrivate *d = data( this, true ); - d->arguments = args; -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/main.cpp b/tools/assistant/compat/main.cpp deleted file mode 100644 index c16c52e..0000000 --- a/tools/assistant/compat/main.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mainwindow.h" -#include "helpdialog.h" -#include "config.h" - -#include <QTcpServer> -#include <QTcpSocket> -#include <QApplication> -#include <QPixmap> -#include <QStringList> -#include <QDir> -#include <QMessageBox> -#include <QPointer> -#include <QTranslator> -#include <QLibraryInfo> -#include <QLocale> -#include <stdlib.h> -#include <stdio.h> - -#if defined(USE_STATIC_JPEG_PLUGIN) - #include <QtPlugin> - Q_IMPORT_PLUGIN(qjpeg) -#endif - -#define INDEX_CHECK( text ) if( i+1 >= argc ) { fprintf(stderr, "%s\n", text); return 1; } - -QT_BEGIN_NAMESPACE - -#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX) -QT_BEGIN_INCLUDE_NAMESPACE -#include <QtDBus/QDBusConnection> -#include <QtDBus/QDBusAbstractAdaptor> -#include <QtDBus/QDBusObjectPath> -#include "tabbedbrowser.h" -QT_END_INCLUDE_NAMESPACE - -class HelpWindowAdaptor : public QDBusAbstractAdaptor -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "com.trolltech.Assistant.HelpWindow") - - Q_PROPERTY(QString source READ source WRITE setSource) - -public: - HelpWindowAdaptor(HelpWindow *w) : QDBusAbstractAdaptor(w), helpWindow(w) - { - setAutoRelaySignals(true); - } - -public Q_SLOTS: - inline QString source() const { return helpWindow->source().toString(); } - inline void setSource(const QString &src) { helpWindow->setSource(src); } - - inline void clearHistory() { helpWindow->clearHistory(); } - inline void backward() { helpWindow->backward(); } - inline void forward() { helpWindow->forward(); } - inline void reload() { helpWindow->reload(); } - inline void home() { helpWindow->home(); } - -private: - HelpWindow *helpWindow; -}; - -class AssistantAdaptor : public QDBusAbstractAdaptor -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "com.trolltech.Assistant.HelpViewer") - -public: - AssistantAdaptor(MainWindow *mw) : QDBusAbstractAdaptor(mw), mw(mw) - { - QDBusConnection connection = QDBusConnection::sessionBus(); - connection.registerService(QLatin1String("com.trolltech.Assistant")); - connection.registerObject(QLatin1String("/Assistant"), mw); - } - -public slots: - void showLink(const QString &link) { mw->showLink(link); } - QDBusObjectPath createNewTab(); - QDBusObjectPath currentTab(); - -private: - QDBusObjectPath pathForBrowser(HelpWindow *window); - MainWindow *mw; -}; - -QDBusObjectPath AssistantAdaptor::createNewTab() -{ - HelpWindow *window = mw->browsers()->newBackgroundTab(); - return pathForBrowser(window); -} - -QDBusObjectPath AssistantAdaptor::currentTab() -{ - HelpWindow *window = mw->browsers()->currentBrowser(); - return pathForBrowser(window); -} - -QDBusObjectPath AssistantAdaptor::pathForBrowser(HelpWindow *window) -{ - int index = mw->browsers()->browsers().indexOf(window); - if (index == -1) - return QDBusObjectPath(); - - QString name(QLatin1String("/Assistant/Tabs/")); - name += QString::number(index); - QDBusObjectPath path(name); - - if (!window->findChild<HelpWindowAdaptor *>()) { - (void)new HelpWindowAdaptor(window); - QDBusConnection::sessionBus().registerObject(name, window); - } - - return path; -} - -#endif // QT_NO_DBUS - -class AssistantSocket : public QTcpSocket -{ - Q_OBJECT -public: - AssistantSocket( int sock, QObject *parent = 0 ); - ~AssistantSocket() {} - -signals: - void showLinkRequest( const QString& ); - -private slots: - void readClient(); - void connectionClosed(); -}; - - -class AssistantServer : public QTcpServer -{ - Q_OBJECT -public: - AssistantServer( QObject* parent = 0 ); - quint16 getPort() const; - -signals: - void showLinkRequest( const QString& ); - void newConnect(); - -public slots: - virtual void incomingConnection( int socket ); - -private: - quint16 p; -}; - -AssistantSocket::AssistantSocket( int sock, QObject *parent ) - : QTcpSocket( parent ) -{ - connect( this, SIGNAL(readyRead()), SLOT(readClient()) ); - connect( this, SIGNAL(disconnected()), SLOT(connectionClosed()) ); - setSocketDescriptor( sock ); -} - -void AssistantSocket::readClient() -{ - QString link = QString(); - while ( canReadLine() ) - link = QLatin1String(readLine()); - if ( !link.isNull() ) { - link = link.replace(QLatin1String("\n"), QLatin1String("")); - link = link.replace(QLatin1String("\r"), QLatin1String("")); - QFileInfo fi(link); - link = fi.absoluteFilePath(); - emit showLinkRequest( link ); - } -} - -void AssistantSocket::connectionClosed() -{ - deleteLater(); -} - -AssistantServer::AssistantServer( QObject *parent ) - : QTcpServer( parent ) -{ - listen(QHostAddress::LocalHost, 0); - if ( !isListening() ) { - QMessageBox::critical( 0, tr( "Qt Assistant" ), - tr( "Failed to bind to port %1" ).arg( serverPort() ) ); - exit( 1 ); - } - p = serverPort(); -} - -quint16 AssistantServer::getPort() const -{ - return p; -} - -void AssistantServer::incomingConnection( int socket ) -{ - AssistantSocket *as = new AssistantSocket( socket, this ); - connect( as, SIGNAL(showLinkRequest(QString)), - this, SIGNAL(showLinkRequest(QString)) ); - emit newConnect(); -} - -int runAssistant( int argc, char ** argv ) -{ - bool withGUI = true; -#ifndef Q_WS_WIN - if ( argc > 1 ) { - QString arg = QString::fromLocal8Bit(argv[1]); - arg = arg.toLower(); - if ( arg == QLatin1String("-addcontentfile") - || arg == QLatin1String("-removecontentfile") - || arg == QLatin1String("-help") - || arg == QLatin1String("/?") - ) - withGUI = false; - } -#endif - QApplication a(argc, argv, withGUI); - a.setOrganizationName(QLatin1String("Trolltech")); - a.setApplicationName(QLatin1String("Assistant")); - - QString resourceDir; - AssistantServer *as = 0; - QStringList catlist; - QString file, profileName, aDocPath; - bool server = false; - bool hideSidebar = false; - bool configLoaded = false; - if ( argc == 2 ) { - file = QString::fromLocal8Bit(argv[1]); - if (file.startsWith(QLatin1String("-")) || file == QLatin1String("/?")) { - file.clear(); - } else { - QFileInfo fi(file); - file = fi.absoluteFilePath(); - file = MainWindow::urlifyFileName(file); - } - } - if ( file.isEmpty() ) { - for ( int i = 1; i < argc; i++ ) { - QString opt = QString::fromLocal8Bit(argv[i]).toLower(); - if ( opt == QLatin1String("-file") ) { - INDEX_CHECK( "Missing file argument!" ); - i++; - file = QFile::decodeName(argv[i]); - } else if ( opt == QLatin1String("-server") ) { - server = true; - } else if ( opt == QLatin1String("-profile") ) { - INDEX_CHECK( "Missing profile argument!" ); - profileName = QFile::decodeName(argv[++i]); - } else if ( opt == QLatin1String("-addcontentfile") ) { - INDEX_CHECK( "Missing content file!" ); - Config *c = Config::loadConfig(QString()); - QFileInfo file( QFile::decodeName(argv[i+1]) ); - if( !file.exists() ) { - fprintf(stderr, "Could not locate content file: %s\n", qPrintable(file.absoluteFilePath())); - return 1; - } - DocuParser *parser = DocuParser::createParser( file.absoluteFilePath() ); - if( parser ) { - QFile f( QFile::decodeName(argv[i+1]) ); - if( !parser->parse( &f ) ) { - fprintf(stderr, "Failed to parse file: %s\n", qPrintable(file.absoluteFilePath())); - return 1; - } - parser->addTo( c->profile() ); - c->setDocRebuild( true ); - c->save(); - } - return 0; - } else if ( opt == QLatin1String("-removecontentfile") ) { - INDEX_CHECK("Missing content file!"); - Config *c = Config::loadConfig(QString()); - Profile *profile = c->profile(); - QString contentFile = QString::fromLocal8Bit(argv[i+i]); - QStringList entries; -#ifdef Q_WS_WIN - contentFile.replace(QLatin1Char('\\'), QLatin1Char('/')); - entries = profile->docs.filter(contentFile, Qt::CaseInsensitive); -#else - entries = profile->docs.filter(contentFile); -#endif - if (entries.count() == 0) { - fprintf(stderr, "Could not locate content file: %s\n", qPrintable(contentFile)); - return 1; - } else if (entries.count() > 1) { - fprintf(stderr, "More than one entry matching file name found, " - "please specify full path to file"); - return 1; - } else { - QFileInfo file(entries[0]); - if( !file.exists() ) { - fprintf(stderr, "Could not locate content file: %s\n", qPrintable(file.absoluteFilePath())); - return 1; - } - profile->removeDocFileEntry( file.absoluteFilePath() ); - c->setDocRebuild( true ); - c->save(); - } - return 0; - } else if ( QString( QLatin1String(argv[i]) ).toLower() == QLatin1String("-docpath") ) { - INDEX_CHECK( "Missing path!" ); - QDir dir(QString::fromLocal8Bit(argv[i+1])); - if ( dir.exists() ) { - Config *c = Config::loadConfig(QString()); - c->saveProfile(Profile::createDefaultProfile(dir.absolutePath())); - c->loadDefaultProfile(); - c->setDocRebuild(true); - c->save(); - configLoaded = true; - ++i; - } else { - fprintf(stderr, "The specified path does not exist!\n"); - return 1; - } - } else if ( opt == QLatin1String("-hidesidebar") ) { - hideSidebar = true; - } else if ( opt == QLatin1String("-help") || opt == QLatin1String("/?") ) { - QString helpText = QLatin1String( "Usage: assistant [option]\n" - "Options:\n" - " -file Filename assistant opens the specified file\n" - " -server reads commands from a socket after\n" - " assistant has started\n" - " -profile fileName starts assistant and displays the\n" - " profile specified in the file fileName.\n" - " -addContentFile file adds the content file 'file' to the set of\n" - " documentation available by default\n" - " -removeContentFile file removes the content file 'file' from the\n" - " documentation available by default\n" - " -docPath path sets the Qt documentation root path to\n" - " 'path' and starts assistant\n" - " -hideSidebar assistant will hide the sidebar.\n" - " -resourceDir assistant will load translations from\n" - " this directory.\n" - " -help shows this help."); -#ifdef Q_WS_WIN - QMessageBox::information( 0, QLatin1String("Qt Assistant"), - QLatin1String("<pre>") + helpText + QLatin1String("</pre>") ); -#else - fprintf(stdout, "%s\n", qPrintable(helpText)); -#endif - exit( 0 ); - } else if ( opt == QLatin1String("-resourcedir") ) { - INDEX_CHECK( "Missing resource directory argument!" ); - resourceDir = QFile::decodeName( argv[++i] ); - } else { - fprintf(stderr, "Unrecognized option %s. Try -help to get help.\n", qPrintable(opt)); - return 1; - } - } - } - - if( resourceDir.isNull() ) - resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath); - - QTranslator translator( 0 ); - translator.load( QLatin1String("assistant_adp_") + QLocale::system().name(), resourceDir ); - a.installTranslator( &translator ); - - QTranslator qtTranslator( 0 ); - qtTranslator.load( QLatin1String("qt_") + QLocale::system().name(), resourceDir ); - a.installTranslator( &qtTranslator ); - - Config *conf = 0; - if (configLoaded) - conf = Config::configuration(); - else - conf = Config::loadConfig( profileName ); - if (!conf) { - fprintf( stderr, "Profile '%s' does not exist!\n", profileName.toLatin1().constData() ); - fflush( stderr ); - return -1; - } - - QStringList links = conf->source(); - conf->hideSideBar( hideSidebar ); - - QPointer<MainWindow> mw = new MainWindow(); - mw->setObjectName(QLatin1String("Assistant")); - - if ( server ) { - as = new AssistantServer(); - printf("%d\n", as->serverPort() ); - fflush( stdout ); - as->connect( as, SIGNAL(showLinkRequest(QString)), - mw, SLOT(showLinkFromClient(QString)) ); - } - -#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX) - new AssistantAdaptor(mw); -#endif // QT_NO_DBUS - - FontSettings settings = conf->fontSettings(); - if (mw->font() != settings.windowFont) - a.setFont(settings.windowFont, "QWidget"); - -#ifdef Q_WS_MAC - // Make sure AssitantClient shows the window in front. - mw->raise(); -#endif - mw->show(); - - if (!file.isEmpty()) - mw->showLink( MainWindow::urlifyFileName(file) ); - else if (file.isEmpty()) - mw->showLinks( links ); - - a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) ); - - int appExec = a.exec(); - delete (MainWindow*)mw; - return appExec; -} - -QT_END_NAMESPACE - -int main( int argc, char ** argv ) -{ - Q_INIT_RESOURCE(assistant); - return QT_PREPEND_NAMESPACE(runAssistant)(argc, argv); -} - -#include "main.moc" diff --git a/tools/assistant/compat/mainwindow.cpp b/tools/assistant/compat/mainwindow.cpp deleted file mode 100644 index 76143a5..0000000 --- a/tools/assistant/compat/mainwindow.cpp +++ /dev/null @@ -1,885 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mainwindow.h" -#include "tabbedbrowser.h" -#include "helpdialog.h" -#include "config.h" -#include "fontsettingsdialog.h" - -#include <QDockWidget> -#include <QDir> -#include <QTimer> -#include <QStatusBar> -#include <QShortcut> -#include <QMessageBox> -#include <QPainter> -#include <QEventLoop> -#include <QtEvents> -#include <QFontDatabase> -#include <QWhatsThis> -#include <QTextDocumentFragment> -#include <QLibraryInfo> -#include <QPrinter> -#include <QPrintDialog> -#include <QAbstractTextDocumentLayout> -#include <QTextDocument> -#include <QTextObject> -#include <QFileDialog> -#include <QThread> - -QT_BEGIN_NAMESPACE - -QList<MainWindow*> MainWindow::windows; - -#if defined(Q_WS_WIN) -extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; -#endif - -MainWindow::MainWindow() -{ - setUnifiedTitleAndToolBarOnMac(true); - ui.setupUi(this); - -#if defined(Q_WS_WIN) - // Workaround for QMimeSourceFactory failing in QFileInfo::isReadable() for - // certain user configs. See task: 34372 - qt_ntfs_permission_lookup = 0; -#endif - setupCompleted = false; - - goActions = QList<QAction*>(); - goActionDocFiles = new QMap<QAction*,QString>; - - windows.append(this); - tabs = new TabbedBrowser(this); - connect(tabs, SIGNAL(tabCountChanged(int)), this, SLOT(updateTabActions(int))); - setCentralWidget(tabs); - - Config *config = Config::configuration(); - - updateProfileSettings(); - - dw = new QDockWidget(this); - dw->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - dw->setWindowTitle(tr("Sidebar")); - dw->setObjectName(QLatin1String("sidebar")); - helpDock = new HelpDialog(dw, this); - dw->setWidget(helpDock); - - addDockWidget(Qt::LeftDockWidgetArea, dw); - - // read geometry configuration - setupGoActions(); - - restoreGeometry(config->windowGeometry()); - restoreState(config->mainWindowState()); - if (config->sideBarHidden()) - dw->hide(); - - tabs->setup(); - QTimer::singleShot(0, this, SLOT(setup())); -#if defined(Q_WS_MAC) - QMenu *windowMenu = new QMenu(tr("&Window"), this); - menuBar()->insertMenu(ui.helpMenu->menuAction(), windowMenu); - windowMenu->addAction(tr("Minimize"), this, - SLOT(showMinimized()), QKeySequence(tr("Ctrl+M"))); - // Use the same forward and backward browser shortcuts as Safari and Internet Explorer do - // on the Mac. This means that if you have access to one of those cool Intellimice, the thing - // works just fine, since that's how Microsoft hacked it. - ui.actionGoPrevious->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Left)); - ui.actionGoNext->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Right)); - - static const QLatin1String MacIconPath(":/trolltech/assistant/images/mac"); - ui.actionGoNext->setIcon(QIcon(MacIconPath + QLatin1String("/next.png"))); - ui.actionGoPrevious->setIcon(QIcon(MacIconPath + QLatin1String("/prev.png"))); - ui.actionGoHome->setIcon(QIcon(MacIconPath + QLatin1String("/home.png"))); - ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png"))); - ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png"))); - ui.actionEditFind->setIcon(QIcon(MacIconPath + QLatin1String("/find.png"))); - ui.actionFilePrint->setIcon(QIcon(MacIconPath + QLatin1String("/print.png"))); - ui.actionZoomOut->setIcon(QIcon(MacIconPath + QLatin1String("/zoomout.png"))); - ui.actionZoomIn->setIcon(QIcon(MacIconPath + QLatin1String("/zoomin.png"))); - ui.actionSyncToc->setIcon(QIcon(MacIconPath + QLatin1String("/synctoc.png"))); - ui.actionHelpWhatsThis->setIcon(QIcon(MacIconPath + QLatin1String("/whatsthis.png"))); -#elif defined(Q_WS_X11) - ui.actionGoNext->setIcon(QIcon::fromTheme("go-next" , ui.actionGoNext->icon())); - ui.actionGoPrevious->setIcon(QIcon::fromTheme("go-previous" , ui.actionGoPrevious->icon())); - ui.actionGoHome->setIcon(QIcon::fromTheme("user-home" , ui.actionGoHome->icon())); - ui.actionEditCopy->setIcon(QIcon::fromTheme("edit-copy" , ui.actionEditCopy->icon())); - ui.actionEditFind->setIcon(QIcon::fromTheme("edit-find" , ui.actionEditFind->icon())); - ui.actionFilePrint->setIcon(QIcon::fromTheme("document-print" , ui.actionFilePrint->icon())); - ui.actionZoomOut->setIcon(QIcon::fromTheme("zoom-out" , ui.actionZoomOut->icon())); - ui.actionZoomIn->setIcon(QIcon::fromTheme("zoom-in" , ui.actionZoomIn->icon())); - ui.actionSyncToc->setIcon(QIcon::fromTheme("view-refresh" , ui.actionSyncToc->icon())); -#endif -} - -MainWindow::~MainWindow() -{ - windows.removeAll(this); - delete goActionDocFiles; -} - -void MainWindow::setup() -{ - if(setupCompleted) - return; - - qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); - statusBar()->showMessage(tr("Initializing Qt Assistant...")); - setupCompleted = true; - helpDock->initialize(); - connect(ui.actionGoPrevious, SIGNAL(triggered()), tabs, SLOT(backward())); - connect(ui.actionGoNext, SIGNAL(triggered()), tabs, SLOT(forward())); - connect(ui.actionEditCopy, SIGNAL(triggered()), tabs, SLOT(copy())); - connect(ui.actionFileExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); - connect(ui.actionAddBookmark, SIGNAL(triggered()), - helpDock, SLOT(addBookmark())); - connect(helpDock, SIGNAL(showLink(QString)), - this, SLOT(showLink(QString))); - connect(helpDock, SIGNAL(showSearchLink(QString,QStringList)), - this, SLOT(showSearchLink(QString,QStringList))); - - connect(ui.bookmarkMenu, SIGNAL(triggered(QAction*)), - this, SLOT(showBookmark(QAction*))); - connect(ui.actionZoomIn, SIGNAL(triggered()), tabs, SLOT(zoomIn())); - connect(ui.actionZoomOut, SIGNAL(triggered()), tabs, SLOT(zoomOut())); - - connect(ui.actionOpenPage, SIGNAL(triggered()), tabs, SLOT(newTab())); - connect(ui.actionClosePage, SIGNAL(triggered()), tabs, SLOT(closeTab())); - connect(ui.actionNextPage, SIGNAL(triggered()), tabs, SLOT(nextTab())); - connect(ui.actionPrevPage, SIGNAL(triggered()), tabs, SLOT(previousTab())); - - -#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) - QShortcut *acc = new QShortcut(tr("SHIFT+CTRL+="), this); - connect(acc, SIGNAL(activated()), ui.actionZoomIn, SIGNAL(triggered())); -#endif - - connect(new QShortcut(tr("Ctrl+T"), this), SIGNAL(activated()), helpDock, SLOT(toggleContents())); - connect(new QShortcut(tr("Ctrl+I"), this), SIGNAL(activated()), helpDock, SLOT(toggleIndex())); - connect(new QShortcut(tr("Ctrl+B"), this), SIGNAL(activated()), helpDock, SLOT(toggleBookmarks())); - connect(new QShortcut(tr("Ctrl+S"), this), SIGNAL(activated()), helpDock, SLOT(toggleSearch())); - connect(new QShortcut(tr("Ctrl+]"), this), SIGNAL(activated()), tabs, SLOT(nextTab())); - connect(new QShortcut(tr("Ctrl+["), this), SIGNAL(activated()), tabs, SLOT(previousTab())); - - Config *config = Config::configuration(); - - setupBookmarkMenu(); - - QAction *viewsAction = createPopupMenu()->menuAction(); - viewsAction->setText(tr("Views")); - ui.viewMenu->addAction(viewsAction); - - const int tabIndex = config->sideBarPage(); - helpDock->tabWidget()->setCurrentIndex(tabIndex); - // The tab index is 0 by default, so we need to force an upate - // to poulate the contents in this case. - if (tabIndex == 0) - helpDock->currentTabChanged(tabIndex); - - ui.actionEditFind->setShortcut(QKeySequence::Find); - ui.actionEditFindNext->setShortcut(QKeySequence::FindNext); - ui.actionEditFindPrev->setShortcut(QKeySequence::FindPrevious); - - QObject::connect(ui.actionEditFind, SIGNAL(triggered()), tabs, SLOT(find())); - QObject::connect(ui.actionEditFindNext, SIGNAL(triggered()), tabs, SLOT(findNext())); - QObject::connect(ui.actionEditFindPrev, SIGNAL(triggered()), tabs, SLOT(findPrevious())); - connect(ui.actionEditFont_Settings, SIGNAL(triggered()), this, SLOT(showFontSettingsDialog())); - - qApp->restoreOverrideCursor(); - ui.actionGoPrevious->setEnabled(false); - ui.actionGoNext->setEnabled(false); - ui.actionEditCopy->setEnabled(false); - - // set the current selected item in the treeview - helpDialog()->locateContents(tabs->currentBrowser()->source().toString()); - connect(tabs, SIGNAL(browserUrlChanged(QString)), helpDock, SLOT(locateContents(QString))); -} - -void MainWindow::browserTabChanged() -{ - HelpWindow *win = tabs->currentBrowser(); - if (win) { - QTextCursor cursor(win->textCursor()); - ui.actionEditCopy->setEnabled(cursor.hasSelection()); - ui.actionGoPrevious->setEnabled(win->isBackwardAvailable()); - ui.actionGoNext->setEnabled(win->isForwardAvailable()); - } -} - -void MainWindow::copyAvailable(bool yes) -{ - ui.actionEditCopy->setEnabled(yes); -} - -void MainWindow::updateTabActions(int index) -{ - bool enabled = (index > 1) ? true : false; - ui.actionPrevPage->setEnabled(enabled); - ui.actionNextPage->setEnabled(enabled); - ui.actionClosePage->setEnabled(enabled); -} - -void MainWindow::setupGoActions() -{ - Config *config = Config::configuration(); - QStringList titles = config->docTitles(); - QAction *action = 0; - - static bool separatorInserted = false; - - foreach (QAction *a, goActions) { - ui.goMenu->removeAction(a); - ui.goActionToolbar->removeAction(a); - } - qDeleteAll(goActions); - goActions.clear(); - goActionDocFiles->clear(); - - int addCount = 0; - - foreach (QString title, titles) { - QPixmap pix = config->docIcon(title); - if(!pix.isNull()) { - if(!separatorInserted) { - ui.goMenu->addSeparator(); - separatorInserted = true; - } - action = new QAction(this); - action->setText(title); - action->setWhatsThis(tr("Displays the main page of a specific documentation set.")); - action->setIcon(QIcon(pix)); - ui.goMenu->addAction(action); - ui.goActionToolbar->addAction(action); - goActions.append(action); - goActionDocFiles->insert(action, config->indexPage(title)); - connect(action, SIGNAL(triggered()), - this, SLOT(showGoActionLink())); - ++addCount; - } - } - if(!addCount) - ui.goActionToolbar->hide(); - else - ui.goActionToolbar->show(); - -} - -bool MainWindow::insertActionSeparator() -{ - ui.goMenu->addSeparator(); - ui.Toolbar->addSeparator(); - return true; -} - -void MainWindow::closeEvent(QCloseEvent *e) -{ - saveSettings(); - e->accept(); -} - -void MainWindow::about() -{ - QMessageBox box(this); - - box.setText(QString::fromLatin1("<center><img src=\":/trolltech/assistant/images/assistant-128.png\">" - "<h3>%1</h3>" - "<p>Version %2</p></center>" - "<p>Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).</p>") - .arg(tr("Qt Assistant")).arg(QLatin1String(QT_VERSION_STR))); - box.setWindowTitle(tr("Qt Assistant")); - box.setIcon(QMessageBox::NoIcon); - box.exec(); -} - -void MainWindow::on_actionAboutApplication_triggered() -{ - QString url = Config::configuration()->aboutURL(); - if (url == QLatin1String("about_qt")) { - QMessageBox::aboutQt(this, QLatin1String("Qt Assistant")); - return; - } - QString text; - if (url.startsWith(QLatin1String("file:"))) - url = url.mid(5); - QFile file(url); - if(file.exists() && file.open(QFile::ReadOnly)) - text = QString::fromUtf8(file.readAll()); - if(text.isNull()) - text = tr("Failed to open about application contents in file: '%1'").arg(url); - - QFileInfo fi(file); - QString path = QDir::cleanPath(fi.absolutePath()); - if (!QDir::searchPaths(QLatin1String("aboutImages")).contains(path)) - QDir::addSearchPath(QLatin1String("aboutImages"), path); - - QMessageBox box(this); - box.setText(text); - box.setWindowTitle(Config::configuration()->aboutApplicationMenuText()); - box.setIcon(QMessageBox::NoIcon); - box.exec(); -} - -void MainWindow::on_actionAboutAssistant_triggered() -{ - about(); -} - -void MainWindow::on_actionGoHome_triggered() -{ - QString home = MainWindow::urlifyFileName(Config::configuration()->homePage()); - showLink(home); -} - -QString MainWindow::urlifyFileName(const QString &fileName) -{ - QString name = fileName; - QUrl url(name); - -#if defined(Q_OS_WIN32) - if (!url.isValid() || url.scheme().isEmpty() || url.scheme().toLower() != QLatin1String("file:")) { - int i = name.indexOf(QLatin1Char('#')); - QString anchor = name.mid(i); - name = name.toLower(); - if (i > -1) - name.replace(i, anchor.length(), anchor); - name.replace(QLatin1Char('\\'), QLatin1Char('/')); - foreach (QFileInfo drive, QDir::drives()) { - if (name.startsWith(drive.absolutePath().toLower())) { - name = QLatin1String("file:") + name; - break; - } - } - } -#else - if (!url.isValid() || url.scheme().isEmpty()) - name.prepend(QLatin1String("file:")); -#endif - return name; -} - -#ifndef QT_NO_PRINTER -class PrintThread : public QThread -{ - QPrinter _printer; - QTextDocument *_document; - -public: - PrintThread(QObject *parent) - : QThread(parent), _printer(QPrinter::HighResolution), _document(0) - { - } - ~PrintThread() - { - wait(); - } - - QPrinter *printer() - { - return &_printer; - } - - void start(QTextDocument *document) - { - _document = document->clone(); - _document->moveToThread(this); - QThread::start(); - } - -protected: - void run() - { - _document->print(printer()); - delete _document; - _document = 0; - } -}; -#endif //QT_NO_PRINTER - -void MainWindow::on_actionFilePrint_triggered() -{ -#ifndef QT_NO_PRINTER - if (!QFontDatabase::supportsThreadedFontRendering()) { - QPrinter printer(QPrinter::HighResolution); - - QPrintDialog dlg(&printer, this); - if (dlg.exec() == QDialog::Accepted) { - qApp->setOverrideCursor(Qt::WaitCursor); - tabs->currentBrowser()->document()->print(&printer); - qApp->restoreOverrideCursor(); - } - return; - } - - PrintThread *thread = new PrintThread(this); - - QPrintDialog dlg(thread->printer(), this); - if (dlg.exec() == QDialog::Accepted) { - connect(thread, SIGNAL(finished()), SLOT(printingFinished())); - connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); - - qApp->setOverrideCursor(Qt::BusyCursor); - thread->start(tabs->currentBrowser()->document()); - } else { - delete thread; - } -#else - Q_ASSERT("No printing support"); -#endif -} - -void MainWindow::printingFinished() -{ - qApp->restoreOverrideCursor(); -} - -void MainWindow::updateBookmarkMenu() -{ - for(QList<MainWindow*>::Iterator it = windows.begin(); it != windows.end(); ++it) - (*it)->setupBookmarkMenu(); -} - -void MainWindow::setupBookmarkMenu() -{ - ui.bookmarkMenu->clear(); - bookmarks.clear(); - ui.bookmarkMenu->addAction(ui.actionAddBookmark); - - QFile f(QDir::homePath() + QLatin1String("/.assistant/bookmarks.") + - Config::configuration()->profileName()); - if (!f.open(QFile::ReadOnly)) - return; - QTextStream ts(&f); - ui.bookmarkMenu->addSeparator(); - while (!ts.atEnd()) { - QString title = ts.readLine(); - QString link = ts.readLine(); - bookmarks.insert(ui.bookmarkMenu->addAction(title), link); - } -} - -void MainWindow::showBookmark(QAction *action) -{ - if (bookmarks.contains(action)) - showLink(bookmarks.value(action)); -} - -void MainWindow::showLinkFromClient(const QString &link) -{ - setWindowState(windowState() & ~Qt::WindowMinimized); - raise(); - activateWindow(); - QString l = MainWindow::urlifyFileName(link); - showLink(l); - if (isMinimized()) - showNormal(); -} - -void MainWindow::showLink(const QString &link) -{ - if(link.isEmpty()) - qWarning("The link is empty!"); - - // don't fill the history with the same url more then once - if (link == tabs->currentBrowser()->source().toString()) - return; - - QUrl url(link); - QFileInfo fi(url.toLocalFile()); - tabs->setSource(url.toString()); - tabs->currentBrowser()->setFocus(); -} - -void MainWindow::showLinks(const QStringList &links) -{ - if (links.size() == 0) { - qWarning("MainWindow::showLinks() - Empty link"); - return; - } - - if (links.size() == 1) { - showLink(MainWindow::urlifyFileName(links.first())); - return; - } - - QStringList::ConstIterator it = links.begin(); - // Initial showing, The tab is empty so update that without creating it first - if (!tabs->currentBrowser()->source().isValid()) { - QPair<HelpWindow*, QString> browser; - browser.first = tabs->currentBrowser(); - browser.second = links.first(); - pendingBrowsers.append(browser); - tabs->setTitle(tabs->currentBrowser(), tr("...")); - } - ++it; - - while(it != links.end()) { - QPair<HelpWindow*, QString> browser; - browser.first = tabs->newBackgroundTab(); - browser.second = *it; - pendingBrowsers.append(browser); - ++it; - } - - startTimer(50); - return; -} - -void MainWindow::removePendingBrowser(HelpWindow *win) -{ - if (!pendingBrowsers.count()) - return; - - QMutableListIterator<QPair<HelpWindow*, QString> > it(pendingBrowsers); - while (it.hasNext()) { - QPair<HelpWindow*, QString> browser = it.next(); - if (browser.first == win) { - it.remove(); - break; - } - } -} - -void MainWindow::timerEvent(QTimerEvent *e) -{ - QPair<HelpWindow*, QString> browser = pendingBrowsers.first(); - pendingBrowsers.pop_front(); - - if (pendingBrowsers.size() == 0) - killTimer(e->timerId()); - - browser.first->setSource(MainWindow::urlifyFileName(browser.second)); -} - -void MainWindow::showQtHelp() -{ - showLink(QLibraryInfo::location(QLibraryInfo::DocumentationPath) + - QLatin1String("/html/index.html")); -} - -MainWindow* MainWindow::newWindow() -{ - saveSettings(); - MainWindow *mw = new MainWindow; - mw->move(geometry().topLeft()); - if (isMaximized()) - mw->showMaximized(); - else - mw->show(); - mw->on_actionGoHome_triggered(); - return mw; -} - -void MainWindow::saveSettings() -{ - Config *config = Config::configuration(); - - config->setSideBarPage(helpDock->tabWidget()->currentIndex()); - config->setWindowGeometry(saveGeometry()); - config->setMainWindowState(saveState()); - - // Create list of the tab urls - QStringList lst; - QList<HelpWindow*> browsers = tabs->browsers(); - foreach (HelpWindow *browser, browsers) - lst << browser->source().toString(); - config->setSource(lst); - config->save(); -} - -TabbedBrowser* MainWindow::browsers() const -{ - return tabs; -} - -void MainWindow::showSearchLink(const QString &link, const QStringList &terms) -{ - HelpWindow * hw = tabs->currentBrowser(); - hw->blockScrolling(true); - hw->setCursor(Qt::WaitCursor); - if (hw->source() == link) - hw->reload(); - else - showLink(link); - hw->setCursor(Qt::ArrowCursor); - - hw->viewport()->setUpdatesEnabled(false); - - QTextCharFormat marker; - marker.setForeground(Qt::red); - - QTextCursor firstHit; - - QTextCursor c = hw->textCursor(); - c.beginEditBlock(); - foreach (QString term, terms) { - c.movePosition(QTextCursor::Start); - hw->setTextCursor(c); - - bool found = hw->find(term, QTextDocument::FindWholeWords); - while (found) { - QTextCursor hit = hw->textCursor(); - if (firstHit.isNull() || hit.position() < firstHit.position()) - firstHit = hit; - - hit.mergeCharFormat(marker); - found = hw->find(term, QTextDocument::FindWholeWords); - } - } - - if (firstHit.isNull()) { - firstHit = hw->textCursor(); - firstHit.movePosition(QTextCursor::Start); - } - firstHit.clearSelection(); - c.endEditBlock(); - hw->setTextCursor(firstHit); - - hw->blockScrolling(false); - hw->viewport()->setUpdatesEnabled(true); -} - - -void MainWindow::showGoActionLink() -{ - const QObject *origin = sender(); - if(!origin || - QString::fromLatin1(origin->metaObject()->className()) != QString::fromLatin1("QAction")) - return; - - QAction *action = (QAction*) origin; - QString docfile = *(goActionDocFiles->find(action)); - showLink(MainWindow::urlifyFileName(docfile)); -} - -void MainWindow::on_actionHelpAssistant_triggered() -{ - showLink(Config::configuration()->assistantDocPath() + QLatin1String("/assistant-manual.html")); -} - -HelpDialog* MainWindow::helpDialog() const -{ - return helpDock; -} - -void MainWindow::backwardAvailable(bool enable) -{ - ui.actionGoPrevious->setEnabled(enable); -} - -void MainWindow::forwardAvailable(bool enable) -{ - ui.actionGoNext->setEnabled(enable); -} - -void MainWindow::updateProfileSettings() -{ - Config *config = Config::configuration(); -#ifndef Q_WS_MAC - setWindowIcon(config->applicationIcon()); -#endif - ui.helpMenu->clear(); - //ui.helpMenu->addAction(ui.actionHelpAssistant); - //ui.helpMenu->addSeparator(); - ui.helpMenu->addAction(ui.actionAboutAssistant); - if (!config->aboutApplicationMenuText().isEmpty()) - ui.helpMenu->addAction(ui.actionAboutApplication); - ui.helpMenu->addSeparator(); - ui.helpMenu->addAction(ui.actionHelpWhatsThis); - - ui.actionAboutApplication->setText(config->aboutApplicationMenuText()); - - if(!config->title().isNull()) - setWindowTitle(config->title()); -} - -void MainWindow::setupPopupMenu(QMenu *m) -{ - m->addAction(ui.actionNewWindow); - m->addAction(ui.actionOpenPage); - m->addAction(ui.actionClosePage); - m->addSeparator(); - m->addAction(ui.actionSaveAs); - m->addSeparator(); - m->addAction(ui.actionGoPrevious); - m->addAction(ui.actionGoNext); - m->addAction(ui.actionGoHome); - m->addSeparator(); - m->addAction(ui.actionZoomIn); - m->addAction(ui.actionZoomOut); - m->addSeparator(); - m->addAction(ui.actionEditCopy); - m->addAction(ui.actionEditFind); -} - -void MainWindow::on_actionSyncToc_triggered() -{ - HelpWindow *w = tabs->currentBrowser(); - if(w) { - qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); - QString link = w->source().toString(); - helpDock->locateContents(link); - helpDock->tabWidget()->setCurrentIndex(0); - qApp->restoreOverrideCursor(); - } -} - -void MainWindow::on_actionNewWindow_triggered() -{ - newWindow()->show(); -} - -void MainWindow::on_actionClose_triggered() -{ - close(); -} - -void MainWindow::on_actionHelpWhatsThis_triggered() -{ - QWhatsThis::enterWhatsThisMode(); -} - -void MainWindow::on_actionSaveAs_triggered() -{ - QString fileName; - QUrl url = tabs->currentBrowser()->source(); - if (url.isValid()) { - QFileInfo fi(url.toLocalFile()); - fileName = fi.fileName(); - } - fileName = QFileDialog::getSaveFileName(this, tr("Save Page"), fileName); - if (fileName.isEmpty()) - return; - - QFile file(fileName); - if (!file.open(QIODevice::WriteOnly)) { - QMessageBox::critical(this, tr("Save Page"), tr("Cannot open file for writing!")); - return; - } - - QFileInfo fi(fileName); - QString fn = fi.fileName(); - int i = fn.lastIndexOf(QLatin1Char('.')); - if (i > -1) - fn = fn.left(i); - QString relativeDestPath = fn + QLatin1String("_images"); - QDir destDir(fi.absolutePath() + QDir::separator() + relativeDestPath); - bool imgDirAvailable = destDir.exists(); - if (!imgDirAvailable) - imgDirAvailable = destDir.mkdir(destDir.absolutePath()); - - // save images - QTextDocument *doc = tabs->currentBrowser()->document()->clone(); - if (url.isValid() && imgDirAvailable) { - QTextBlock::iterator it; - for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) { - for (it = block.begin(); !(it.atEnd()); ++it) { - QTextFragment fragment = it.fragment(); - if (fragment.isValid()) { - QTextImageFormat fm = fragment.charFormat().toImageFormat(); - if (fm.isValid() && !fm.name().isEmpty()) { - QUrl imagePath = tabs->currentBrowser()->source().resolved(fm.name()); - if (!imagePath.isValid()) - continue; - QString from = imagePath.toLocalFile(); - QString destName = fm.name(); - int j = destName.lastIndexOf(QLatin1Char('/')); - if (j > -1) - destName = destName.mid(j+1); - QFileInfo info(from); - if (info.exists()) { - if (!QFile::copy(from, destDir.absolutePath() - + QDir::separator() + destName)) - continue; - fm.setName(QLatin1String("./") + relativeDestPath + QLatin1String("/") + destName); - QTextCursor cursor(doc); - cursor.setPosition(fragment.position()); - cursor.setPosition(fragment.position() + fragment.length(), - QTextCursor::KeepAnchor); - cursor.setCharFormat(fm); - } - } - } - } - } - } - QString src = doc->toHtml(QByteArray("utf-8")); - QTextStream s(&file); - s.setCodec("utf-8"); - s << src; - s.flush(); - file.close(); -} - -void MainWindow::showFontSettingsDialog() -{ - Config *config = Config::configuration(); - FontSettings settings = config->fontSettings(); - - { // It is important that the dialog be deleted before UI mode changes. - FontSettingsDialog dialog; - if (!dialog.showDialog(&settings)) - return; - } - - config->setFontPointSize(settings.browserFont.pointSizeF()); - config->setFontSettings(settings); - - updateApplicationFontSettings(settings); -} - -void MainWindow::updateApplicationFontSettings(FontSettings &settings) -{ - QFont font = settings.windowFont; - if (this->font() != font) - qApp->setFont(font, "QWidget"); - - font = settings.browserFont; - QList<HelpWindow*> browsers = tabs->browsers(); - foreach (HelpWindow *browser, browsers) { - if (browser->font() != font) - browser->setFont(font); - } -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/mainwindow.h b/tools/assistant/compat/mainwindow.h deleted file mode 100644 index a08064d..0000000 --- a/tools/assistant/compat/mainwindow.h +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include "ui_mainwindow.h" -#include "config.h" - -#include <QPointer> -#include <QMap> - -QT_BEGIN_NAMESPACE - -class TabbedBrowser; -class HelpDialog; -class HelpWindow; -class QMenu; -class QDockWidget; - -class MainWindow : public QMainWindow -{ - Q_OBJECT -public: - MainWindow(); - virtual ~MainWindow(); - - TabbedBrowser *browsers() const; - HelpDialog *helpDialog() const; - - void setupPopupMenu(QMenu *menu); - static QString urlifyFileName(const QString &fileName); - - void removePendingBrowser(HelpWindow *win); - -public slots: - MainWindow *newWindow(); - - void setup(); - void showLink(const QString &link); - void showLinks(const QStringList &links); - void saveSettings(); - void updateBookmarkMenu(); - void printingFinished(); - -private slots: - void on_actionNewWindow_triggered(); - void on_actionGoHome_triggered(); - void on_actionFilePrint_triggered(); - void on_actionClose_triggered(); - void on_actionHelpWhatsThis_triggered(); - void on_actionHelpAssistant_triggered(); - void on_actionAboutApplication_triggered(); - void on_actionAboutAssistant_triggered(); - void on_actionSaveAs_triggered(); - void on_actionSyncToc_triggered(); - - void about(); - void setupBookmarkMenu(); - void showBookmark(QAction *action); - void showLinkFromClient(const QString &link); - void showQtHelp(); - void showSearchLink(const QString &link, const QStringList &terms); - void showGoActionLink(); - void updateProfileSettings(); - void backwardAvailable(bool); - void forwardAvailable(bool); - - void browserTabChanged(); - void copyAvailable(bool yes); - void updateTabActions(int index); - void showFontSettingsDialog(); - -protected: - void closeEvent(QCloseEvent *); - void timerEvent(QTimerEvent *); - -private: - void setupGoActions(); - bool insertActionSeparator(); - void updateApplicationFontSettings(FontSettings &settings); - -private: - Ui::MainWindow ui; - - QList<QAction*> goActions; - uint setupCompleted:1; - TabbedBrowser *tabs; - QMap<QAction*, QString> bookmarks; - HelpDialog *helpDock; - QDockWidget *dw; - static QList<MainWindow*> windows; - QMap<QAction*,QString> *goActionDocFiles; - QList<QPair<HelpWindow*,QString> > pendingBrowsers; -}; - -#endif // MAINWINDOW_H - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/mainwindow.ui b/tools/assistant/compat/mainwindow.ui deleted file mode 100644 index 535e27e..0000000 --- a/tools/assistant/compat/mainwindow.ui +++ /dev/null @@ -1,457 +0,0 @@ -<ui version="4.0" > - <comment>********************************************************************* -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -*********************************************************************</comment> - <class>MainWindow</class> - <widget class="QMainWindow" name="MainWindow" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>949</width> - <height>670</height> - </rect> - </property> - <property name="windowTitle" > - <string>Qt Assistant by Nokia</string> - </property> - <widget class="QWidget" name="__qt_central_widget" /> - <widget class="QToolBar" name="Toolbar" > - <property name="windowTitle" > - <string>Toolbar</string> - </property> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <attribute name="toolBarArea" > - <enum>TopToolBarArea</enum> - </attribute> - <attribute name="toolBarBreak" > - <bool>false</bool> - </attribute> - <addaction name="actionGoPrevious" /> - <addaction name="actionGoNext" /> - <addaction name="actionGoHome" /> - <addaction name="actionSyncToc" /> - <addaction name="separator" /> - <addaction name="actionEditCopy" /> - <addaction name="actionEditFind" /> - <addaction name="actionFilePrint" /> - <addaction name="separator" /> - <addaction name="actionZoomIn" /> - <addaction name="actionZoomOut" /> - <addaction name="separator" /> - <addaction name="actionHelpWhatsThis" /> - </widget> - <widget class="QToolBar" name="goActionToolbar" > - <property name="windowTitle" > - <string>Go</string> - </property> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <attribute name="toolBarArea" > - <enum>TopToolBarArea</enum> - </attribute> - <attribute name="toolBarBreak" > - <bool>false</bool> - </attribute> - </widget> - <widget class="QMenuBar" name="menubar" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>949</width> - <height>29</height> - </rect> - </property> - <widget class="QMenu" name="helpMenu" > - <property name="title" > - <string>&Help</string> - </property> - <addaction name="actionHelpAssistant" /> - <addaction name="separator" /> - <addaction name="actionAboutAssistant" /> - <addaction name="actionAboutApplication" /> - <addaction name="separator" /> - <addaction name="actionHelpWhatsThis" /> - </widget> - <widget class="QMenu" name="fileMenu" > - <property name="title" > - <string>&File</string> - </property> - <addaction name="actionNewWindow" /> - <addaction name="actionOpenPage" /> - <addaction name="actionClosePage" /> - <addaction name="separator" /> - <addaction name="actionSaveAs" /> - <addaction name="separator" /> - <addaction name="actionFilePrint" /> - <addaction name="separator" /> - <addaction name="actionClose" /> - <addaction name="actionFileExit" /> - </widget> - <widget class="QMenu" name="bookmarkMenu" > - <property name="title" > - <string>Boo&kmarks</string> - </property> - </widget> - <widget class="QMenu" name="goMenu" > - <property name="title" > - <string>&Go</string> - </property> - <addaction name="actionGoPrevious" /> - <addaction name="actionGoNext" /> - <addaction name="actionGoHome" /> - <addaction name="actionSyncToc" /> - <addaction name="separator" /> - <addaction name="actionNextPage" /> - <addaction name="actionPrevPage" /> - </widget> - <widget class="QMenu" name="viewMenu" > - <property name="title" > - <string>&View</string> - </property> - <addaction name="actionZoomIn" /> - <addaction name="actionZoomOut" /> - </widget> - <widget class="QMenu" name="editMenu" > - <property name="title" > - <string>&Edit</string> - </property> - <addaction name="actionEditCopy" /> - <addaction name="actionEditFind" /> - <addaction name="actionEditFindNext" /> - <addaction name="actionEditFindPrev" /> - <addaction name="separator" /> - <addaction name="actionEditFont_Settings" /> - </widget> - <addaction name="fileMenu" /> - <addaction name="editMenu" /> - <addaction name="viewMenu" /> - <addaction name="goMenu" /> - <addaction name="bookmarkMenu" /> - <addaction name="helpMenu" /> - </widget> - <action name="actionFilePrint" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/print.png</iconset> - </property> - <property name="text" > - <string>&Print...</string> - </property> - <property name="whatsThis" > - <string>Print the currently displayed page.</string> - </property> - <property name="shortcut" > - <string>Ctrl+P</string> - </property> - </action> - <action name="actionFileExit" > - <property name="text" > - <string>E&xit</string> - </property> - <property name="whatsThis" > - <string>Quit Qt Assistant.</string> - </property> - <property name="shortcut" > - <string>Ctrl+Q</string> - </property> - <property name="menuRole" > - <enum>QAction::QuitRole</enum> - </property> - </action> - <action name="actionEditCopy" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/editcopy.png</iconset> - </property> - <property name="text" > - <string>&Copy</string> - </property> - <property name="whatsThis" > - <string>Copy the selected text to the clipboard.</string> - </property> - <property name="shortcut" > - <string>Ctrl+C</string> - </property> - </action> - <action name="actionEditFind" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/find.png</iconset> - </property> - <property name="text" > - <string>&Find in Text...</string> - </property> - <property name="whatsThis" > - <string>Open the Find dialog. Qt Assistant will search the currently displayed page for the text you enter.</string> - </property> - <property name="shortcut" > - <string>Ctrl+F</string> - </property> - </action> - <action name="actionEditFindNext" > - <property name="text" > - <string>Find &Next</string> - </property> - <property name="shortcut" > - <string>F3</string> - </property> - </action> - <action name="actionEditFindPrev" > - <property name="text" > - <string>Find &Previous</string> - </property> - <property name="shortcut" > - <string>Shift+F3</string> - </property> - </action> - <action name="actionGoHome" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/home.png</iconset> - </property> - <property name="text" > - <string>&Home</string> - </property> - <property name="whatsThis" > - <string>Go to the home page. Qt Assistant's home page is the Qt Reference Documentation.</string> - </property> - <property name="shortcut" > - <string>Ctrl+Home</string> - </property> - </action> - <action name="actionGoPrevious" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/previous.png</iconset> - </property> - <property name="text" > - <string>&Previous</string> - </property> - <property name="whatsThis" > - <string>Go to the previous page.</string> - </property> - <property name="shortcut" > - <string>Alt+Left</string> - </property> - </action> - <action name="actionGoNext" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/next.png</iconset> - </property> - <property name="text" > - <string>&Next</string> - </property> - <property name="whatsThis" > - <string>Go to the next page.</string> - </property> - <property name="shortcut" > - <string>Alt+Right</string> - </property> - </action> - <action name="actionAboutAssistant" > - <property name="text" > - <string>About Qt Assistant</string> - </property> - <property name="whatsThis" > - <string>Display further information about Qt Assistant.</string> - </property> - <property name="menuRole" > - <enum>QAction::AboutRole</enum> - </property> - </action> - <action name="actionAboutApplication" > - <property name="text" > - <string>About Qt</string> - </property> - <property name="menuRole" > - <enum>QAction::AboutQtRole</enum> - </property> - </action> - <action name="actionZoomIn" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/zoomin.png</iconset> - </property> - <property name="text" > - <string>Zoom &in</string> - </property> - <property name="whatsThis" > - <string>Zoom in on the document, i.e. increase the font size.</string> - </property> - <property name="shortcut" > - <string>Ctrl++</string> - </property> - </action> - <action name="actionZoomOut" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/zoomout.png</iconset> - </property> - <property name="text" > - <string>Zoom &out</string> - </property> - <property name="whatsThis" > - <string>Zoom out on the document, i.e. decrease the font size.</string> - </property> - <property name="shortcut" > - <string>Ctrl+-</string> - </property> - </action> - <action name="actionNewWindow" > - <property name="text" > - <string>New Window</string> - </property> - <property name="whatsThis" > - <string>Open a new window.</string> - </property> - <property name="shortcut" > - <string>Ctrl+N</string> - </property> - </action> - <action name="actionClose" > - <property name="text" > - <string>&Close</string> - </property> - <property name="whatsThis" > - <string>Close the current window.</string> - </property> - <property name="shortcut" > - <string>Ctrl+W</string> - </property> - </action> - <action name="actionAddBookmark" > - <property name="text" > - <string>&Add Bookmark</string> - </property> - <property name="whatsThis" > - <string>Add the currently displayed page as a new bookmark.</string> - </property> - </action> - <action name="actionHelpWhatsThis" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/whatsthis.png</iconset> - </property> - <property name="text" > - <string>What's This?</string> - </property> - <property name="statusTip" > - <string>"What's This?" context sensitive help.</string> - </property> - <property name="whatsThis" > - <string>"What's This?" context sensitive help.</string> - </property> - <property name="shortcut" > - <string>Shift+F1</string> - </property> - </action> - <action name="actionOpenPage" > - <property name="text" > - <string>Add Tab</string> - </property> - <property name="shortcut" > - <string>Ctrl+Alt+N</string> - </property> - </action> - <action name="actionNextPage" > - <property name="text" > - <string>Next Tab</string> - </property> - <property name="shortcut" > - <string>Ctrl+Alt+Right</string> - </property> - </action> - <action name="actionPrevPage" > - <property name="text" > - <string>Previous Tab</string> - </property> - <property name="shortcut" > - <string>Ctrl+Alt+Left</string> - </property> - </action> - <action name="actionClosePage" > - <property name="text" > - <string>Close Tab</string> - </property> - <property name="shortcut" > - <string>Ctrl+Alt+Q</string> - </property> - </action> - <action name="actionHelpAssistant" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/assistant.png</iconset> - </property> - <property name="text" > - <string>Qt Assistant Manual</string> - </property> - <property name="shortcut" > - <string>F1</string> - </property> - </action> - <action name="actionSaveAs" > - <property name="text" > - <string>Save Page As...</string> - </property> - <property name="shortcut" > - <string>Ctrl+Alt+S</string> - </property> - </action> - <action name="actionSyncToc" > - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/synctoc.png</iconset> - </property> - <property name="text" > - <string>Sync with Table of Contents</string> - </property> - <property name="whatsThis" > - <string>Select the page in contents tab.</string> - </property> - </action> - <action name="actionEditFont_Settings" > - <property name="text" > - <string>Font Settings...</string> - </property> - <property name="menuRole" > - <enum>QAction::PreferencesRole</enum> - </property> - </action> - </widget> - <resources> - <include location="assistant.qrc" /> - </resources> - <connections/> -</ui> diff --git a/tools/assistant/compat/profile.cpp b/tools/assistant/compat/profile.cpp deleted file mode 100644 index 2878a20..0000000 --- a/tools/assistant/compat/profile.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "profile.h" -#include <QTextCodec> -#include <QFileInfo> -#include <QRegExp> -#include <QDir> -#include <QList> -#include <QLibraryInfo> - -QT_BEGIN_NAMESPACE - -#define QT_TITLE QLatin1String("Qt Reference Documentation") -#define DESIGNER_TITLE QLatin1String("Qt Designer Manual") -#define ASSISTANT_TITLE QLatin1String("Qt Assistant Manual") -#define LINGUIST_TITLE QLatin1String("Qt Linguist Manual") -#define QMAKE_TITLE QLatin1String("qmake Manual") - -Profile *Profile::createDefaultProfile(const QString &docPath) -{ - QString path = QLibraryInfo::location(QLibraryInfo::DocumentationPath); - if (!docPath.isEmpty()) - path = docPath; - path = QDir::cleanPath(path) + QLatin1String("/html/"); - - Profile *profile = new Profile; - profile->valid = true; - profile->type = DefaultProfile; - profile->props[QLatin1String("name")] = QLatin1String("default"); - profile->props[QLatin1String("applicationicon")] = QLatin1String("assistant.png"); - profile->props[QLatin1String("aboutmenutext")] = QLatin1String("About Qt"); - profile->props[QLatin1String("abouturl")] = QLatin1String("about_qt"); - profile->props[QLatin1String("basepath")] = path; - profile->props[QLatin1String("startpage")] = path + QLatin1String("index.html"); - - profile->addDCFTitle( path + QLatin1String("qt.dcf"), QT_TITLE ); - profile->addDCFTitle( path + QLatin1String("designer.dcf"), DESIGNER_TITLE ); - profile->addDCFTitle( path + QLatin1String("assistant.dcf"), ASSISTANT_TITLE ); - profile->addDCFTitle( path + QLatin1String("linguist.dcf"), LINGUIST_TITLE ); - profile->addDCFTitle( path + QLatin1String("qmake.dcf"), QMAKE_TITLE ); - - profile->addDCFIcon( QT_TITLE, QLatin1String("qt.png") ); - profile->addDCFIcon( DESIGNER_TITLE, QLatin1String("designer.png") ); - profile->addDCFIcon( ASSISTANT_TITLE, QLatin1String("assistant.png") ); - profile->addDCFIcon( LINGUIST_TITLE, QLatin1String("linguist.png") ); - - profile->addDCFIndexPage( QT_TITLE, path + QLatin1String("index.html") ); - profile->addDCFIndexPage( DESIGNER_TITLE, path + QLatin1String("designer-manual.html") ); - profile->addDCFIndexPage( ASSISTANT_TITLE, path + QLatin1String("assistant-manual.html") ); - profile->addDCFIndexPage( LINGUIST_TITLE, path + QLatin1String("linguist-manual.html") ); - profile->addDCFIndexPage( QMAKE_TITLE, path + QLatin1String("qmake-manual.html") ); - - profile->addDCFImageDir( QT_TITLE, QLatin1String("../../gif/") ); - profile->addDCFImageDir( DESIGNER_TITLE, QLatin1String("../../gif/") ); - profile->addDCFImageDir( ASSISTANT_TITLE, QLatin1String("../../gif/") ); - profile->addDCFImageDir( LINGUIST_TITLE, QLatin1String("../../gif/") ); - profile->addDCFImageDir( QMAKE_TITLE, QLatin1String("../../gif/") ); - - return profile; -} - -Profile::Profile() - : valid( true ), dparser( 0 ) -{ - type = DefaultProfile; -} - -bool Profile::isValid() const -{ - return valid; -} - -void Profile::addDCFTitle(const QString &dcf, const QString &title) -{ - QString absdcf = QFileInfo(dcf).absoluteFilePath(); - dcfTitles[title] = absdcf; - if (!docs.contains(absdcf)) - docs << absdcf; -} - -void Profile::addDCF(const QString &docfile) -{ - if( !docs.contains( docfile ) == 0 ) - docs << docfile; -} - -void Profile::addDCFIcon(const QString docfile, const QString &icon) -{ - icons[docfile] = icon; -} - -void Profile::addDCFIndexPage(const QString title, const QString &indexPage) -{ - indexPages[title] = indexPage; -} - -void Profile::addDCFImageDir(const QString docfile, const QString &imgDir) -{ - imageDirs[docfile] = imgDir; -} - -void Profile::addProperty(const QString &name, const QString &value) -{ - props[name] = value; -} - -bool Profile::hasDocFile(const QString &name) -{ - return docs.contains( name ); -} - -void Profile::removeDocFileEntry(const QString &docfile) -{ - docs.removeAll(docfile); - QStringList titles; - - for( QMap<QString,QString>::Iterator it = dcfTitles.begin(); - it != dcfTitles.end(); ++it ) { - if( (*it) == docfile ) { - indexPages.remove( *it ); - icons.remove( *it ); - imageDirs.remove( *it ); - titles << it.key(); - } - } - - for( QStringList::ConstIterator title = titles.constBegin(); - title != titles.constEnd(); ++title ) - dcfTitles.remove( *title ); - -#ifdef ASSISTANT_DEBUG - qDebug() << "docs:\n - " << docs.join("\n - "); - qDebug() << "titles:\n - " << titles.join("\n - "); - qDebug() << "keys:\n - " << ((QStringList*)&(dcfTitles.keys()))->join("\n - "); - qDebug() << "values:\n - " << ((QStringList*)&(dcfTitles.values()))->join("\n - "); -#endif -} - -QString Profile::storableFilePath(const QString &fileName) -{ - QString path = QLibraryInfo::location(QLibraryInfo::DocumentationPath).replace(QLatin1String("\\"), QLatin1String("/")); - QString fName = fileName; - if (fName.startsWith(path)) - fName.replace(0, path.length(), QLatin1String("$DOCPATH$")); - return fName; -} - -QString Profile::loadableFilePath(const QString &fileName) -{ - QString path = QLibraryInfo::location(QLibraryInfo::DocumentationPath).replace(QLatin1String("\\"), QLatin1String("/")); - QString fName = fileName; - if (fName.startsWith(QLatin1String("$DOCPATH$"))) - fName.replace(0, 9, path); - return fName; -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/profile.h b/tools/assistant/compat/profile.h deleted file mode 100644 index 1aa9719..0000000 --- a/tools/assistant/compat/profile.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PROFILE_H -#define PROFILE_H - -#include <QFileInfo> -#include <QString> -#include <QStringList> -#include <QMap> - -QT_BEGIN_NAMESPACE - -class DocuParser; - -class Profile -{ -public: - enum ProfileType { DefaultProfile, UserProfile }; - Profile(); - - bool isValid() const; - - void addDCF( const QString &docfile ); - void addDCFIcon( const QString title, const QString &icon ); - void addDCFIndexPage( const QString title, const QString &indexPage ); - void addDCFImageDir( const QString title, const QString &imgDir ); - void addDCFTitle( const QString &dcf, const QString &title ); - void addProperty( const QString &name, const QString &value ); - bool hasDocFile( const QString &docFile ); - void removeDocFileEntry( const QString &title ); - - ProfileType profileType() const { return type; } - void setProfileType( ProfileType t ) { type = t; } - - DocuParser *docuParser() const { return dparser; } - void setDocuParser( DocuParser *dp ) { dparser = dp; } - - static Profile* createDefaultProfile(const QString &docPath = QString()); - static QString makeRelativePath(const QString &base, const QString &path); - static QString storableFilePath(const QString &fileName); - static QString loadableFilePath(const QString &fileName); - - uint valid:1; - ProfileType type; - DocuParser *dparser; - QMap<QString,QString> props; - QMap<QString,QString> icons; - QMap<QString,QString> indexPages; - QMap<QString,QString> imageDirs; - QMap<QString,QString> dcfTitles; - QStringList docs; -}; - -QT_END_NAMESPACE - -#endif // PROFILE_H diff --git a/tools/assistant/compat/tabbedbrowser.cpp b/tools/assistant/compat/tabbedbrowser.cpp deleted file mode 100644 index c3c1572..0000000 --- a/tools/assistant/compat/tabbedbrowser.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "tabbedbrowser.h" -#include "mainwindow.h" -#include "helpwindow.h" -#include "config.h" - -#include <QStyleOptionTab> -#include <QToolTip> -#include <QFileInfo> -#include <QToolButton> -#include <QPixmap> -#include <QIcon> -#include <QStyle> -#include <QTimer> -#include <QStackedWidget> -#include <QTimer> -#include <QTextBlock> -#include <QKeyEvent> - -QT_BEGIN_NAMESPACE - -#ifdef Q_WS_MAC -const QLatin1String ImageLocation(":trolltech/assistant/images/mac/"); -#else -const QLatin1String ImageLocation(":trolltech/assistant/images/win/"); -#endif - -TabbedBrowser::TabbedBrowser(MainWindow *parent) - : QWidget(parent) -{ - ui.setupUi(this); - init(); - - QStackedWidget *stack = qFindChild<QStackedWidget*>(ui.tab); - Q_ASSERT(stack); - stack->setContentsMargins(0, 0, 0, 0); - connect(stack, SIGNAL(currentChanged(int)), parent, SLOT(browserTabChanged())); - - 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); -} - -TabbedBrowser::~TabbedBrowser() -{ -} - -MainWindow *TabbedBrowser::mainWindow() const -{ - return static_cast<MainWindow*>(parentWidget()); -} - -void TabbedBrowser::forward() -{ - currentBrowser()->forward(); - emit browserUrlChanged(currentBrowser()->source().toString()); -} - -void TabbedBrowser::backward() -{ - currentBrowser()->backward(); - emit browserUrlChanged(currentBrowser()->source().toString()); -} - -void TabbedBrowser::setSource( const QString &ref ) -{ - HelpWindow * win = currentBrowser(); - win->setSource(ref); -} - -void TabbedBrowser::reload() -{ - currentBrowser()->reload(); -} - -void TabbedBrowser::home() -{ - currentBrowser()->home(); -} - -HelpWindow *TabbedBrowser::currentBrowser() const -{ - return static_cast<HelpWindow*>(ui.tab->currentWidget()); -} - -void TabbedBrowser::nextTab() -{ - if(ui.tab->currentIndex()<=ui.tab->count()-1) - ui.tab->setCurrentIndex(ui.tab->currentIndex()+1); -} - -void TabbedBrowser::previousTab() -{ - int idx = ui.tab->currentIndex()-1; - if(idx>=0) - ui.tab->setCurrentIndex(idx); -} - -HelpWindow *TabbedBrowser::createHelpWindow() -{ - MainWindow *mainWin = mainWindow(); - HelpWindow *win = new HelpWindow(mainWin, 0); - win->setFrameStyle(QFrame::NoFrame); - win->setPalette(palette()); - win->setSearchPaths(Config::configuration()->mimePaths()); - ui.tab->addTab(win, tr("...")); - connect(win, SIGNAL(highlighted(QString)), - (const QObject*) (mainWin->statusBar()), SLOT(showMessage(QString))); - connect(win, SIGNAL(backwardAvailable(bool)), - mainWin, SLOT(backwardAvailable(bool))); - connect(win, SIGNAL(forwardAvailable(bool)), - mainWin, SLOT(forwardAvailable(bool))); - connect(win, SIGNAL(sourceChanged(QUrl)), this, SLOT(sourceChanged())); - - ui.tab->cornerWidget(Qt::TopRightCorner)->setEnabled(ui.tab->count() > 1); - win->installEventFilter(this); - win->viewport()->installEventFilter(this); - ui.editFind->installEventFilter(this); - return win; -} - -HelpWindow *TabbedBrowser::newBackgroundTab() -{ - HelpWindow *win = createHelpWindow(); - emit tabCountChanged(ui.tab->count()); - return win; -} - -void TabbedBrowser::newTab(const QString &lnk) -{ - QString link(lnk); - if(link.isNull()) { - HelpWindow *w = currentBrowser(); - if(w) - link = w->source().toString(); - } - HelpWindow *win = createHelpWindow(); - ui.tab->setCurrentIndex(ui.tab->indexOf(win)); - if(!link.isNull()) { - win->setSource(link); - } - - emit tabCountChanged(ui.tab->count()); -} - -void TabbedBrowser::zoomIn() -{ - currentBrowser()->zoomIn(); - Config::configuration()->setFontPointSize(currentBrowser()->font().pointSizeF()); -} - -void TabbedBrowser::zoomOut() -{ - currentBrowser()->zoomOut(); - Config::configuration()->setFontPointSize(currentBrowser()->font().pointSizeF()); -} - -void TabbedBrowser::init() -{ - - lastCurrentTab = 0; - while(ui.tab->count()) { - QWidget *page = ui.tab->widget(0); - ui.tab->removeTab(0); - delete page; - } - - connect(ui.tab, SIGNAL(currentChanged(int)), - this, SLOT(transferFocus())); - - QTabBar *tabBar = qFindChild<QTabBar*>(ui.tab); - QStyleOptionTab opt; - if (tabBar) { - opt.init(tabBar); - opt.shape = tabBar->shape(); - tabBar->setContextMenuPolicy(Qt::CustomContextMenu); - connect(tabBar, SIGNAL(customContextMenuRequested(QPoint)), SLOT(openTabMenu(QPoint))); - } - - // workaround for sgi style - QPalette pal = palette(); - pal.setColor(QPalette::Active, QPalette::Button, pal.color(QPalette::Active, QPalette::Window)); - pal.setColor(QPalette::Disabled, QPalette::Button, pal.color(QPalette::Disabled, QPalette::Window)); - pal.setColor(QPalette::Inactive, QPalette::Button, pal.color(QPalette::Inactive, QPalette::Window)); - - QToolButton *newTabButton = new QToolButton(this); - ui.tab->setCornerWidget(newTabButton, Qt::TopLeftCorner); - newTabButton->setCursor(Qt::ArrowCursor); - newTabButton->setAutoRaise(true); - newTabButton->setIcon(QIcon(ImageLocation + QLatin1String("addtab.png"))); - QObject::connect(newTabButton, SIGNAL(clicked()), this, SLOT(newTab())); - newTabButton->setToolTip(tr("Add page")); - - QToolButton *closeTabButton = new QToolButton(this); - closeTabButton->setPalette(pal); - ui.tab->setCornerWidget(closeTabButton, Qt::TopRightCorner); - closeTabButton->setCursor(Qt::ArrowCursor); - closeTabButton->setAutoRaise(true); - closeTabButton->setIcon(QIcon(ImageLocation + QLatin1String("closetab.png"))); - QObject::connect(closeTabButton, SIGNAL(clicked()), this, SLOT(closeTab())); - closeTabButton->setToolTip(tr("Close page")); - closeTabButton->setEnabled(false); - - QObject::connect(ui.toolClose, SIGNAL(clicked()), ui.frameFind, SLOT(hide())); - QObject::connect(ui.toolPrevious, SIGNAL(clicked()), this, SLOT(findPrevious())); - QObject::connect(ui.toolNext, SIGNAL(clicked()), this, SLOT(findNext())); - QObject::connect(ui.editFind, SIGNAL(returnPressed()), this, SLOT(findNext())); - QObject::connect(ui.editFind, SIGNAL(textEdited(QString)), - this, SLOT(find(QString))); - ui.frameFind->setVisible(false); - ui.labelWrapped->setVisible(false); - autoHideTimer = new QTimer(this); - autoHideTimer->setInterval(5000); - autoHideTimer->setSingleShot(true); - QObject::connect(autoHideTimer, SIGNAL(timeout()), ui.frameFind, SLOT(hide())); -} - -void TabbedBrowser::updateTitle(const QString &title) -{ - ui.tab->setTabText(ui.tab->indexOf(currentBrowser()), title.trimmed()); -} - -void TabbedBrowser::newTab() -{ - newTab(QString()); -} - -void TabbedBrowser::transferFocus() -{ - if(currentBrowser()) { - currentBrowser()->setFocus(); - } - mainWindow()->setWindowTitle(Config::configuration()->title() - + QLatin1String(" - ") - + currentBrowser()->documentTitle()); -} - -void TabbedBrowser::initHelpWindow(HelpWindow * /*win*/) -{ -} - -void TabbedBrowser::setup() -{ - newTab(QString()); -} - -void TabbedBrowser::copy() -{ - currentBrowser()->copy(); -} - -void TabbedBrowser::closeTab() -{ - if(ui.tab->count()==1) - return; - HelpWindow *win = currentBrowser(); - mainWindow()->removePendingBrowser(win); - ui.tab->removeTab(ui.tab->indexOf(win)); - QTimer::singleShot(0, win, SLOT(deleteLater())); - ui.tab->cornerWidget(Qt::TopRightCorner)->setEnabled(ui.tab->count() > 1); - emit tabCountChanged(ui.tab->count()); -} - -QStringList TabbedBrowser::sources() const -{ - QStringList lst; - int cnt = ui.tab->count(); - for(int i=0; i<cnt; i++) { - lst.append(((QTextBrowser*) ui.tab->widget(i))->source().toString()); - } - return lst; -} - -QList<HelpWindow*> TabbedBrowser::browsers() const -{ - QList<HelpWindow*> list; - for (int i=0; i<ui.tab->count(); ++i) { - Q_ASSERT(qobject_cast<HelpWindow*>(ui.tab->widget(i))); - list.append(static_cast<HelpWindow*>(ui.tab->widget(i))); - } - return list; -} - -void TabbedBrowser::sourceChanged() -{ - HelpWindow *win = qobject_cast<HelpWindow *>(QObject::sender()); - Q_ASSERT(win); - QString docTitle(win->documentTitle()); - if (docTitle.isEmpty()) - docTitle = QLatin1String("..."); - // Make the classname in the title a bit more visible (otherwise - // we just see the "Qt 4.0 : Q..." which isn't really helpful ;-) - QString qtTitle = QLatin1String("Qt ") + QString::number( (QT_VERSION >> 16) & 0xff ) - + QLatin1String(".") + QString::number( (QT_VERSION >> 8) & 0xff ) - + QLatin1String(": "); - if (docTitle.startsWith(qtTitle)) - docTitle = docTitle.mid(qtTitle.length()); - setTitle(win, docTitle); - ui.frameFind->hide(); - ui.labelWrapped->hide(); - win->setTextCursor(win->cursorForPosition(QPoint(0, 0))); -} - -void TabbedBrowser::setTitle(HelpWindow *win, const QString &title) -{ - const QString tt = title.trimmed(); - ui.tab->setTabText(ui.tab->indexOf(win), tt); - if (win == currentBrowser()) - mainWindow()->setWindowTitle(Config::configuration()->title() + QLatin1String(" - ") + tt); -} - -void TabbedBrowser::keyPressEvent(QKeyEvent *e) -{ - int key = e->key(); - QString ttf = ui.editFind->text(); - QString text = e->text(); - - if (ui.frameFind->isVisible()) { - switch (key) { - case Qt::Key_Escape: - ui.frameFind->hide(); - ui.labelWrapped->hide(); - return; - case Qt::Key_Backspace: - ttf.chop(1); - break; - case Qt::Key_Return: - case Qt::Key_Enter: - // Return/Enter key events are not accepted by QLineEdit - return; - default: - if (text.isEmpty()) { - QWidget::keyPressEvent(e); - return; - } - ttf += text; - } - } else { - if (text.isEmpty() || text[0].isSpace() || !text[0].isPrint()) { - QWidget::keyPressEvent(e); - return; - } - if (text.startsWith(QLatin1Char('/'))) { - ui.editFind->clear(); - find(); - return; - } - ttf = text; - ui.frameFind->show(); - } - - ui.editFind->setText(ttf); - find(ttf, false, false); -} - -void TabbedBrowser::findNext() -{ - find(ui.editFind->text(), true, false); -} - -void TabbedBrowser::findPrevious() -{ - find(ui.editFind->text(), false, true); -} - -void TabbedBrowser::find() -{ - ui.frameFind->show(); - ui.editFind->setFocus(Qt::ShortcutFocusReason); - ui.editFind->selectAll(); - autoHideTimer->stop(); -} - -void TabbedBrowser::find(QString ttf, bool forward, bool backward) -{ - HelpWindow *browser = currentBrowser(); - QTextDocument *doc = browser->document(); - QString oldText = ui.editFind->text(); - QTextCursor c = browser->textCursor(); - QTextDocument::FindFlags options; - QPalette p = ui.editFind->palette(); - p.setColor(QPalette::Active, QPalette::Base, Qt::white); - - if (c.hasSelection()) - c.setPosition(forward ? c.position() : c.anchor(), QTextCursor::MoveAnchor); - - QTextCursor newCursor = c; - - if (!ttf.isEmpty()) { - if (backward) - options |= QTextDocument::FindBackward; - - if (ui.checkCase->isChecked()) - options |= QTextDocument::FindCaseSensitively; - - if (ui.checkWholeWords->isChecked()) - options |= QTextDocument::FindWholeWords; - - newCursor = doc->find(ttf, c, options); - ui.labelWrapped->hide(); - - if (newCursor.isNull()) { - QTextCursor ac(doc); - ac.movePosition(options & QTextDocument::FindBackward - ? QTextCursor::End : QTextCursor::Start); - newCursor = doc->find(ttf, ac, options); - if (newCursor.isNull()) { - p.setColor(QPalette::Active, QPalette::Base, QColor(255, 102, 102)); - newCursor = c; - } else - ui.labelWrapped->show(); - } - } - - if (!ui.frameFind->isVisible()) - ui.frameFind->show(); - browser->setTextCursor(newCursor); - ui.editFind->setPalette(p); - if (!ui.editFind->hasFocus()) - autoHideTimer->start(); -} - -bool TabbedBrowser::eventFilter(QObject *o, QEvent *e) -{ - if (o == ui.editFind) { - if (e->type() == QEvent::FocusIn && autoHideTimer->isActive()) - autoHideTimer->stop(); - } else if (e->type() == QEvent::KeyPress && ui.frameFind->isVisible()) { // assume textbrowser - QKeyEvent *ke = static_cast<QKeyEvent *>(e); - if (ke->key() == Qt::Key_Space) { - keyPressEvent(ke); - return true; - } - } - - return QWidget::eventFilter(o, e); -} - -void TabbedBrowser::openTabMenu(const QPoint& pos) -{ - QTabBar *tabBar = qFindChild<QTabBar*>(ui.tab); - - QMenu m(QLatin1String(""), tabBar); - QAction *new_action = m.addAction(tr("New Tab")); - QAction *close_action = m.addAction(tr("Close Tab")); - QAction *close_others_action = m.addAction(tr("Close Other Tabs")); - - if (tabBar->count() == 1) { - close_action->setEnabled(false); - close_others_action->setEnabled(false); - } - - QAction *action_picked = m.exec(tabBar->mapToGlobal(pos)); - if (!action_picked) - return; - - if (action_picked == new_action) { - newTab(); - return; - } - - QList<HelpWindow*> windowList = browsers(); - for (int i = 0; i < tabBar->count(); ++i) { - if (tabBar->tabRect(i).contains(pos)) { - HelpWindow *win = static_cast<HelpWindow*>(ui.tab->widget(i)); - if (action_picked == close_action) { - mainWindow()->removePendingBrowser(win); - QTimer::singleShot(0, win, SLOT(deleteLater())); - } - windowList.removeOne(win); - break; - } - } - - if (action_picked == close_others_action) { - foreach (HelpWindow* win, windowList) { - mainWindow()->removePendingBrowser(win); - QTimer::singleShot(0, win, SLOT(deleteLater())); - windowList.removeOne(win); - } - } - - ui.tab->cornerWidget(Qt::TopRightCorner)->setEnabled(windowList.count() > 1); - emit tabCountChanged(windowList.count()); -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/tabbedbrowser.h b/tools/assistant/compat/tabbedbrowser.h deleted file mode 100644 index 0e32505..0000000 --- a/tools/assistant/compat/tabbedbrowser.h +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TABBEDBROWSER_H -#define TABBEDBROWSER_H - -#include "ui_tabbedbrowser.h" - -QT_BEGIN_NAMESPACE - -class MainWindow; -class HelpWindow; -class QStyleSheet; -class QMimeSourceFactory; -class QTimer; - -class TabbedBrowser : public QWidget -{ - Q_OBJECT -public: - TabbedBrowser(MainWindow *parent); - virtual ~TabbedBrowser(); - - MainWindow *mainWindow() const; - HelpWindow *currentBrowser() const; - QStringList sources() const; - QList<HelpWindow*> browsers() const; - - HelpWindow* newBackgroundTab(); - HelpWindow* createHelpWindow(); - - void setTitle(HelpWindow*, const QString &); - -signals: - void tabCountChanged(int count); - void browserUrlChanged(const QString &link); - -protected: - void keyPressEvent(QKeyEvent *); - bool eventFilter(QObject *o, QEvent *e); - -public slots: - void init(); - void forward(); - void backward(); - void setSource(const QString &ref); - void reload(); - void home(); - void nextTab(); - void previousTab(); - void newTab(const QString &lnk); - void zoomIn(); - void zoomOut(); - void updateTitle(const QString &title); - void newTab(); - void transferFocus(); - void initHelpWindow(HelpWindow *win); - void setup(); - void copy(); - void closeTab(); - void sourceChanged(); - - void find(); - void findNext(); - void findPrevious(); - -private slots: - void find(QString, bool forward = false, bool backward = false); - void openTabMenu(const QPoint& pos); - -private: - Ui::TabbedBrowser ui; - QWidget *lastCurrentTab; - QFont tabFont; - - QString fixedFontFam; - QColor lnkColor; - bool underlineLnk; - QTimer *autoHideTimer; -}; - -QT_END_NAMESPACE - -#endif // TABBEDBROWSER_H diff --git a/tools/assistant/compat/tabbedbrowser.ui b/tools/assistant/compat/tabbedbrowser.ui deleted file mode 100644 index 411f145..0000000 --- a/tools/assistant/compat/tabbedbrowser.ui +++ /dev/null @@ -1,233 +0,0 @@ -<ui version="4.0" > - <author></author> - <comment>********************************************************************* -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -*********************************************************************</comment> - <exportmacro></exportmacro> - <class>TabbedBrowser</class> - <widget class="QWidget" name="TabbedBrowser" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>710</width> - <height>664</height> - </rect> - </property> - <property name="windowTitle" > - <string>TabbedBrowser</string> - </property> - <layout class="QVBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>0</number> - </property> - <item> - <widget class="QTabWidget" name="tab" > - <widget class="QWidget" name="frontpage" > - <attribute name="title" > - <string>Untitled</string> - </attribute> - <layout class="QGridLayout" > - <property name="margin" > - <number>8</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - </layout> - </widget> - </widget> - </item> - <item> - <widget class="QFrame" name="frameFind" > - <property name="frameShape" > - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow" > - <enum>QFrame::Raised</enum> - </property> - <layout class="QHBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QToolButton" name="toolClose" > - <property name="text" > - <string/> - </property> - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/close.png</iconset> - </property> - <property name="autoRaise" > - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="editFind" > - <property name="sizePolicy" > - <sizepolicy> - <hsizetype>0</hsizetype> - <vsizetype>0</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize" > - <size> - <width>150</width> - <height>0</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="toolPrevious" > - <property name="text" > - <string>Previous</string> - </property> - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/previous.png</iconset> - </property> - <property name="toolButtonStyle" > - <enum>Qt::ToolButtonTextBesideIcon</enum> - </property> - <property name="autoRaise" > - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="toolNext" > - <property name="minimumSize" > - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="text" > - <string>Next</string> - </property> - <property name="icon" > - <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/next.png</iconset> - </property> - <property name="toolButtonStyle" > - <enum>Qt::ToolButtonTextBesideIcon</enum> - </property> - <property name="autoRaise" > - <bool>true</bool> - </property> - <property name="arrowType" > - <enum>Qt::NoArrow</enum> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="checkCase" > - <property name="text" > - <string>Case Sensitive</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="checkWholeWords" > - <property name="text" > - <string>Whole words</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="labelWrapped" > - <property name="minimumSize" > - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="maximumSize" > - <size> - <width>105</width> - <height>20</height> - </size> - </property> - <property name="text" > - <string><img src=":/trolltech/assistant/images/wrap.png">&nbsp;Search wrapped</string> - </property> - <property name="textFormat" > - <enum>Qt::RichText</enum> - </property> - <property name="scaledContents" > - <bool>true</bool> - </property> - <property name="alignment" > - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" > - <size> - <width>81</width> - <height>21</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <pixmapfunction></pixmapfunction> - <resources> - <include location="assistant.qrc" /> - </resources> - <connections/> -</ui> diff --git a/tools/assistant/compat/topicchooser.cpp b/tools/assistant/compat/topicchooser.cpp deleted file mode 100644 index b2e7e98..0000000 --- a/tools/assistant/compat/topicchooser.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "topicchooser.h" - -#include <QLabel> -#include <QListWidget> -#include <QPushButton> - -QT_BEGIN_NAMESPACE - -TopicChooser::TopicChooser(QWidget *parent, const QStringList &lnkNames, - const QStringList &lnks, const QString &title) - : QDialog(parent), links(lnks), linkNames(lnkNames) -{ - ui.setupUi(this); - - ui.label->setText(tr("Choose a topic for <b>%1</b>").arg(title)); - ui.listbox->addItems(linkNames); - if (ui.listbox->count() != 0) - ui.listbox->setCurrentRow(0); - ui.listbox->setFocus(); -} - -QString TopicChooser::link() const -{ - if (ui.listbox->currentRow() == -1) - return QString(); - QString s = ui.listbox->item(ui.listbox->currentRow())->text(); - if (s.isEmpty()) - return s; - int i = linkNames.indexOf(s); - return links[i]; -} - -QString TopicChooser::getLink(QWidget *parent, const QStringList &lnkNames, - const QStringList &lnks, const QString &title) -{ - TopicChooser *dlg = new TopicChooser(parent, lnkNames, lnks, title); - QString lnk; - if (dlg->exec() == QDialog::Accepted) - lnk = dlg->link(); - delete dlg; - return lnk; -} - -void TopicChooser::on_buttonDisplay_clicked() -{ - accept(); -} - -void TopicChooser::on_buttonCancel_clicked() -{ - reject(); -} - -void TopicChooser::on_listbox_itemActivated(QListWidgetItem *item) -{ - Q_UNUSED(item); - accept(); -} - -QT_END_NAMESPACE diff --git a/tools/assistant/compat/topicchooser.ui b/tools/assistant/compat/topicchooser.ui deleted file mode 100644 index 18ff61b..0000000 --- a/tools/assistant/compat/topicchooser.ui +++ /dev/null @@ -1,162 +0,0 @@ -<ui version="4.0" > - <comment>********************************************************************* -** -** Copyright (C) 2010 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -*********************************************************************</comment> - <class>TopicChooser</class> - <widget class="QDialog" name="TopicChooser" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>391</width> - <height>223</height> - </rect> - </property> - <property name="windowTitle" > - <string>Choose Topic</string> - </property> - <property name="whatsThis" > - <string>Select a topic from the list and click the <b>Display</b>-button to open the online help.</string> - </property> - <property name="sizeGripEnabled" > - <bool>true</bool> - </property> - <layout class="QVBoxLayout" > - <property name="spacing" > - <number>6</number> - </property> - <property name="leftMargin" > - <number>11</number> - </property> - <property name="topMargin" > - <number>11</number> - </property> - <property name="rightMargin" > - <number>11</number> - </property> - <property name="bottomMargin" > - <number>11</number> - </property> - <item> - <widget class="QLabel" name="label" > - <property name="text" > - <string>&Topics</string> - </property> - <property name="buddy" > - <cstring>listbox</cstring> - </property> - </widget> - </item> - <item> - <widget class="QListWidget" name="listbox" > - <property name="whatsThis" > - <string>Displays a list of available help topics for the keyword.</string> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="spacing" > - <number>6</number> - </property> - <property name="leftMargin" > - <number>0</number> - </property> - <property name="topMargin" > - <number>0</number> - </property> - <property name="rightMargin" > - <number>0</number> - </property> - <property name="bottomMargin" > - <number>0</number> - </property> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType" > - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="buttonDisplay" > - <property name="whatsThis" > - <string>Open the topic selected in the list.</string> - </property> - <property name="text" > - <string>&Display</string> - </property> - <property name="autoDefault" > - <bool>true</bool> - </property> - <property name="default" > - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="buttonCancel" > - <property name="whatsThis" > - <string>Close the Dialog.</string> - </property> - <property name="text" > - <string>&Close</string> - </property> - <property name="autoDefault" > - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/tools/assistant/lib/lib.pro b/tools/assistant/lib/lib.pro index 51933de..26d3456 100644 --- a/tools/assistant/lib/lib.pro +++ b/tools/assistant/lib/lib.pro @@ -23,7 +23,6 @@ unix:QMAKE_PKGCONFIG_REQUIRES += QtNetwork \ QtSql \ QtXml LIBS_PRIVATE += -l$$qclucene - RESOURCES += helpsystem.qrc SOURCES += qhelpenginecore.cpp \ qhelpengine.cpp \ @@ -41,6 +40,7 @@ SOURCES += qhelpenginecore.cpp \ qhelpsearchindexwriter_default.cpp \ qhelpsearchindexreader_default.cpp \ qhelpsearchindexreader.cpp \ + qclucenefieldnames.cpp \ qhelp_global.cpp # access to clucene @@ -63,7 +63,8 @@ HEADERS += qhelpenginecore.h \ qhelpsearchindex_default_p.h \ qhelpsearchindexwriter_default_p.h \ qhelpsearchindexreader_default_p.h \ - qhelpsearchindexreader_p.h + qhelpsearchindexreader_p.h \ + qclucenefieldnames_p.h # access to clucene HEADERS += qhelpsearchindexwriter_clucene_p.h \ diff --git a/tools/assistant/lib/qclucenefieldnames.cpp b/tools/assistant/lib/qclucenefieldnames.cpp new file mode 100644 index 0000000..84e3a1a --- /dev/null +++ b/tools/assistant/lib/qclucenefieldnames.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qclucenefieldnames_p.h" + +QT_BEGIN_NAMESPACE + +namespace qt { +namespace fulltextsearch { +namespace clucene { +const QString AttributeField(QLatin1String("attribute")); +const QString ContentField(QLatin1String("content")); +const QString NamespaceField(QLatin1String("namespace")); +const QString PathField(QLatin1String("path")); +const QString TitleField(QLatin1String("title")); +const QString TitleTokenizedField(QLatin1String("titleTokenized")); +} // namespace clucene +} // namespace fulltextsearch +} // namespace qt + +QT_END_NAMESPACE diff --git a/tools/assistant/compat/fontsettingsdialog.h b/tools/assistant/lib/qclucenefieldnames_p.h index 6599d2a..ae13515 100644 --- a/tools/assistant/compat/fontsettingsdialog.h +++ b/tools/assistant/lib/qclucenefieldnames_p.h @@ -39,39 +39,27 @@ ** ****************************************************************************/ -#ifndef _FONT_SETTINGS_DIALOG_H_ -#define _FONT_SETTINGS_DIALOG_H_ +#ifndef QCLUCENEFIELDNAMES_P_H +#define QCLUCENEFIELDNAMES_P_H -#include <QtCore/QObject> -#include <QtGui/QDialog> +#include <QtCore/QtGlobal> +#include <QtCore/QString> QT_BEGIN_NAMESPACE -class FontPanel; -struct FontSettings; -class QDialogButtonBox; - -class FontSettingsDialog : public QDialog -{ - Q_OBJECT - -public: - FontSettingsDialog(QWidget *parent = 0); - ~FontSettingsDialog(); - - bool showDialog(FontSettings *settings); - -private: - void updateFontSettings(FontSettings *settings); - void setupFontSettingsDialog(const FontSettings *settings); - -private: - FontPanel *m_windowFontPanel; - FontPanel *m_browserFontPanel; - QDialogButtonBox *m_dialogButtonBox; -}; - -#endif // _FONT_SETTINGS_DIALOG_H_ - +namespace qt { +namespace fulltextsearch { +namespace clucene { + extern const QString AttributeField; + extern const QString ContentField; + extern const QString NamespaceField; + extern const QString PathField; + extern const QString TitleField; + extern const QString TitleTokenizedField; +} // namespace clucene +} // namespace fulltextsearch +} // namespace qt QT_END_NAMESPACE + +#endif // QCLUCENEFIELDNAMES_P_H diff --git a/tools/assistant/lib/qhelp_global.cpp b/tools/assistant/lib/qhelp_global.cpp index 539b504..d8a94d3 100644 --- a/tools/assistant/lib/qhelp_global.cpp +++ b/tools/assistant/lib/qhelp_global.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include <QtCore/QCoreApplication> #include <QtCore/QRegExp> #include <QtCore/QMutexLocker> #include <QtGui/QTextDocument> @@ -60,7 +61,7 @@ QString QHelpGlobal::uniquifyConnectionName(const QString &name, void *pointer) QString QHelpGlobal::documentTitle(const QString &content) { - QString title = QObject::tr("Untitled"); + QString title = QCoreApplication::translate("QHelp", "Untitled"); if (!content.isEmpty()) { int start = content.indexOf(QLatin1String("<title>"), 0, Qt::CaseInsensitive) + 7; int end = content.indexOf(QLatin1String("</title>"), 0, Qt::CaseInsensitive); @@ -86,17 +87,18 @@ QString QHelpGlobal::codecFromData(const QByteArray &data) QString QHelpGlobal::codecFromHtmlData(const QByteArray &data) { - QString content = QString::fromUtf8(data.constData(), data.size()); - int start = content.indexOf(QLatin1String("<meta"), 0, Qt::CaseInsensitive); + QString head = QString::fromUtf8(data.constData(), qMin(1000, data.size())); + int start = head.indexOf(QLatin1String("<meta"), 0, Qt::CaseInsensitive); if (start > 0) { - int end; QRegExp r(QLatin1String("charset=([^\"\\s]+)")); while (start != -1) { - end = content.indexOf(QLatin1Char('>'), start) + 1; - const QString &meta = content.mid(start, end - start).toLower(); + const int end = head.indexOf(QLatin1Char('>'), start) + 1; + if (end <= start) + break; + const QString &meta = head.mid(start, end - start).toLower(); if (r.indexIn(meta) != -1) return r.cap(1); - start = content.indexOf(QLatin1String("<meta"), end, + start = head.indexOf(QLatin1String("<meta"), end, Qt::CaseInsensitive); } } @@ -105,8 +107,8 @@ QString QHelpGlobal::codecFromHtmlData(const QByteArray &data) QString QHelpGlobal::codecFromXmlData(const QByteArray &data) { - QString content = QString::fromUtf8(data.constData(), data.size()); + QString head = QString::fromUtf8(data.constData(), qMin(1000, data.size())); const QRegExp encodingExp(QLatin1String("^\\s*<\\?xml version=" "\"\\d\\.\\d\" encoding=\"([^\"]+)\"\\?>.*")); - return encodingExp.exactMatch(content) ? encodingExp.cap(1) : QString(); + return encodingExp.exactMatch(head) ? encodingExp.cap(1) : QString(); } diff --git a/tools/assistant/lib/qhelpcollectionhandler.cpp b/tools/assistant/lib/qhelpcollectionhandler.cpp index cb7e457..235f737 100644 --- a/tools/assistant/lib/qhelpcollectionhandler.cpp +++ b/tools/assistant/lib/qhelpcollectionhandler.cpp @@ -308,10 +308,8 @@ bool QHelpCollectionHandler::addCustomFilter(const QString &filterName, m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?")); m_query.bindValue(0, filterName); m_query.exec(); - while (m_query.next()) { + if (m_query.next()) nameId = m_query.value(0).toInt(); - break; - } m_query.exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable")); QStringList idsToInsert = attributes; diff --git a/tools/assistant/lib/qhelpenginecore.cpp b/tools/assistant/lib/qhelpenginecore.cpp index 066e4d5..71306af 100644 --- a/tools/assistant/lib/qhelpenginecore.cpp +++ b/tools/assistant/lib/qhelpenginecore.cpp @@ -119,7 +119,7 @@ bool QHelpEngineCorePrivate::setup() QHelpDBReader *reader = new QHelpDBReader(absFileName, QHelpGlobal::uniquifyConnectionName(info.fileName, this), this); if (!reader->init()) { - emit q->warning(tr("Cannot open documentation file %1: %2!") + emit q->warning(QHelpEngineCore::tr("Cannot open documentation file %1: %2!") .arg(absFileName, reader->errorMessage())); continue; } @@ -406,8 +406,9 @@ QStringList QHelpEngineCore::customFilters() const /*! Adds the new custom filter \a filterName. The filter attributes - are specified by \a attributes. The function returns false if - the filter can not be added, e.g. when the filter already exists. + are specified by \a attributes. If the filter already exists, + its attribute set is replaced. The function returns true if + the operation succeeded, otherwise it returns false. \sa customFilters(), removeCustomFilter() */ diff --git a/tools/assistant/lib/qhelpgenerator.cpp b/tools/assistant/lib/qhelpgenerator.cpp index 4b94ebf..783f016 100644 --- a/tools/assistant/lib/qhelpgenerator.cpp +++ b/tools/assistant/lib/qhelpgenerator.cpp @@ -47,6 +47,7 @@ #include <QtCore/QFileInfo> #include <QtCore/QDir> #include <QtCore/QDebug> +#include <QtCore/QSet> #include <QtCore/QVariant> #include <QtCore/QDateTime> #include <QtCore/QTextCodec> @@ -537,7 +538,8 @@ bool QHelpGenerator::insertFiles(const QStringList &files, const QString &rootPa } int fileId = -1; - if (!d->fileMap.contains(fileName)) { + QMap<QString, int>::Iterator fileMapIt = d->fileMap.find(fileName); + if (fileMapIt == d->fileMap.end()) { fileDataList.append(qCompress(data)); fileNameData.name = fileName; @@ -551,18 +553,20 @@ bool QHelpGenerator::insertFiles(const QStringList &files, const QString &rootPa ++tableFileId; } else { - fileId = d->fileMap.value(fileName); + fileId = fileMapIt.value(); + QSet<int> &fileFilterSet = d->fileFilterMap[fileId]; + QSet<int> &tmpFileFilterSet = tmpFileFilterMap[fileId]; foreach (const int &filter, filterAtts) { - if (!d->fileFilterMap.value(fileId).contains(filter) - && !tmpFileFilterMap.value(fileId).contains(filter)) { - d->fileFilterMap[fileId].insert(filter); - tmpFileFilterMap[fileId].insert(filter); + if (!fileFilterSet.contains(filter) + && !tmpFileFilterSet.contains(filter)) { + fileFilterSet.insert(filter); + tmpFileFilterSet.insert(filter); } } } } - if (tmpFileFilterMap.count()) { + if (!tmpFileFilterMap.isEmpty()) { d->query->exec(QLatin1String("BEGIN")); QMap<int, QSet<int> >::const_iterator it = tmpFileFilterMap.constBegin(); while (it != tmpFileFilterMap.constEnd()) { @@ -625,8 +629,7 @@ bool QHelpGenerator::registerCustomFilter(const QString &filterName, while (d->query->next()) { attributeMap.insert(d->query->value(1).toString(), d->query->value(0).toInt()); - if (idsToInsert.contains(d->query->value(1).toString())) - idsToInsert.removeAll(d->query->value(1).toString()); + idsToInsert.removeAll(d->query->value(1).toString()); } foreach (const QString &id, idsToInsert) { @@ -674,7 +677,7 @@ bool QHelpGenerator::registerCustomFilter(const QString &filterName, return true; } -bool QHelpGenerator::insertKeywords(const QList<QHelpDataIndexItem> keywords, +bool QHelpGenerator::insertKeywords(const QList<QHelpDataIndexItem> &keywords, const QStringList &filterAttributes) { if (!d->query) @@ -704,7 +707,17 @@ bool QHelpGenerator::insertKeywords(const QList<QHelpDataIndexItem> keywords, int i = 0; d->query->exec(QLatin1String("BEGIN")); + QSet<QString> indices; foreach (const QHelpDataIndexItem &itm, keywords) { + + /* + * Identical ids make no sense and just confuse the Assistant user, + * so we ignore all repetitions. + */ + if (indices.contains(itm.identifier)) + continue; + indices.insert(itm.identifier); + pos = itm.reference.indexOf(QLatin1Char('#')); fileName = itm.reference.left(pos); if (pos > -1) @@ -716,8 +729,9 @@ bool QHelpGenerator::insertKeywords(const QList<QHelpDataIndexItem> keywords, if (fName.startsWith(QLatin1String("./"))) fName = fName.mid(2); - if (d->fileMap.contains(fName)) - fileId = d->fileMap.value(fName); + QMap<QString, int>::ConstIterator it = d->fileMap.find(fName); + if (it != d->fileMap.end()) + fileId = it.value(); else fileId = 1; @@ -749,7 +763,7 @@ bool QHelpGenerator::insertKeywords(const QList<QHelpDataIndexItem> keywords, d->query->exec(QLatin1String("COMMIT")); d->query->exec(QLatin1String("SELECT COUNT(Id) FROM IndexTable")); - if (d->query->next() && d->query->value(0).toInt() >= keywords.count()) + if (d->query->next() && d->query->value(0).toInt() >= indices.count()) return true; return false; } @@ -824,4 +838,68 @@ bool QHelpGenerator::insertMetaData(const QMap<QString, QVariant> &metaData) return true; } +bool QHelpGenerator::checkLinks(const QHelpDataInterface &helpData) +{ + /* + * Step 1: Gather the canoncal file paths of all files in the project. + * We use a set, because there will be a lot of look-ups. + */ + QSet<QString> files; + foreach (const QHelpDataFilterSection &filterSection, helpData.filterSections()) { + foreach (const QString &file, filterSection.files()) { + QFileInfo fileInfo(helpData.rootPath() + QDir::separator() + file); + const QString &canonicalFileName = fileInfo.canonicalFilePath(); + if (!fileInfo.exists()) + emit warning(tr("File '%1' does not exist.").arg(file)); + else + files.insert(canonicalFileName); + } + } + + /* + * Step 2: Check the hypertext and image references of all HTML files. + * Note that we don't parse the files, but simply grep for the + * respective HTML elements. Therefore. contents that are e.g. + * commented out can cause false warning. + */ + bool allLinksOk = true; + foreach (const QString &fileName, files) { + if (!fileName.endsWith(QLatin1String("html")) + && !fileName.endsWith(QLatin1String("htm"))) + continue; + QFile htmlFile(fileName); + if (!htmlFile.open(QIODevice::ReadOnly)) { + emit warning(tr("File '%1' cannot be opened.").arg(fileName)); + continue; + } + const QRegExp linkPattern(QLatin1String("<(?:a href|img src)=\"?([^#\">]+)[#\">]")); + QTextStream stream(&htmlFile); + const QString codec = QHelpGlobal::codecFromData(htmlFile.read(1000)); + stream.setCodec(QTextCodec::codecForName(codec.toLatin1().constData())); + const QString &content = stream.readAll(); + QStringList invalidLinks; + for (int pos = linkPattern.indexIn(content); pos != -1; + pos = linkPattern.indexIn(content, pos + 1)) { + const QString& linkedFileName = linkPattern.cap(1); + if (linkedFileName.contains(QLatin1String("://"))) + continue; + const QString curDir = QFileInfo(fileName).dir().path(); + const QString &canonicalLinkedFileName = + QFileInfo(curDir + QDir::separator() + linkedFileName).canonicalFilePath(); + if (!files.contains(canonicalLinkedFileName) + && !invalidLinks.contains(canonicalLinkedFileName)) { + emit warning(tr("File '%1' contains an invalid link to file '%2'"). + arg(fileName).arg(linkedFileName)); + allLinksOk = false; + invalidLinks.append(canonicalLinkedFileName); + } + } + } + + if (!allLinksOk) + d->error = tr("Invalid links in HTML files."); + return allLinksOk; +} + QT_END_NAMESPACE + diff --git a/tools/assistant/lib/qhelpgenerator_p.h b/tools/assistant/lib/qhelpgenerator_p.h index c589e25..823a07a 100644 --- a/tools/assistant/lib/qhelpgenerator_p.h +++ b/tools/assistant/lib/qhelpgenerator_p.h @@ -74,6 +74,7 @@ public: bool generate(QHelpDataInterface *helpData, const QString &outputFileName); + bool checkLinks(const QHelpDataInterface &helpData); QString error() const; Q_SIGNALS: @@ -96,7 +97,7 @@ private: const QStringList &filterAttribs, bool forceUpdate = false); bool registerVirtualFolder(const QString &folderName, const QString &ns); bool insertFilterAttributes(const QStringList &attributes); - bool insertKeywords(const QList<QHelpDataIndexItem> keywords, + bool insertKeywords(const QList<QHelpDataIndexItem> &keywords, const QStringList &filterAttributes); bool insertFiles(const QStringList &files, const QString &rootPath, const QStringList &filterAttributes); diff --git a/tools/assistant/lib/qhelpprojectdata.cpp b/tools/assistant/lib/qhelpprojectdata.cpp index 869a446..83491a0 100644 --- a/tools/assistant/lib/qhelpprojectdata.cpp +++ b/tools/assistant/lib/qhelpprojectdata.cpp @@ -41,6 +41,7 @@ #include "qhelpprojectdata_p.h" +#include <QtCore/QCoreApplication> #include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QStack> @@ -82,7 +83,7 @@ private: void QHelpProjectDataPrivate::raiseUnknownTokenError() { - raiseError(QObject::tr("Unknown token.")); + raiseError(QCoreApplication::translate("QHelpProject", "Unknown token.")); } void QHelpProjectDataPrivate::readData(const QByteArray &contents) @@ -95,12 +96,14 @@ void QHelpProjectDataPrivate::readData(const QByteArray &contents) && attributes().value(QLatin1String("version")) == QLatin1String("1.0")) readProject(); else - raiseError(QObject::tr("Unknown token. Expected \"QtHelpProject\"!")); + raiseError(QCoreApplication::translate("QHelpProject", + "Unknown token. Expected \"QtHelpProject\"!")); } } if (hasError()) { - raiseError(QObject::tr("Error in line %1: %2").arg(lineNumber()) + raiseError(QCoreApplication::translate("QHelpProject", + "Error in line %1: %2").arg(lineNumber()) .arg(errorString())); } } @@ -113,11 +116,15 @@ void QHelpProjectDataPrivate::readProject() if (name() == QLatin1String("virtualFolder")) { virtualFolder = readElementText(); if (virtualFolder.contains(QLatin1String("/"))) - raiseError(QObject::tr("A virtual folder must not contain a \'/\' character!")); + raiseError(QCoreApplication::translate("QHelpProject", + "A virtual folder must not contain " + "a \'/\' character!")); } else if (name() == QLatin1String("namespace")) { namespaceName = readElementText(); if (namespaceName.contains(QLatin1String("/"))) - raiseError(QObject::tr("A namespace must not contain a \'/\' character!")); + raiseError(QCoreApplication::translate("QHelpProject", + "A namespace must not contain a " + "\'/\' character!")); } else if (name() == QLatin1String("customFilter")) { readCustomFilter(); } else if (name() == QLatin1String("filterSection")) { @@ -125,17 +132,21 @@ void QHelpProjectDataPrivate::readProject() } else if (name() == QLatin1String("metaData")) { QString n = attributes().value(QLatin1String("name")).toString(); if (!metaData.contains(n)) - metaData[n] = attributes().value(QLatin1String("value")).toString(); + metaData[n] + = attributes().value(QLatin1String("value")).toString(); else - metaData.insert(n, attributes().value(QLatin1String("value")).toString()); + metaData.insert(n, attributes(). + value(QLatin1String("value")).toString()); } else { raiseUnknownTokenError(); } } else if (isEndElement() && name() == QLatin1String("QtHelpProject")) { if (namespaceName.isEmpty()) - raiseError(QObject::tr("Missing namespace in QtHelpProject.")); + raiseError(QCoreApplication::translate("QHelpProject", + "Missing namespace in QtHelpProject.")); else if (virtualFolder.isEmpty()) - raiseError(QObject::tr("Missing virtual folder in QtHelpProject")); + raiseError(QCoreApplication::translate("QHelpProject", + "Missing virtual folder in QtHelpProject")); break; } } @@ -223,12 +234,14 @@ void QHelpProjectDataPrivate::readKeywords() if (attributes().value(QLatin1String("ref")).toString().isEmpty() || (attributes().value(QLatin1String("name")).toString().isEmpty() && attributes().value(QLatin1String("id")).toString().isEmpty())) - raiseError(QObject::tr("Missing attribute in keyword at line %1.") - .arg(lineNumber())); - filterSectionList.last().addIndex( - QHelpDataIndexItem(attributes().value(QLatin1String("name")).toString(), - attributes().value(QLatin1String("id")).toString(), - attributes().value(QLatin1String("ref")).toString())); + raiseError(QCoreApplication::translate("QHelpProject", + "Missing attribute in keyword at line %1.") + .arg(lineNumber())); + filterSectionList.last() + .addIndex(QHelpDataIndexItem(attributes(). + value(QLatin1String("name")).toString(), + attributes().value(QLatin1String("id")).toString(), + attributes().value(QLatin1String("ref")).toString())); } else { raiseUnknownTokenError(); } @@ -346,8 +359,8 @@ bool QHelpProjectData::readData(const QString &fileName) d->rootPath = QFileInfo(fileName).absolutePath(); QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { - d->errorMsg = QObject::tr("The input file %1 could not be opened!") - .arg(fileName); + d->errorMsg = QCoreApplication::translate("QHelpProject", + "The input file %1 could not be opened!").arg(fileName); return false; } diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp index b5bec44..ee6dcfb 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp +++ b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp @@ -39,16 +39,19 @@ ** ****************************************************************************/ -#include "qhelpenginecore.h" -#include "fulltextsearch/qsearchable_p.h" -#include "fulltextsearch/qqueryparser_p.h" #include "fulltextsearch/qindexreader_p.h" +#include "fulltextsearch/qqueryparser_p.h" +#include "fulltextsearch/qsearchable_p.h" +#include "qclucenefieldnames_p.h" +#include "qhelpenginecore.h" + #include "qhelpsearchindexreader_clucene_p.h" #include <QtCore/QDir> #include <QtCore/QSet> #include <QtCore/QString> #include <QtCore/QFileInfo> +#include <QtCore/QSharedPointer> #include <QtCore/QStringList> #include <QtCore/QTextStream> #include <QtCore/QMutexLocker> @@ -108,64 +111,88 @@ void QHelpSearchIndexReaderClucene::run() #if !defined(QT_NO_EXCEPTIONS) try { #endif - QCLuceneBooleanQuery booleanQuery; + QCLuceneBooleanQuery booleanQueryTitle; + QCLuceneBooleanQuery booleanQueryContent; QCLuceneStandardAnalyzer analyzer; - if (!buildQuery(booleanQuery, queryList, analyzer)) { + const QStringList& attribList = + engine.filterAttributes(engine.currentFilter()); + bool titleQueryIsValid = buildQuery(queryList, TitleTokenizedField, + attribList, booleanQueryTitle, analyzer); + bool contentQueryIsValid = buildQuery(queryList, ContentField, + attribList, booleanQueryContent, analyzer); + if (!titleQueryIsValid && !contentQueryIsValid) { emit searchingFinished(0); return; } - const QStringList attribList = engine.filterAttributes(engine.currentFilter()); - if (!attribList.isEmpty()) { - QCLuceneQuery* query = QCLuceneQueryParser::parse(QLatin1String("+") - + attribList.join(QLatin1String(" +")), QLatin1String("attribute"), analyzer); + QCLuceneIndexSearcher indexSearcher(indexPath); - if (!query) { + // QCLuceneHits object must be allocated on the heap, because + // there is no default constructor. + QSharedPointer<QCLuceneHits> titleHits; + QSharedPointer<QCLuceneHits> contentHits; + if (titleQueryIsValid) { + titleHits = QSharedPointer<QCLuceneHits>(new QCLuceneHits( + indexSearcher.search(booleanQueryTitle))); + } + if (contentQueryIsValid) { + contentHits = QSharedPointer<QCLuceneHits>(new QCLuceneHits( + indexSearcher.search(booleanQueryContent))); + } + bool boost = true; + if ((titleHits.isNull() || titleHits->length() == 0) + && (contentHits.isNull() || contentHits->length() == 0)) { + booleanQueryTitle = QCLuceneBooleanQuery(); + booleanQueryContent = QCLuceneBooleanQuery(); + titleQueryIsValid = + buildTryHarderQuery(queryList, TitleTokenizedField, + attribList, booleanQueryTitle, analyzer); + contentQueryIsValid = + buildTryHarderQuery(queryList, ContentField, attribList, + booleanQueryContent, analyzer); + if (!titleQueryIsValid && !contentQueryIsValid) { emit searchingFinished(0); return; } - booleanQuery.add(query, true, true, false); - } - - QCLuceneIndexSearcher indexSearcher(indexPath); - QCLuceneHits hits = indexSearcher.search(booleanQuery); - - bool boost = true; - QCLuceneBooleanQuery tryHarderQuery; - if (hits.length() == 0) { - if (buildTryHarderQuery(tryHarderQuery, queryList, analyzer)) { - if (!attribList.isEmpty()) { - QCLuceneQuery* query = QCLuceneQueryParser::parse(QLatin1String("+") - + attribList.join(QLatin1String(" +")), QLatin1String("attribute"), - analyzer); - tryHarderQuery.add(query, true, true, false); - } - hits = indexSearcher.search(tryHarderQuery); - boost = (hits.length() == 0); + if (titleQueryIsValid) { + titleHits = QSharedPointer<QCLuceneHits>(new QCLuceneHits( + indexSearcher.search(booleanQueryTitle))); + } + if (contentQueryIsValid) { + contentHits = QSharedPointer<QCLuceneHits>(new QCLuceneHits( + indexSearcher.search(booleanQueryContent))); } + boost = false; } + QList<QSharedPointer<QCLuceneHits> > cluceneHitsList; + if (!titleHits.isNull()) + cluceneHitsList.append(titleHits); + if (!contentHits.isNull()) + cluceneHitsList.append(contentHits); QSet<QString> pathSet; QCLuceneDocument document; const QStringList namespaceList = engine.registeredDocumentations(); - for (qint32 i = 0; i < hits.length(); i++) { - document = hits.document(i); - const QString path = document.get(QLatin1String("path")); - if (!pathSet.contains(path) && namespaceList.contains( - document.get(QLatin1String("namespace")), Qt::CaseInsensitive)) { - pathSet.insert(path); - hitList.append(qMakePair(path, document.get(QLatin1String("title")))); - } - document.clear(); + foreach (QSharedPointer<QCLuceneHits> hits, cluceneHitsList) { + for (qint32 i = 0; i < hits->length(); i++) { + document = hits->document(i); + const QString path = document.get(PathField); + if (!pathSet.contains(path) && namespaceList.contains( + document.get(NamespaceField), Qt::CaseInsensitive)) { + pathSet.insert(path); + hitList.append(qMakePair(path, document.get(TitleField))); + } + document.clear(); - mutex.lock(); - if (m_cancel) { + mutex.lock(); + if (m_cancel) { + mutex.unlock(); + emit searchingFinished(0); + return; + } mutex.unlock(); - emit searchingFinished(0); - return; } - mutex.unlock(); } indexSearcher.close(); @@ -185,144 +212,205 @@ void QHelpSearchIndexReaderClucene::run() } } -bool QHelpSearchIndexReaderClucene::defaultQuery(const QString &term, QCLuceneBooleanQuery &booleanQuery, - QCLuceneStandardAnalyzer &analyzer) +bool QHelpSearchIndexReaderClucene::buildQuery( + const QList<QHelpSearchQuery> &queries, const QString &fieldName, + const QStringList &filterAttributes, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) { - const QLatin1String c("content"); - const QLatin1String t("titleTokenized"); - - QCLuceneQuery *query = QCLuceneQueryParser::parse(term, c, analyzer); - QCLuceneQuery *query2 = QCLuceneQueryParser::parse(term, t, analyzer); - if (query && query2) { - booleanQuery.add(query, true, false, false); - booleanQuery.add(query2, true, false, false); - return true; + bool queryIsValid = false; + foreach (const QHelpSearchQuery &query, queries) { + if (fieldName != ContentField && isNegativeQuery(query)) { + queryIsValid = false; + break; + } + switch (query.fieldName) { + case QHelpSearchQuery::FUZZY: + if (addFuzzyQuery(query, fieldName, booleanQuery, analyzer)) + queryIsValid = true; + break; + case QHelpSearchQuery::WITHOUT: + if (fieldName != ContentField) + return false; + if (addWithoutQuery(query, fieldName, booleanQuery)) + queryIsValid = true; + break; + case QHelpSearchQuery::PHRASE: + if (addPhraseQuery(query, fieldName, booleanQuery)) + queryIsValid = true; + break; + case QHelpSearchQuery::ALL: + if (addAllQuery(query, fieldName, booleanQuery)) + queryIsValid = true; + break; + case QHelpSearchQuery::DEFAULT: + if (addDefaultQuery(query, fieldName, true, booleanQuery, analyzer)) + queryIsValid = true; + break; + case QHelpSearchQuery::ATLEAST: + if (addAtLeastQuery(query, fieldName, booleanQuery, analyzer)) + queryIsValid = true; + break; + default: + Q_ASSERT(!"Invalid field name"); + } } - return false; + if (queryIsValid && !filterAttributes.isEmpty()) { + queryIsValid = + addAttributesQuery(filterAttributes, booleanQuery, analyzer); + } + + return queryIsValid; } -bool QHelpSearchIndexReaderClucene::buildQuery(QCLuceneBooleanQuery &booleanQuery, - const QList<QHelpSearchQuery> &queryList, QCLuceneStandardAnalyzer &analyzer) +bool QHelpSearchIndexReaderClucene::buildTryHarderQuery( + const QList<QHelpSearchQuery> &queries, const QString &fieldName, + const QStringList &filterAttributes, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) { - foreach (const QHelpSearchQuery query, queryList) { - switch (query.fieldName) { - case QHelpSearchQuery::FUZZY: { - const QLatin1String fuzzy("~"); - foreach (const QString &term, query.wordList) { - if (term.isEmpty() - || !defaultQuery(term.toLower() + fuzzy, booleanQuery, analyzer)) { - return false; - } - } - } break; - - case QHelpSearchQuery::WITHOUT: { - QStringList stopWords = QCLuceneStopAnalyzer().englishStopWords(); - foreach (const QString &term, query.wordList) { - if (stopWords.contains(term, Qt::CaseInsensitive)) - continue; - - QCLuceneQuery *query = new QCLuceneTermQuery(QCLuceneTerm( - QLatin1String("content"), term.toLower())); - QCLuceneQuery *query2 = new QCLuceneTermQuery(QCLuceneTerm( - QLatin1String("titleTokenized"), term.toLower())); - - if (query && query2) { - booleanQuery.add(query, true, false, true); - booleanQuery.add(query2, true, false, true); - } else { - return false; - } - } - } break; - - case QHelpSearchQuery::PHRASE: { - const QString &term = query.wordList.at(0).toLower(); - if (term.contains(QLatin1Char(' '))) { - QStringList termList = term.split(QLatin1String(" ")); - QCLucenePhraseQuery *q = new QCLucenePhraseQuery(); - QStringList stopWords = QCLuceneStopAnalyzer().englishStopWords(); - foreach (const QString &term, termList) { - if (!stopWords.contains(term, Qt::CaseInsensitive)) - q->addTerm(QCLuceneTerm(QLatin1String("content"), term.toLower())); - } - booleanQuery.add(q, true, true, false); - } else { - QCLuceneQuery *query = new QCLuceneTermQuery(QCLuceneTerm( - QLatin1String("content"), term.toLower())); - QCLuceneQuery *query2 = new QCLuceneTermQuery(QCLuceneTerm( - QLatin1String("titleTokenized"), term.toLower())); - - if (query && query2) { - booleanQuery.add(query, true, true, false); - booleanQuery.add(query2, true, false, false); - } else { - return false; - } - } - } break; + if (queries.isEmpty()) + return false; + const QHelpSearchQuery &query = queries.front(); + if (query.fieldName != QHelpSearchQuery::DEFAULT) + return false; + if (isNegativeQuery(query)) + return false; + if (!addDefaultQuery(query, fieldName, false, booleanQuery, analyzer)) + return false; + if (filterAttributes.isEmpty()) + return true; + return addAttributesQuery(filterAttributes, booleanQuery, analyzer); +} - case QHelpSearchQuery::ALL: { - QStringList stopWords = QCLuceneStopAnalyzer().englishStopWords(); - foreach (const QString &term, query.wordList) { - if (stopWords.contains(term, Qt::CaseInsensitive)) - continue; +bool QHelpSearchIndexReaderClucene::isNegativeQuery(const QHelpSearchQuery &query) const +{ + const QString &search = query.wordList.join(" "); + return search.contains('!') || search.contains('-') + || search.contains(QLatin1String(" NOT ")); +} - QCLuceneQuery *query = new QCLuceneTermQuery(QCLuceneTerm( - QLatin1String("content"), term.toLower())); +bool QHelpSearchIndexReaderClucene::addFuzzyQuery(const QHelpSearchQuery &query, + const QString &fieldName, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) +{ + bool queryIsValid = false; + const QLatin1String fuzzy("~"); + foreach (const QString &term, query.wordList) { + if (!term.isEmpty()) { + QCLuceneQuery *lQuery = + QCLuceneQueryParser::parse(term + fuzzy, fieldName, analyzer); + if (lQuery != 0) { + booleanQuery.add(lQuery, true, false, false); + queryIsValid = true; + } + } + } + return queryIsValid; +} - if (query) { - booleanQuery.add(query, true, true, false); - } else { - return false; - } - } - } break; +bool QHelpSearchIndexReaderClucene::addWithoutQuery(const QHelpSearchQuery &query, + const QString &fieldName, QCLuceneBooleanQuery &booleanQuery) +{ + bool queryIsValid = false; + const QStringList &stopWords = QCLuceneStopAnalyzer().englishStopWords(); + foreach (const QString &term, query.wordList) { + if (stopWords.contains(term, Qt::CaseInsensitive)) + continue; + QCLuceneQuery *lQuery = new QCLuceneTermQuery(QCLuceneTerm( + fieldName, term.toLower())); + booleanQuery.add(lQuery, true, false, true); + queryIsValid = true; + } + return queryIsValid; +} - case QHelpSearchQuery::DEFAULT: { - foreach (const QString &term, query.wordList) { - QCLuceneQuery *query = QCLuceneQueryParser::parse(term.toLower(), - QLatin1String("content"), analyzer); +bool QHelpSearchIndexReaderClucene::addPhraseQuery(const QHelpSearchQuery &query, + const QString &fieldName, QCLuceneBooleanQuery &booleanQuery) +{ + bool queryIsValid = false; + const QString &term = query.wordList.at(0).toLower(); + if (term.contains(QLatin1Char(' '))) { + const QStringList termList = term.split(QLatin1String(" ")); + QCLucenePhraseQuery *q = new QCLucenePhraseQuery(); + const QStringList stopWords = QCLuceneStopAnalyzer().englishStopWords(); + foreach (const QString &term, termList) { + if (!stopWords.contains(term, Qt::CaseInsensitive)) + q->addTerm(QCLuceneTerm(fieldName, term.toLower())); + } + if (!q->getTerms().isEmpty()) { + booleanQuery.add(q, true, true, false); + queryIsValid = true; + } + } else { + QCLuceneQuery *lQuery = new QCLuceneTermQuery(QCLuceneTerm( + fieldName, term.toLower())); + booleanQuery.add(lQuery, true, true, false); + queryIsValid = true; + } + return queryIsValid; +} - if (query) - booleanQuery.add(query, true, true, false); - } - } break; +bool QHelpSearchIndexReaderClucene::addAllQuery(const QHelpSearchQuery &query, + const QString &fieldName, QCLuceneBooleanQuery &booleanQuery) +{ + bool queryIsValid = false; + const QStringList &stopWords = QCLuceneStopAnalyzer().englishStopWords(); + foreach (const QString &term, query.wordList) { + if (stopWords.contains(term, Qt::CaseInsensitive)) + continue; + QCLuceneQuery *lQuery = new QCLuceneTermQuery(QCLuceneTerm( + fieldName, term.toLower())); + booleanQuery.add(lQuery, true, true, false); + queryIsValid = true; + } + return queryIsValid; +} - case QHelpSearchQuery::ATLEAST: { - foreach (const QString &term, query.wordList) { - if (term.isEmpty() || !defaultQuery(term.toLower(), booleanQuery, analyzer)) - return false; - } - } +bool QHelpSearchIndexReaderClucene::addDefaultQuery(const QHelpSearchQuery &query, + const QString &fieldName, bool allTermsRequired, + QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) +{ + bool queryIsValid = false; + foreach (const QString &term, query.wordList) { + QCLuceneQuery *lQuery = + QCLuceneQueryParser::parse(term.toLower(), fieldName, analyzer); + if (lQuery) { + booleanQuery.add(lQuery, true, allTermsRequired, false); + queryIsValid = true; } } - - return true; + return queryIsValid; } -bool QHelpSearchIndexReaderClucene::buildTryHarderQuery(QCLuceneBooleanQuery &booleanQuery, - const QList<QHelpSearchQuery> &queryList, QCLuceneStandardAnalyzer &analyzer) +bool QHelpSearchIndexReaderClucene::addAtLeastQuery( + const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery, QCLuceneAnalyzer &analyzer) { - bool retVal = false; - foreach (const QHelpSearchQuery query, queryList) { - switch (query.fieldName) { - default: break; - case QHelpSearchQuery::DEFAULT: { - foreach (const QString &term, query.wordList) { - QCLuceneQuery *query = QCLuceneQueryParser::parse(term.toLower(), - QLatin1String("content"), analyzer); - - if (query) { - retVal = true; - booleanQuery.add(query, true, false, false); - } - } - } break; + bool queryIsValid = false; + foreach (const QString &term, query.wordList) { + if (!term.isEmpty()) { + QCLuceneQuery *lQuery = + QCLuceneQueryParser::parse(term, fieldName, analyzer); + if (lQuery) { + booleanQuery.add(lQuery, true, false, false); + queryIsValid = true; + } } } - return retVal; + return queryIsValid; +} + +bool QHelpSearchIndexReaderClucene::addAttributesQuery( + const QStringList &filterAttributes, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) +{ + QCLuceneQuery* lQuery = QCLuceneQueryParser::parse(QLatin1String("+") + + filterAttributes.join(QLatin1String(" +")), AttributeField, analyzer); + if (!lQuery) + return false; + booleanQuery.add(lQuery, true, true, false); + return true; } void QHelpSearchIndexReaderClucene::boostSearchHits(const QHelpEngineCore &engine, @@ -336,21 +424,22 @@ void QHelpSearchIndexReaderClucene::boostSearchHits(const QHelpEngineCore &engin QCLuceneStandardAnalyzer analyzer; QCLuceneQuery *parsedQuery = QCLuceneQueryParser::parse( - joinedQuery, QLatin1String("content"), analyzer); + joinedQuery, ContentField, analyzer); if (parsedQuery) { joinedQuery = parsedQuery->toString(); delete parsedQuery; } - int length = QString(QLatin1String("content:")).length(); - int index = joinedQuery.indexOf(QLatin1String("content:")); + const QString contentString(ContentField + QLatin1String(":")); + int length = contentString.length(); + int index = joinedQuery.indexOf(contentString); QString term; int nextIndex = 0; QStringList searchTerms; while (index != -1) { - nextIndex = joinedQuery.indexOf(QLatin1String("content:"), index + 1); + nextIndex = joinedQuery.indexOf(contentString, index + 1); term = joinedQuery.mid(index + length, nextIndex - (length + index)).simplified(); if (term.startsWith(QLatin1String("\"")) && term.endsWith(QLatin1String("\""))) { diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h index 3e3b9dd..04c0088 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h +++ b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h @@ -53,16 +53,19 @@ // We mean it. // -#include "qhelpsearchindexreader_p.h" +#include <QtCore/QList> +#include <QtCore/QString> +#include <QtCore/QStringList> #include "fulltextsearch/qanalyzer_p.h" #include "fulltextsearch/qquery_p.h" +#include "qhelpsearchindexreader_p.h" QT_BEGIN_NAMESPACE namespace qt { - namespace fulltextsearch { - namespace clucene { +namespace fulltextsearch { +namespace clucene { class QHelpSearchIndexReaderClucene : public QHelpSearchIndexReader { @@ -74,18 +77,38 @@ public: private: void run(); - bool defaultQuery(const QString &term, QCLuceneBooleanQuery &booleanQuery, - QCLuceneStandardAnalyzer &analyzer); - bool buildQuery(QCLuceneBooleanQuery &booleanQuery, const QList<QHelpSearchQuery> &queryList, - QCLuceneStandardAnalyzer &analyzer); - bool buildTryHarderQuery(QCLuceneBooleanQuery &booleanQuery, - const QList<QHelpSearchQuery> &queryList, QCLuceneStandardAnalyzer &analyzer); void boostSearchHits(const QHelpEngineCore &engine, QList<QHelpSearchEngine::SearchHit> &hitList, const QList<QHelpSearchQuery> &queryList); + bool buildQuery(const QList<QHelpSearchQuery> &queries, + const QString &fieldName, + const QStringList &filterAttributes, + QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer); + bool buildTryHarderQuery(const QList<QHelpSearchQuery> &queries, + const QString &fieldName, + const QStringList &filterAttributes, + QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer); + bool addFuzzyQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery, QCLuceneAnalyzer &analyzer); + bool addWithoutQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery); + bool addPhraseQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery); + bool addAllQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery); + bool addDefaultQuery(const QHelpSearchQuery &query, const QString &fieldName, + bool allTermsRequired, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer); + bool addAtLeastQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery, QCLuceneAnalyzer &analyzer); + bool addAttributesQuery(const QStringList &filterAttributes, + QCLuceneBooleanQuery &booleanQuery, QCLuceneAnalyzer &analyzer); + bool isNegativeQuery(const QHelpSearchQuery &query) const; }; - } // namespace clucene - } // namespace fulltextsearch +} // namespace clucene +} // namespace fulltextsearch } // namespace qt QT_END_NAMESPACE diff --git a/tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp b/tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp index e3cc2b0..6e49e54 100644 --- a/tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp +++ b/tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "qclucenefieldnames_p.h" #include "qhelpenginecore.h" #include "qhelp_global.h" #include "fulltextsearch/qhits_p.h" @@ -407,17 +408,17 @@ public: QString parsedTitle = QHelpGlobal::documentTitle(data); if(!parsedData.isEmpty()) { - document->add(new QCLuceneField(QLatin1String("content"), + document->add(new QCLuceneField(ContentField, parsedData,QCLuceneField::INDEX_TOKENIZED)); - document->add(new QCLuceneField(QLatin1String("path"), fileName, + document->add(new QCLuceneField(PathField, fileName, QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED)); - document->add(new QCLuceneField(QLatin1String("title"), parsedTitle, + document->add(new QCLuceneField(TitleField, parsedTitle, QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED)); - document->add(new QCLuceneField(QLatin1String("titleTokenized"), parsedTitle, + document->add(new QCLuceneField(TitleTokenizedField, parsedTitle, QCLuceneField::STORE_YES | QCLuceneField::INDEX_TOKENIZED)); - document->add(new QCLuceneField(QLatin1String("namespace"), namespaceName, + document->add(new QCLuceneField(NamespaceField, namespaceName, QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED)); - document->add(new QCLuceneField(QLatin1String("attribute"), attributes, + document->add(new QCLuceneField(AttributeField, attributes, QCLuceneField::STORE_YES | QCLuceneField::INDEX_TOKENIZED)); return true; } @@ -613,67 +614,69 @@ void QHelpSearchIndexWriter::optimizeIndex() void QHelpSearchIndexWriter::run() { - QMutexLocker mutexLocker(&mutex); +#if !defined(QT_NO_EXCEPTIONS) + try { +#endif + QMutexLocker mutexLocker(&mutex); - if (m_cancel) - return; + if (m_cancel) + return; - const bool reindex = this->m_reindex; - const QString collectionFile(this->m_collectionFile); + const bool reindex = this->m_reindex; + const QString collectionFile(this->m_collectionFile); - mutexLocker.unlock(); + mutexLocker.unlock(); - QHelpEngineCore engine(collectionFile, 0); - if (!engine.setupData()) - return; + QHelpEngineCore engine(collectionFile, 0); + if (!engine.setupData()) + return; - const QLatin1String key("CluceneIndexedNamespaces"); - if (reindex) - engine.setCustomValue(key, QLatin1String("")); - - QMap<QString, QDateTime> indexMap; - const QLatin1String oldKey("CluceneSearchNamespaces"); - if (!engine.customValue(oldKey, QString()).isNull()) { - // old style qhc file < 4.4.2, need to convert... - const QStringList indexedNamespaces = engine.customValue(oldKey). - toString().split(QLatin1String("|"), QString::SkipEmptyParts); - foreach (const QString &nameSpace, indexedNamespaces) - indexMap.insert(nameSpace, QDateTime()); - engine.removeCustomValue(oldKey); - } else { - QDataStream dataStream(engine.customValue(key).toByteArray()); - dataStream >> indexMap; - } + const QLatin1String key("CluceneIndexedNamespaces"); + if (reindex) + engine.setCustomValue(key, QLatin1String("")); + + QMap<QString, QDateTime> indexMap; + const QLatin1String oldKey("CluceneSearchNamespaces"); + if (!engine.customValue(oldKey, QString()).isNull()) { + // old style qhc file < 4.4.2, need to convert... + const QStringList indexedNamespaces + = engine.customValue(oldKey).toString() + .split(QLatin1String("|"), QString::SkipEmptyParts); + foreach (const QString &nameSpace, indexedNamespaces) + indexMap.insert(nameSpace, QDateTime()); + engine.removeCustomValue(oldKey); + } else { + QDataStream dataStream(engine.customValue(key).toByteArray()); + dataStream >> indexMap; + } - QString indexPath = m_indexFilesFolder; + QString indexPath = m_indexFilesFolder; - QFileInfo fInfo(indexPath); - if (fInfo.exists() && !fInfo.isWritable()) { - qWarning("Full Text Search, could not create index (missing permissions for '%s').", qPrintable(indexPath)); - return; - } + QFileInfo fInfo(indexPath); + if (fInfo.exists() && !fInfo.isWritable()) { + qWarning("Full Text Search, could not create index (missing permissions for '%s').", + qPrintable(indexPath)); + return; + } - emit indexingStarted(); + emit indexingStarted(); - QCLuceneIndexWriter *writer = 0; - QCLuceneStandardAnalyzer analyzer; - const QStringList registeredDocs = engine.registeredDocumentations(); + QCLuceneIndexWriter *writer = 0; + QCLuceneStandardAnalyzer analyzer; + const QStringList registeredDocs = engine.registeredDocumentations(); - QLocalSocket localSocket; - localSocket.connectToServer(QString(QLatin1String("QtAssistant%1")) - .arg(QLatin1String(QT_VERSION_STR))); + QLocalSocket localSocket; + localSocket.connectToServer(QString(QLatin1String("QtAssistant%1")) + .arg(QLatin1String(QT_VERSION_STR))); - QLocalServer localServer; - bool otherInstancesRunning = true; - if (!localSocket.waitForConnected()) { - otherInstancesRunning = false; - localServer.listen(QString(QLatin1String("QtAssistant%1")) - .arg(QLatin1String(QT_VERSION_STR))); - } + QLocalServer localServer; + bool otherInstancesRunning = true; + if (!localSocket.waitForConnected()) { + otherInstancesRunning = false; + localServer.listen(QString(QLatin1String("QtAssistant%1")) + .arg(QLatin1String(QT_VERSION_STR))); + } -#if !defined(QT_NO_EXCEPTIONS) - try { -#endif // check if it's locked, and if the other instance is running if (!otherInstancesRunning && QCLuceneIndexReader::isLocked(indexPath)) QCLuceneIndexReader::unlock(indexPath); @@ -705,7 +708,8 @@ void QHelpSearchIndexWriter::run() removeDocuments(indexPath, namespaceName); } else { QString path = engine.documentationFileName(namespaceName); - if (indexMap.value(namespaceName) < QFileInfo(path).lastModified()) { + if (indexMap.value(namespaceName) + < QFileInfo(path).lastModified()) { // make sure we remove some outdated indexed stuff indexMap.remove(namespaceName); removeDocuments(indexPath, namespaceName); @@ -713,9 +717,7 @@ void QHelpSearchIndexWriter::run() if (indexMap.contains(namespaceName)) { // make sure we really have content indexed for namespace - // NOTE: Extra variable just for GCC 3.3.5 - QLatin1String key("namespace"); - QCLuceneTermQuery query(QCLuceneTerm(key, namespaceName)); + QCLuceneTermQuery query(QCLuceneTerm(NamespaceField, namespaceName)); QCLuceneIndexSearcher indexSearcher(indexPath); QCLuceneHits hits = indexSearcher.search(query); if (hits.length() <= 0) @@ -728,94 +730,85 @@ void QHelpSearchIndexWriter::run() indexMap.clear(); writer = new QCLuceneIndexWriter(indexPath, analyzer, true); } -#if !defined(QT_NO_EXCEPTIONS) - } catch (...) { - qWarning("Full Text Search, could not create index writer in '%s'.", - qPrintable(indexPath)); - return; - } -#endif -#if !defined(QT_NO_EXCEPTIONS) - try { -#endif writer->setMergeFactor(100); writer->setMinMergeDocs(1000); writer->setMaxFieldLength(QCLuceneIndexWriter::DEFAULT_MAX_FIELD_LENGTH); -#if !defined(QT_NO_EXCEPTIONS) - } catch (...) { - qWarning("Full Text Search, could not set writer properties."); - return; - } -#endif - QStringList namespaces; - foreach(const QString &namespaceName, registeredDocs) { - mutexLocker.relock(); - if (m_cancel) { - closeIndexWriter(writer); - emit indexingFinished(); - return; - } - mutexLocker.unlock(); + QStringList namespaces; + foreach(const QString &namespaceName, registeredDocs) { + mutexLocker.relock(); + if (m_cancel) { + closeIndexWriter(writer); + emit indexingFinished(); + return; + } + mutexLocker.unlock(); - namespaces.append(namespaceName); - if (indexMap.contains(namespaceName)) - continue; + namespaces.append(namespaceName); + if (indexMap.contains(namespaceName)) + continue; - const QList<QStringList> attributeSets = - engine.filterAttributeSets(namespaceName); + const QList<QStringList> attributeSets = + engine.filterAttributeSets(namespaceName); - if (attributeSets.isEmpty()) { - const QList<QUrl> docFiles = indexableFiles(&engine, namespaceName, - QStringList()); - if (!addDocuments(docFiles, engine, QStringList(), namespaceName, - writer, analyzer)) - break; - } else { - bool bail = false; - foreach (const QStringList &attributes, attributeSets) { - const QList<QUrl> docFiles = indexableFiles(&engine, - namespaceName, attributes); - if (!addDocuments(docFiles, engine, attributes, namespaceName, - writer, analyzer)) { - bail = true; + if (attributeSets.isEmpty()) { + const QList<QUrl> docFiles = indexableFiles(&engine, namespaceName, + QStringList()); + if (!addDocuments(docFiles, engine, QStringList(), namespaceName, + writer, analyzer)) break; + } else { + bool bail = false; + foreach (const QStringList &attributes, attributeSets) { + const QList<QUrl> docFiles = indexableFiles(&engine, + namespaceName, attributes); + if (!addDocuments(docFiles, engine, attributes, namespaceName, + writer, analyzer)) { + bail = true; + break; + } } + if (bail) + break; } - if (bail) - break; - } - mutexLocker.relock(); - if (!m_cancel) { - QString path(engine.documentationFileName(namespaceName)); - indexMap.insert(namespaceName, QFileInfo(path).lastModified()); - writeIndexMap(engine, indexMap); + mutexLocker.relock(); + if (!m_cancel) { + QString path(engine.documentationFileName(namespaceName)); + indexMap.insert(namespaceName, QFileInfo(path).lastModified()); + writeIndexMap(engine, indexMap); + } + mutexLocker.unlock(); } - mutexLocker.unlock(); - } - closeIndexWriter(writer); + closeIndexWriter(writer); - mutexLocker.relock(); - if (!m_cancel) { - mutexLocker.unlock(); - - QStringList indexedNamespaces = indexMap.keys(); - foreach(const QString &namespaceName, indexedNamespaces) { - mutexLocker.relock(); - if (m_cancel) - break; + mutexLocker.relock(); + if (!m_cancel) { mutexLocker.unlock(); - if (!namespaces.contains(namespaceName)) { - indexMap.remove(namespaceName); - writeIndexMap(engine, indexMap); - removeDocuments(indexPath, namespaceName); + QStringList indexedNamespaces = indexMap.keys(); + foreach(const QString &namespaceName, indexedNamespaces) { + mutexLocker.relock(); + if (m_cancel) + break; + mutexLocker.unlock(); + + if (!namespaces.contains(namespaceName)) { + indexMap.remove(namespaceName); + writeIndexMap(engine, indexMap); + removeDocuments(indexPath, namespaceName); + } } } + +#if !defined(QT_NO_EXCEPTIONS) + } catch (...) { + qWarning("%s: Failed because of CLucene exception.", Q_FUNC_INFO); } +#endif + emit indexingFinished(); } @@ -858,8 +851,7 @@ void QHelpSearchIndexWriter::removeDocuments(const QString &indexPath, return; QCLuceneIndexReader reader = QCLuceneIndexReader::open(indexPath); - reader.deleteDocuments(QCLuceneTerm(QLatin1String("namespace"), - namespaceName)); + reader.deleteDocuments(QCLuceneTerm(NamespaceField, namespaceName)); reader.close(); } diff --git a/tools/assistant/lib/qhelpsearchquerywidget.cpp b/tools/assistant/lib/qhelpsearchquerywidget.cpp index 3c3919e..1634a0d 100644 --- a/tools/assistant/lib/qhelpsearchquerywidget.cpp +++ b/tools/assistant/lib/qhelpsearchquerywidget.cpp @@ -41,8 +41,6 @@ #include "qhelpsearchquerywidget.h" -#include <QtCore/QDebug> - #include <QtCore/QAbstractListModel> #include <QtCore/QObject> #include <QtCore/QStringList> @@ -101,8 +99,9 @@ private: }; QHelpSearchQueryWidgetPrivate() - : QObject(), simpleSearch(true), - searchCompleter(new CompleterModel(this), this) + : QObject() + , simpleSearch(true) + , searchCompleter(new CompleterModel(this), this) { searchButton = 0; advancedSearchWidget = 0; @@ -136,33 +135,6 @@ private: #endif } - QString escapeString(const QString &text) - { - QString retValue = text; - const QString escape(QLatin1String("\\")); - QStringList escapableCharsList; - escapableCharsList << QLatin1String("\\") << QLatin1String("+") - << QLatin1String("-") << QLatin1String("!") << QLatin1String("(") - << QLatin1String(")") << QLatin1String(":") << QLatin1String("^") - << QLatin1String("[") << QLatin1String("]") << QLatin1String("{") - << QLatin1String("}") << QLatin1String("~"); - - // make sure we won't end up with an empty string - foreach (const QString &escapeChar, escapableCharsList) { - if (retValue.contains(escapeChar)) - retValue.replace(escapeChar, QLatin1String("")); - } - if (retValue.trimmed().isEmpty()) - return retValue; - - retValue = text; // now really escape the string... - foreach (const QString &escapeChar, escapableCharsList) { - if (retValue.contains(escapeChar)) - retValue.replace(escapeChar, escape + escapeChar); - } - return retValue; - } - QStringList buildTermList(const QString query) { bool s = false; @@ -222,8 +194,8 @@ private: } } - void nextOrPrevQuery(int maxOrMinIndex, int addend, - QToolButton *thisButton, QToolButton *otherButton) + void nextOrPrevQuery(int maxOrMinIndex, int addend, QToolButton *thisButton, + QToolButton *otherButton) { QueryHistory *queryHist; QList<QLineEdit *> lineEdits; @@ -233,7 +205,7 @@ private: } else { queryHist = &complexQueries; lineEdits << allQuery << atLeastQuery << similarQuery - << withoutQuery << exactQuery; + << withoutQuery << exactQuery; } foreach (QLineEdit *lineEdit, lineEdits) lineEdit->clear(); @@ -278,11 +250,11 @@ private: void enableOrDisableToolButtons() { - const QueryHistory &queryHist = - simpleSearch ? simpleQueries : complexQueries; + const QueryHistory &queryHist = simpleSearch ? simpleQueries + : complexQueries; prevQueryButton->setEnabled(queryHist.curQuery > 0); - nextQueryButton->setEnabled(queryHist.curQuery < - queryHist.queries.size() - 1); + nextQueryButton->setEnabled(queryHist.curQuery + < queryHist.queries.size() - 1); } private slots: @@ -306,41 +278,45 @@ private slots: QList<QHelpSearchQuery> queryList; #if !defined(QT_CLUCENE_SUPPORT) queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT, - QStringList(defaultQuery->text()))); + QStringList(defaultQuery->text()))); #else if (defaultQuery->isEnabled()) { queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT, - buildTermList(escapeString(defaultQuery->text())))); + buildTermList(defaultQuery->text()))); } else { const QRegExp exp(QLatin1String("\\s+")); - QStringList lst = similarQuery->text().split(exp, QString::SkipEmptyParts); + QStringList lst = similarQuery->text().split(exp, + QString::SkipEmptyParts); if (!lst.isEmpty()) { QStringList fuzzy; foreach (const QString &term, lst) - fuzzy += buildTermList(escapeString(term)); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY, fuzzy)); + fuzzy += buildTermList(term); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY, + fuzzy)); } lst = withoutQuery->text().split(exp, QString::SkipEmptyParts); if (!lst.isEmpty()) { QStringList without; foreach (const QString &term, lst) - without.append(escapeString(term)); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT, without)); + without.append(term); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT, + without)); } if (!exactQuery->text().isEmpty()) { QString phrase = exactQuery->text().remove(QLatin1Char('\"')); - phrase = escapeString(phrase.simplified()); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE, QStringList(phrase))); + phrase = phrase.simplified(); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE, + QStringList(phrase))); } lst = allQuery->text().split(exp, QString::SkipEmptyParts); if (!lst.isEmpty()) { QStringList all; foreach (const QString &term, lst) - all.append(escapeString(term)); + all.append(term); queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all)); } @@ -348,8 +324,9 @@ private slots: if (!lst.isEmpty()) { QStringList atLeast; foreach (const QString &term, lst) - atLeast += buildTermList(escapeString(term)); - queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST, atLeast)); + atLeast += buildTermList(term); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST, + atLeast)); } } #endif @@ -363,8 +340,9 @@ private slots: void nextQuery() { - nextOrPrevQuery((simpleSearch ? simpleQueries : complexQueries).queries.size() - 1, - 1, nextQueryButton, prevQueryButton); + nextOrPrevQuery((simpleSearch ? simpleQueries + : complexQueries).queries.size() - 1, 1, nextQueryButton, + prevQueryButton); } void prevQuery() @@ -415,8 +393,9 @@ private: \fn void QHelpSearchQueryWidget::search() This signal is emitted when a the user has the search button invoked. - After reciving the signal you can ask the QHelpSearchQueryWidget for the build list - of QHelpSearchQuery's that you may pass to the QHelpSearchEngine's search() function. + After reciving the signal you can ask the QHelpSearchQueryWidget for the + build list of QHelpSearchQuery's that you may pass to the QHelpSearchEngine's + search() function. */ /*! @@ -544,7 +523,8 @@ QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const QList<QHelpSearchQuery>() : queryHist.queries.last(); } -/*! \reimp +/*! + \reimp */ void QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent) { diff --git a/tools/assistant/lib/qhelpsearchresultwidget.cpp b/tools/assistant/lib/qhelpsearchresultwidget.cpp index ad540c6..8e476d5 100644 --- a/tools/assistant/lib/qhelpsearchresultwidget.cpp +++ b/tools/assistant/lib/qhelpsearchresultwidget.cpp @@ -304,7 +304,7 @@ private: last = resultLastToShow > count ? count : resultLastToShow; } } - hitsLabel->setText(tr("%1 - %2 of %3 Hits").arg(first).arg(last).arg(count)); + hitsLabel->setText(QHelpSearchResultWidget::tr("%1 - %2 of %3 Hits").arg(first).arg(last).arg(count)); } private: diff --git a/tools/assistant/tools/assistant/aboutdialog.cpp b/tools/assistant/tools/assistant/aboutdialog.cpp index 0ab8659..26d488d 100644 --- a/tools/assistant/tools/assistant/aboutdialog.cpp +++ b/tools/assistant/tools/assistant/aboutdialog.cpp @@ -38,6 +38,8 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "helpviewer.h" +#include "tracer.h" #include <QtCore/QBuffer> @@ -56,6 +58,7 @@ QT_BEGIN_NAMESPACE AboutLabel::AboutLabel(QWidget *parent) : QTextBrowser(parent) { + TRACE_OBJ setFrameStyle(QFrame::NoFrame); QPalette p; p.setColor(QPalette::Base, p.color(QPalette::Background)); @@ -64,6 +67,7 @@ AboutLabel::AboutLabel(QWidget *parent) void AboutLabel::setText(const QString &text, const QByteArray &resources) { + TRACE_OBJ QDataStream in(resources); in >> m_resourceMap; @@ -72,6 +76,7 @@ void AboutLabel::setText(const QString &text, const QByteArray &resources) QSize AboutLabel::minimumSizeHint() const { + TRACE_OBJ QTextDocument *doc = document(); doc->adjustSize(); return QSize(int(doc->size().width()), int(doc->size().height())); @@ -79,6 +84,7 @@ QSize AboutLabel::minimumSizeHint() const QVariant AboutLabel::loadResource(int type, const QUrl &name) { + TRACE_OBJ if (type == 2 || type == 3) { if (m_resourceMap.contains(name.toString())) { return m_resourceMap.value(name.toString()); @@ -89,9 +95,9 @@ QVariant AboutLabel::loadResource(int type, const QUrl &name) void AboutLabel::setSource(const QUrl &url) { - if (url.isValid() - && (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("ftp") - || url.scheme() == QLatin1String("mailto") || url.path().endsWith(QLatin1String("pdf")))) { + TRACE_OBJ + 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"), @@ -103,6 +109,7 @@ void AboutLabel::setSource(const QUrl &url) AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint|Qt::WindowTitleHint|Qt::WindowSystemMenuHint) { + TRACE_OBJ m_pixmapLabel = 0; m_aboutLabel = new AboutLabel(); @@ -121,12 +128,14 @@ AboutDialog::AboutDialog(QWidget *parent) void AboutDialog::setText(const QString &text, const QByteArray &resources) { + TRACE_OBJ m_aboutLabel->setText(text, resources); updateSize(); } void AboutDialog::setPixmap(const QPixmap &pixmap) { + TRACE_OBJ if (!m_pixmapLabel) { m_pixmapLabel = new QLabel(); m_layout->addWidget(m_pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter); @@ -137,11 +146,13 @@ void AboutDialog::setPixmap(const QPixmap &pixmap) QString AboutDialog::documentTitle() const { + TRACE_OBJ return m_aboutLabel->documentTitle(); } void AboutDialog::updateSize() { + TRACE_OBJ QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size(); int limit = qMin(screenSize.width()/2, 500); diff --git a/tools/assistant/tools/assistant/assistant.pro b/tools/assistant/tools/assistant/assistant.pro index 2a654fc..d57aa99 100644 --- a/tools/assistant/tools/assistant/assistant.pro +++ b/tools/assistant/tools/assistant/assistant.pro @@ -1,71 +1,81 @@ include($$QT_SOURCE_TREE/tools/shared/fontpanel/fontpanel.pri) - TEMPLATE = app LANGUAGE = C++ TARGET = assistant - -contains(QT_CONFIG, webkit) { - QT += webkit -} - -CONFIG += qt warn_on help - +contains(QT_CONFIG, webkit):QT += webkit +CONFIG += qt \ + warn_on \ + help QT += network - PROJECTNAME = Assistant DESTDIR = ../../../../bin - -target.path=$$[QT_INSTALL_BINS] +target.path = $$[QT_INSTALL_BINS] INSTALLS += target +DEPENDPATH += ../shared -### Work around a qmake issue when statically linking to -### not-yet-installed plugins +# ## Work around a qmake issue when statically linking to +# ## not-yet-installed plugins QMAKE_LIBDIR += $$QT_BUILD_TREE/plugins/sqldrivers +HEADERS += aboutdialog.h \ + bookmarkdialog.h \ + bookmarkfiltermodel.h \ + bookmarkitem.h \ + bookmarkmanager.h \ + bookmarkmodel.h \ + centralwidget.h \ + cmdlineparser.h \ + contentwindow.h \ + findwidget.h \ + filternamedialog.h \ + helpenginewrapper.h \ + helpviewer.h \ + indexwindow.h \ + installdialog.h \ + mainwindow.h \ + preferencesdialog.h \ + qtdocinstaller.h \ + remotecontrol.h \ + searchwidget.h \ + topicchooser.h \ + tracer.h \ + xbelsupport.h \ + ../shared/collectionconfiguration.h +win32:HEADERS += remotecontrol_win.h -HEADERS += helpviewer.h \ - mainwindow.h \ - indexwindow.h \ - topicchooser.h \ - contentwindow.h \ - searchwidget.h \ - preferencesdialog.h \ - filternamedialog.h \ - centralwidget.h \ - installdialog.h \ - bookmarkmanager.h \ - remotecontrol.h \ - cmdlineparser.h \ - aboutdialog.h \ - qtdocinstaller.h - -win32 { - HEADERS += remotecontrol_win.h -} - -SOURCES += helpviewer.cpp \ - main.cpp \ - mainwindow.cpp \ - indexwindow.cpp \ - topicchooser.cpp \ - contentwindow.cpp \ - searchwidget.cpp \ - preferencesdialog.cpp \ - filternamedialog.cpp \ - centralwidget.cpp \ - installdialog.cpp \ - bookmarkmanager.cpp \ - remotecontrol.cpp \ - cmdlineparser.cpp \ - aboutdialog.cpp \ - qtdocinstaller.cpp +SOURCES += aboutdialog.cpp \ + bookmarkdialog.cpp \ + bookmarkfiltermodel.cpp \ + bookmarkitem.cpp \ + bookmarkmanager.cpp \ + bookmarkmodel.cpp \ + centralwidget.cpp \ + cmdlineparser.cpp \ + contentwindow.cpp \ + findwidget.cpp \ + filternamedialog.cpp \ + helpenginewrapper.cpp \ + helpviewer.cpp \ + indexwindow.cpp \ + installdialog.cpp \ + main.cpp \ + mainwindow.cpp \ + preferencesdialog.cpp \ + qtdocinstaller.cpp \ + remotecontrol.cpp \ + searchwidget.cpp \ + topicchooser.cpp \ + xbelsupport.cpp \ + ../shared/collectionconfiguration.cpp \ -FORMS += topicchooser.ui \ - preferencesdialog.ui \ - filternamedialog.ui \ - installdialog.ui \ - bookmarkdialog.ui +FORMS += bookmarkdialog.ui \ + bookmarkwidget.ui \ + filternamedialog.ui \ + installdialog.ui \ + preferencesdialog.ui \ + topicchooser.ui -RESOURCES += assistant.qrc assistant_images.qrc +RESOURCES += assistant.qrc \ + assistant_images.qrc win32 { !wince*:LIBS += -lshell32 diff --git a/tools/assistant/tools/assistant/assistant.qch b/tools/assistant/tools/assistant/assistant.qch Binary files differindex 78fe9f3..e6d5299 100644 --- a/tools/assistant/tools/assistant/assistant.qch +++ b/tools/assistant/tools/assistant/assistant.qch diff --git a/tools/assistant/tools/assistant/assistant_images.qrc b/tools/assistant/tools/assistant/assistant_images.qrc index 58e03b5..34918c0 100644 --- a/tools/assistant/tools/assistant/assistant_images.qrc +++ b/tools/assistant/tools/assistant/assistant_images.qrc @@ -4,6 +4,7 @@ <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> diff --git a/tools/assistant/tools/assistant/bookmarkdialog.cpp b/tools/assistant/tools/assistant/bookmarkdialog.cpp new file mode 100644 index 0000000..f081c15 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkdialog.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "tracer.h" + +#include "bookmarkdialog.h" +#include "bookmarkfiltermodel.h" +#include "bookmarkitem.h" +#include "bookmarkmodel.h" + +#include <QtGui/QKeyEvent> +#include <QtGui/QMenu> + +QT_BEGIN_NAMESPACE + +BookmarkDialog::BookmarkDialog(BookmarkModel *sourceModel, const QString &title, + const QString &url, QWidget *parent) + : QDialog(parent) + , m_url(url) + , m_title(title) + , bookmarkModel(sourceModel) +{ + TRACE_OBJ + ui.setupUi(this); + + ui.bookmarkEdit->setText(m_title); + ui.newFolderButton->setVisible(false); + ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(accepted())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(rejected())); + connect(ui.newFolderButton, SIGNAL(clicked()), this, SLOT(addFolder())); + connect(ui.toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked())); + connect(ui.bookmarkEdit, SIGNAL(textChanged(QString)), this, + SLOT(textChanged(QString))); + + bookmarkProxyModel = new BookmarkFilterModel(this); + bookmarkProxyModel->setSourceModel(bookmarkModel); + ui.bookmarkFolders->setModel(bookmarkProxyModel); + connect(ui.bookmarkFolders, SIGNAL(currentIndexChanged(int)), this, + SLOT(currentIndexChanged(int))); + + bookmarkTreeModel = new BookmarkTreeModel(this); + bookmarkTreeModel->setSourceModel(bookmarkModel); + ui.treeView->setModel(bookmarkTreeModel); + + ui.treeView->expandAll(); + ui.treeView->setVisible(false); + ui.treeView->installEventFilter(this); + ui.treeView->viewport()->installEventFilter(this); + ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(ui.treeView, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(customContextMenuRequested(QPoint))); + connect(ui.treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, + QModelIndex)), this, SLOT(currentIndexChanged(QModelIndex))); + + ui.bookmarkFolders->setCurrentIndex(0); + ui.treeView->setCurrentIndex(ui.treeView->indexAt(QPoint(2, 2))); +} + +BookmarkDialog::~BookmarkDialog() +{ + TRACE_OBJ +} + +bool BookmarkDialog::eventFilter(QObject *object, QEvent *event) +{ + TRACE_OBJ + if (object != ui.treeView && object != ui.treeView->viewport()) + return QWidget::eventFilter(object, event); + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); + switch (ke->key()) { + case Qt::Key_F2: { + bookmarkModel->setItemsEditable(true); + ui.treeView->edit(ui.treeView->currentIndex()); + bookmarkModel->setItemsEditable(false); + } break; + default: break; + } + } + + return QObject::eventFilter(object, event); +} + +void BookmarkDialog::currentIndexChanged(int row) +{ + TRACE_OBJ + QModelIndex next = bookmarkProxyModel->index(row, 0, QModelIndex()); + if (next.isValid()) { + next = bookmarkProxyModel->mapToSource(next); + ui.treeView->setCurrentIndex(bookmarkTreeModel->mapFromSource(next)); + } +} + +void BookmarkDialog::currentIndexChanged(const QModelIndex &index) +{ + TRACE_OBJ + const QModelIndex current = bookmarkTreeModel->mapToSource(index); + if (current.isValid()) { + const int row = bookmarkProxyModel->mapFromSource(current).row(); + ui.bookmarkFolders->setCurrentIndex(row); + } +} + +void BookmarkDialog::accepted() +{ + TRACE_OBJ + QModelIndex index = ui.treeView->currentIndex(); + if (index.isValid()) { + index = bookmarkModel->addItem(bookmarkTreeModel->mapToSource(index)); + if (BookmarkItem *item = bookmarkModel->itemFromIndex(index)) + item->setData(DataVector() << m_title << m_url << false); + } else + rejected(); + + accept(); +} + +void BookmarkDialog::rejected() +{ + TRACE_OBJ + foreach (const QPersistentModelIndex &index, cache) + bookmarkModel->removeItem(index); + reject(); +} + +void BookmarkDialog::addFolder() +{ + TRACE_OBJ + QModelIndex index = ui.treeView->currentIndex(); + if (index.isValid()) { + index = bookmarkModel->addItem(bookmarkTreeModel->mapToSource(index), + true); + cache.append(index); + + index = bookmarkTreeModel->mapFromSource(index); + if (index.isValid()) { + bookmarkModel->setItemsEditable(true); + ui.treeView->edit(index); + ui.treeView->expand(index); + ui.treeView->setCurrentIndex(index); + bookmarkModel->setItemsEditable(false); + } + } +} + +void BookmarkDialog::toolButtonClicked() +{ + TRACE_OBJ + const bool visible = !ui.treeView->isVisible(); + ui.treeView->setVisible(visible); + ui.newFolderButton->setVisible(visible); + + if (visible) { + resize(QSize(width(), 400)); + ui.toolButton->setText(QLatin1String("-")); + } else { + resize(width(), minimumHeight()); + ui.toolButton->setText(QLatin1String("+")); + } +} + +void BookmarkDialog::textChanged(const QString& text) +{ + m_title = text; +} + +void BookmarkDialog::customContextMenuRequested(const QPoint &point) +{ + TRACE_OBJ + QMenu menu(QLatin1String(""), this); + QAction *renameItem = menu.addAction(tr("Rename Folder")); + + QAction *picked = menu.exec(ui.treeView->mapToGlobal(point)); + if (picked == renameItem) { + bookmarkModel->setItemsEditable(true); + ui.treeView->edit(ui.treeView->currentIndex()); + bookmarkModel->setItemsEditable(false); + } +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/bookmarkdialog.h b/tools/assistant/tools/assistant/bookmarkdialog.h new file mode 100644 index 0000000..ba38c7a --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkdialog.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef BOOKMARKDIALOG_H +#define BOOKMARKDIALOG_H + +#include "ui_bookmarkdialog.h" + +QT_BEGIN_NAMESPACE + +class BookmarkModel; +class BookmarkFilterModel; +class BookmarkTreeModel; + +class BookmarkDialog : public QDialog +{ + Q_OBJECT +public: + BookmarkDialog(BookmarkModel *bookmarkModel, const QString &title, + const QString &url, QWidget *parent = 0); + ~BookmarkDialog(); + +private: + bool eventFilter(QObject *object, QEvent *event); + +private slots: + void currentIndexChanged(int index); + void currentIndexChanged(const QModelIndex &index); + + void accepted(); + void rejected(); + + void addFolder(); + void toolButtonClicked(); + void textChanged(const QString& text); + void customContextMenuRequested(const QPoint &point); + +private: + QString m_url; + QString m_title; + Ui::BookmarkDialog ui; + QList<QPersistentModelIndex> cache; + + BookmarkModel *bookmarkModel; + BookmarkTreeModel *bookmarkTreeModel; + BookmarkFilterModel *bookmarkProxyModel; +}; + +QT_END_NAMESPACE + +#endif // BOOKMARKDIALOG_H diff --git a/tools/assistant/tools/assistant/bookmarkdialog.ui b/tools/assistant/tools/assistant/bookmarkdialog.ui index 7a878f9..5131531 100644 --- a/tools/assistant/tools/assistant/bookmarkdialog.ui +++ b/tools/assistant/tools/assistant/bookmarkdialog.ui @@ -1,38 +1,39 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>BookmarkDialog</class> - <widget class="QDialog" name="BookmarkDialog" > - <property name="geometry" > + <widget class="QDialog" name="BookmarkDialog"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>450</width> - <height>135</height> + <height>133</height> </rect> </property> - <property name="sizePolicy" > - <sizepolicy vsizetype="Preferred" hsizetype="Preferred" > + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string>Add Bookmark</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_3" > + <layout class="QVBoxLayout" name="verticalLayout_3"> <item> - <layout class="QHBoxLayout" name="horizontalLayout" > + <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <layout class="QVBoxLayout" name="verticalLayout_2" > + <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <widget class="QLabel" name="label" > - <property name="text" > + <widget class="QLabel" name="label"> + <property name="text"> <string>Bookmark:</string> </property> </widget> </item> <item> - <widget class="QLabel" name="label_2" > - <property name="text" > + <widget class="QLabel" name="label_2"> + <property name="text"> <string>Add in Folder:</string> </property> </widget> @@ -40,35 +41,35 @@ </layout> </item> <item> - <layout class="QVBoxLayout" name="verticalLayout" > + <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QLineEdit" name="bookmarkEdit" /> + <widget class="QLineEdit" name="bookmarkEdit"/> </item> <item> - <widget class="QComboBox" name="bookmarkFolders" /> + <widget class="QComboBox" name="bookmarkFolders"/> </item> </layout> </item> </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_3" > + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <widget class="QToolButton" name="toolButton" > - <property name="minimumSize" > + <widget class="QToolButton" name="toolButton"> + <property name="minimumSize"> <size> <width>25</width> <height>20</height> </size> </property> - <property name="text" > + <property name="text"> <string>+</string> </property> </widget> </item> <item> - <widget class="Line" name="line" > - <property name="orientation" > + <widget class="Line" name="line"> + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> </widget> @@ -76,30 +77,39 @@ </layout> </item> <item> - <widget class="QTreeView" name="treeView" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Ignored" hsizetype="Expanding" > + <widget class="QTreeView" name="treeView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Ignored"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> + <property name="uniformRowHeights"> + <bool>true</bool> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="headerHidden"> + <bool>true</bool> + </property> </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_4" > + <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> - <widget class="QPushButton" name="newFolderButton" > - <property name="text" > + <widget class="QPushButton" name="newFolderButton"> + <property name="text"> <string>New Folder</string> </property> </widget> </item> <item> - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="orientation" > + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="standardButtons" > + <property name="standardButtons"> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> </property> </widget> @@ -116,11 +126,11 @@ <receiver>BookmarkDialog</receiver> <slot>accept()</slot> <hints> - <hint type="sourcelabel" > + <hint type="sourcelabel"> <x>248</x> <y>254</y> </hint> - <hint type="destinationlabel" > + <hint type="destinationlabel"> <x>157</x> <y>274</y> </hint> @@ -132,11 +142,11 @@ <receiver>BookmarkDialog</receiver> <slot>reject()</slot> <hints> - <hint type="sourcelabel" > + <hint type="sourcelabel"> <x>316</x> <y>260</y> </hint> - <hint type="destinationlabel" > + <hint type="destinationlabel"> <x>286</x> <y>274</y> </hint> diff --git a/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp b/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp new file mode 100644 index 0000000..5874493 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp @@ -0,0 +1,322 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "bookmarkfiltermodel.h" + +#include "bookmarkitem.h" +#include "bookmarkmodel.h" + +BookmarkFilterModel::BookmarkFilterModel(QObject *parent) + : QAbstractProxyModel(parent) + , hideBookmarks(true) + , sourceModel(0) +{ +} + +void +BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel) +{ + beginResetModel(); + + QAbstractProxyModel::setSourceModel(sourceModel); + sourceModel = qobject_cast<BookmarkModel*> (_sourceModel); + + connect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, + SLOT(changed(QModelIndex, QModelIndex))); + + connect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)), + this, SLOT(rowsInserted(QModelIndex, int, int))); + + connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), + this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int))); + connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, + SLOT(rowsRemoved(QModelIndex, int, int))); + + connect(sourceModel, SIGNAL(layoutAboutToBeChanged()), this, + SLOT(layoutAboutToBeChanged())); + connect(sourceModel, SIGNAL(layoutChanged()), this, + SLOT(layoutChanged())); + + connect(sourceModel, SIGNAL(modelAboutToBeReset()), this, + SLOT(modelAboutToBeReset())); + connect(sourceModel, SIGNAL(modelReset()), this, SLOT(modelReset())); + + if (sourceModel) + setupCache(sourceModel->index(0, 0, QModelIndex())); + + endResetModel(); +} + +int +BookmarkFilterModel::rowCount(const QModelIndex &index) const +{ + Q_UNUSED(index) + return cache.count(); +} + +int +BookmarkFilterModel::columnCount(const QModelIndex &index) const +{ + Q_UNUSED(index) + if (sourceModel) + return sourceModel->columnCount(); + return 0; +} + +QModelIndex +BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const +{ + const int row = proxyIndex.row(); + if (proxyIndex.isValid() && row >= 0 && row < cache.count()) + return cache[row]; + return QModelIndex(); +} + +QModelIndex +BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + return index(cache.indexOf(sourceIndex), 0, QModelIndex()); +} + +QModelIndex +BookmarkFilterModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child) + return QModelIndex(); +} + +QModelIndex +BookmarkFilterModel::index(int row, int column, const QModelIndex &index) const +{ + Q_UNUSED(index) + if (row < 0 || column < 0 || cache.count() <= row + || !sourceModel || sourceModel->columnCount() <= column) { + return QModelIndex(); + } + return createIndex(row, 0); +} + +Qt::DropActions +BookmarkFilterModel::supportedDropActions () const +{ + if (sourceModel) + return sourceModel->supportedDropActions(); + return Qt::IgnoreAction; +} + +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 +{ + if (sourceModel) + return sourceModel->data(mapToSource(index), role); + return QVariant(); +} + +bool +BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value, + int role) +{ + if (sourceModel) + return sourceModel->setData(mapToSource(index), value, role); + return false; +} + +void +BookmarkFilterModel::filterBookmarks() +{ + if (sourceModel) { + beginResetModel(); + hideBookmarks = true; + setupCache(sourceModel->index(0, 0, QModelIndex())); + endResetModel(); + } +} + +void +BookmarkFilterModel::filterBookmarkFolders() +{ + if (sourceModel) { + beginResetModel(); + hideBookmarks = false; + setupCache(sourceModel->index(0, 0, QModelIndex())); + endResetModel(); + } +} + +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) +{ + if (!sourceModel) + return; + + QModelIndex cachePrevious = parent; + if (BookmarkItem *parentItem = sourceModel->itemFromIndex(parent)) { + BookmarkItem *newItem = parentItem->child(start); + + // iterate over tree hirarchie to find the previous folder + for (int i = 0; i < parentItem->childCount(); ++i) { + if (BookmarkItem *child = parentItem->child(i)) { + const QModelIndex &tmp = sourceModel->indexFromItem(child); + if (tmp.data(UserRoleFolder).toBool() && child != newItem) + cachePrevious = tmp; + } + } + + const QModelIndex &newIndex = sourceModel->indexFromItem(newItem); + const bool isFolder = newIndex.data(UserRoleFolder).toBool(); + if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) { + beginInsertRows(mapFromSource(parent), start, end); + cache.insert(cache.indexOf(cachePrevious) + 1, newIndex); + endInsertRows(); + } + } +} + +void +BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent, int start, + int end) +{ + if (!sourceModel) + return; + + if (BookmarkItem *parentItem = sourceModel->itemFromIndex(parent)) { + if (BookmarkItem *child = parentItem->child(start)) { + indexToRemove = sourceModel->indexFromItem(child); + if (cache.contains(indexToRemove)) + beginRemoveRows(mapFromSource(parent), start, end); + } + } +} + +void +BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int) +{ + if (cache.contains(indexToRemove)) { + cache.removeAll(indexToRemove); + endRemoveRows(); + } +} + +void +BookmarkFilterModel::layoutAboutToBeChanged() +{ + // TODO: ??? +} + +void +BookmarkFilterModel::layoutChanged() +{ + // TODO: ??? +} + +void +BookmarkFilterModel::modelAboutToBeReset() +{ + beginResetModel(); +} + +void +BookmarkFilterModel::modelReset() +{ + if (sourceModel) + setupCache(sourceModel->index(0, 0, QModelIndex())); + endResetModel(); +} + +void +BookmarkFilterModel::setupCache(const QModelIndex &parent) +{ + cache.clear(); + collectItems(parent); +} + +void +BookmarkFilterModel::collectItems(const QModelIndex &parent) +{ + if (parent.isValid()) { + bool isFolder = sourceModel->data(parent, UserRoleFolder).toBool(); + if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) + cache.append(parent); + + if (sourceModel->hasChildren(parent)) { + for (int i = 0; i < sourceModel->rowCount(parent); ++i) + collectItems(sourceModel->index(i, 0, parent)); + } + } +} + +// -- BookmarkTreeModel + +BookmarkTreeModel::BookmarkTreeModel(QObject *parent) + : QSortFilterProxyModel(parent) +{ +} + +int +BookmarkTreeModel::columnCount(const QModelIndex &parent) const +{ + return qMin(1, QSortFilterProxyModel::columnCount(parent)); +} + +bool +BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const +{ + Q_UNUSED(row) + BookmarkModel *model = qobject_cast<BookmarkModel*> (sourceModel()); + if (model->rowCount(parent) > 0 + && model->data(model->index(row, 0, parent), UserRoleFolder).toBool()) + return true; + return false; +}
\ No newline at end of file diff --git a/tools/assistant/tools/assistant/bookmarkfiltermodel.h b/tools/assistant/tools/assistant/bookmarkfiltermodel.h new file mode 100644 index 0000000..4ea7ab9 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkfiltermodel.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef BOOKMARKFILTERMODEL_H +#define BOOKMARKFILTERMODEL_H + +#include <QtCore/QPersistentModelIndex> + +#include <QtGui/QAbstractProxyModel> +#include <QtGui/QSortFilterProxyModel> + +QT_BEGIN_NAMESPACE + +class BookmarkItem; +class BookmarkModel; + +typedef QList<QPersistentModelIndex> PersistentModelIndexCache; + +class BookmarkFilterModel : public QAbstractProxyModel +{ + Q_OBJECT +public: + explicit BookmarkFilterModel(QObject *parent = 0); + + void setSourceModel(QAbstractItemModel *sourceModel); + + int rowCount(const QModelIndex &index) const; + int columnCount(const QModelIndex &index) const; + + QModelIndex mapToSource(const QModelIndex &proxyIndex) const; + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; + + QModelIndex parent(const QModelIndex &child) const; + QModelIndex index(int row, int column, const QModelIndex &parent) const; + + Qt::DropActions supportedDropActions () const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + + void filterBookmarks(); + void filterBookmarkFolders(); + +private slots: + void changed(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void rowsInserted(const QModelIndex &parent, int start, int end); + void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void rowsRemoved(const QModelIndex &parent, int start, int end); + void layoutAboutToBeChanged(); + void layoutChanged(); + void modelAboutToBeReset(); + void modelReset(); + +private: + void setupCache(const QModelIndex &parent); + void collectItems(const QModelIndex &parent); + +private: + bool hideBookmarks; + BookmarkModel *sourceModel; + PersistentModelIndexCache cache; + QPersistentModelIndex indexToRemove; +}; + +// -- BookmarkTreeModel + +class BookmarkTreeModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + BookmarkTreeModel(QObject *parent = 0); + int columnCount(const QModelIndex &parent = QModelIndex()) const; + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; +}; + +QT_END_NAMESPACE + +#endif // BOOKMARKFILTERMODEL_H diff --git a/tools/assistant/tools/assistant/bookmarkitem.cpp b/tools/assistant/tools/assistant/bookmarkitem.cpp new file mode 100644 index 0000000..8036959 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkitem.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "bookmarkitem.h" + +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +BookmarkItem::BookmarkItem(const DataVector &data, BookmarkItem *parent) + : m_data(data) + , m_parent(parent) +{ +} + +BookmarkItem::~BookmarkItem() +{ + qDeleteAll(m_children); +} + +BookmarkItem* +BookmarkItem::parent() const +{ + return m_parent; +} + +void +BookmarkItem::setParent(BookmarkItem *parent) +{ + m_parent = parent; +} + +void +BookmarkItem::addChild(BookmarkItem *child) +{ + child->setParent(this); + m_children.append(child); +} + +BookmarkItem* +BookmarkItem::child(int number) const +{ + if (number >= 0 && number < m_children.count()) + return m_children[number]; + return 0; +} + +int BookmarkItem::childCount() const +{ + return m_children.count(); +} + +int BookmarkItem::childNumber() const +{ + if (m_parent) + return m_parent->m_children.indexOf(const_cast<BookmarkItem*>(this)); + return 0; +} + +QVariant +BookmarkItem::data(int column) const +{ + if (column == 0) + return m_data[0]; + + if (column == 1 || column == UserRoleUrl) + return m_data[1]; + + if (column == UserRoleFolder) + return m_data[1].toString() == QLatin1String("Folder"); + + if (column == UserRoleExpanded) + return m_data[2]; + + return QVariant(); +} + +void +BookmarkItem::setData(const DataVector &data) +{ + m_data = data; +} + +bool +BookmarkItem::setData(int column, const QVariant &newValue) +{ + int index = -1; + if (column == 0 || column == 1) + index = column; + + if (column == UserRoleUrl || column == UserRoleFolder) + index = 1; + + if (column == UserRoleExpanded) + index = 2; + + if (index < 0) + return false; + + m_data[index] = newValue; + return true; +} + +bool +BookmarkItem::insertChildren(bool isFolder, int position, int count) +{ + if (position < 0 || position > m_children.size()) + return false; + + for (int row = 0; row < count; ++row) { + m_children.insert(position, new BookmarkItem(DataVector() + << QObject::tr(isFolder ? "New Folder" : "Untitled") + << (isFolder ? "Folder" : "about:blank") << false, this)); + } + + return true; +} + +bool +BookmarkItem::removeChildren(int position, int count) +{ + if (position < 0 || position > m_children.size()) + return false; + + for (int row = 0; row < count; ++row) + delete m_children.takeAt(position); + + return true; +} + +void +BookmarkItem::dumpTree(int indent) const +{ + const QString tree(indent, ' '); + qDebug() << tree + (data(UserRoleFolder).toBool() ? "Folder" : "Bookmark") + << "Label:" << data(0).toString() << "parent:" << m_parent << "this:" + << this; + + foreach (BookmarkItem *item, m_children) + item->dumpTree(indent + 4); +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/bookmarkitem.h b/tools/assistant/tools/assistant/bookmarkitem.h new file mode 100644 index 0000000..7acaf86 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkitem.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef BOOKMARKITEM_H +#define BOOKMARKITEM_H + +#include <QtCore/QVariant> +#include <QtCore/QVector> + +QT_BEGIN_NAMESPACE + +enum { + UserRoleUrl = Qt::UserRole + 50, + UserRoleFolder = Qt::UserRole + 100, + UserRoleExpanded = Qt::UserRole + 150 +}; + +typedef QVector<QVariant> DataVector; + +class BookmarkItem +{ +public: + BookmarkItem(const DataVector &data, BookmarkItem *parent = 0); + ~BookmarkItem(); + + BookmarkItem *parent() const; + void setParent(BookmarkItem *parent); + + void addChild(BookmarkItem *child); + BookmarkItem *child(int number) const; + + int childCount() const; + int childNumber() const; + + QVariant data(int column) const; + void setData(const DataVector &data); + bool setData(int column, const QVariant &value); + + bool insertChildren(bool isFolder, int position, int count); + bool removeChildren(int position, int count); + + void dumpTree(int indent) const; + +private: + DataVector m_data; + + BookmarkItem *m_parent; + QList<BookmarkItem*> m_children; +}; + +QT_END_NAMESPACE + +#endif // BOOKMARKITEM_H diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp index 0ce1b9d..8fba811 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.cpp +++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp @@ -38,549 +38,210 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "bookmarkmanager.h" +#include "bookmarkdialog.h" +#include "bookmarkfiltermodel.h" +#include "bookmarkitem.h" +#include "bookmarkmodel.h" #include "centralwidget.h" +#include "helpenginewrapper.h" +#include <QtGui/QFileDialog> #include <QtGui/QMenu> -#include <QtGui/QIcon> -#include <QtGui/QStyle> -#include <QtGui/QLabel> -#include <QtGui/QLayout> -#include <QtCore/QEvent> -#include <QtGui/QComboBox> #include <QtGui/QKeyEvent> -#include <QtGui/QLineEdit> #include <QtGui/QMessageBox> -#include <QtGui/QHeaderView> -#include <QtGui/QToolButton> -#include <QtGui/QPushButton> -#include <QtGui/QApplication> -#include <QtHelp/QHelpEngineCore> -#include <QtGui/QDialogButtonBox> #include <QtGui/QSortFilterProxyModel> -QT_BEGIN_NAMESPACE - -BookmarkDialog::BookmarkDialog(BookmarkManager *manager, const QString &title, - const QString &url, QWidget *parent) - : QDialog(parent) - , m_url(url) - , m_title(title) - , bookmarkManager(manager) -{ - ui.setupUi(this); - - installEventFilter(this); - ui.treeView->installEventFilter(this); - ui.treeView->viewport()->installEventFilter(this); - - ui.bookmarkEdit->setText(title); - ui.newFolderButton->setVisible(false); - ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); - ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders()); - - proxyModel = new QSortFilterProxyModel(this); - proxyModel->setFilterKeyColumn(0); - proxyModel->setDynamicSortFilter(true); - proxyModel->setFilterRole(Qt::UserRole + 10); - proxyModel->setSourceModel(bookmarkManager->treeBookmarkModel()); - proxyModel->setFilterRegExp(QRegExp(QLatin1String("Folder"), - Qt::CaseSensitive, QRegExp::FixedString)); - ui.treeView->setModel(proxyModel); - - ui.treeView->expandAll(); - ui.treeView->setVisible(false); - ui.treeView->header()->setVisible(false); - ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); - - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(addAccepted())); - connect(ui.newFolderButton, SIGNAL(clicked()), this, SLOT(addNewFolder())); - connect(ui.toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked())); - connect(ui.bookmarkEdit, SIGNAL(textChanged(QString)), this, - SLOT(textChanged(QString))); - - connect(bookmarkManager->treeBookmarkModel(), - SIGNAL(itemChanged(QStandardItem*)), - this, SLOT(itemChanged(QStandardItem*))); - - connect(ui.bookmarkFolders, SIGNAL(currentIndexChanged(QString)), this, - SLOT(selectBookmarkFolder(QString))); - - connect(ui.treeView, SIGNAL(customContextMenuRequested(QPoint)), this, - SLOT(customContextMenuRequested(QPoint))); - - connect(ui.treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, - QModelIndex)), this, SLOT(currentChanged(QModelIndex))); -} - -BookmarkDialog::~BookmarkDialog() -{ -} - -void BookmarkDialog::addAccepted() -{ - QItemSelectionModel *model = ui.treeView->selectionModel(); - const QModelIndexList &list = model->selection().indexes(); +#include <QFile> +#include "xbelsupport.h" - QModelIndex index; - if (!list.isEmpty()) - index = proxyModel->mapToSource(list.at(0)); +QT_BEGIN_NAMESPACE - bookmarkManager->addNewBookmark(index, ui.bookmarkEdit->text(), m_url); - accept(); -} +// -- BookmarkManager::BookmarkWidget -void BookmarkDialog::addNewFolder() +void BookmarkManager::BookmarkWidget::focusInEvent(QFocusEvent *event) { - QItemSelectionModel *model = ui.treeView->selectionModel(); - const QModelIndexList &list = model->selection().indexes(); + TRACE_OBJ + if (event->reason() != Qt::MouseFocusReason) { + ui.lineEdit->selectAll(); + ui.lineEdit->setFocus(); - QModelIndex index; - if (!list.isEmpty()) - index = list.at(0); - - QModelIndex newFolder = - bookmarkManager->addNewFolder(proxyModel->mapToSource(index)); - if (newFolder.isValid()) { - ui.treeView->expand(index); - const QModelIndex &index = proxyModel->mapFromSource(newFolder); - model->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); - - ui.bookmarkFolders->clear(); - ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders()); - - const QString &name = index.data().toString(); - ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name)); + // force the focus in event on bookmark manager + emit focusInEvent(); } - ui.treeView->setFocus(); } -void BookmarkDialog::toolButtonClicked() -{ - bool visible = !ui.treeView->isVisible(); - ui.treeView->setVisible(visible); - ui.newFolderButton->setVisible(visible); - - if (visible) { - resize(QSize(width(), 400)); - ui.toolButton->setText(QLatin1String("-")); - } else { - resize(width(), minimumHeight()); - ui.toolButton->setText(QLatin1String("+")); - } -} +// -- BookmarkManager::BookmarkTreeView -void BookmarkDialog::itemChanged(QStandardItem *item) +BookmarkManager::BookmarkTreeView::BookmarkTreeView(QWidget *parent) + : QTreeView(parent) { - if (renameItem != item) { - renameItem = item; - oldText = item->text(); - return; - } + TRACE_OBJ + setAcceptDrops(true); + setDragEnabled(true); + setAutoExpandDelay(1000); + setUniformRowHeights(true); + setDropIndicatorShown(true); + setExpandsOnDoubleClick(true); - if (item->text() != oldText) { - ui.bookmarkFolders->clear(); - ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders()); + connect(this, SIGNAL(expanded(QModelIndex)), this, + SLOT(setExpandedData(QModelIndex))); + connect(this, SIGNAL(collapsed(QModelIndex)), this, + SLOT(setExpandedData(QModelIndex))); - QString name = tr("Bookmarks"); - const QModelIndex &index = ui.treeView->currentIndex(); - if (index.isValid()) - name = index.data().toString(); - ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name)); - } } -void BookmarkDialog::textChanged(const QString &string) +void BookmarkManager::BookmarkTreeView::subclassKeyPressEvent(QKeyEvent *event) { - ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!string.isEmpty()); + TRACE_OBJ + QTreeView::keyPressEvent(event); } -void BookmarkDialog::selectBookmarkFolder(const QString &folderName) +void BookmarkManager::BookmarkTreeView::setExpandedData(const QModelIndex &index) { - if (folderName.isEmpty()) - return; - - if (folderName == tr("Bookmarks")) { - ui.treeView->clearSelection(); - return; - } - - QStandardItemModel *model = bookmarkManager->treeBookmarkModel(); - QList<QStandardItem*> list = model->findItems(folderName, - Qt::MatchCaseSensitive | Qt::MatchRecursive, 0); - if (!list.isEmpty()) { - const QModelIndex &index = model->indexFromItem(list.at(0)); - QItemSelectionModel *model = ui.treeView->selectionModel(); - if (model) { - model->setCurrentIndex(proxyModel->mapFromSource(index), - QItemSelectionModel::ClearAndSelect); - } - } + TRACE_OBJ + if (BookmarkModel *treeModel = qobject_cast<BookmarkModel*> (model())) + treeModel->setData(index, isExpanded(index), UserRoleExpanded); } -void BookmarkDialog::customContextMenuRequested(const QPoint &point) -{ - QModelIndex index = ui.treeView->indexAt(point); - if (!index.isValid()) - return; +// -- BookmarkManager - QMenu menu(QLatin1String(""), this); +QMutex BookmarkManager::mutex; +BookmarkManager* BookmarkManager::bookmarkManager = 0; - QAction *removeItem = menu.addAction(tr("Delete Folder")); - QAction *renameItem = menu.addAction(tr("Rename Folder")); +// -- public - QAction *picked = menu.exec(ui.treeView->mapToGlobal(point)); - if (!picked) - return; - - const QModelIndex &proxyIndex = proxyModel->mapToSource(index); - if (picked == removeItem) { - bookmarkManager->removeBookmarkItem(ui.treeView, proxyIndex); - ui.bookmarkFolders->clear(); - ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders()); - - QString name = tr("Bookmarks"); - index = ui.treeView->currentIndex(); - if (index.isValid()) - name = index.data().toString(); - ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name)); - } - else if (picked == renameItem) { - BookmarkModel *model = bookmarkManager->treeBookmarkModel(); - if (QStandardItem *item = model->itemFromIndex(proxyIndex)) { - item->setEditable(true); - ui.treeView->edit(index); - item->setEditable(false); - } - } -} - -void BookmarkDialog::currentChanged(const QModelIndex ¤t) -{ - QString text = tr("Bookmarks"); - if (current.isValid()) - text = current.data().toString(); - ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(text)); -} - -bool BookmarkDialog::eventFilter(QObject *object, QEvent *e) +BookmarkManager* BookmarkManager::instance() { - if (object != ui.treeView && object != ui.treeView->viewport()) - return QWidget::eventFilter(object, e); - - if (e->type() == QEvent::KeyPress) { - QKeyEvent *ke = static_cast<QKeyEvent*>(e); - switch (ke->key()) { - case Qt::Key_F2: { - const QModelIndex &index = ui.treeView->currentIndex(); - const QModelIndex &source = proxyModel->mapToSource(index); - QStandardItem *item = - bookmarkManager->treeBookmarkModel()->itemFromIndex(source); - if (item) { - item->setEditable(true); - ui.treeView->edit(index); - item->setEditable(false); - } - } break; - - case Qt::Key_Delete: { - const QModelIndex &index = ui.treeView->currentIndex(); - bookmarkManager->removeBookmarkItem(ui.treeView, - proxyModel->mapToSource(index)); - ui.bookmarkFolders->clear(); - ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders()); - - QString name = tr("Bookmarks"); - if (index.isValid()) - name = index.data().toString(); - ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name)); - } break; - - default: - break; - } + TRACE_OBJ + if (!bookmarkManager) { + QMutexLocker _(&mutex); + if (!bookmarkManager) + bookmarkManager = new BookmarkManager(); } - - return QObject::eventFilter(object, e); + return bookmarkManager; } - -// #pragma mark -- BookmarkWidget - - -BookmarkWidget::BookmarkWidget(BookmarkManager *manager, QWidget *parent, - bool showButtons) - : QWidget(parent) - , addButton(0) - , removeButton(0) - , bookmarkManager(manager) +void BookmarkManager::destroy() { - setup(showButtons); - - installEventFilter(this); - treeView->installEventFilter(this); - treeView->viewport()->installEventFilter(this); + TRACE_OBJ + delete bookmarkManager; + bookmarkManager = 0; } -BookmarkWidget::~BookmarkWidget() +QWidget* BookmarkManager::bookmarkDockWidget() const { + TRACE_OBJ + if (bookmarkWidget) + return bookmarkWidget; + return 0; } -void BookmarkWidget::removeClicked() +void BookmarkManager::takeBookmarksMenu(QMenu* menu) { - const QModelIndex &index = treeView->currentIndex(); - if (searchField->text().isEmpty()) { - bookmarkManager->removeBookmarkItem(treeView, - filterBookmarkModel->mapToSource(index)); - } + TRACE_OBJ + bookmarkMenu = menu; + refeshBookmarkMenu(); } -void BookmarkWidget::filterChanged() -{ - bool searchBookmarks = searchField->text().isEmpty(); - if (!searchBookmarks) { - regExp.setPattern(searchField->text()); - filterBookmarkModel->setSourceModel(bookmarkManager->listBookmarkModel()); - } else { - regExp.setPattern(QLatin1String("")); - filterBookmarkModel->setSourceModel(bookmarkManager->treeBookmarkModel()); - } +// -- public slots - if (addButton) - addButton->setEnabled(searchBookmarks); - - if (removeButton) - removeButton->setEnabled(searchBookmarks); - - filterBookmarkModel->setFilterRegExp(regExp); - - const QModelIndex &index = treeView->indexAt(QPoint(1, 1)); - if (index.isValid()) - treeView->setCurrentIndex(index); - - if (searchBookmarks) - expandItems(); -} - -void BookmarkWidget::expand(const QModelIndex &index) +void BookmarkManager::addBookmark(const QString &title, const QString &url) { - const QModelIndex &source = filterBookmarkModel->mapToSource(index); - QStandardItem *item = - bookmarkManager->treeBookmarkModel()->itemFromIndex(source); - if (item) - item->setData(treeView->isExpanded(index), Qt::UserRole + 11); + TRACE_OBJ + showBookmarkDialog(title.isEmpty() ? tr("Untiled") : title, + url.isEmpty() ? QLatin1String("about:blank") : url); } -void BookmarkWidget::activated(const QModelIndex &index) -{ - if (!index.isValid()) - return; +// -- private - QString data = index.data(Qt::UserRole + 10).toString(); - if (data != QLatin1String("Folder")) - emit requestShowLink(data); -} - -void BookmarkWidget::customContextMenuRequested(const QPoint &point) +BookmarkManager::BookmarkManager() + : typeAndSearch(false) + , bookmarkMenu(0) + , bookmarkModel(new BookmarkModel) + , bookmarkWidget(new BookmarkWidget) + , bookmarkTreeView(new BookmarkTreeView) { - QModelIndex index = treeView->indexAt(point); - if (!index.isValid()) - return; + TRACE_OBJ + bookmarkWidget->installEventFilter(this); + connect(bookmarkWidget->ui.add, SIGNAL(clicked()), this, + SLOT(addBookmark())); + connect(bookmarkWidget->ui.remove, SIGNAL(clicked()), this, + SLOT(removeBookmark())); + connect(bookmarkWidget->ui.lineEdit, SIGNAL(textChanged(QString)), this, + SLOT(textChanged(QString))); + connect(bookmarkWidget, SIGNAL(focusInEvent()), this, SLOT(focusInEvent())); - QAction *showItem = 0; - QAction *removeItem = 0; - QAction *renameItem = 0; - QAction *showItemNewTab = 0; - - QMenu menu(QLatin1String(""), this); - QString data = index.data(Qt::UserRole + 10).toString(); - if (data == QLatin1String("Folder")) { - removeItem = menu.addAction(tr("Delete Folder")); - renameItem = menu.addAction(tr("Rename Folder")); - } else { - showItem = menu.addAction(tr("Show Bookmark")); - showItemNewTab = menu.addAction(tr("Show Bookmark in New Tab")); - if (searchField->text().isEmpty()) { - menu.addSeparator(); - removeItem = menu.addAction(tr("Delete Bookmark")); - renameItem = menu.addAction(tr("Rename Bookmark")); - } - } + bookmarkTreeView->setModel(bookmarkModel); + bookmarkTreeView->installEventFilter(this); + bookmarkTreeView->viewport()->installEventFilter(this); + bookmarkTreeView->setContextMenuPolicy(Qt::CustomContextMenu); + bookmarkWidget->ui.stackedWidget->addWidget(bookmarkTreeView); - QAction *pickedAction = menu.exec(treeView->mapToGlobal(point)); - if (!pickedAction) - return; + connect(bookmarkTreeView, SIGNAL(activated(QModelIndex)), this, + SLOT(setSourceFromIndex(QModelIndex))); + connect(bookmarkTreeView, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(customContextMenuRequested(QPoint))); - if (pickedAction == showItem) { - emit requestShowLink(data); - } - else if (pickedAction == showItemNewTab) { - CentralWidget::instance()->setSourceInNewTab(data); - } - else if (pickedAction == removeItem) { - bookmarkManager->removeBookmarkItem(treeView, - filterBookmarkModel->mapToSource(index)); - } - else if (pickedAction == renameItem) { - const QModelIndex &source = filterBookmarkModel->mapToSource(index); - QStandardItem *item = - bookmarkManager->treeBookmarkModel()->itemFromIndex(source); - if (item) { - item->setEditable(true); - treeView->edit(index); - item->setEditable(false); - } - } + connect(&HelpEngineWrapper::instance(), SIGNAL(setupFinished()), this, + SLOT(setupFinished())); + connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, + SLOT(refeshBookmarkMenu())); } -void BookmarkWidget::setup(bool showButtons) +BookmarkManager::~BookmarkManager() { - regExp.setPatternSyntax(QRegExp::FixedString); - regExp.setCaseSensitivity(Qt::CaseInsensitive); - - QLayout *vlayout = new QVBoxLayout(this); - vlayout->setMargin(4); - - QLabel *label = new QLabel(tr("Filter:"), this); - vlayout->addWidget(label); - - searchField = new QLineEdit(this); - vlayout->addWidget(searchField); - connect(searchField, SIGNAL(textChanged(QString)), this, - SLOT(filterChanged())); - - treeView = new TreeView(this); - vlayout->addWidget(treeView); - -#ifdef Q_OS_MAC -# define SYSTEM "mac" -#else -# define SYSTEM "win" -#endif - - if (showButtons) { - QLayout *hlayout = new QHBoxLayout(); - vlayout->addItem(hlayout); - - hlayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding)); - - addButton = new QToolButton(this); - addButton->setText(tr("Add")); - addButton->setIcon(QIcon(QLatin1String(":/trolltech/assistant/images/" - SYSTEM "/addtab.png"))); - addButton->setAutoRaise(true); - addButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - hlayout->addWidget(addButton); - connect(addButton, SIGNAL(clicked()), this, SIGNAL(addBookmark())); - - removeButton = new QToolButton(this); - removeButton->setText(tr("Remove")); - removeButton->setIcon(QIcon(QLatin1String(":/trolltech/assistant/images/" - SYSTEM "/closetab.png"))); - removeButton->setAutoRaise(true); - removeButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - hlayout->addWidget(removeButton); - connect(removeButton, SIGNAL(clicked()), this, SLOT(removeClicked())); - } - - filterBookmarkModel = new QSortFilterProxyModel(this); - treeView->setModel(filterBookmarkModel); - - treeView->setDragEnabled(true); - treeView->setAcceptDrops(true); - treeView->setAutoExpandDelay(1000); - treeView->setDropIndicatorShown(true); - treeView->header()->setVisible(false); - treeView->setContextMenuPolicy(Qt::CustomContextMenu); - - connect(treeView, SIGNAL(expanded(QModelIndex)), this, - SLOT(expand(QModelIndex))); - connect(treeView, SIGNAL(collapsed(QModelIndex)), this, - SLOT(expand(QModelIndex))); - connect(treeView, SIGNAL(activated(QModelIndex)), this, - SLOT(activated(QModelIndex))); - connect(treeView, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(customContextMenuRequested(QPoint))); - - filterBookmarkModel->setFilterKeyColumn(0); - filterBookmarkModel->setDynamicSortFilter(true); - filterBookmarkModel->setSourceModel(bookmarkManager->treeBookmarkModel()); - - expandItems(); + TRACE_OBJ + HelpEngineWrapper::instance().setBookmarks(bookmarkModel->bookmarks()); } -void BookmarkWidget::expandItems() +void BookmarkManager::removeItem(const QModelIndex &index) { - QStandardItemModel *model = bookmarkManager->treeBookmarkModel(); - QList<QStandardItem*>list = model->findItems(QLatin1String("*"), - Qt::MatchWildcard | Qt::MatchRecursive, 0); - foreach (const QStandardItem *item, list) { - const QModelIndex &index = model->indexFromItem(item); - treeView->setExpanded(filterBookmarkModel->mapFromSource(index), - item->data(Qt::UserRole + 11).toBool()); + TRACE_OBJ + QModelIndex current = index; + if (typeAndSearch) { // need to map because of proxy + current = typeAndSearchModel->mapToSource(current); + current = bookmarkFilterModel->mapToSource(current); + } else if (!bookmarkModel->parent(index).isValid()) { + return; // check if we should delete the "Bookmarks Menu", bail } -} - -void BookmarkWidget::focusInEvent(QFocusEvent *e) -{ - if (e->reason() != Qt::MouseFocusReason) { - searchField->selectAll(); - searchField->setFocus(); - - QModelIndex index = treeView->indexAt(QPoint(1, 1)); - if (index.isValid()) - treeView->setCurrentIndex(index); + if (bookmarkModel->hasChildren(current)) { + int value = QMessageBox::question(bookmarkTreeView, tr("Remove"), + tr("You are going to delete a Folder, this will also<br>" + "remove it's content. Are you sure to continue?"), + QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); + if (value == QMessageBox::Cancel) + return; } + bookmarkModel->removeItem(current); } -bool BookmarkWidget::eventFilter(QObject *object, QEvent *e) +bool BookmarkManager::eventFilter(QObject *object, QEvent *event) { - if (object != this && object != treeView - && object != treeView->viewport()) { - return QWidget::eventFilter(object, e); - } + if (object != bookmarkTreeView && object != bookmarkTreeView->viewport() + && object != bookmarkWidget) + return QObject::eventFilter(object, event); - if (e->type() == QEvent::KeyPress) { - QKeyEvent *ke = static_cast<QKeyEvent*>(e); - const bool tree = object == treeView || object == treeView->viewport(); + TRACE_OBJ + const bool isWidget = object == bookmarkWidget; + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast<QKeyEvent*>(event); switch (ke->key()) { case Qt::Key_F2: { - const QModelIndex &index = treeView->currentIndex(); - const QModelIndex &src = filterBookmarkModel->mapToSource(index); - if (tree && searchField->text().isEmpty()) { - if (QStandardItem *item = bookmarkManager->treeBookmarkModel() - ->itemFromIndex(src)) { - item->setEditable(true); - treeView->edit(index); - item->setEditable(false); - } - } - } break; - - case Qt::Key_Enter: { - case Qt::Key_Return: - if (tree) { - const QString &data = treeView->selectionModel()->currentIndex() - .data(Qt::UserRole + 10).toString(); - if (!data.isEmpty() && data != QLatin1String("Folder")) - emit requestShowLink(data); - } + renameBookmark(bookmarkTreeView->currentIndex()); } break; case Qt::Key_Delete: { - const QModelIndex &index = treeView->currentIndex(); - const QModelIndex &src = filterBookmarkModel->mapToSource(index); - if (tree && searchField->text().isEmpty()) - bookmarkManager->removeBookmarkItem(treeView, src); + removeItem(bookmarkTreeView->currentIndex()); } break; - case Qt::Key_Up: { + case Qt::Key_Up: { // needs event filter on widget case Qt::Key_Down: - if (!tree) - treeView->subclassKeyPressEvent(ke); + if (isWidget) + bookmarkTreeView->subclassKeyPressEvent(ke); } break; case Qt::Key_Escape: { @@ -591,324 +252,255 @@ bool BookmarkWidget::eventFilter(QObject *object, QEvent *e) } } - if (e->type() == QEvent::MouseButtonRelease) { - QMouseEvent *me = static_cast<QMouseEvent*>(e); - bool controlPressed = me->modifiers() & Qt::ControlModifier; - if(((me->button() == Qt::LeftButton) && controlPressed) - || (me->button() == Qt::MidButton)) { - const QModelIndex &index = treeView->currentIndex(); - const QString &data = index.data(Qt::UserRole + 10).toString(); - if (!data.isEmpty() && data != QLatin1String("Folder")) - CentralWidget::instance()->setSourceInNewTab(data); + if (event->type() == QEvent::MouseButtonRelease && !isWidget) { + QMouseEvent *me = static_cast<QMouseEvent*>(event); + switch (me->button()) { + case Qt::LeftButton: { + if (me->modifiers() & Qt::ControlModifier) + setSourceFromIndex(bookmarkTreeView->currentIndex(), true); + } break; + + case Qt::MidButton: { + setSourceFromIndex(bookmarkTreeView->currentIndex(), true); + } break; + + default: break; } } - return QWidget::eventFilter(object, e); + return QObject::eventFilter(object, event); } - -// #pragma mark -- BookmarkModel - - -BookmarkModel::BookmarkModel(int rows, int columns, QObject *parent) - : QStandardItemModel(rows, columns, parent) +void BookmarkManager::buildBookmarksMenu(const QModelIndex &index, QMenu* menu) { -} + TRACE_OBJ + if (!index.isValid()) + return; -BookmarkModel::~BookmarkModel() -{ + const QString &text = index.data().toString(); + const QIcon &icon = qVariantValue<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) + buildBookmarksMenu(bookmarkModel->index(i, 0, index), subMenu); + } + } else { + QAction *action = menu->addAction(icon, text); + action->setData(index.data(UserRoleUrl).toString()); + } } -Qt::DropActions BookmarkModel::supportedDropActions() const +void BookmarkManager::showBookmarkDialog(const QString &name, const QString &url) { - return Qt::MoveAction; + TRACE_OBJ + BookmarkDialog dialog(bookmarkModel, name, url, bookmarkTreeView); + dialog.exec(); } -Qt::ItemFlags BookmarkModel::flags(const QModelIndex &index) const -{ - Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index); - if ((!index.isValid()) // can only happen for the invisible root item - || index.data(Qt::UserRole + 10).toString() == QLatin1String("Folder")) - return (Qt::ItemIsDropEnabled | defaultFlags) &~ Qt::ItemIsDragEnabled; +// -- private slots - return (Qt::ItemIsDragEnabled | defaultFlags) &~ Qt::ItemIsDropEnabled; -} +void BookmarkManager::setupFinished() +{ + TRACE_OBJ + bookmarkModel->setBookmarks(HelpEngineWrapper::instance().bookmarks()); + bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView); + refeshBookmarkMenu(); -// #pragma mark -- BookmarkManager + bookmarkTreeView->hideColumn(1); + bookmarkTreeView->header()->setVisible(false); + bookmarkTreeView->header()->setStretchLastSection(true); + bookmarkFilterModel = new BookmarkFilterModel(this); + bookmarkFilterModel->setSourceModel(bookmarkModel); + bookmarkFilterModel->filterBookmarkFolders(); -BookmarkManager::BookmarkManager(QHelpEngineCore *_helpEngine) - : treeModel(new BookmarkModel(0, 1, this)) - , listModel(new BookmarkModel(0, 1, this)) - , renameItem(0) - , helpEngine(_helpEngine) -{ - folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon); - - connect(treeModel, SIGNAL(itemChanged(QStandardItem*)), this, - SLOT(itemChanged(QStandardItem*))); - connect(treeModel, SIGNAL(itemChanged(QStandardItem*)), this, - SIGNAL(bookmarksChanged())); - connect(treeModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SIGNAL(bookmarksChanged())); + typeAndSearchModel = new QSortFilterProxyModel(this); + typeAndSearchModel->setDynamicSortFilter(true); + typeAndSearchModel->setSourceModel(bookmarkFilterModel); } -BookmarkManager::~BookmarkManager() +void BookmarkManager::addBookmark() { - treeModel->clear(); - listModel->clear(); + TRACE_OBJ + if (CentralWidget *widget = CentralWidget::instance()) { + showBookmarkDialog(widget->currentTitle(), + widget->currentSource().toString()); + } } -BookmarkModel* BookmarkManager::treeBookmarkModel() +void BookmarkManager::removeBookmark() { - return treeModel; + TRACE_OBJ + removeItem(bookmarkTreeView->currentIndex()); } -BookmarkModel* BookmarkManager::listBookmarkModel() -{ - return listModel; -} +//void BookmarkManager::manageBookmarks() +//{ +// TRACE_OBJ +//} -void BookmarkManager::saveBookmarks() +void BookmarkManager::refeshBookmarkMenu() { - QByteArray bookmarks; - QDataStream stream(&bookmarks, QIODevice::WriteOnly); + TRACE_OBJ + if (!bookmarkMenu) + return; - readBookmarksRecursive(treeModel->invisibleRootItem(), stream, 0); - helpEngine->setCustomValue(QLatin1String("Bookmarks"), bookmarks); -} + bookmarkMenu->clear(); -QStringList BookmarkManager::bookmarkFolders() const -{ - QStringList folders(tr("Bookmarks")); + //bookmarkMenu->addAction(tr("Manage Bookmarks..."), this, + // SLOT(manageBookmarks())); + bookmarkMenu->addAction(tr("Import..."), this, SLOT(importBookmarks())); + bookmarkMenu->addAction(tr("Export..."), this, SLOT(exportBookmarks())); + bookmarkMenu->addAction(tr("Add Bookmark..."), this, SLOT(addBookmark()), + QKeySequence(tr("Ctrl+D"))); + bookmarkMenu->addSeparator(); - QList<QStandardItem*>list = treeModel->findItems(QLatin1String("*"), - Qt::MatchWildcard | Qt::MatchRecursive, 0); + const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex()); + for (int i = 0; i < bookmarkModel->rowCount(root); ++i) + buildBookmarksMenu(bookmarkModel->index(i, 0, root), bookmarkMenu); - QString data; - foreach (const QStandardItem *item, list) { - data = item->data(Qt::UserRole + 10).toString(); - if (data == QLatin1String("Folder")) - folders << item->data(Qt::DisplayRole).toString(); - } - return folders; + connect(bookmarkMenu, SIGNAL(triggered(QAction*)), this, + SLOT(setSourceFromAction(QAction*))); } -QModelIndex BookmarkManager::addNewFolder(const QModelIndex &index) +void BookmarkManager::renameBookmark(const QModelIndex &index) { - QStandardItem *item = new QStandardItem(uniqueFolderName()); - item->setEditable(false); - item->setData(false, Qt::UserRole + 11); - item->setData(QLatin1String("Folder"), Qt::UserRole + 10); - item->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon)); - - if (index.isValid()) { - treeModel->itemFromIndex(index)->appendRow(item); - } else { - treeModel->appendRow(item); - } - return treeModel->indexFromItem(item); + // check if we should rename the "Bookmarks Menu", bail + if (!typeAndSearch && !bookmarkModel->parent(index).isValid()) + return; + + bookmarkModel->setItemsEditable(true); + bookmarkTreeView->edit(index); + bookmarkModel->setItemsEditable(false); } -void BookmarkManager::removeBookmarkItem(QTreeView *treeView, - const QModelIndex &index) +void BookmarkManager::importBookmarks() { - QStandardItem *item = treeModel->itemFromIndex(index); - if (item) { - QString data = index.data(Qt::UserRole + 10).toString(); - if (data == QLatin1String("Folder") && item->rowCount() > 0) { - int value = QMessageBox::question(treeView, tr("Remove"), - tr("You are going to delete a Folder, this will also<br>" - "remove it's content. Are you sure to continue?"), - QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); - - if (value == QMessageBox::Cancel) - return; - } + TRACE_OBJ + const QString &fileName = QFileDialog::getOpenFileName(0, tr("Open File"), + QDir::currentPath(), tr("Files (*.xbel)")); - if (data != QLatin1String("Folder")) { - QList<QStandardItem*>itemList = listModel->findItems(item->text()); - foreach (const QStandardItem *i, itemList) { - if (i->data(Qt::UserRole + 10) == data) { - listModel->removeRow(i->row()); - break; - } - } - } else { - removeBookmarkFolderItems(item); - } - treeModel->removeRow(item->row(), index.parent()); + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (file.open(QIODevice::ReadOnly)) { + XbelReader reader(bookmarkModel); + reader.readFromFile(&file); } } -void BookmarkManager::showBookmarkDialog(QWidget *parent, const QString &name, - const QString &url) +void BookmarkManager::exportBookmarks() { - BookmarkDialog dialog(this, name, url, parent); - dialog.exec(); -} + TRACE_OBJ + QString fileName = QFileDialog::getSaveFileName(0, tr("Save File"), + QLatin1String("untitled.xbel"), tr("Files (*.xbel)")); -void BookmarkManager::addNewBookmark(const QModelIndex &index, - const QString &name, const QString &url) -{ - QStandardItem *item = new QStandardItem(name); - item->setEditable(false); - item->setData(false, Qt::UserRole + 11); - item->setData(url, Qt::UserRole + 10); + const QLatin1String suffix(".xbel"); + if (!fileName.endsWith(suffix)) + fileName.append(suffix); - if (index.isValid()) - treeModel->itemFromIndex(index)->appendRow(item); - else - treeModel->appendRow(item); - listModel->appendRow(item->clone()); - emit bookmarksChanged(); + QFile file(fileName); + if (file.open(QIODevice::WriteOnly)) { + XbelWriter writer(bookmarkModel); + writer.writeToFile(&file); + } else { + QMessageBox::information(bookmarkTreeView, tr("Qt Assistant"), + tr("Unable to save bookmarks."), tr("OK")); + } } -void BookmarkManager::fillBookmarkMenu(QMenu *menu) +void BookmarkManager::setSourceFromAction(QAction *action) { - if (!menu || !treeModel) - return; + TRACE_OBJ + const QVariant &data = action->data(); - map.clear(); - fillBookmarkMenu(menu, treeModel->invisibleRootItem()); + if (data.canConvert<QUrl>()) + emit setSource(data.toUrl()); } -void BookmarkManager::fillBookmarkMenu(QMenu *menu, QStandardItem *root) +void BookmarkManager::setSourceFromIndex(const QModelIndex &index, bool newTab) { - for (int i = 0; i < root->rowCount(); ++i) { - QStandardItem *item = root->child(i); - if (item && item->data(Qt::UserRole + 10) - .toString() == QLatin1String("Folder")) { - QMenu* newMenu = menu->addMenu(folderIcon, item->text()); - if (item->rowCount() > 0) - fillBookmarkMenu(newMenu, item); - } else { - map.insert(menu->addAction(item->text()), item->index()); - } - } -} + TRACE_OBJ + QAbstractItemModel *base = bookmarkModel; + if (typeAndSearch) + base = typeAndSearchModel; -QUrl BookmarkManager::urlForAction(QAction* action) const -{ - if (map.contains(action)) { - const QModelIndex &index = map.value(action); - if (QStandardItem* item = treeModel->itemFromIndex(index)) - return QUrl(item->data(Qt::UserRole + 10).toString()); + if (base->data(index, UserRoleFolder).toBool()) + return; + + const QVariant &data = base->data(index, UserRoleUrl); + if (data.canConvert<QUrl>()) { + if (newTab) + emit setSourceInNewTab(data.toUrl()); + else + emit setSource(data.toUrl()); } - return QUrl(); } -void BookmarkManager::itemChanged(QStandardItem *item) +void BookmarkManager::customContextMenuRequested(const QPoint &point) { - if (renameItem != item) { - renameItem = item; - oldText = item->text(); + TRACE_OBJ + QModelIndex index = bookmarkTreeView->indexAt(point); + if (!index.isValid()) return; - } - if (item->text() != oldText) { - if (item->data(Qt::UserRole + 10).toString() != QLatin1String("Folder")) { - QList<QStandardItem*>itemList = listModel->findItems(oldText); - if (itemList.count() > 0) - itemList.at(0)->setText(item->text()); - } - } -} + // check if we should open the menu on "Bookmarks Menu", bail + if (!typeAndSearch && !bookmarkModel->parent(index).isValid()) + return; -void BookmarkManager::setupBookmarkModels() -{ - treeModel->clear(); - listModel->clear(); - - qint32 depth; - bool expanded; - QString name, type; - QList<int> lastDepths; - QList<QStandardItem*> parents; - - QByteArray ba = - helpEngine->customValue(QLatin1String("Bookmarks")).toByteArray(); - QDataStream stream(ba); - while (!stream.atEnd()) { - stream >> depth >> name >> type >> expanded; - - QStandardItem *item = new QStandardItem(name); - item->setEditable(false); - item->setData(type, Qt::UserRole + 10); - item->setData(expanded, Qt::UserRole + 11); - if (depth == 0) { - parents.clear(); lastDepths.clear(); - treeModel->appendRow(item); - parents << item; lastDepths << depth; - } else { - if (depth <= lastDepths.last()) { - while (depth <= lastDepths.last() && parents.count() > 0) { - parents.pop_back(); lastDepths.pop_back(); - } - } - parents.last()->appendRow(item); - if (type == QLatin1String("Folder")) { - parents << item; lastDepths << depth; - } - } + QAction *remove = 0; + QAction *rename = 0; + QAction *showItem = 0; + QAction *showItemInNewTab = 0; - if (type == QLatin1String("Folder")) - item->setIcon(folderIcon); - else - listModel->appendRow(item->clone()); + QMenu menu(QLatin1String("")); + if (!typeAndSearch && bookmarkModel->data(index, UserRoleFolder).toBool()) { + remove = menu.addAction(tr("Delete Folder")); + rename = menu.addAction(tr("Rename Folder")); + } else { + showItem = menu.addAction(tr("Show Bookmark")); + showItemInNewTab = menu.addAction(tr("Show Bookmark in New Tab")); + menu.addSeparator(); + remove = menu.addAction(tr("Delete Bookmark")); + rename = menu.addAction(tr("Rename Bookmark")); } -} -QString BookmarkManager::uniqueFolderName() const -{ - QString folderName = tr("New Folder"); - QList<QStandardItem*> list = treeModel->findItems(folderName, - Qt::MatchContains | Qt::MatchRecursive, 0); - if (!list.isEmpty()) { - QStringList names; - foreach (const QStandardItem *item, list) - names << item->text(); - - for (int i = 1; i <= names.count(); ++i) { - folderName = (tr("New Folder") + QLatin1String(" %1")).arg(i); - if (!names.contains(folderName)) - break; - } - } - return folderName; + QAction *pickedAction = menu.exec(bookmarkTreeView->mapToGlobal(point)); + if (pickedAction == rename) + renameBookmark(index); + else if (pickedAction == remove) + removeItem(index); + else if (pickedAction == showItem || pickedAction == showItemInNewTab) + setSourceFromIndex(index, pickedAction == showItemInNewTab); } -void BookmarkManager::removeBookmarkFolderItems(QStandardItem *item) +void BookmarkManager::focusInEvent() { - for (int j = 0; j < item->rowCount(); ++j) { - QStandardItem *child = item->child(j); - if (child->rowCount() > 0) - removeBookmarkFolderItems(child); - - QString data = child->data(Qt::UserRole + 10).toString(); - QList<QStandardItem*>itemList = listModel->findItems(child->text()); - foreach (const QStandardItem *i, itemList) { - if (i->data(Qt::UserRole + 10) == data) { - listModel->removeRow(i->row()); - break; - } - } - } + TRACE_OBJ + const QModelIndex &index = bookmarkTreeView->indexAt(QPoint(2, 2)); + if (index.isValid()) + bookmarkTreeView->setCurrentIndex(index); } -void BookmarkManager::readBookmarksRecursive(const QStandardItem *item, - QDataStream &stream, const qint32 depth) const +void BookmarkManager::textChanged(const QString &text) { - for (int j = 0; j < item->rowCount(); ++j) { - const QStandardItem *child = item->child(j); - stream << depth; - stream << child->data(Qt::DisplayRole).toString(); - stream << child->data(Qt::UserRole + 10).toString(); - stream << child->data(Qt::UserRole + 11).toBool(); - - if (child->rowCount() > 0) - readBookmarksRecursive(child, stream, (depth +1)); + TRACE_OBJ + if (!bookmarkWidget->ui.lineEdit->text().isEmpty()) { + if (!typeAndSearch) { + typeAndSearch = true; + bookmarkTreeView->setItemsExpandable(false); + bookmarkTreeView->setRootIsDecorated(false); + bookmarkTreeView->setModel(typeAndSearchModel); + } + typeAndSearchModel->setFilterRegExp(QRegExp(text)); + } else { + typeAndSearch = false; + bookmarkTreeView->setModel(bookmarkModel); + bookmarkTreeView->setItemsExpandable(true); + bookmarkTreeView->setRootIsDecorated(true); + bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView); } } diff --git a/tools/assistant/tools/assistant/bookmarkmanager.h b/tools/assistant/tools/assistant/bookmarkmanager.h index da36833..88342d5 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.h +++ b/tools/assistant/tools/assistant/bookmarkmanager.h @@ -38,178 +38,118 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - #ifndef BOOKMARKMANAGER_H #define BOOKMARKMANAGER_H -#include "ui_bookmarkdialog.h" - -#include <QtCore/QUrl> -#include <QtCore/QObject> -#include <QtCore/QString> -#include <QtCore/QByteArray> -#include <QtCore/QDataStream> - -#include <QtGui/QIcon> -#include <QtGui/QDialog> -#include <QtGui/QWidget> +#include <QtCore/QMutex> #include <QtGui/QTreeView> -#include <QtGui/QStandardItemModel> + +#include "ui_bookmarkwidget.h" QT_BEGIN_NAMESPACE -class QEvent; -class QLineEdit; -class QTreeView; -class QToolButton; -class QStandardItem; -class QHelpEngineCore; -class QAbstractItemModel; +class BookmarkModel; +class BookmarkFilterModel; +class QKeyEvent; class QSortFilterProxyModel; -class BookmarkManager; - -class BookmarkDialog : public QDialog +class BookmarkManager : public QObject { Q_OBJECT + class BookmarkWidget; + class BookmarkTreeView; + class BookmarkListView; + Q_DISABLE_COPY(BookmarkManager); public: - BookmarkDialog(BookmarkManager *manager, const QString &title, - const QString &url, QWidget *parent = 0); - ~BookmarkDialog(); + static BookmarkManager* instance(); + static void destroy(); -private slots: - void addAccepted(); - void addNewFolder(); - void toolButtonClicked(); - void itemChanged(QStandardItem *item); - void textChanged(const QString& string); - void selectBookmarkFolder(const QString &folderName); - void customContextMenuRequested(const QPoint &point); - void currentChanged(const QModelIndex& current); + QWidget* bookmarkDockWidget() const; + void takeBookmarksMenu(QMenu* menu); -private: - bool eventFilter(QObject *object, QEvent *e); +public slots: + void addBookmark(const QString &title, const QString &url); + +signals: + void escapePressed(); + void setSource(const QUrl &url); + void setSourceInNewTab(const QUrl &url); private: - QString m_url; - QString m_title; + BookmarkManager(); + ~BookmarkManager(); - QString oldText; - QStandardItem *renameItem; + void removeItem(const QModelIndex &index); + bool eventFilter(QObject *object, QEvent *event); + void buildBookmarksMenu(const QModelIndex &index, QMenu *menu); + void showBookmarkDialog(const QString &name, const QString &url); - Ui::BookmarkDialog ui; - BookmarkManager *bookmarkManager; - QSortFilterProxyModel *proxyModel; -}; +private slots: + void setupFinished(); -class TreeView : public QTreeView { - Q_OBJECT -public: - TreeView(QWidget* parent = 0) : QTreeView(parent) {} - void subclassKeyPressEvent(QKeyEvent* event) - { - QTreeView::keyPressEvent(event); - } -}; + void addBookmark(); + void removeBookmark(); +// void manageBookmarks(); + void refeshBookmarkMenu(); + void renameBookmark(const QModelIndex &index); -class BookmarkWidget : public QWidget -{ - Q_OBJECT + void importBookmarks(); + void exportBookmarks(); -public: - BookmarkWidget(BookmarkManager *manager, QWidget *parent = 0, - bool showButtons = true); - ~BookmarkWidget(); + void setSourceFromAction(QAction *action); + void setSourceFromIndex(const QModelIndex &index, bool newTab = false); -signals: - void addBookmark(); - void requestShowLink(const QUrl &url); - void escapePressed(); - -private slots: - void removeClicked(); - void filterChanged(); - void expand(const QModelIndex& index); - void activated(const QModelIndex &index); + void focusInEvent(); + void textChanged(const QString &text); void customContextMenuRequested(const QPoint &point); private: - void setup(bool showButtons); - void expandItems(); - void focusInEvent(QFocusEvent *e); - bool eventFilter(QObject *object, QEvent *event); + bool typeAndSearch; -private: - QRegExp regExp; - TreeView *treeView; - QLineEdit *searchField; - QToolButton *addButton; - QToolButton *removeButton; - BookmarkManager *bookmarkManager; - QSortFilterProxyModel* filterBookmarkModel; -}; + static QMutex mutex; + static BookmarkManager *bookmarkManager; -class BookmarkModel : public QStandardItemModel -{ - Q_OBJECT + QMenu *bookmarkMenu; -public: - BookmarkModel(int rows, int columns, QObject *parent = 0); - ~BookmarkModel(); + BookmarkModel *bookmarkModel; + BookmarkFilterModel *bookmarkFilterModel; + QSortFilterProxyModel *typeAndSearchModel; - Qt::DropActions supportedDropActions() const; - Qt::ItemFlags flags(const QModelIndex &index) const; + BookmarkWidget *bookmarkWidget; + BookmarkTreeView *bookmarkTreeView; }; -class BookmarkManager : public QObject +class BookmarkManager::BookmarkWidget : public QWidget { Q_OBJECT - public: - BookmarkManager(QHelpEngineCore* helpEngine); - ~BookmarkManager(); + BookmarkWidget(QWidget *parent = 0) + : QWidget(parent) { ui.setupUi(this); } + virtual ~BookmarkWidget() {} - BookmarkModel* treeBookmarkModel(); - BookmarkModel* listBookmarkModel(); - - void saveBookmarks(); - QStringList bookmarkFolders() const; - QModelIndex addNewFolder(const QModelIndex& index); - void removeBookmarkItem(QTreeView *treeView, const QModelIndex& index); - void showBookmarkDialog(QWidget* parent, const QString &name, - const QString &url); - void addNewBookmark(const QModelIndex& index, const QString &name, - const QString &url); - void setupBookmarkModels(); - - void fillBookmarkMenu(QMenu *menu); - QUrl urlForAction(QAction* action) const; + Ui::BookmarkWidget ui; signals: - void bookmarksChanged(); - -private slots: - void itemChanged(QStandardItem *item); + void focusInEvent(); private: - QString uniqueFolderName() const; - void removeBookmarkFolderItems(QStandardItem *item); - void readBookmarksRecursive(const QStandardItem *item, QDataStream &stream, - const qint32 depth) const; - void fillBookmarkMenu(QMenu *menu, QStandardItem *root); + void focusInEvent(QFocusEvent *event); +}; -private: - QString oldText; - QIcon folderIcon; - - BookmarkModel *treeModel; - BookmarkModel *listModel; - QStandardItem *renameItem; - QHelpEngineCore *helpEngine; - QMap<QAction*, QModelIndex> map; +class BookmarkManager::BookmarkTreeView : public QTreeView +{ + Q_OBJECT +public: + BookmarkTreeView(QWidget *parent = 0); + ~BookmarkTreeView() {} + + void subclassKeyPressEvent(QKeyEvent *event); + +private slots: + void setExpandedData(const QModelIndex &index); }; QT_END_NAMESPACE -#endif +#endif // BOOKMARKMANAGER_H diff --git a/tools/assistant/tools/assistant/bookmarkmodel.cpp b/tools/assistant/tools/assistant/bookmarkmodel.cpp new file mode 100644 index 0000000..c785f16 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkmodel.cpp @@ -0,0 +1,425 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "bookmarkmodel.h" +#include "bookmarkitem.h" + +#include <QtCore/QMimeData> +#include <QtCore/QStack> + +#include <QtGui/QApplication> +#include <QtGui/QStyle> +#include <QtGui/QTreeView> + +const QLatin1String MIMETYPE("application/bookmarks.assistant"); + +BookmarkModel::BookmarkModel() + : QAbstractItemModel() + , m_folder(false) + , m_editable(false) + , rootItem(0) +{ +} + +BookmarkModel::~BookmarkModel() +{ + delete rootItem; +} + +QByteArray +BookmarkModel::bookmarks() const +{ + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + + const QModelIndex &root = index(0,0, QModelIndex()); + for (int i = 0; i < rowCount(root); ++i) + collectItems(index(i, 0, root), 0, &stream); + + return ba; +} + +void +BookmarkModel::setBookmarks(const QByteArray &bookmarks) +{ + folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon); + bookmarkIcon = QIcon(QLatin1String(":/trolltech/assistant/images/bookmark.png")); + + 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); + + 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); + if (url == QLatin1String("Folder")) { + parents.top()->addChild(item); + parents.push(item); + } else { + parents.top()->addChild(item); + } + } + + cache.clear(); + const QModelIndex &root = index(0,0, QModelIndex()); + + setupCache(root); + cache.insert(static_cast<BookmarkItem*> (root.internalPointer()), root); +} + +void +BookmarkModel::setItemsEditable(bool editable) +{ + m_editable = editable; +} + +void +BookmarkModel::expandFoldersIfNeeeded(QTreeView *treeView) +{ + foreach (const QModelIndex &index, cache) + treeView->setExpanded(index, index.data(UserRoleExpanded).toBool()); +} + +QModelIndex +BookmarkModel::addItem(const QModelIndex &parent, bool isFolder) +{ + m_folder = isFolder; + QModelIndex next; + if (insertRow(rowCount(parent), parent)) + next = index(rowCount(parent) - 1, 0, parent); + m_folder = false; + + return next; +} + +bool +BookmarkModel::removeItem(const QModelIndex &index) +{ + if (!index.isValid()) + return false; + + QModelIndexList indexes; + if (rowCount(index) > 0) + indexes = collectItems(index); + indexes.append(index); + + foreach (const QModelIndex &itemToRemove, indexes) { + if (!removeRow(itemToRemove.row(), itemToRemove.parent())) + return false; + cache.remove(itemFromIndex(itemToRemove)); + } + return true; +} + +int +BookmarkModel::rowCount(const QModelIndex &index) const +{ + if (BookmarkItem *item = itemFromIndex(index)) + return item->childCount(); + return 0; +} + +int +BookmarkModel::columnCount(const QModelIndex &/*index*/) const +{ + return 2; +} + +QModelIndex +BookmarkModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + if (BookmarkItem *childItem = itemFromIndex(index)) { + if (BookmarkItem *parent = childItem->parent()) { + if (parent != rootItem) + return createIndex(parent->childNumber(), 0, parent); + } + } + return QModelIndex(); +} + +QModelIndex +BookmarkModel::index(int row, int column, const QModelIndex &index) const +{ + if (index.isValid() && (index.column() != 0 && index.column() != 1)) + return QModelIndex(); + + if (BookmarkItem *parent = itemFromIndex(index)) { + if (BookmarkItem *childItem = parent->child(row)) + return createIndex(row, column, childItem); + } + return QModelIndex(); +} + +Qt::DropActions +BookmarkModel::supportedDropActions () const +{ + return /* Qt::CopyAction | */Qt::MoveAction; +} + +Qt::ItemFlags +BookmarkModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + Qt::ItemFlags defaultFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + + if (m_editable) + defaultFlags |= Qt::ItemIsEditable; + + if (itemFromIndex(index) && index.data(UserRoleFolder).toBool() + && index.column() > 0) { + defaultFlags &= ~Qt::ItemIsEditable; + return defaultFlags | Qt::ItemIsDropEnabled; + } + + return defaultFlags | Qt::ItemIsDragEnabled; +} + +QVariant +BookmarkModel::data(const QModelIndex &index, int role) const +{ + if (index.isValid()) { + if (BookmarkItem *item = itemFromIndex(index)) { + switch (role) { + case Qt::EditRole: { + case Qt::DisplayRole: + if (index.data(UserRoleFolder).toBool() && index.column() == 1) + return QLatin1String(""); + return item->data(index.column()); + } break; + case Qt::DecorationRole: { + if (index.column() == 0) + return index.data(UserRoleFolder).toBool() + ? folderIcon : bookmarkIcon; + } break; + default:; + return item->data(role); + } + } + } + return QVariant(); +} + +bool +BookmarkModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + bool result = false; + if (role != Qt::EditRole && role != UserRoleExpanded) + return result; + + if (BookmarkItem *item = itemFromIndex(index)) { + if (role == Qt::EditRole) { + const bool isFolder = index.data(UserRoleFolder).toBool(); + if (!isFolder || (isFolder && index.column() == 0)) + result = item->setData(index.column(), value); + } else if (role == UserRoleExpanded) { + result = item->setData(UserRoleExpanded, value); + } + } + + if (result) + emit dataChanged(index, index); + return result; +} + +QVariant +BookmarkModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (rootItem && orientation == Qt::Horizontal && role == Qt::DisplayRole) + return rootItem->data(section); + return QVariant(); +} + +QModelIndex +BookmarkModel::indexFromItem(BookmarkItem *item) const +{ + return cache.value(item, QModelIndex()); +} + +BookmarkItem* +BookmarkModel::itemFromIndex(const QModelIndex &index) const +{ + if (index.isValid()) + return static_cast<BookmarkItem*>(index.internalPointer()); + return rootItem; +} + +bool +BookmarkModel::insertRows(int position, int rows, const QModelIndex &parent) +{ + if (!parent.data(UserRoleFolder).toBool()) + return false; + + bool success = false; + if (BookmarkItem *parentItem = itemFromIndex(parent)) { + beginInsertRows(parent, position, position + rows - 1); + success = parentItem->insertChildren(m_folder, position, rows); + if (success) { + const QModelIndex ¤t = index(position, 0, parent); + cache.insert(itemFromIndex(current), current); + } + endInsertRows(); + } + return success; +} + +bool +BookmarkModel::removeRows(int position, int rows, const QModelIndex &index) +{ + bool success = false; + if (BookmarkItem *parent = itemFromIndex(index)) { + beginRemoveRows(index, position, position + rows - 1); + success = parent->removeChildren(position, rows); + endRemoveRows(); + } + return success; +} + +QStringList +BookmarkModel::mimeTypes() const +{ + return QStringList() << MIMETYPE; +} + +QMimeData* +BookmarkModel::mimeData(const QModelIndexList &indexes) const +{ + if (indexes.isEmpty()) + return 0; + + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + + foreach (const QModelIndex &index, indexes) { + if (index.column() == 0) + collectItems(index, 0, &stream); + } + + QMimeData *mimeData = new QMimeData(); + mimeData->setData(MIMETYPE, data); + return mimeData; +} + +bool +BookmarkModel::dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) +{ + if (action == Qt::IgnoreAction) + return true; + + if (!data->hasFormat(MIMETYPE) || column > 0) + return false; + + QByteArray ba = data->data(MIMETYPE); + QDataStream stream(&ba, QIODevice::ReadOnly); + while (stream.atEnd()) + return false; + + qint32 depth; + bool expanded; + QString name, url; + while (!stream.atEnd()) { + stream >> depth >> name >> url >> expanded; + if (insertRow(qMax(0, row), parent)) { + const QModelIndex ¤t = index(qMax(0, row), 0, parent); + if (current.isValid()) { + BookmarkItem* item = itemFromIndex(current); + item->setData(DataVector() << name << url << expanded); + } + } + } + return true; +} + +void +BookmarkModel::setupCache(const QModelIndex &parent) +{ + const QModelIndexList &list = collectItems(parent); + foreach (const QModelIndex &index, list) + cache.insert(itemFromIndex(index), index); +} + +QModelIndexList +BookmarkModel::collectItems(const QModelIndex &parent) const +{ + QModelIndexList list; + for (int i = rowCount(parent) - 1; i >= 0 ; --i) { + const QModelIndex &next = index(i, 0, parent); + if (data(next, UserRoleFolder).toBool()) + list += collectItems(next); + list.append(next); + } + return list; +} + +void +BookmarkModel::collectItems(const QModelIndex &parent, qint32 depth, + QDataStream *stream) const +{ + if (parent.isValid()) { + *stream << depth; + *stream << parent.data().toString(); + *stream << parent.data(UserRoleUrl).toString(); + *stream << parent.data(UserRoleExpanded).toBool(); + + for (int i = 0; i < rowCount(parent); ++i) { + if (parent.data(UserRoleFolder).toBool()) + collectItems(index(i, 0 , parent), depth + 1, stream); + } + } +} diff --git a/tools/assistant/tools/assistant/bookmarkmodel.h b/tools/assistant/tools/assistant/bookmarkmodel.h new file mode 100644 index 0000000..6b2a0b8 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkmodel.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef BOOKMARKMODEL_H +#define BOOKMARKMODEL_H + +#include <QtCore/QAbstractItemModel> + +#include <QtGui/QIcon> + +QT_BEGIN_NAMESPACE + +class BookmarkItem; +class QMimeData; +class QTreeView; + +typedef QMap<BookmarkItem*, QPersistentModelIndex> ItemModelIndexCache; + +class BookmarkModel : public QAbstractItemModel +{ + Q_OBJECT +public: + BookmarkModel(); + ~BookmarkModel(); + + QByteArray bookmarks() const; + void setBookmarks(const QByteArray &bookmarks); + + void setItemsEditable(bool editable); + void expandFoldersIfNeeeded(QTreeView *treeView); + + QModelIndex addItem(const QModelIndex &parent, bool isFolder = false); + bool removeItem(const QModelIndex &index); + + int rowCount(const QModelIndex &index = QModelIndex()) const; + int columnCount(const QModelIndex &index = QModelIndex()) const; + + QModelIndex parent(const QModelIndex &index) const; + QModelIndex index(int row, int column, const QModelIndex &index) const; + + Qt::DropActions supportedDropActions () const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + + QModelIndex indexFromItem(BookmarkItem *item) const; + BookmarkItem *itemFromIndex(const QModelIndex &index) const; + + bool insertRows(int position, int rows, const QModelIndex &parent); + bool removeRows(int position, int rows, const QModelIndex &parent); + + QStringList mimeTypes() const; + QMimeData* mimeData(const QModelIndexList &indexes) const; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, + int column, const QModelIndex &parent); + +private: + void setupCache(const QModelIndex &parent); + QModelIndexList collectItems(const QModelIndex &parent) const; + void collectItems(const QModelIndex &parent, qint32 depth, + QDataStream *stream) const; + +private: + int columns; + bool m_folder; + bool m_editable; + QIcon folderIcon; + QIcon bookmarkIcon; + QTreeView *treeView; + BookmarkItem *rootItem; + ItemModelIndexCache cache; +}; + +QT_END_NAMESPACE + +#endif // BOOKMARKMODEL_H diff --git a/tools/assistant/tools/assistant/bookmarkwidget.ui b/tools/assistant/tools/assistant/bookmarkwidget.ui new file mode 100644 index 0000000..3015740 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkwidget.ui @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>BookmarkWidget</class> + <widget class="QWidget" name="BookmarkWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>235</width> + <height>606</height> + </rect> + </property> + <property name="windowTitle"> + <string>Bookmarks</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Filter:</string> + </property> + </widget> + </item> + <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> + </layout> + </item> + <item> + <widget class="QLineEdit" name="lineEdit"/> + </item> + <item> + <widget class="QStackedWidget" name="stackedWidget"/> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <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="QPushButton" name="add"> + <property name="text"> + <string>Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="remove"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index 0e4096b..03af06c 100644 --- a/tools/assistant/tools/assistant/centralwidget.cpp +++ b/tools/assistant/tools/assistant/centralwidget.cpp @@ -38,36 +38,30 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "centralwidget.h" +#include "findwidget.h" +#include "helpenginewrapper.h" #include "helpviewer.h" #include "searchwidget.h" #include "mainwindow.h" -#include "preferencesdialog.h" +#include "../shared/collectionconfiguration.h" -#include <QtCore/QDir> -#include <QtCore/QEvent> #include <QtCore/QTimer> -#include <QtGui/QMenu> -#include <QtGui/QLabel> +#include <QtGui/QApplication> +#include <QtGui/QKeyEvent> #include <QtGui/QLayout> +#include <QtGui/QMenu> #include <QtGui/QPrinter> -#include <QtGui/QLineEdit> -#include <QtGui/QCheckBox> #include <QtGui/QTabBar> #include <QtGui/QTabWidget> #include <QtGui/QToolButton> -#include <QtGui/QMouseEvent> -#include <QtGui/QSpacerItem> -#include <QtGui/QTextCursor> +#include <QtGui/QPageSetupDialog> #include <QtGui/QPrintDialog> -#include <QtGui/QApplication> -#include <QtGui/QTextDocumentFragment> #include <QtGui/QPrintPreviewDialog> -#include <QtGui/QPageSetupDialog> -#include <QtHelp/QHelpEngine> #include <QtHelp/QHelpSearchEngine> QT_BEGIN_NAMESPACE @@ -86,137 +80,20 @@ namespace { CentralWidget *staticCentralWidget = 0; } -FindWidget::FindWidget(QWidget *parent) - : QWidget(parent) - , appPalette(qApp->palette()) -{ - QHBoxLayout *hboxLayout = new QHBoxLayout(this); - QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); - -#ifndef Q_OS_MAC - hboxLayout->setMargin(0); - hboxLayout->setSpacing(6); - resourcePath.append(QLatin1String("win")); -#else - resourcePath.append(QLatin1String("mac")); -#endif - - toolClose = setupToolButton(QLatin1String(""), - resourcePath + QLatin1String("/closetab.png")); - hboxLayout->addWidget(toolClose); - - editFind = new QLineEdit(this); - hboxLayout->addWidget(editFind); - editFind->setMinimumSize(QSize(150, 0)); - connect(editFind, SIGNAL(textChanged(QString)), this, SLOT(updateButtons())); - - toolPrevious = setupToolButton(tr("Previous"), - resourcePath + QLatin1String("/previous.png")); - hboxLayout->addWidget(toolPrevious); - - toolNext = setupToolButton(tr("Next"), - resourcePath + QLatin1String("/next.png")); - hboxLayout->addWidget(toolNext); - - checkCase = new QCheckBox(tr("Case Sensitive"), this); - hboxLayout->addWidget(checkCase); - - checkWholeWords = new QCheckBox(tr("Whole words"), this); - hboxLayout->addWidget(checkWholeWords); -#if !defined(QT_NO_WEBKIT) - checkWholeWords->hide(); -#endif - labelWrapped = new QLabel(this); - labelWrapped->setScaledContents(true); - labelWrapped->setTextFormat(Qt::RichText); - labelWrapped->setMinimumSize(QSize(0, 20)); - labelWrapped->setMaximumSize(QSize(105, 20)); - labelWrapped->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter); - labelWrapped->setText(tr("<img src=\":/trolltech/assistant/images/wrap.png\"" - "> Search wrapped")); - hboxLayout->addWidget(labelWrapped); - - QSpacerItem *spacerItem = new QSpacerItem(20, 20, QSizePolicy::Expanding, - QSizePolicy::Minimum); - hboxLayout->addItem(spacerItem); - setMinimumWidth(minimumSizeHint().width()); - labelWrapped->hide(); - - updateButtons(); -} +// -- CentralWidget -FindWidget::~FindWidget() -{ -} -void FindWidget::hideEvent(QHideEvent* event) -{ -#if !defined(QT_NO_WEBKIT) - // TODO: remove this once webkit supports setting the palette - if (!event->spontaneous()) - qApp->setPalette(appPalette); -#else - Q_UNUSED(event); -#endif -} - -void FindWidget::showEvent(QShowEvent* event) -{ -#if !defined(QT_NO_WEBKIT) - // TODO: remove this once webkit supports setting the palette - if (!event->spontaneous()) { - QPalette p = appPalette; - p.setColor(QPalette::Inactive, QPalette::Highlight, - p.color(QPalette::Active, QPalette::Highlight)); - p.setColor(QPalette::Inactive, QPalette::HighlightedText, - p.color(QPalette::Active, QPalette::HighlightedText)); - qApp->setPalette(p); - } -#else - Q_UNUSED(event); -#endif -} - -void FindWidget::updateButtons() -{ - if (editFind->text().isEmpty()) { - toolPrevious->setEnabled(false); - toolNext->setEnabled(false); - } else { - toolPrevious->setEnabled(true); - toolNext->setEnabled(true); - } -} - -QToolButton* FindWidget::setupToolButton(const QString &text, const QString &icon) -{ - QToolButton *toolButton = new QToolButton(this); - - toolButton->setText(text); - toolButton->setAutoRaise(true); - toolButton->setIcon(QIcon(icon)); - toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - - return toolButton; -} - - -// -- - - -CentralWidget::CentralWidget(QHelpEngine *engine, MainWindow *parent) +CentralWidget::CentralWidget(MainWindow *parent) : QWidget(parent) , lastTabPage(0) - , collectionFile(engine->collectionFile()) - , findBar(0) , tabWidget(0) , findWidget(0) - , helpEngine(engine) , printer(0) , usesDefaultCollection(parent->usesDefaultCollection()) , m_searchWidget(0) { + TRACE_OBJ globalActionList.clear(); staticCentralWidget = this; QVBoxLayout *vboxLayout = new QVBoxLayout(this); @@ -253,20 +130,15 @@ CentralWidget::CentralWidget(QHelpEngine *engine, MainWindow *parent) vboxLayout->addWidget(tabWidget); - findBar = new QWidget(this); - findWidget = new FindWidget(findBar); - findBar->setMinimumHeight(findWidget->minimumSizeHint().height()); - findWidget->move(0, 0); - vboxLayout->addWidget(findBar); - findBar->hide(); - findWidget->editFind->installEventFilter(this); - - connect(findWidget->toolClose, SIGNAL(clicked()), findBar, SLOT(hide())); - connect(findWidget->toolNext, SIGNAL(clicked()), this, SLOT(findNext())); - connect(findWidget->editFind, SIGNAL(returnPressed()), this, SLOT(findNext())); - connect(findWidget->editFind, SIGNAL(textChanged(QString)), this, - SLOT(findCurrentText(QString))); - connect(findWidget->toolPrevious, SIGNAL(clicked()), this, SLOT(findPrevious())); + 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) { @@ -288,45 +160,40 @@ CentralWidget::CentralWidget(QHelpEngine *engine, MainWindow *parent) CentralWidget::~CentralWidget() { + TRACE_OBJ #ifndef QT_NO_PRINTER delete printer; #endif - QHelpEngineCore engine(collectionFile, 0); - if (!engine.setupData()) - return; - - QString zoomCount; - QString currentPages; - QLatin1Char separator('|'); + 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() + separator; - zoomCount += QString::number(viewer->zoom()) + separator; + currentPages << viewer->source().toString(); + zoomFactors << QString::number(viewer->zoom()); } } - engine.setCustomValue(QLatin1String("LastTabPage"), lastTabPage); - engine.setCustomValue(QLatin1String("LastShownPages"), currentPages); - engine.setCustomValue(QLatin1String("SearchWasAttached"), searchAttached); -#if !defined(QT_NO_WEBKIT) - engine.setCustomValue(QLatin1String("LastPagesZoomWebView"), zoomCount); -#else - engine.setCustomValue(QLatin1String("LastPagesZoomTextBrowser"), zoomCount); -#endif + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + helpEngine.setLastTabPage(tabWidget->currentIndex()); + helpEngine.setLastShownPages(currentPages); + helpEngine.setSearchWasAttached(searchAttached); + helpEngine.setLastZoomFactors(zoomFactors); } CentralWidget *CentralWidget::instance() { + TRACE_OBJ return staticCentralWidget; } void CentralWidget::newTab() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); #if !defined(QT_NO_WEBKIT) if (viewer && viewer->hasLoadFinished()) @@ -338,6 +205,7 @@ void CentralWidget::newTab() void CentralWidget::zoomIn() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (viewer) viewer->zoomIn(); @@ -348,6 +216,7 @@ void CentralWidget::zoomIn() void CentralWidget::zoomOut() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (viewer) viewer->zoomOut(); @@ -356,13 +225,9 @@ void CentralWidget::zoomOut() m_searchWidget->zoomOut(); } -void CentralWidget::findNext() -{ - find(findWidget->editFind->text(), true); -} - void CentralWidget::nextPage() { + TRACE_OBJ int index = tabWidget->currentIndex() + 1; if (index >= tabWidget->count()) index = 0; @@ -371,6 +236,7 @@ void CentralWidget::nextPage() void CentralWidget::resetZoom() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (viewer) viewer->resetZoom(); @@ -381,19 +247,16 @@ void CentralWidget::resetZoom() void CentralWidget::previousPage() { + TRACE_OBJ int index = tabWidget->currentIndex() -1; if (index < 0) index = tabWidget->count() -1; tabWidget->setCurrentIndex(index); } -void CentralWidget::findPrevious() -{ - find(findWidget->editFind->text(), false); -} - void CentralWidget::closeTab() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (!viewer|| tabWidget->count() == 1) return; @@ -404,12 +267,13 @@ void CentralWidget::closeTab() void CentralWidget::setSource(const QUrl &url) { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); HelpViewer *lastViewer = qobject_cast<HelpViewer*>(tabWidget->widget(lastTabPage)); if (!viewer && !lastViewer) { - viewer = new HelpViewer(helpEngine, this); + viewer = new HelpViewer(this); viewer->installEventFilter(this); lastTabPage = tabWidget->addTab(viewer, QString()); tabWidget->setCurrentIndex(lastTabPage); @@ -427,18 +291,14 @@ void CentralWidget::setSource(const QUrl &url) void CentralWidget::setupWidget() { - int option = helpEngine->customValue(QLatin1String("StartOption"), - ShowLastPages).toInt(); - + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + int option = helpEngine.startOption(); if (option != ShowLastPages) { QString homePage; - if (option == ShowHomePage) { - homePage = helpEngine->customValue(QLatin1String("defaultHomepage"), - QLatin1String("help")).toString(); - homePage = helpEngine->customValue(QLatin1String("homepage"), - homePage).toString(); - } - if (option == ShowBlankPage) + if (option == ShowHomePage) + homePage = helpEngine.homePage(); + else if (option == ShowBlankPage) homePage = QLatin1String("about:blank"); setSource(homePage); } else { @@ -448,11 +308,9 @@ void CentralWidget::setupWidget() void CentralWidget::setLastShownPages() { - const QLatin1String key("LastShownPages"); - QString value = helpEngine->customValue(key, QString()).toString(); - const QStringList lastShownPageList = value.split(QLatin1Char('|'), - QString::SkipEmptyParts); - + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + const QStringList lastShownPageList = helpEngine.lastShownPages(); const int pageCount = lastShownPageList.count(); if (pageCount == 0) { if (usesDefaultCollection) @@ -461,48 +319,39 @@ void CentralWidget::setLastShownPages() setSource(QUrl(QLatin1String("about:blank"))); return; } + QStringList zoomFactors = helpEngine.lastZoomFactors(); + while (zoomFactors.count() < pageCount) + zoomFactors.append(CollectionConfiguration::DefaultZoomFactor); -#if !defined(QT_NO_WEBKIT) - const QLatin1String zoom("LastPagesZoomWebView"); -#else - const QLatin1String zoom("LastPagesZoomTextBrowser"); -#endif - - value = helpEngine->customValue(zoom, QString()).toString(); - QVector<QString> zoomVector = value.split(QLatin1Char('|'), - QString::SkipEmptyParts).toVector(); - - const int zoomCount = zoomVector.count(); - zoomVector.insert(zoomCount, pageCount - zoomCount, QLatin1String("0.0")); - - QVector<QString>::const_iterator zIt = zoomVector.constBegin(); - QStringList::const_iterator it = lastShownPageList.constBegin(); - for (; it != lastShownPageList.constEnd(); ++it, ++zIt) - setSourceInNewTab((*it), (*zIt).toFloat()); - - const QLatin1String lastTab("LastTabPage"); - int tab = helpEngine->customValue(lastTab, 1).toInt(); - - const QLatin1String searchKey("SearchWasAttached"); const bool searchIsAttached = m_searchWidget->isAttached(); - const bool searchWasAttached = helpEngine->customValue(searchKey).toBool(); - - if (searchWasAttached && !searchIsAttached) - tabWidget->setCurrentIndex(--tab); + const bool searchWasAttached = helpEngine.searchWasAttached(); + int tabToShow = helpEngine.lastTabPage(); + if (searchWasAttached && !searchIsAttached && tabToShow != 0) + --tabToShow; else if (!searchWasAttached && searchIsAttached) - tabWidget->setCurrentIndex(++tab); - else - tabWidget->setCurrentIndex(tab); + ++tabToShow; + + for (int curTab = 0; curTab < pageCount; ++curTab) { + const QString &curFile = lastShownPageList.at(curTab); + if (helpEngine.findFile(curFile).isValid()) + setSourceInNewTab(curFile, zoomFactors.at(curTab).toFloat()); + else if (curTab + searchIsAttached <= tabToShow) + --tabToShow; + } + + tabWidget->setCurrentIndex(tabToShow); } bool CentralWidget::hasSelection() const { + TRACE_OBJ const HelpViewer *viewer = currentHelpViewer(); return viewer ? viewer->hasSelection() : false; } QUrl CentralWidget::currentSource() const { + TRACE_OBJ const HelpViewer *viewer = currentHelpViewer(); if (viewer) return viewer->source(); @@ -512,6 +361,7 @@ QUrl CentralWidget::currentSource() const QString CentralWidget::currentTitle() const { + TRACE_OBJ const HelpViewer *viewer = currentHelpViewer(); if (viewer) return viewer->documentTitle(); @@ -521,6 +371,7 @@ QString CentralWidget::currentTitle() const void CentralWidget::copySelection() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (viewer) viewer->copy(); @@ -528,13 +379,13 @@ void CentralWidget::copySelection() void CentralWidget::showTextSearch() { - findBar->show(); - findWidget->editFind->selectAll(); - findWidget->editFind->setFocus(Qt::ShortcutFocusReason); + TRACE_OBJ + findWidget->show(); } void CentralWidget::initPrinter() { + TRACE_OBJ #ifndef QT_NO_PRINTER if (!printer) printer = new QPrinter(QPrinter::HighResolution); @@ -543,6 +394,7 @@ void CentralWidget::initPrinter() void CentralWidget::print() { + TRACE_OBJ #ifndef QT_NO_PRINTER HelpViewer *viewer = currentHelpViewer(); if (!viewer) @@ -550,23 +402,23 @@ void CentralWidget::print() initPrinter(); - QPrintDialog *dlg = new QPrintDialog(printer, this); + QPrintDialog dlg(printer, this); #if defined(QT_NO_WEBKIT) if (viewer->textCursor().hasSelection()) - dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection); + dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection); #endif - dlg->addEnabledOption(QAbstractPrintDialog::PrintPageRange); - dlg->addEnabledOption(QAbstractPrintDialog::PrintCollateCopies); - dlg->setWindowTitle(tr("Print Document")); - if (dlg->exec() == QDialog::Accepted) { + dlg.addEnabledOption(QAbstractPrintDialog::PrintPageRange); + dlg.addEnabledOption(QAbstractPrintDialog::PrintCollateCopies); + dlg.setWindowTitle(tr("Print Document")); + if (dlg.exec() == QDialog::Accepted) { viewer->print(printer); } - delete dlg; #endif } void CentralWidget::printPreview() { + TRACE_OBJ #ifndef QT_NO_PRINTER initPrinter(); QPrintPreviewDialog preview(printer, this); @@ -578,6 +430,7 @@ void CentralWidget::printPreview() void CentralWidget::printPreview(QPrinter *p) { + TRACE_OBJ #ifndef QT_NO_PRINTER HelpViewer *viewer = currentHelpViewer(); if (viewer) @@ -587,6 +440,7 @@ void CentralWidget::printPreview(QPrinter *p) void CentralWidget::pageSetup() { + TRACE_OBJ #ifndef QT_NO_PRINTER initPrinter(); QPageSetupDialog dlg(printer); @@ -596,11 +450,13 @@ void CentralWidget::pageSetup() bool CentralWidget::isHomeAvailable() const { + TRACE_OBJ return currentHelpViewer() ? true : false; } void CentralWidget::home() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (viewer) viewer->home(); @@ -608,6 +464,7 @@ void CentralWidget::home() bool CentralWidget::isForwardAvailable() const { + TRACE_OBJ const HelpViewer *viewer = currentHelpViewer(); if (viewer) return viewer->isForwardAvailable(); @@ -617,6 +474,7 @@ bool CentralWidget::isForwardAvailable() const void CentralWidget::forward() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (viewer) viewer->forward(); @@ -624,6 +482,7 @@ void CentralWidget::forward() bool CentralWidget::isBackwardAvailable() const { + TRACE_OBJ const HelpViewer *viewer = currentHelpViewer(); if (viewer) return viewer->isBackwardAvailable(); @@ -633,6 +492,7 @@ bool CentralWidget::isBackwardAvailable() const void CentralWidget::backward() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (viewer) viewer->backward(); @@ -641,16 +501,19 @@ void CentralWidget::backward() QList<QAction*> CentralWidget::globalActions() const { + TRACE_OBJ return globalActionList; } void CentralWidget::setGlobalActions(const QList<QAction*> &actions) { + TRACE_OBJ globalActionList = actions; } void CentralWidget::setSourceInNewTab(const QUrl &url, qreal zoom) { + TRACE_OBJ HelpViewer *viewer; #if defined(QT_NO_WEBKIT) @@ -659,7 +522,7 @@ void CentralWidget::setSourceInNewTab(const QUrl &url, qreal zoom) return; #endif - viewer = new HelpViewer(helpEngine, this); + viewer = new HelpViewer(this); viewer->installEventFilter(this); viewer->setSource(url); viewer->setFocus(Qt::OtherFocusReason); @@ -683,7 +546,8 @@ void CentralWidget::setSourceInNewTab(const QUrl &url, qreal zoom) HelpViewer *CentralWidget::newEmptyTab() { - HelpViewer *viewer = new HelpViewer(helpEngine, this); + TRACE_OBJ + HelpViewer *viewer = new HelpViewer(this); viewer->installEventFilter(this); viewer->setFocus(Qt::OtherFocusReason); #if defined(QT_NO_WEBKIT) @@ -695,13 +559,9 @@ HelpViewer *CentralWidget::newEmptyTab() return viewer; } -void CentralWidget::findCurrentText(const QString &text) -{ - find(text, true); -} - void CentralWidget::connectSignals() { + TRACE_OBJ const HelpViewer *viewer = currentHelpViewer(); if (viewer) { connect(viewer, SIGNAL(copyAvailable(bool)), this, @@ -721,11 +581,13 @@ void CentralWidget::connectSignals() HelpViewer *CentralWidget::currentHelpViewer() const { + TRACE_OBJ return qobject_cast<HelpViewer*>(tabWidget->currentWidget()); } void CentralWidget::activateTab(bool onlyHelpViewer) { + TRACE_OBJ if (currentHelpViewer()) { currentHelpViewer()->setFocus(); } else { @@ -739,6 +601,7 @@ void CentralWidget::activateTab(bool onlyHelpViewer) void CentralWidget::setTabTitle(const QUrl &url) { + TRACE_OBJ Q_UNUSED(url) #if !defined(QT_NO_WEBKIT) QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); @@ -760,6 +623,7 @@ void CentralWidget::setTabTitle(const QUrl &url) void CentralWidget::currentPageChanged(int index) { + TRACE_OBJ const HelpViewer *viewer = currentHelpViewer(); if (viewer) lastTabPage = index; @@ -775,6 +639,7 @@ void CentralWidget::currentPageChanged(int index) void CentralWidget::showTabBarContextMenu(const QPoint &point) { + TRACE_OBJ HelpViewer *viewer = helpViewerFromTabPosition(tabWidget, point); if (!viewer) return; @@ -822,11 +687,12 @@ void CentralWidget::showTabBarContextMenu(const QPoint &point) } if (pickedAction == newBookmark) - emit addNewBookmark(viewer->documentTitle(), viewer->source().toString()); + emit addBookmark(viewer->documentTitle(), viewer->source().toString()); } bool CentralWidget::eventFilter(QObject *object, QEvent *e) { + TRACE_OBJ if (e->type() == QEvent::KeyPress) { QKeyEvent *ke = static_cast<QKeyEvent*>(e); switch (ke->key()) { @@ -834,14 +700,6 @@ bool CentralWidget::eventFilter(QObject *object, QEvent *e) return QWidget::eventFilter(object, e); } break; - case Qt::Key_Escape: { - if (findWidget->editFind == object) { - findBar->hide(); - if (HelpViewer *viewer = currentHelpViewer()) - viewer->setFocus(); - } - } break; - case Qt::Key_Backspace: { HelpViewer *viewer = currentHelpViewer(); if (viewer == object) { @@ -882,43 +740,51 @@ bool CentralWidget::eventFilter(QObject *object, QEvent *e) void CentralWidget::keyPressEvent(QKeyEvent *e) { + TRACE_OBJ const QString &text = e->text(); if (text.startsWith(QLatin1Char('/'))) { - if (!findBar->isVisible()) { - findBar->show(); - findWidget->editFind->clear(); + if (!findWidget->isVisible()) { + findWidget->showAndClear(); } else { - findWidget->editFind->selectAll(); + findWidget->show(); } - findWidget->editFind->setFocus(); - return; + } else { + QWidget::keyPressEvent(e); } - QWidget::keyPressEvent(e); } -void CentralWidget::find(const QString &ttf, bool forward) +void CentralWidget::findNext() { - QPalette p = findWidget->editFind->palette(); - p.setColor(QPalette::Active, QPalette::Base, Qt::white); + find(findWidget->text(), true); +} - bool found = false; +void CentralWidget::findPrevious() +{ + TRACE_OBJ + find(findWidget->text(), false); +} +void CentralWidget::find(const QString &ttf, bool forward) +{ + TRACE_OBJ + bool found = false; #if defined(QT_NO_WEBKIT) found = findInTextBrowser(ttf, forward); #else found = findInWebPage(ttf, forward); #endif - if (!found && !ttf.isEmpty()) - p.setColor(QPalette::Active, QPalette::Base, QColor(255, 102, 102)); + if (!found && ttf.isEmpty()) + found = true; // the line edit is empty, no need to mark it red... if (!findWidget->isVisible()) findWidget->show(); - findWidget->editFind->setPalette(p); + findWidget->setPalette(found); } bool CentralWidget::findInWebPage(const QString &ttf, bool forward) { + TRACE_OBJ #if !defined(QT_NO_WEBKIT) if (HelpViewer *viewer = currentHelpViewer()) { bool found = false; @@ -927,21 +793,23 @@ bool CentralWidget::findInWebPage(const QString &ttf, bool forward) if (!forward) options |= QWebPage::FindBackward; - if (findWidget->checkCase->isChecked()) + if (findWidget->caseSensitive()) options |= QWebPage::FindCaseSensitively; found = viewer->findText(ttf, options); - findWidget->labelWrapped->hide(); + findWidget->setTextWrappedVisible(false); if (!found) { options |= QWebPage::FindWrapsAroundDocument; found = viewer->findText(ttf, options); if (found) - findWidget->labelWrapped->show(); + 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; @@ -949,12 +817,16 @@ bool CentralWidget::findInWebPage(const QString &ttf, bool forward) // this needs to stay, case for active search results page return findInTextBrowser(ttf, forward); +#else + Q_UNUSED(ttf); + Q_UNUSED(forward); #endif return false; } bool CentralWidget::findInTextBrowser(const QString &ttf, bool forward) { + TRACE_OBJ QTextBrowser *browser = qobject_cast<QTextBrowser*>(currentHelpViewer()); if (tabWidget->currentWidget() == m_searchWidget) browser = qFindChild<QTextBrowser*>(m_searchWidget); @@ -978,13 +850,10 @@ bool CentralWidget::findInTextBrowser(const QString &ttf, bool forward) if (!forward) options |= QTextDocument::FindBackward; - if (findWidget->checkCase->isChecked()) + if (findWidget->caseSensitive()) options |= QTextDocument::FindCaseSensitively; - if (findWidget->checkWholeWords->isChecked()) - options |= QTextDocument::FindWholeWords; - - findWidget->labelWrapped->hide(); + findWidget->setTextWrappedVisible(false); bool found = true; QTextCursor newCursor = doc->find(ttf, cursor, options); @@ -997,7 +866,7 @@ bool CentralWidget::findInTextBrowser(const QString &ttf, bool forward) found = false; newCursor = cursor; } else { - findWidget->labelWrapped->show(); + findWidget->setTextWrappedVisible(true); } } browser->setTextCursor(newCursor); @@ -1006,6 +875,7 @@ bool CentralWidget::findInTextBrowser(const QString &ttf, bool forward) void CentralWidget::updateBrowserFont() { + TRACE_OBJ QFont font; bool searchAttached = searchWidgetAttached(); if (searchAttached) { @@ -1019,8 +889,14 @@ void CentralWidget::updateBrowserFont() setBrowserFontFor(tabWidget->widget(i), font); } +bool CentralWidget::searchWidgetAttached() const +{ + return m_searchWidget && m_searchWidget->isAttached(); +} + void CentralWidget::createSearchWidget(QHelpSearchEngine *searchEngine) { + TRACE_OBJ if (m_searchWidget) return; @@ -1037,8 +913,9 @@ void CentralWidget::createSearchWidget(QHelpSearchEngine *searchEngine) void CentralWidget::activateSearchWidget(bool updateLastTabPage) { + TRACE_OBJ if (!m_searchWidget) - createSearchWidget(helpEngine->searchEngine()); + createSearchWidget(HelpEngineWrapper::instance().searchEngine()); if (!m_searchWidget->isAttached()) { tabWidget->insertTab(0, m_searchWidget, tr("Search")); @@ -1054,6 +931,7 @@ void CentralWidget::activateSearchWidget(bool updateLastTabPage) void CentralWidget::removeSearchWidget() { + TRACE_OBJ if (searchWidgetAttached()) { tabWidget->removeTab(0); m_searchWidget->setAttached(false); @@ -1062,6 +940,7 @@ void CentralWidget::removeSearchWidget() int CentralWidget::availableHelpViewer() const { + TRACE_OBJ int count = tabWidget->count(); if (searchWidgetAttached()) count--; @@ -1070,6 +949,7 @@ int CentralWidget::availableHelpViewer() const bool CentralWidget::enableTabCloseAction() const { + TRACE_OBJ int minTabCount = 1; if (searchWidgetAttached()) minTabCount = 2; @@ -1079,6 +959,7 @@ bool CentralWidget::enableTabCloseAction() const QString CentralWidget::quoteTabTitle(const QString &title) const { + TRACE_OBJ QString s = title; return s.replace(QLatin1Char('&'), QLatin1String("&&")); } @@ -1086,6 +967,7 @@ QString CentralWidget::quoteTabTitle(const QString &title) const void CentralWidget::setSourceFromSearch(const QUrl &url) { + TRACE_OBJ setSource(url); #if defined(QT_NO_WEBKIT) highlightSearchTerms(); @@ -1098,6 +980,7 @@ CentralWidget::setSourceFromSearch(const QUrl &url) void CentralWidget::setSourceFromSearchInNewTab(const QUrl &url) { + TRACE_OBJ setSourceInNewTab(url); #if defined(QT_NO_WEBKIT) highlightSearchTerms(); @@ -1110,11 +993,13 @@ CentralWidget::setSourceFromSearchInNewTab(const QUrl &url) void CentralWidget::highlightSearchTerms() { + TRACE_OBJ HelpViewer *viewer = currentHelpViewer(); if (!viewer) return; - QHelpSearchEngine *searchEngine = helpEngine->searchEngine(); + QHelpSearchEngine *searchEngine = + HelpEngineWrapper::instance().searchEngine(); QList<QHelpSearchQuery> queryList = searchEngine->query(); QStringList terms; @@ -1174,8 +1059,33 @@ CentralWidget::highlightSearchTerms() #endif } + +void CentralWidget::closeOrReloadTabs(const QList<int> &indices, bool tryReload) +{ + 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"))); +} + void CentralWidget::closeTabAt(int index) { + TRACE_OBJ HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(index)); tabWidget->removeTab(index); QTimer::singleShot(0, viewer, SLOT(deleteLater())); @@ -1183,8 +1093,9 @@ void CentralWidget::closeTabAt(int index) QMap<int, QString> CentralWidget::currentSourceFileList() const { + TRACE_OBJ QMap<int, QString> sourceList; - for (int i = 1; i < tabWidget->count(); ++i) { + 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()); @@ -1194,8 +1105,9 @@ QMap<int, QString> CentralWidget::currentSourceFileList() const void CentralWidget::getBrowserFontFor(QWidget *viewer, QFont *font) { - const QLatin1String key("useBrowserFont"); - if (!helpEngine->customValue(key, false).toBool()) { + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + if (!helpEngine.usesBrowserFont()) { *font = qApp->font(); // case for QTextBrowser and SearchWidget #if !defined(QT_NO_WEBKIT) QWebView *view = qobject_cast<QWebView*> (viewer); @@ -1206,13 +1118,13 @@ void CentralWidget::getBrowserFontFor(QWidget *viewer, QFont *font) } #endif } else { - *font = qVariantValue<QFont>(helpEngine->customValue( - QLatin1String("browserFont"))); + *font = helpEngine.browserFont(); } } void CentralWidget::setBrowserFontFor(QWidget *widget, const QFont &font) { + TRACE_OBJ #if !defined(QT_NO_WEBKIT) QWebView *view = qobject_cast<QWebView*> (widget); if (view) { diff --git a/tools/assistant/tools/assistant/centralwidget.h b/tools/assistant/tools/assistant/centralwidget.h index 9e32985..6c3e93c 100644 --- a/tools/assistant/tools/assistant/centralwidget.h +++ b/tools/assistant/tools/assistant/centralwidget.h @@ -38,78 +38,27 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - #ifndef CENTRALWIDGET_H #define CENTRALWIDGET_H #include <QtCore/QUrl> -#include <QtCore/QPoint> -#include <QtCore/QObject> - #include <QtGui/QWidget> -#include "searchwidget.h" - QT_BEGIN_NAMESPACE -class QEvent; -class QLabel; -class QAction; -class QCheckBox; -class QLineEdit; -class QTextBrowser; -class QToolButton; - +class FindWidget; class HelpViewer; -class QTabWidget; -class QHelpEngine; -class CentralWidget; -class PrintHelper; class MainWindow; - class QHelpSearchEngine; - -class FindWidget : public QWidget -{ - Q_OBJECT - -public: - FindWidget(QWidget *parent = 0); - ~FindWidget(); - -signals: - void findNext(); - void findPrevious(); - -protected: - void hideEvent(QHideEvent* event); - void showEvent(QShowEvent * event); - -private slots: - void updateButtons(); - -private: - QToolButton* setupToolButton(const QString &text, const QString &icon); - -private: - QLineEdit *editFind; - QCheckBox *checkCase; - QLabel *labelWrapped; - QToolButton *toolNext; - QToolButton *toolClose; - QToolButton *toolPrevious; - QCheckBox *checkWholeWords; - - QPalette appPalette; - friend class CentralWidget; -}; +class QTabWidget; +class SearchWidget; class CentralWidget : public QWidget { Q_OBJECT public: - CentralWidget(QHelpEngine *engine, MainWindow *parent); + CentralWidget(MainWindow *parent); ~CentralWidget(); void setupWidget(); @@ -122,11 +71,8 @@ public: QList<QAction*> globalActions() const; void setGlobalActions(const QList<QAction*> &actions); HelpViewer *currentHelpViewer() const; - void activateTab(bool onlyHelpViewer = false); - bool searchWidgetAttached() const { - return m_searchWidget && m_searchWidget->isAttached(); - } + bool searchWidgetAttached() const; void createSearchWidget(QHelpSearchEngine *searchEngine); void activateSearchWidget(bool updateLastTabPage = false); void removeSearchWidget(); @@ -134,6 +80,7 @@ public: int availableHelpViewer() const; bool enableTabCloseAction() const; + void closeOrReloadTabs(const QList<int> &indices, bool tryReload); void closeTabAt(int index); QMap<int, QString> currentSourceFileList() const; @@ -142,11 +89,9 @@ public: public slots: void zoomIn(); void zoomOut(); - void findNext(); void nextPage(); void resetZoom(); void previousPage(); - void findPrevious(); void copySelection(); void showTextSearch(); void print(); @@ -155,12 +100,17 @@ public slots: void updateBrowserFont(); void setSource(const QUrl &url); void setSourceInNewTab(const QUrl &url, qreal zoom = 0.0); - void findCurrentText(const QString &text); HelpViewer *newEmptyTab(); void home(); void forward(); void backward(); + void activateTab(bool onlyHelpViewer = false); + + void findNext(); + void findPrevious(); + void find(const QString &text, bool forward); + signals: void currentViewerChanged(); void copyAvailable(bool yes); @@ -168,7 +118,7 @@ signals: void highlighted(const QString &link); void forwardAvailable(bool available); void backwardAvailable(bool available); - void addNewBookmark(const QString &title, const QString &url); + void addBookmark(const QString &title, const QString &url); protected: void keyPressEvent(QKeyEvent *); @@ -187,7 +137,6 @@ private slots: private: void connectSignals(); bool eventFilter(QObject *object, QEvent *e); - void find(const QString &ttf, bool forward); bool findInWebPage(const QString &ttf, bool forward); bool findInTextBrowser(const QString &ttf, bool forward); void initPrinter(); @@ -199,13 +148,10 @@ private: private: int lastTabPage; - QString collectionFile; QList<QAction*> globalActionList; - QWidget *findBar; QTabWidget *tabWidget; FindWidget *findWidget; - QHelpEngine *helpEngine; QPrinter *printer; bool usesDefaultCollection; diff --git a/tools/assistant/tools/assistant/cmdlineparser.cpp b/tools/assistant/tools/assistant/cmdlineparser.cpp index 38814a5..bbc0c37 100644 --- a/tools/assistant/tools/assistant/cmdlineparser.cpp +++ b/tools/assistant/tools/assistant/cmdlineparser.cpp @@ -38,29 +38,17 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include <QtCore/QFileInfo> +#include <QtCore/QStringBuilder> #include <QtGui/QMessageBox> #include "cmdlineparser.h" QT_BEGIN_NAMESPACE -#define CHECK_NEXT_ARG \ - ++i < arguments.count() && !arguments.at(i).startsWith(QLatin1String("-")) - -CmdLineParser::CmdLineParser() - : m_enableRemoteControl(false), - m_contents(Untouched), - m_index(Untouched), - m_bookmarks(Untouched), - m_search(Untouched), - m_register(None), - m_removeSearchIndex(false), - m_copy(false), - m_quiet(false) -{ - m_helpMessage = QLatin1String( +const QString CmdLineParser::m_helpMessage = QLatin1String( "Usage: assistant [Options]\n\n" "-collectionFile file Uses the specified collection\n" " file instead of the default one\n" @@ -85,156 +73,72 @@ CmdLineParser::CmdLineParser() " file.\n" "-setCurrentFilter filter Set the filter as the active filter.\n" "-remove-search-index Removes the full text search index.\n" + "-rebuild-search-index Re-builds the full text search index (potentially slow).\n" "-quiet Does not display any error or\n" " status message.\n" "-help Displays this help.\n" ); -} -CmdLineParser::Result CmdLineParser::parse(const QStringList &arguments) -{ - QString error; - bool showHelp = false; - for (int j=1; j<arguments.count(); ++j) { - if (arguments.at(j).toLower() == QLatin1String("-quiet")) { +CmdLineParser::CmdLineParser(const QStringList &arguments) + : m_pos(0), + m_enableRemoteControl(false), + m_contents(Untouched), + m_index(Untouched), + m_bookmarks(Untouched), + m_search(Untouched), + m_register(None), + m_removeSearchIndex(false), + m_rebuildSearchIndex(false), + m_quiet(false) +{ + TRACE_OBJ + for (int i = 1; i < arguments.count(); ++i) { + const QString &arg = arguments.at(i); + if (arg.toLower() == "-quiet") m_quiet = true; - break; - } + else + m_arguments.append(arg); } +} - for (int i=1; i<arguments.count(); ++i) { - QString arg = arguments.at(i).toLower(); - if (arg == QLatin1String("-collectionfile")) { - if (CHECK_NEXT_ARG) { - m_collectionFile = getFileName(arguments.at(i)); - if (m_collectionFile.isEmpty()) { - error = QObject::tr("The specified collection file does not exist!"); - break; - } - } else { - error = QObject::tr("Missing collection file!"); - break; - } - } else if (arg == QLatin1String("-showurl")) { - if (CHECK_NEXT_ARG) { - QUrl url(arguments.at(i)); - if (url.isValid()) { - m_url = url; - } else { - error = QObject::tr("Invalid URL!"); - break; - } - } else { - error = QObject::tr("Missing URL!"); - break; - } - } else if (arg == QLatin1String("-enableremotecontrol")) { +CmdLineParser::Result CmdLineParser::parse() +{ + TRACE_OBJ + bool showHelp = false; + + while (m_error.isEmpty() && hasMoreArgs()) { + const QString &arg = nextArg().toLower(); + if (arg == QLatin1String("-collectionfile")) + handleCollectionFileOption(); + else if (arg == QLatin1String("-showurl")) + handleShowUrlOption(); + else if (arg == QLatin1String("-enableremotecontrol")) m_enableRemoteControl = true; - } else if (arg == QLatin1String("-show")) { - if (CHECK_NEXT_ARG) { - arg = arguments.at(i).toLower(); - if (arg == QLatin1String("contents")) { - m_contents = Show; - } else if (arg == QLatin1String("index")) { - m_index = Show; - } else if (arg == QLatin1String("bookmarks")) { - m_bookmarks = Show; - } else if (arg == QLatin1String("search")) { - m_search = Show; - } else { - error = QObject::tr("Unknown widget: %1").arg(arg); - break; - } - } else { - error = QObject::tr("Missing widget!"); - break; - } - } else if (arg == QLatin1String("-hide")) { - if (CHECK_NEXT_ARG) { - arg = arguments.at(i).toLower(); - if (arg == QLatin1String("contents")) { - m_contents = Hide; - } else if (arg == QLatin1String("index")) { - m_index = Hide; - } else if (arg == QLatin1String("bookmarks")) { - m_bookmarks = Hide; - } else if (arg == QLatin1String("search")) { - m_search = Hide; - } else { - error = QObject::tr("Unknown widget: %1").arg(arg); - break; - } - } else { - error = QObject::tr("Missing widget!"); - break; - } - } else if (arg == QLatin1String("-activate")) { - if (CHECK_NEXT_ARG) { - arg = arguments.at(i).toLower(); - if (arg == QLatin1String("contents")) { - m_contents = Activate; - } else if (arg == QLatin1String("index")) { - m_index = Activate; - } else if (arg == QLatin1String("bookmarks")) { - m_bookmarks = Activate; - } else if (arg == QLatin1String("search")) { - m_search = Activate; - } else { - error = QObject::tr("Unknown widget: %1").arg(arg); - break; - } - } else { - error = QObject::tr("Missing widget!"); - break; - } - } else if (arg == QLatin1String("-register")) { - if (CHECK_NEXT_ARG) { - m_helpFile = getFileName(arguments.at(i)); - if (m_helpFile.isEmpty()) { - error = QObject::tr("The specified Qt help file does not exist!"); - break; - } - m_register = Register; - } else { - error = QObject::tr("Missing help file!"); - break; - } - } else if (arg == QLatin1String("-unregister")) { - if (CHECK_NEXT_ARG) { - m_helpFile = getFileName(arguments.at(i)); - if (m_helpFile.isEmpty()) { - error = QObject::tr("The specified Qt help file does not exist!"); - break; - } - m_register = Unregister; - } else { - error = QObject::tr("Missing help file!"); - break; - } - } else if (arg == QLatin1String("-setcurrentfilter")) { - if (CHECK_NEXT_ARG) { - m_currentFilter = arguments.at(i); - } else { - error = QObject::tr("Missing filter argument!"); - break; - } - } else if (arg == QLatin1String("-remove-search-index")) { + else if (arg == QLatin1String("-show")) + handleShowOption(); + else if (arg == QLatin1String("-hide")) + handleHideOption(); + else if (arg == QLatin1String("-activate")) + handleActivateOption(); + else if (arg == QLatin1String("-register")) + handleRegisterOption(); + else if (arg == QLatin1String("-unregister")) + handleUnregisterOption(); + else if (arg == QLatin1String("-setcurrentfilter")) + handleSetCurrentFilterOption(); + else if (arg == QLatin1String("-remove-search-index")) m_removeSearchIndex = true; - } else if (arg == QLatin1String("-quiet")) { - continue; - } else if (arg == QLatin1String("-help")) { + else if (arg == QLatin1String("-rebuild-search-index")) + m_rebuildSearchIndex = true; + else if (arg == QLatin1String("-help")) showHelp = true; - } else if (arg == QLatin1String("-copy")) { - m_copy = true; - } else { - error = QObject::tr("Unknown option: %1").arg(arg); - break; - } + else + m_error = tr("Unknown option: %1").arg(arg); } - if (!error.isEmpty()) { - showMessage(error + QLatin1String("\n\n\n") + m_helpMessage, true); + if (!m_error.isEmpty()) { + showMessage(m_error + QLatin1String("\n\n\n") + m_helpMessage, true); return Error; } else if (showHelp) { showMessage(m_helpMessage, false); @@ -243,8 +147,125 @@ CmdLineParser::Result CmdLineParser::parse(const QStringList &arguments) return Ok; } +bool CmdLineParser::hasMoreArgs() const +{ + TRACE_OBJ + return m_pos < m_arguments.count(); +} + +const QString &CmdLineParser::nextArg() +{ + TRACE_OBJ + Q_ASSERT(hasMoreArgs()); + return m_arguments.at(m_pos++); +} + +void CmdLineParser::handleCollectionFileOption() +{ + TRACE_OBJ + if (hasMoreArgs()) { + const QString &fileName = nextArg(); + m_collectionFile = getFileName(fileName); + if (m_collectionFile.isEmpty()) + m_error = tr("The collection file '%1' does not exist!"). + arg(fileName); + } else { + m_error = tr("Missing collection file!"); + } +} + +void CmdLineParser::handleShowUrlOption() +{ + TRACE_OBJ + if (hasMoreArgs()) { + const QString &urlString = nextArg(); + QUrl url(urlString); + if (url.isValid()) { + m_url = url; + } else + m_error = tr("Invalid URL '%1'!").arg(urlString); + } else { + m_error = tr("Missing URL!"); + } +} + +void CmdLineParser::handleShowOption() +{ + TRACE_OBJ + handleShowOrHideOrActivateOption(Show); +} + +void CmdLineParser::handleHideOption() +{ + TRACE_OBJ + handleShowOrHideOrActivateOption(Hide); +} + +void CmdLineParser::handleActivateOption() +{ + TRACE_OBJ + handleShowOrHideOrActivateOption(Activate); +} + +void CmdLineParser::handleShowOrHideOrActivateOption(ShowState state) +{ + TRACE_OBJ + if (hasMoreArgs()) { + const QString &widget = nextArg().toLower(); + if (widget == QLatin1String("contents")) + m_contents = state; + else if (widget == QLatin1String("index")) + m_index = state; + else if (widget == QLatin1String("bookmarks")) + m_bookmarks = state; + else if (widget == QLatin1String("search")) + m_search = state; + else + m_error = tr("Unknown widget: %1").arg(widget); + } else { + m_error = tr("Missing widget!"); + } +} + +void CmdLineParser::handleRegisterOption() +{ + TRACE_OBJ + handleRegisterOrUnregisterOption(Register); +} + +void CmdLineParser::handleUnregisterOption() +{ + TRACE_OBJ + handleRegisterOrUnregisterOption(Unregister); +} + +void CmdLineParser::handleRegisterOrUnregisterOption(RegisterState state) +{ + TRACE_OBJ + if (hasMoreArgs()) { + const QString &fileName = nextArg(); + m_helpFile = getFileName(fileName); + if (m_helpFile.isEmpty()) + m_error = tr("The Qt help file '%1' does not exist!").arg(fileName); + else + m_register = state; + } else { + m_error = tr("Missing help file!"); + } +} + +void CmdLineParser::handleSetCurrentFilterOption() +{ + TRACE_OBJ + if (hasMoreArgs()) + m_currentFilter = nextArg(); + else + m_error = tr("Missing filter argument!"); +} + QString CmdLineParser::getFileName(const QString &fileName) { + TRACE_OBJ QFileInfo fi(fileName); if (!fi.exists()) return QString(); @@ -253,14 +274,15 @@ QString CmdLineParser::getFileName(const QString &fileName) void CmdLineParser::showMessage(const QString &msg, bool error) { + TRACE_OBJ if (m_quiet) return; #ifdef Q_OS_WIN - QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>"); + QString message = QLatin1String("<pre>") % msg % QLatin1String("</pre>"); if (error) - QMessageBox::critical(0, QObject::tr("Qt Assistant"), s); + QMessageBox::critical(0, tr("Error"), message); else - QMessageBox::information(0, QObject::tr("Qt Assistant"), s); + QMessageBox::information(0, tr("Notice"), message); #else fprintf(error ? stderr : stdout, "%s\n", qPrintable(msg)); #endif @@ -268,61 +290,79 @@ void CmdLineParser::showMessage(const QString &msg, bool error) void CmdLineParser::setCollectionFile(const QString &file) { + TRACE_OBJ m_collectionFile = file; } QString CmdLineParser::collectionFile() const { + TRACE_OBJ return m_collectionFile; } QUrl CmdLineParser::url() const { + TRACE_OBJ return m_url; } bool CmdLineParser::enableRemoteControl() const { + TRACE_OBJ return m_enableRemoteControl; } CmdLineParser::ShowState CmdLineParser::contents() const { + TRACE_OBJ return m_contents; } CmdLineParser::ShowState CmdLineParser::index() const { + TRACE_OBJ return m_index; } CmdLineParser::ShowState CmdLineParser::bookmarks() const { + TRACE_OBJ return m_bookmarks; } CmdLineParser::ShowState CmdLineParser::search() const { + TRACE_OBJ return m_search; } QString CmdLineParser::currentFilter() const { + TRACE_OBJ return m_currentFilter; } bool CmdLineParser::removeSearchIndex() const { + TRACE_OBJ return m_removeSearchIndex; } +bool CmdLineParser::rebuildSearchIndex() const +{ + TRACE_OBJ + return m_rebuildSearchIndex; +} + CmdLineParser::RegisterState CmdLineParser::registerRequest() const { + TRACE_OBJ return m_register; } QString CmdLineParser::helpFile() const { + TRACE_OBJ return m_helpFile; } diff --git a/tools/assistant/tools/assistant/cmdlineparser.h b/tools/assistant/tools/assistant/cmdlineparser.h index 17707cb..5573081 100644 --- a/tools/assistant/tools/assistant/cmdlineparser.h +++ b/tools/assistant/tools/assistant/cmdlineparser.h @@ -42,6 +42,7 @@ #ifndef CMDLINEPARSER_H #define CMDLINEPARSER_H +#include <QtCore/QCoreApplication> #include <QtCore/QStringList> #include <QtCore/QUrl> @@ -49,13 +50,14 @@ QT_BEGIN_NAMESPACE class CmdLineParser { + Q_DECLARE_TR_FUNCTIONS(CmdLineParser) public: enum Result {Ok, Help, Error}; enum ShowState {Untouched, Show, Hide, Activate}; enum RegisterState {None, Register, Unregister}; - CmdLineParser(); - Result parse(const QStringList &arguments); + CmdLineParser(const QStringList &arguments); + Result parse(); void setCollectionFile(const QString &file); QString collectionFile() const; @@ -68,17 +70,30 @@ public: ShowState search() const; QString currentFilter() const; bool removeSearchIndex() const; + bool rebuildSearchIndex() const; RegisterState registerRequest() const; QString helpFile() const; - bool copy() const { return m_copy; } - void showMessage(const QString &msg, bool error); private: QString getFileName(const QString &fileName); + bool hasMoreArgs() const; + const QString &nextArg(); + void handleCollectionFileOption(); + void handleShowUrlOption(); + void handleShowOption(); + void handleHideOption(); + void handleActivateOption(); + void handleShowOrHideOrActivateOption(ShowState state); + void handleRegisterOption(); + void handleUnregisterOption(); + void handleRegisterOrUnregisterOption(RegisterState state); + void handleSetCurrentFilterOption(); - QString m_helpMessage; + QStringList m_arguments; + int m_pos; + static const QString m_helpMessage; QString m_collectionFile; QString m_cloneFile; QString m_helpFile; @@ -92,8 +107,9 @@ private: RegisterState m_register; QString m_currentFilter; bool m_removeSearchIndex; - bool m_copy; + bool m_rebuildSearchIndex; bool m_quiet; + QString m_error; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/contentwindow.cpp b/tools/assistant/tools/assistant/contentwindow.cpp index 4640673..976ed7a 100644 --- a/tools/assistant/tools/assistant/contentwindow.cpp +++ b/tools/assistant/tools/assistant/contentwindow.cpp @@ -38,25 +38,26 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "contentwindow.h" #include "centralwidget.h" +#include "helpenginewrapper.h" +#include "helpviewer.h" #include <QtGui/QLayout> #include <QtGui/QFocusEvent> #include <QtGui/QMenu> -#include <QtHelp/QHelpEngine> #include <QtHelp/QHelpContentWidget> QT_BEGIN_NAMESPACE -ContentWindow::ContentWindow(QHelpEngine *helpEngine) - : m_helpEngine(helpEngine) - , m_contentWidget(0) +ContentWindow::ContentWindow() + : m_contentWidget(HelpEngineWrapper::instance().contentWidget()) , m_expandDepth(-2) { - m_contentWidget = m_helpEngine->contentWidget(); + TRACE_OBJ m_contentWidget->viewport()->installEventFilter(this); m_contentWidget->setContextMenuPolicy(Qt::CustomContextMenu); @@ -76,10 +77,12 @@ ContentWindow::ContentWindow(QHelpEngine *helpEngine) ContentWindow::~ContentWindow() { + TRACE_OBJ } bool ContentWindow::syncToContent(const QUrl& url) { + TRACE_OBJ QModelIndex idx = m_contentWidget->indexOf(url); if (!idx.isValid()) return false; @@ -89,6 +92,8 @@ bool ContentWindow::syncToContent(const QUrl& url) void ContentWindow::expandTOC() { + TRACE_OBJ + Q_ASSERT(m_expandDepth >= -2); if (m_expandDepth > -2) { expandToDepth(m_expandDepth); m_expandDepth = -2; @@ -97,27 +102,34 @@ void ContentWindow::expandTOC() void ContentWindow::expandToDepth(int depth) { + TRACE_OBJ + Q_ASSERT(depth >= -2); m_expandDepth = depth; if (depth == -1) m_contentWidget->expandAll(); + else if (depth == 0) + m_contentWidget->collapseAll(); else - m_contentWidget->expandToDepth(depth); + m_contentWidget->expandToDepth(depth - 1); } void ContentWindow::focusInEvent(QFocusEvent *e) { + TRACE_OBJ if (e->reason() != Qt::MouseFocusReason) m_contentWidget->setFocus(); } void ContentWindow::keyPressEvent(QKeyEvent *e) { + TRACE_OBJ if (e->key() == Qt::Key_Escape) emit escapePressed(); } bool ContentWindow::eventFilter(QObject *o, QEvent *e) { + TRACE_OBJ if (m_contentWidget && o == m_contentWidget->viewport() && e->type() == QEvent::MouseButtonRelease) { QMouseEvent *me = static_cast<QMouseEvent*>(e); @@ -132,7 +144,7 @@ bool ContentWindow::eventFilter(QObject *o, QEvent *e) qobject_cast<QHelpContentModel*>(m_contentWidget->model()); if (contentModel) { QHelpContentItem *itm = contentModel->contentItemAt(index); - if (itm && !isPdfFile(itm)) + if (itm && HelpViewer::canOpenPage(itm->url().path())) CentralWidget::instance()->setSourceInNewTab(itm->url()); } } else if (button == Qt::LeftButton) { @@ -146,6 +158,7 @@ bool ContentWindow::eventFilter(QObject *o, QEvent *e) void ContentWindow::showContextMenu(const QPoint &pos) { + TRACE_OBJ if (!m_contentWidget->indexAt(pos).isValid()) return; @@ -157,7 +170,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 (isPdfFile(itm)) + if (!HelpViewer::canOpenPage(itm->url().path())) newTab->setEnabled(false); menu.move(m_contentWidget->mapToGlobal(pos)); @@ -171,6 +184,7 @@ void ContentWindow::showContextMenu(const QPoint &pos) void ContentWindow::itemClicked(const QModelIndex &index) { + TRACE_OBJ QHelpContentModel *contentModel = qobject_cast<QHelpContentModel*>(m_contentWidget->model()); @@ -181,10 +195,4 @@ void ContentWindow::itemClicked(const QModelIndex &index) } } -bool ContentWindow::isPdfFile(QHelpContentItem *item) const -{ - const QString &path = item->url().path(); - return path.endsWith(QLatin1String(".pdf"), Qt::CaseInsensitive); -} - QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/contentwindow.h b/tools/assistant/tools/assistant/contentwindow.h index f3bf060..62855dd 100644 --- a/tools/assistant/tools/assistant/contentwindow.h +++ b/tools/assistant/tools/assistant/contentwindow.h @@ -57,7 +57,7 @@ class ContentWindow : public QWidget Q_OBJECT public: - ContentWindow(QHelpEngine *helpEngine); + ContentWindow(); ~ContentWindow(); bool syncToContent(const QUrl &url); @@ -78,8 +78,7 @@ private: bool eventFilter(QObject *o, QEvent *e); bool isPdfFile(QHelpContentItem *item) const; - QHelpEngine *m_helpEngine; - QHelpContentWidget *m_contentWidget; + 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 b8726a4..3b4b5f8 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 © 2010 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.6.2</div></td>\n" \ + "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.7.0</div></td>\n" \ "</tr></table></div></address>" diff --git a/tools/assistant/tools/assistant/filternamedialog.cpp b/tools/assistant/tools/assistant/filternamedialog.cpp index 1560e04..f75f999 100644 --- a/tools/assistant/tools/assistant/filternamedialog.cpp +++ b/tools/assistant/tools/assistant/filternamedialog.cpp @@ -38,6 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include <QtGui/QPushButton> @@ -48,6 +49,7 @@ QT_BEGIN_NAMESPACE FilterNameDialog::FilterNameDialog(QWidget *parent) : QDialog(parent) { + TRACE_OBJ m_ui.setupUi(this); connect(m_ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept())); @@ -61,11 +63,13 @@ FilterNameDialog::FilterNameDialog(QWidget *parent) QString FilterNameDialog::filterName() const { + TRACE_OBJ return m_ui.lineEdit->text(); } void FilterNameDialog::updateOkButton() { + TRACE_OBJ m_ui.buttonBox->button(QDialogButtonBox::Ok) ->setDisabled(m_ui.lineEdit->text().isEmpty()); } diff --git a/tools/assistant/tools/assistant/findwidget.cpp b/tools/assistant/tools/assistant/findwidget.cpp new file mode 100644 index 0000000..2e40ab0 --- /dev/null +++ b/tools/assistant/tools/assistant/findwidget.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "tracer.h" +#include "findwidget.h" + +#include <QtGui/QApplication> +#include <QtGui/QCheckBox> +#include <QtGui/QHideEvent> +#include <QtGui/QKeyEvent> +#include <QtGui/QLabel> +#include <QtGui/QLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QToolButton> + +QT_BEGIN_NAMESPACE + +FindWidget::FindWidget(QWidget *parent) + : QWidget(parent) + , appPalette(qApp->palette()) +{ + TRACE_OBJ + installEventFilter(this); + QHBoxLayout *hboxLayout = new QHBoxLayout(this); + QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); + +#ifndef Q_OS_MAC + hboxLayout->setMargin(0); + hboxLayout->setSpacing(6); + resourcePath.append(QLatin1String("win")); +#else + resourcePath.append(QLatin1String("mac")); +#endif + + toolClose = setupToolButton(QLatin1String(""), + resourcePath + QLatin1String("/closetab.png")); + hboxLayout->addWidget(toolClose); + + editFind = new QLineEdit(this); + hboxLayout->addWidget(editFind); + editFind->setMinimumSize(QSize(150, 0)); + connect(editFind, SIGNAL(textChanged(QString)), this, + SLOT(textChanged(QString))); + connect(editFind, SIGNAL(returnPressed()), this, SIGNAL(findNext())); + connect(editFind, SIGNAL(textChanged(QString)), this, SLOT(updateButtons())); + + toolPrevious = setupToolButton(tr("Previous"), + resourcePath + QLatin1String("/previous.png")); + connect(toolPrevious, SIGNAL(clicked()), this, SIGNAL(findPrevious())); + + hboxLayout->addWidget(toolPrevious); + + toolNext = setupToolButton(tr("Next"), + resourcePath + QLatin1String("/next.png")); + hboxLayout->addWidget(toolNext); + connect(toolNext, SIGNAL(clicked()), this, SIGNAL(findNext())); + + checkCase = new QCheckBox(tr("Case Sensitive"), this); + hboxLayout->addWidget(checkCase); + + labelWrapped = new QLabel(this); + labelWrapped->setScaledContents(true); + labelWrapped->setTextFormat(Qt::RichText); + labelWrapped->setMinimumSize(QSize(0, 20)); + labelWrapped->setMaximumSize(QSize(105, 20)); + labelWrapped->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter); + labelWrapped->setText(tr("<img src=\":/trolltech/assistant/images/wrap.png\"" + "> Search wrapped")); + hboxLayout->addWidget(labelWrapped); + + QSpacerItem *spacerItem = new QSpacerItem(20, 20, QSizePolicy::Expanding, + QSizePolicy::Minimum); + hboxLayout->addItem(spacerItem); + setMinimumWidth(minimumSizeHint().width()); + labelWrapped->hide(); + + updateButtons(); +} + +FindWidget::~FindWidget() +{ + TRACE_OBJ +} + +void FindWidget::show() +{ + TRACE_OBJ + QWidget::show(); + editFind->selectAll(); + editFind->setFocus(Qt::ShortcutFocusReason); +} + +void FindWidget::showAndClear() +{ + TRACE_OBJ + show(); + editFind->clear(); +} + +QString FindWidget::text() const +{ + TRACE_OBJ + return editFind->text(); +} + +bool FindWidget::caseSensitive() const +{ + TRACE_OBJ + return checkCase->isChecked(); +} + +void FindWidget::setPalette(bool found) +{ + TRACE_OBJ + QPalette palette = editFind->palette(); + palette.setColor(QPalette::Active, QPalette::Base, found ? Qt::white + : QColor(255, 102, 102)); + editFind->setPalette(palette); +} + +void FindWidget::setTextWrappedVisible(bool visible) +{ + TRACE_OBJ + labelWrapped->setVisible(visible); +} + +void FindWidget::hideEvent(QHideEvent* event) +{ + TRACE_OBJ +#if !defined(QT_NO_WEBKIT) + // TODO: remove this once webkit supports setting the palette + if (!event->spontaneous()) + qApp->setPalette(appPalette); +#else + Q_UNUSED(event); +#endif +} + +void FindWidget::showEvent(QShowEvent* event) +{ + TRACE_OBJ +#if !defined(QT_NO_WEBKIT) + // TODO: remove this once webkit supports setting the palette + if (!event->spontaneous()) { + QPalette p = appPalette; + p.setColor(QPalette::Inactive, QPalette::Highlight, + p.color(QPalette::Active, QPalette::Highlight)); + p.setColor(QPalette::Inactive, QPalette::HighlightedText, + p.color(QPalette::Active, QPalette::HighlightedText)); + qApp->setPalette(p); + } +#else + Q_UNUSED(event); +#endif +} + +void FindWidget::updateButtons() +{ + TRACE_OBJ + const bool enable = !editFind->text().isEmpty(); + toolNext->setEnabled(enable); + toolPrevious->setEnabled(enable); +} + +void FindWidget::textChanged(const QString &text) +{ + TRACE_OBJ + emit find(text, true); +} + +bool FindWidget::eventFilter(QObject *object, QEvent *e) +{ + TRACE_OBJ + if (e->type() == QEvent::KeyPress) { + if ((static_cast<QKeyEvent*>(e))->key() == Qt::Key_Escape) { + hide(); + emit escapePressed(); + } + } + return QWidget::eventFilter(object, e); +} + +QToolButton* FindWidget::setupToolButton(const QString &text, const QString &icon) +{ + TRACE_OBJ + QToolButton *toolButton = new QToolButton(this); + + toolButton->setText(text); + toolButton->setAutoRaise(true); + toolButton->setIcon(QIcon(icon)); + toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + + return toolButton; +} + +QT_END_NAMESPACE diff --git a/tools/assistant/compat/helpwindow.h b/tools/assistant/tools/assistant/findwidget.h index c20a21f..cf78003 100644 --- a/tools/assistant/compat/helpwindow.h +++ b/tools/assistant/tools/assistant/findwidget.h @@ -38,63 +38,64 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef FINDWIDGET_H +#define FINDWIDGET_H -#ifndef HELPWINDOW_H -#define HELPWINDOW_H - -#include <QTextBrowser> +#include <QtGui/QWidget> QT_BEGIN_NAMESPACE -class MainWindow; -class QKeyEvent; -class QMime; -class QMouseEvent; -class QMenu; +class QCheckBox; +class QLabel; +class QLineEdit; +class QToolButton; -class HelpWindow : public QTextBrowser +class FindWidget : public QWidget { Q_OBJECT public: - HelpWindow( MainWindow *m, QWidget *parent = 0); - void setSource( const QUrl &name ); - void blockScrolling( bool b ); - void openLinkInNewWindow( const QString &link ); - void openLinkInNewPage( const QString &link ); - void addMimePath( const QString &path ); + FindWidget(QWidget *parent = 0); + ~FindWidget(); + + void show(); + void showAndClear(); - void mousePressEvent(QMouseEvent *e); - void keyPressEvent(QKeyEvent *); + QString text() const; + bool caseSensitive() const; + + void setPalette(bool found); + void setTextWrappedVisible(bool visible); signals: - void chooseWebBrowser(); - void choosePDFReader(); + void escapePressed(); -protected: - virtual void contextMenuEvent(QContextMenuEvent *e); - virtual void mouseReleaseEvent(QMouseEvent *e); + void findNext(); + void findPrevious(); + void find(const QString &text, bool forward); -protected slots: - void ensureCursorVisible(); +protected: + void hideEvent(QHideEvent* event); + void showEvent(QShowEvent * event); private slots: - void openLinkInNewWindow(); - void openLinkInNewPage(); + void updateButtons(); + void textChanged(const QString &text); - bool isKDERunning() const; +private: + bool eventFilter(QObject *object, QEvent *e); + QToolButton* setupToolButton(const QString &text, const QString &icon); private: - bool hasAnchorAt(const QPoint& pos); - - MainWindow *mw; - QString lastAnchor; - bool blockScroll; - bool shiftPressed; - bool newWindow; - bool fwdAvail; - bool backAvail; + QPalette appPalette; + + QLineEdit *editFind; + QCheckBox *checkCase; + QLabel *labelWrapped; + QToolButton *toolNext; + QToolButton *toolClose; + QToolButton *toolPrevious; }; QT_END_NAMESPACE -#endif // HELPWINDOW_H +#endif // FINDWIDGET_H diff --git a/tools/assistant/tools/assistant/helpenginewrapper.cpp b/tools/assistant/tools/assistant/helpenginewrapper.cpp new file mode 100644 index 0000000..76211c5 --- /dev/null +++ b/tools/assistant/tools/assistant/helpenginewrapper.cpp @@ -0,0 +1,808 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "tracer.h" + +#include "helpenginewrapper.h" +#include "../shared/collectionconfiguration.h" + +#include <QtCore/QDateTime> +#include <QtCore/QFileInfo> +#include <QtCore/QFileSystemWatcher> +#include <QtCore/QPair> +#include <QtCore/QSharedPointer> +#include <QtCore/QTimer> +#include <QtHelp/QHelpContentModel> +#include <QtHelp/QHelpEngine> +#include <QtHelp/QHelpIndexModel> +#include <QtHelp/QHelpSearchEngine> + +QT_BEGIN_NAMESPACE + +namespace { + const QString Unfiltered; + const QString AppFontKey(QLatin1String("appFont")); + const QString AppWritingSystemKey(QLatin1String("appWritingSystem")); + const QString BookmarksKey(QLatin1String("Bookmarks")); + const QString BrowserFontKey(QLatin1String("browserFont")); + const QString BrowserWritingSystemKey(QLatin1String("browserWritingSystem")); + const QString HomePageKey(QLatin1String("homepage")); + const QString MainWindowKey(QLatin1String("MainWindow")); + const QString MainWindowGeometryKey(QLatin1String("MainWindowGeometry")); + const QString SearchWasAttachedKey(QLatin1String("SearchWasAttached")); + const QString StartOptionKey(QLatin1String("StartOption")); + const QString UseAppFontKey(QLatin1String("useAppFont")); + const QString UseBrowserFontKey(QLatin1String("useBrowserFont")); + const QString VersionKey(QString(QLatin1String("qtVersion%1$$$%2")). + arg(QLatin1String(QT_VERSION_STR))); +} // anonymous namespace + +class TimeoutForwarder : public QObject +{ + Q_OBJECT +public: + TimeoutForwarder(const QString &fileName); +private slots: + void forward(); +private: + friend class HelpEngineWrapperPrivate; + + const QString m_fileName; +}; + +class HelpEngineWrapperPrivate : public QObject +{ + Q_OBJECT + friend class HelpEngineWrapper; + friend class TimeoutForwarder; +private slots: + void qchFileChanged(const QString &fileName); + +signals: + void documentationRemoved(const QString &namespaceName); + void documentationUpdated(const QString &namespaceName); + +private: + HelpEngineWrapperPrivate(const QString &collectionFile); + + void initFileSystemWatchers(); + void checkDocFilesWatched(); + void qchFileChanged(const QString &fileName, bool fromTimeout); + + static const int UpdateGracePeriod = 2000; + + QHelpEngine * const m_helpEngine; + QFileSystemWatcher * const m_qchWatcher; + typedef QPair<QDateTime, QSharedPointer<TimeoutForwarder> > RecentSignal; + QMap<QString, RecentSignal> m_recentQchUpdates; +}; + +const QString HelpEngineWrapper::TrUnfiltered = tr("Unfiltered"); + +HelpEngineWrapper *HelpEngineWrapper::helpEngineWrapper = 0; + +HelpEngineWrapper &HelpEngineWrapper::instance(const QString &collectionFile) +{ + TRACE_OBJ + /* + * Note that this Singleton cannot be static, because it has to be + * deleted before the QApplication. + */ + if (helpEngineWrapper == 0) + helpEngineWrapper = new HelpEngineWrapper(collectionFile); + return *helpEngineWrapper; +} + +void HelpEngineWrapper::removeInstance() +{ + TRACE_OBJ + delete helpEngineWrapper; + helpEngineWrapper = 0; +} + +HelpEngineWrapper::HelpEngineWrapper(const QString &collectionFile) + : d(new HelpEngineWrapperPrivate(collectionFile)) +{ + TRACE_OBJ + connect(d, SIGNAL(documentationRemoved(QString)), + this, SIGNAL(documentationRemoved(QString))); + connect(d, SIGNAL(documentationUpdated(QString)), + this, SIGNAL(documentationUpdated(QString))); + connect(d->m_helpEngine, SIGNAL(currentFilterChanged(QString)), + this, SLOT(handleCurrentFilterChanged(QString))); + connect(d->m_helpEngine, SIGNAL(setupFinished()), + this, SIGNAL(setupFinished())); +} + +HelpEngineWrapper::~HelpEngineWrapper() +{ + TRACE_OBJ + delete d; +} + +QHelpSearchEngine *HelpEngineWrapper::searchEngine() const +{ + TRACE_OBJ + return d->m_helpEngine->searchEngine(); +} + +QHelpContentModel *HelpEngineWrapper::contentModel() const +{ + TRACE_OBJ + return d->m_helpEngine->contentModel(); +} + +QHelpIndexModel *HelpEngineWrapper::indexModel() const +{ + TRACE_OBJ + return d->m_helpEngine->indexModel(); +} + +QHelpContentWidget *HelpEngineWrapper::contentWidget() +{ + TRACE_OBJ + return d->m_helpEngine->contentWidget(); +} + +QHelpIndexWidget *HelpEngineWrapper::indexWidget() +{ + TRACE_OBJ + return d->m_helpEngine->indexWidget(); +} + +const QStringList HelpEngineWrapper::registeredDocumentations() const +{ + TRACE_OBJ + return d->m_helpEngine->registeredDocumentations(); +} + +const QString HelpEngineWrapper::collectionFile() const +{ + TRACE_OBJ + return d->m_helpEngine->collectionFile(); +} + +bool HelpEngineWrapper::registerDocumentation(const QString &docFile) +{ + TRACE_OBJ + d->checkDocFilesWatched(); + if (!d->m_helpEngine->registerDocumentation(docFile)) + return false; + d->m_qchWatcher->addPath(docFile); + d->checkDocFilesWatched(); + return true; +} + +bool HelpEngineWrapper::unregisterDocumentation(const QString &namespaceName) +{ + TRACE_OBJ + d->checkDocFilesWatched(); + const QString &file = d->m_helpEngine->documentationFileName(namespaceName); + if (!d->m_helpEngine->unregisterDocumentation(namespaceName)) + return false; + d->m_qchWatcher->removePath(file); + d->checkDocFilesWatched(); + return true; +} + +bool HelpEngineWrapper::setupData() +{ + TRACE_OBJ + return d->m_helpEngine->setupData(); +} + +bool HelpEngineWrapper::addCustomFilter(const QString &filterName, + const QStringList &attributes) +{ + TRACE_OBJ + return d->m_helpEngine->addCustomFilter(filterName, attributes); +} + +bool HelpEngineWrapper::removeCustomFilter(const QString &filterName) +{ + TRACE_OBJ + return d->m_helpEngine->removeCustomFilter(filterName); +} + +void HelpEngineWrapper::setCurrentFilter(const QString ¤tFilter) +{ + TRACE_OBJ + const QString &filter + = currentFilter == TrUnfiltered ? Unfiltered : currentFilter; + d->m_helpEngine->setCurrentFilter(filter); +} + +const QString HelpEngineWrapper::currentFilter() const +{ + TRACE_OBJ + const QString &filter = d->m_helpEngine->currentFilter(); + return filter == Unfiltered ? TrUnfiltered : filter; +} + +const QStringList HelpEngineWrapper::customFilters() const +{ + TRACE_OBJ + QStringList filters = d->m_helpEngine->customFilters(); + filters.removeOne(Unfiltered); + filters.prepend(TrUnfiltered); + return filters; +} + +QUrl HelpEngineWrapper::findFile(const QUrl &url) const +{ + TRACE_OBJ + return d->m_helpEngine->findFile(url); +} + +QByteArray HelpEngineWrapper::fileData(const QUrl &url) const +{ + TRACE_OBJ + return d->m_helpEngine->fileData(url); +} + +QMap<QString, QUrl> HelpEngineWrapper::linksForIdentifier(const QString &id) const +{ + TRACE_OBJ + return d->m_helpEngine->linksForIdentifier(id); +} + +const QStringList HelpEngineWrapper::filterAttributes() const +{ + TRACE_OBJ + return d->m_helpEngine->filterAttributes(); +} + +const QStringList HelpEngineWrapper::filterAttributes(const QString &filterName) const +{ + TRACE_OBJ + return d->m_helpEngine->filterAttributes(filterName); +} + +QString HelpEngineWrapper::error() const +{ + TRACE_OBJ + return d->m_helpEngine->error(); +} + +const QStringList HelpEngineWrapper::qtDocInfo(const QString &component) const +{ + TRACE_OBJ + return d->m_helpEngine->customValue(VersionKey.arg(component)).toString(). + split(CollectionConfiguration::ListSeparator); +} + +void HelpEngineWrapper::setQtDocInfo(const QString &component, + const QStringList &doc) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(VersionKey.arg(component), + doc.join(CollectionConfiguration::ListSeparator)); +} + +const QStringList HelpEngineWrapper::lastShownPages() const +{ + TRACE_OBJ + return CollectionConfiguration::lastShownPages(*d->m_helpEngine); +} + +void HelpEngineWrapper::setLastShownPages(const QStringList &lastShownPages) +{ + TRACE_OBJ + CollectionConfiguration::setLastShownPages(*d->m_helpEngine, lastShownPages); +} + +const QStringList HelpEngineWrapper::lastZoomFactors() const +{ + TRACE_OBJ + return CollectionConfiguration::lastZoomFactors(*d->m_helpEngine); +} + +void HelpEngineWrapper::setLastZoomFactors(const QStringList &lastZoomFactors) +{ + TRACE_OBJ + CollectionConfiguration::setLastZoomFactors(*d->m_helpEngine, lastZoomFactors); +} + +const QString HelpEngineWrapper::cacheDir() const +{ + TRACE_OBJ + return CollectionConfiguration::cacheDir(*d->m_helpEngine); +} + +bool HelpEngineWrapper::cacheDirIsRelativeToCollection() const +{ + TRACE_OBJ + return CollectionConfiguration::cacheDirIsRelativeToCollection(*d->m_helpEngine); +} + +void HelpEngineWrapper::setCacheDir(const QString &cacheDir, + bool relativeToCollection) +{ + TRACE_OBJ + CollectionConfiguration::setCacheDir(*d->m_helpEngine, cacheDir, + relativeToCollection); +} + +bool HelpEngineWrapper::filterFunctionalityEnabled() const +{ + TRACE_OBJ + return CollectionConfiguration::filterFunctionalityEnabled(*d->m_helpEngine); +} + +void HelpEngineWrapper::setFilterFunctionalityEnabled(bool enabled) +{ + TRACE_OBJ + CollectionConfiguration::setFilterFunctionalityEnabled(*d->m_helpEngine, + enabled); +} + +bool HelpEngineWrapper::filterToolbarVisible() const +{ + TRACE_OBJ + return CollectionConfiguration::filterToolbarVisible(*d->m_helpEngine); +} + +void HelpEngineWrapper::setFilterToolbarVisible(bool visible) +{ + TRACE_OBJ + CollectionConfiguration::setFilterToolbarVisible(*d->m_helpEngine, visible); +} + +bool HelpEngineWrapper::addressBarEnabled() const +{ + TRACE_OBJ + return CollectionConfiguration::addressBarEnabled(*d->m_helpEngine); +} + +void HelpEngineWrapper::setAddressBarEnabled(bool enabled) +{ + TRACE_OBJ + CollectionConfiguration::setAddressBarEnabled(*d->m_helpEngine, enabled); +} + +bool HelpEngineWrapper::addressBarVisible() const +{ + TRACE_OBJ + return CollectionConfiguration::addressBarVisible(*d->m_helpEngine); +} + +void HelpEngineWrapper::setAddressBarVisible(bool visible) +{ + TRACE_OBJ + CollectionConfiguration::setAddressBarVisible(*d->m_helpEngine, visible); +} + +bool HelpEngineWrapper::documentationManagerEnabled() const +{ + TRACE_OBJ + return CollectionConfiguration::documentationManagerEnabled(*d->m_helpEngine); +} + +void HelpEngineWrapper::setDocumentationManagerEnabled(bool enabled) +{ + TRACE_OBJ + CollectionConfiguration::setDocumentationManagerEnabled(*d->m_helpEngine, + enabled); +} + +const QByteArray HelpEngineWrapper::aboutMenuTexts() const +{ + TRACE_OBJ + return CollectionConfiguration::aboutMenuTexts(*d->m_helpEngine); +} + +void HelpEngineWrapper::setAboutMenuTexts(const QByteArray &texts) +{ + TRACE_OBJ + CollectionConfiguration::setAboutMenuTexts(*d->m_helpEngine, texts); +} + +const QByteArray HelpEngineWrapper::aboutIcon() const +{ + TRACE_OBJ + return CollectionConfiguration::aboutIcon(*d->m_helpEngine); +} + +void HelpEngineWrapper::setAboutIcon(const QByteArray &icon) +{ + TRACE_OBJ + CollectionConfiguration::setAboutIcon(*d->m_helpEngine, icon); +} + +const QByteArray HelpEngineWrapper::aboutImages() const +{ + TRACE_OBJ + return CollectionConfiguration::aboutImages(*d->m_helpEngine); +} + +void HelpEngineWrapper::setAboutImages(const QByteArray &images) +{ + TRACE_OBJ + CollectionConfiguration::setAboutImages(*d->m_helpEngine, images); +} + +const QByteArray HelpEngineWrapper::aboutTexts() const +{ + TRACE_OBJ + return CollectionConfiguration::aboutTexts(*d->m_helpEngine); +} + +void HelpEngineWrapper::setAboutTexts(const QByteArray &texts) +{ + TRACE_OBJ + CollectionConfiguration::setAboutTexts(*d->m_helpEngine, texts); +} + +const QString HelpEngineWrapper::windowTitle() const +{ + TRACE_OBJ + return CollectionConfiguration::windowTitle(*d->m_helpEngine); +} + +void HelpEngineWrapper::setWindowTitle(const QString &windowTitle) +{ + TRACE_OBJ + CollectionConfiguration::setWindowTitle(*d->m_helpEngine, windowTitle); +} + +const QByteArray HelpEngineWrapper::applicationIcon() const +{ + TRACE_OBJ + return CollectionConfiguration::applicationIcon(*d->m_helpEngine); +} + +void HelpEngineWrapper::setApplicationIcon(const QByteArray &icon) +{ + TRACE_OBJ + CollectionConfiguration::setApplicationIcon(*d->m_helpEngine, icon); +} + +const QByteArray HelpEngineWrapper::mainWindow() const +{ + TRACE_OBJ + return d->m_helpEngine->customValue(MainWindowKey).toByteArray(); +} + +void HelpEngineWrapper::setMainWindow(const QByteArray &mainWindow) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(MainWindowKey, mainWindow); +} + +const QByteArray HelpEngineWrapper::mainWindowGeometry() const +{ + TRACE_OBJ + return d->m_helpEngine->customValue(MainWindowGeometryKey).toByteArray(); +} + +void HelpEngineWrapper::setMainWindowGeometry(const QByteArray &geometry) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(MainWindowGeometryKey, geometry); +} + +const QByteArray HelpEngineWrapper::bookmarks() const +{ + TRACE_OBJ + return d->m_helpEngine->customValue(BookmarksKey).toByteArray(); +} + +void HelpEngineWrapper::setBookmarks(const QByteArray &bookmarks) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(BookmarksKey, bookmarks); +} + +int HelpEngineWrapper::lastTabPage() const +{ + TRACE_OBJ + return CollectionConfiguration::lastTabPage(*d->m_helpEngine); +} + +void HelpEngineWrapper::setLastTabPage(int lastPage) +{ + TRACE_OBJ + 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 + return d->m_helpEngine->customValue(StartOptionKey, ShowLastPages).toInt(); +} + +void HelpEngineWrapper::setStartOption(int option) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(StartOptionKey, option); +} + +const QString HelpEngineWrapper::homePage() const +{ + TRACE_OBJ + const QString &homePage + = d->m_helpEngine->customValue(HomePageKey).toString(); + if (!homePage.isEmpty()) + return homePage; + return defaultHomePage(); +} + +void HelpEngineWrapper::setHomePage(const QString &page) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(HomePageKey, page); + +} + +const QString HelpEngineWrapper::defaultHomePage() const +{ + TRACE_OBJ + return CollectionConfiguration::defaultHomePage(*d->m_helpEngine); +} + +void HelpEngineWrapper::setDefaultHomePage(const QString &page) +{ + TRACE_OBJ + CollectionConfiguration::setDefaultHomePage(*d->m_helpEngine, page); +} + +bool HelpEngineWrapper::hasFontSettings() const +{ + TRACE_OBJ + return d->m_helpEngine->customValue(UseAppFontKey).isValid(); +} + +bool HelpEngineWrapper::usesAppFont() const +{ + TRACE_OBJ + return d->m_helpEngine->customValue(UseAppFontKey).toBool(); +} + +void HelpEngineWrapper::setUseAppFont(bool useAppFont) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(UseAppFontKey, useAppFont); +} + +bool HelpEngineWrapper::usesBrowserFont() const +{ + TRACE_OBJ + return d->m_helpEngine->customValue(UseBrowserFontKey, false).toBool(); +} + +void HelpEngineWrapper::setUseBrowserFont(bool useBrowserFont) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(UseBrowserFontKey, useBrowserFont); +} + +const QFont HelpEngineWrapper::appFont() const +{ + TRACE_OBJ + return qVariantValue<QFont>(d->m_helpEngine->customValue(AppFontKey)); +} + +void HelpEngineWrapper::setAppFont(const QFont &font) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(AppFontKey, font); +} + +QFontDatabase::WritingSystem HelpEngineWrapper::appWritingSystem() const +{ + TRACE_OBJ + return static_cast<QFontDatabase::WritingSystem>( + d->m_helpEngine->customValue(AppWritingSystemKey).toInt()); +} + +void HelpEngineWrapper::setAppWritingSystem(QFontDatabase::WritingSystem system) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(AppWritingSystemKey, system); +} + +const QFont HelpEngineWrapper::browserFont() const +{ + TRACE_OBJ + return qVariantValue<QFont>(d->m_helpEngine->customValue(BrowserFontKey)); +} + +void HelpEngineWrapper::setBrowserFont(const QFont &font) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(BrowserFontKey, font); +} + +QFontDatabase::WritingSystem HelpEngineWrapper::browserWritingSystem() const +{ + TRACE_OBJ + return static_cast<QFontDatabase::WritingSystem>( + d->m_helpEngine->customValue(BrowserWritingSystemKey).toInt()); +} + +void HelpEngineWrapper::setBrowserWritingSystem(QFontDatabase::WritingSystem system) +{ + TRACE_OBJ + d->m_helpEngine->setCustomValue(BrowserWritingSystemKey, system); +} + +void HelpEngineWrapper::handleCurrentFilterChanged(const QString &filter) +{ + const QString &filterToReport + = filter == Unfiltered ? TrUnfiltered : filter; + emit currentFilterChanged(filterToReport); +} + + +TimeoutForwarder::TimeoutForwarder(const QString &fileName) + : m_fileName(fileName) +{ + TRACE_OBJ +} + +void TimeoutForwarder::forward() +{ + TRACE_OBJ + HelpEngineWrapper::instance().d->qchFileChanged(m_fileName, true); +} + + +HelpEngineWrapperPrivate::HelpEngineWrapperPrivate(const QString &collectionFile) + : m_helpEngine(new QHelpEngine(collectionFile, this)), + m_qchWatcher(new QFileSystemWatcher(this)) +{ + TRACE_OBJ + if (!m_helpEngine->customFilters().contains(Unfiltered)) + m_helpEngine->addCustomFilter(Unfiltered, QStringList()); + initFileSystemWatchers(); +} + +void HelpEngineWrapperPrivate::initFileSystemWatchers() +{ + TRACE_OBJ + foreach(const QString &ns, m_helpEngine->registeredDocumentations()) { + const QString &docFile = m_helpEngine->documentationFileName(ns); + m_qchWatcher->addPath(docFile); + connect(m_qchWatcher, SIGNAL(fileChanged(QString)), + this, SLOT(qchFileChanged(QString))); + } + checkDocFilesWatched(); +} + +void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName) +{ + TRACE_OBJ + qchFileChanged(fileName, false); +} + +void HelpEngineWrapperPrivate::checkDocFilesWatched() +{ + TRACE_OBJ + const int watchedFilesCount = m_qchWatcher->files().count(); + const int docFilesCount = m_helpEngine->registeredDocumentations().count(); + if (watchedFilesCount != docFilesCount) { + qWarning("Strange: Have %d docs, but %d are being watched", + watchedFilesCount, docFilesCount); + } +} + +void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName, + bool fromTimeout) +{ + TRACE_OBJ + + /* + * We don't use QHelpEngineCore::namespaceName(fileName), because the file + * may not exist anymore or contain a different namespace. + */ + QString ns; + foreach (const QString &curNs, m_helpEngine->registeredDocumentations()) { + if (m_helpEngine->documentationFileName(curNs) == fileName) { + ns = curNs; + break; + } + } + + /* + * We can't do an assertion here, because QFileSystemWatcher may send the + * signal more than once. + */ + if (ns.isEmpty()) { + m_recentQchUpdates.remove(fileName); + return; + } + + /* + * Since the QFileSystemWatcher typically sends the signal more than once, + * we repeatedly delay our reaction a bit until we think the last signal + * was sent. + */ + + QMap<QString, RecentSignal>::Iterator it = m_recentQchUpdates.find(fileName); + const QDateTime &now = QDateTime::currentDateTime(); + + // Case 1: This is the first recent signal for the file. + if (it == m_recentQchUpdates.end()) { + QSharedPointer<TimeoutForwarder> forwarder(new TimeoutForwarder(fileName)); + m_recentQchUpdates.insert(fileName, RecentSignal(now, forwarder)); + QTimer::singleShot(UpdateGracePeriod, forwarder.data(), SLOT(forward())); + return; + } + + // Case 2: The last signal for this file has not expired yet. + if (it.value().first > now.addMSecs(-UpdateGracePeriod)) { + if (!fromTimeout) + it.value().first = now; + else + QTimer::singleShot(UpdateGracePeriod, it.value().second.data(), + SLOT(forward())); + return; + } + + // Case 3: The last signal for this file has expired. + if (m_helpEngine->unregisterDocumentation(ns)) { + if (!QFileInfo(fileName).exists() + || !m_helpEngine->registerDocumentation(fileName)) { + m_qchWatcher->removePath(fileName); + emit documentationRemoved(ns); + } else { + emit documentationUpdated(ns); + } + m_helpEngine->setupData(); + } + 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 new file mode 100644 index 0000000..a30fab8 --- /dev/null +++ b/tools/assistant/tools/assistant/helpenginewrapper.h @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HELPENGINEWRAPPER_H +#define HELPENGINEWRAPPER_H + +#include <QtCore/QMap> +#include <QtCore/QObject> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QUrl> +#include <QtGui/QFont> +#include <QtGui/QFontDatabase> + +QT_BEGIN_NAMESPACE + +class QFileSystemWatcher; +class QHelpContentModel; +class QHelpContentWidget; +class QHelpIndexModel; +class QHelpIndexWidget; +class QHelpSearchEngine; + +enum { + ShowHomePage = 0, + ShowBlankPage = 1, + ShowLastPages = 2 +}; + +class HelpEngineWrapperPrivate; +class TimeoutForwarder; + +class HelpEngineWrapper : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(HelpEngineWrapper) + friend class TimeoutForwarder; +public: + static HelpEngineWrapper &instance(const QString &collectionFile = QString()); + static void removeInstance(); + + // Forwarded help engine member functions, possibly enriched. + QHelpSearchEngine *searchEngine() const; + QHelpContentModel *contentModel() const; + QHelpIndexModel *indexModel() const; + QHelpContentWidget *contentWidget(); + QHelpIndexWidget *indexWidget(); + bool setupData(); + const QStringList registeredDocumentations() const; + const QString collectionFile() const; + bool registerDocumentation(const QString &docFile); + bool unregisterDocumentation(const QString &namespaceName); + bool addCustomFilter(const QString &filterName, + const QStringList &attributes); + bool removeCustomFilter(const QString &filterName); + void setCurrentFilter(const QString &filterName); + const QString currentFilter() const; + const QStringList customFilters() const; + QUrl findFile(const QUrl &url) const; + QByteArray fileData(const QUrl &url) const; + QMap<QString, QUrl> linksForIdentifier(const QString &id) const; + const QStringList filterAttributes() const; + const QStringList filterAttributes(const QString &filterName) const; + QString error() const; + + const QStringList qtDocInfo(const QString &component) const; + void setQtDocInfo(const QString &component, const QStringList &doc); + + const QString homePage() const; + void setHomePage(const QString &page); + const QString defaultHomePage() const; + void setDefaultHomePage(const QString &page); + + int lastTabPage() const; + void setLastTabPage(int lastPage); + + // TODO: Don't allow last pages and zoom factors to be set in isolation + // Perhaps also fill up missing elements automatically or assert. + const QStringList lastShownPages() const; + void setLastShownPages(const QStringList &lastShownPages); + const QStringList lastZoomFactors() const; + void setLastZoomFactors(const QStringList &lastZoomFactors); + + const QString cacheDir() const; + bool cacheDirIsRelativeToCollection() const; + void setCacheDir(const QString &cacheDir, bool relativeToCollection); + + bool filterFunctionalityEnabled() const; + void setFilterFunctionalityEnabled(bool enabled); + + bool filterToolbarVisible() const; + void setFilterToolbarVisible(bool visible); + + bool addressBarEnabled() const; + void setAddressBarEnabled(bool enabled); + + bool addressBarVisible() const; + void setAddressBarVisible(bool visible); + + bool documentationManagerEnabled() const; + void setDocumentationManagerEnabled(bool enabled); + + const QByteArray aboutMenuTexts() const; + void setAboutMenuTexts(const QByteArray &texts); + const QByteArray aboutTexts() const; + void setAboutTexts(const QByteArray &texts); + const QByteArray aboutIcon() const; + void setAboutIcon(const QByteArray &icon); + const QByteArray aboutImages() const; + void setAboutImages(const QByteArray &images); + + const QString windowTitle() const; + void setWindowTitle(const QString &windowTitle); + + const QByteArray applicationIcon() const; + void setApplicationIcon(const QByteArray &icon); + + const QByteArray mainWindow() const; + void setMainWindow(const QByteArray &mainWindow); + const QByteArray mainWindowGeometry() const; + void setMainWindowGeometry(const QByteArray &geometry); + + const QByteArray bookmarks() const; + void setBookmarks(const QByteArray &bookmarks); + + int startOption() const; + void setStartOption(int option); + + bool searchWasAttached() const; + void setSearchWasAttached(bool attached); + + bool hasFontSettings() const; + bool usesAppFont() const; + void setUseAppFont(bool useAppFont); + bool usesBrowserFont() const; + void setUseBrowserFont(bool useBrowserFont); + const QFont appFont() const; + void setAppFont(const QFont &font); + QFontDatabase::WritingSystem appWritingSystem() const; + void setAppWritingSystem(QFontDatabase::WritingSystem system); + const QFont browserFont() const; + void setBrowserFont(const QFont &font); + QFontDatabase::WritingSystem browserWritingSystem() const; + void setBrowserWritingSystem(QFontDatabase::WritingSystem system); + + static const QString TrUnfiltered; + +signals: + + // For asynchronous doc updates triggered by external actions. + void documentationRemoved(const QString &namespaceName); + void documentationUpdated(const QString &namespaceName); + + // Forwarded from QHelpEngineCore. + void currentFilterChanged(const QString ¤tFilter); + void setupFinished(); + +private slots: + void handleCurrentFilterChanged(const QString &filter); + +private: + HelpEngineWrapper(const QString &collectionFile); + ~HelpEngineWrapper(); + + static HelpEngineWrapper *helpEngineWrapper; + + HelpEngineWrapperPrivate *d; +}; + +QT_END_NAMESPACE + +#endif // HELPENGINEWRAPPER_H diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp index be6245a..8e4d3ed 100644 --- a/tools/assistant/tools/assistant/helpviewer.cpp +++ b/tools/assistant/tools/assistant/helpviewer.cpp @@ -38,14 +38,18 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "helpviewer.h" #include "centralwidget.h" +#include "helpenginewrapper.h" #include <QtCore/QDir> #include <QtCore/QEvent> #include <QtCore/QVariant> #include <QtCore/QByteArray> +#include <QtCore/QStringBuilder> +#include <QtCore/QTemporaryFile> #include <QtCore/QTimer> #include <QtGui/QMenu> @@ -55,14 +59,19 @@ #include <QtGui/QMessageBox> #include <QtGui/QDesktopServices> -#include <QtHelp/QHelpEngine> - #include <QNetworkAccessManager> #include <QNetworkReply> #include <QNetworkRequest> QT_BEGIN_NAMESPACE +namespace { + const QString 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>"); +} + #if !defined(QT_NO_WEBKIT) class HelpNetworkReply : public QNetworkReply @@ -88,6 +97,7 @@ HelpNetworkReply::HelpNetworkReply(const QNetworkRequest &request, const QByteArray &fileData, const QString& mimeType) : data(fileData), origLen(fileData.length()) { + TRACE_OBJ setRequest(request); setOpenMode(QIODevice::ReadOnly); @@ -99,11 +109,13 @@ HelpNetworkReply::HelpNetworkReply(const QNetworkRequest &request, void HelpNetworkReply::abort() { + TRACE_OBJ // nothing to do } qint64 HelpNetworkReply::readData(char *buffer, qint64 maxlen) { + TRACE_OBJ qint64 len = qMin(qint64(data.length()), maxlen); if (len) { qMemCopy(buffer, data.constData(), len); @@ -117,25 +129,23 @@ qint64 HelpNetworkReply::readData(char *buffer, qint64 maxlen) class HelpNetworkAccessManager : public QNetworkAccessManager { public: - HelpNetworkAccessManager(QHelpEngine *engine, QObject *parent); + HelpNetworkAccessManager(QObject *parent); protected: virtual QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData = 0); - -private: - QHelpEngine *helpEngine; }; -HelpNetworkAccessManager::HelpNetworkAccessManager(QHelpEngine *engine, - QObject *parent) - : QNetworkAccessManager(parent), helpEngine(engine) +HelpNetworkAccessManager::HelpNetworkAccessManager(QObject *parent) + : QNetworkAccessManager(parent) { + TRACE_OBJ } QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/, const QNetworkRequest &request, QIODevice* /*outgoingData*/) { + TRACE_OBJ const QUrl& url = request.url(); QString mimeType = url.toString(); if (mimeType.endsWith(QLatin1String(".svg")) @@ -151,14 +161,17 @@ QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/, mimeType = QLatin1String("text/html"); } - const QByteArray &ba = helpEngine->fileData(url); - return new HelpNetworkReply(request, ba.isEmpty() ? " " : ba, mimeType); + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + const QByteArray &data = helpEngine.findFile(url).isValid() + ? helpEngine.fileData(url) + : PageNotFoundMessage.arg(url.toString()).toUtf8(); + return new HelpNetworkReply(request, data, mimeType); } class HelpPage : public QWebPage { public: - HelpPage(CentralWidget *central, QHelpEngine *engine, QObject *parent); + HelpPage(CentralWidget *central, QObject *parent); protected: virtual QWebPage *createWindow(QWebPage::WebWindowType); @@ -169,7 +182,6 @@ protected: private: CentralWidget *centralWidget; - QHelpEngine *helpEngine; bool closeNewTabIfNeeded; friend class HelpViewer; @@ -177,18 +189,19 @@ private: Qt::KeyboardModifiers m_keyboardModifiers; }; -HelpPage::HelpPage(CentralWidget *central, QHelpEngine *engine, QObject *parent) +HelpPage::HelpPage(CentralWidget *central, QObject *parent) : QWebPage(parent) , centralWidget(central) - , helpEngine(engine) , closeNewTabIfNeeded(false) , m_pressedButtons(Qt::NoButton) , m_keyboardModifiers(Qt::NoModifier) { + TRACE_OBJ } QWebPage *HelpPage::createWindow(QWebPage::WebWindowType) { + TRACE_OBJ HelpPage* newPage = static_cast<HelpPage*>(centralWidget->newEmptyTab()->page()); if (newPage) newPage->closeNewTabIfNeeded = closeNewTabIfNeeded; @@ -196,21 +209,9 @@ QWebPage *HelpPage::createWindow(QWebPage::WebWindowType) return newPage; } -static bool isLocalUrl(const QUrl &url) -{ - const QString scheme = url.scheme(); - if (scheme.isEmpty() - || scheme == QLatin1String("file") - || scheme == QLatin1String("qrc") - || scheme == QLatin1String("data") - || scheme == QLatin1String("qthelp") - || scheme == QLatin1String("about")) - return true; - return false; -} - void HelpPage::triggerAction(WebAction action, bool checked) { + TRACE_OBJ switch (action) { case OpenLinkInNewWindow: closeNewTabIfNeeded = true; @@ -223,26 +224,25 @@ void HelpPage::triggerAction(WebAction action, bool checked) bool HelpPage::acceptNavigationRequest(QWebFrame *, const QNetworkRequest &request, QWebPage::NavigationType type) { + TRACE_OBJ const QUrl &url = request.url(); const bool closeNewTab = closeNewTabIfNeeded; closeNewTabIfNeeded = false; - if (isLocalUrl(url)) { + if (HelpViewer::isLocalUrl(url)) { const QString& path = url.path(); - if (path.endsWith(QLatin1String(".pdf"))) { - const int lastDash = path.lastIndexOf(QChar('/')); - QString fileName = QDir::tempPath() + QDir::separator(); - if (lastDash < 0) - fileName += path; - else - fileName += path.mid(lastDash + 1, path.length()); - - QFile tmpFile(QDir::cleanPath(fileName)); - if (tmpFile.open(QIODevice::ReadWrite)) { - tmpFile.write(helpEngine->fileData(url)); - tmpFile.close(); + if (!HelpViewer::canOpenPage(path)) { + QTemporaryFile tmpTmpFile; + if (!tmpTmpFile.open()) + return false; + const QString extension = QFileInfo(path).completeSuffix(); + QFile actualTmpFile(tmpTmpFile.fileName() % QLatin1String(".") + % extension); + if (actualTmpFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) { + actualTmpFile.write(HelpEngineWrapper::instance().fileData(url)); + actualTmpFile.close(); + QDesktopServices::openUrl(QUrl(actualTmpFile.fileName())); } - QDesktopServices::openUrl(QUrl(tmpFile.fileName())); if (closeNewTab) QMetaObject::invokeMethod(CentralWidget::instance(), "closeTab"); @@ -266,17 +266,18 @@ bool HelpPage::acceptNavigationRequest(QWebFrame *, return false; } -HelpViewer::HelpViewer(QHelpEngine *engine, CentralWidget *parent) +HelpViewer::HelpViewer(CentralWidget *parent) : QWebView(parent) - , helpEngine(engine) , parentWidget(parent) , loadFinished(false) + , helpEngine(HelpEngineWrapper::instance()) { + TRACE_OBJ setAcceptDrops(false); - setPage(new HelpPage(parent, helpEngine, this)); + setPage(new HelpPage(parent, this)); - page()->setNetworkAccessManager(new HelpNetworkAccessManager(engine, this)); + page()->setNetworkAccessManager(new HelpNetworkAccessManager(this)); QAction* action = pageAction(QWebPage::OpenLinkInNewWindow); action->setText(tr("Open Link in New Tab")); @@ -301,6 +302,7 @@ HelpViewer::HelpViewer(QHelpEngine *engine, CentralWidget *parent) void HelpViewer::setSource(const QUrl &url) { + TRACE_OBJ loadFinished = false; if (url.toString() == QLatin1String("help")) { load(QUrl(QLatin1String("qthelp://com.trolltech.com." @@ -312,34 +314,25 @@ void HelpViewer::setSource(const QUrl &url) void HelpViewer::resetZoom() { + TRACE_OBJ setTextSizeMultiplier(1.0); } void HelpViewer::zoomIn(qreal range) { + TRACE_OBJ setTextSizeMultiplier(textSizeMultiplier() + range / 10.0); } void HelpViewer::zoomOut(qreal range) { + TRACE_OBJ setTextSizeMultiplier(qMax(0.0, textSizeMultiplier() - range / 10.0)); } -void HelpViewer::home() -{ - QString homepage = helpEngine->customValue(QLatin1String("homepage"), - QLatin1String("")).toString(); - - if (homepage.isEmpty()) { - homepage = helpEngine->customValue(QLatin1String("defaultHomepage"), - QLatin1String("help")).toString(); - } - - setSource(homepage); -} - void HelpViewer::wheelEvent(QWheelEvent *e) { + TRACE_OBJ if (e->modifiers() & Qt::ControlModifier) { const int delta = e->delta(); if (delta > 0) @@ -354,6 +347,7 @@ void HelpViewer::wheelEvent(QWheelEvent *e) void HelpViewer::mouseReleaseEvent(QMouseEvent *e) { + TRACE_OBJ if (e->button() == Qt::XButton1) { triggerPageAction(QWebPage::Back); return; @@ -369,6 +363,7 @@ void HelpViewer::mouseReleaseEvent(QMouseEvent *e) void HelpViewer::actionChanged() { + TRACE_OBJ QAction *a = qobject_cast<QAction *>(sender()); if (a == pageAction(QWebPage::Copy)) emit copyAvailable(a->isEnabled()); @@ -380,6 +375,7 @@ void HelpViewer::actionChanged() void HelpViewer::mousePressEvent(QMouseEvent *event) { + TRACE_OBJ HelpPage *currentPage = static_cast<HelpPage*>(page()); if (currentPage) { currentPage->m_pressedButtons = event->buttons(); @@ -390,31 +386,34 @@ void HelpViewer::mousePressEvent(QMouseEvent *event) void HelpViewer::setLoadFinished(bool ok) { + TRACE_OBJ loadFinished = ok; emit sourceChanged(url()); } #else // !defined(QT_NO_WEBKIT) -HelpViewer::HelpViewer(QHelpEngine *engine, CentralWidget *parent) +HelpViewer::HelpViewer(CentralWidget *parent) : QTextBrowser(parent) , zoomCount(0) , controlPressed(false) , lastAnchor(QString()) - , helpEngine(engine) , parentWidget(parent) + , helpEngine(HelpEngineWrapper::instance()) { + TRACE_OBJ document()->setDocumentMargin(8); } void HelpViewer::setSource(const QUrl &url) { + TRACE_OBJ bool help = url.toString() == QLatin1String("help"); if (url.isValid() && !help) { if (launchedWithExternalApp(url)) return; - QUrl u = helpEngine->findFile(url); + QUrl u = helpEngine.findFile(url); if (u.isValid()) { QTextBrowser::setSource(u); return; @@ -426,15 +425,14 @@ void HelpViewer::setSource(const QUrl &url) "assistantinternal-1.0.0/assistant/assistant.html"))); } else { QTextBrowser::setSource(url); - setHtml(tr("<title>Error 404...</title><div align=\"center\"><br><br>" - "<h1>The page could not be found</h1><br><h3>'%1'</h3></div>") - .arg(url.toString())); + setHtml(PageNotFoundMessage.arg(url.toString())); emit sourceChanged(url); } } void HelpViewer::resetZoom() { + TRACE_OBJ if (zoomCount == 0) return; @@ -444,6 +442,7 @@ void HelpViewer::resetZoom() void HelpViewer::zoomIn(int range) { + TRACE_OBJ if (zoomCount == 10) return; @@ -453,6 +452,7 @@ void HelpViewer::zoomIn(int range) void HelpViewer::zoomOut(int range) { + TRACE_OBJ if (zoomCount == -5) return; @@ -462,12 +462,11 @@ void HelpViewer::zoomOut(int range) bool HelpViewer::launchedWithExternalApp(const QUrl &url) { - bool isPdf = url.path().endsWith(QLatin1String(".pdf")); - if (url.scheme() == QLatin1String("http") - || url.scheme() == QLatin1String("ftp") - || url.scheme() == QLatin1String("mailto") || isPdf) { + TRACE_OBJ + const bool canOpen = canOpenPage(url.path()); + if (!isLocalUrl(url) || !canOpen) { bool launched = false; - if (isPdf && url.scheme() == QLatin1String("qthelp")) { + if (!canOpen && url.scheme() == QLatin1String("qthelp")) { const QString& path = url.path(); const int lastDash = path.lastIndexOf(QChar('/')); QString fileName = QDir::tempPath() + QDir::separator(); @@ -478,7 +477,7 @@ bool HelpViewer::launchedWithExternalApp(const QUrl &url) QFile tmpFile(QDir::cleanPath(fileName)); if (tmpFile.open(QIODevice::ReadWrite)) { - tmpFile.write(helpEngine->fileData(url)); + tmpFile.write(helpEngine.fileData(url)); tmpFile.close(); } launched = QDesktopServices::openUrl(QUrl(tmpFile.fileName())); @@ -497,9 +496,10 @@ bool HelpViewer::launchedWithExternalApp(const QUrl &url) QVariant HelpViewer::loadResource(int type, const QUrl &name) { + TRACE_OBJ QByteArray ba; if (type < 4) { - ba = helpEngine->fileData(name); + ba = helpEngine.fileData(name); if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) { QImage image; image.loadFromData(ba, "svg"); @@ -512,6 +512,7 @@ QVariant HelpViewer::loadResource(int type, const QUrl &name) void HelpViewer::openLinkInNewTab() { + TRACE_OBJ if(lastAnchor.isEmpty()) return; @@ -521,12 +522,14 @@ void HelpViewer::openLinkInNewTab() void HelpViewer::openLinkInNewTab(const QString &link) { + TRACE_OBJ lastAnchor = link; openLinkInNewTab(); } bool HelpViewer::hasAnchorAt(const QPoint& pos) { + TRACE_OBJ lastAnchor = anchorAt(pos); if (lastAnchor.isEmpty()) return false; @@ -543,6 +546,7 @@ bool HelpViewer::hasAnchorAt(const QPoint& pos) void HelpViewer::contextMenuEvent(QContextMenuEvent *e) { + TRACE_OBJ QMenu menu(QLatin1String(""), 0); QUrl link; @@ -566,6 +570,7 @@ void HelpViewer::contextMenuEvent(QContextMenuEvent *e) void HelpViewer::mouseReleaseEvent(QMouseEvent *e) { + TRACE_OBJ if (e->button() == Qt::XButton1) { QTextBrowser::backward(); return; @@ -588,6 +593,7 @@ void HelpViewer::mouseReleaseEvent(QMouseEvent *e) void HelpViewer::keyPressEvent(QKeyEvent *e) { + TRACE_OBJ if ((e->key() == Qt::Key_Home && e->modifiers() != Qt::NoModifier) || (e->key() == Qt::Key_End && e->modifiers() != Qt::NoModifier)) { QKeyEvent* event = new QKeyEvent(e->type(), e->key(), Qt::NoModifier, @@ -597,21 +603,9 @@ void HelpViewer::keyPressEvent(QKeyEvent *e) QTextBrowser::keyPressEvent(e); } -void HelpViewer::home() -{ - QString homepage = helpEngine->customValue(QLatin1String("homepage"), - QLatin1String("")).toString(); - - if (homepage.isEmpty()) { - homepage = helpEngine->customValue(QLatin1String("defaultHomepage"), - QLatin1String("help")).toString(); - } - - setSource(homepage); -} - void HelpViewer::wheelEvent(QWheelEvent *e) { + TRACE_OBJ if (e->modifiers() == Qt::CTRL) { e->accept(); (e->delta() > 0) ? zoomIn() : zoomOut(); @@ -623,4 +617,31 @@ void HelpViewer::wheelEvent(QWheelEvent *e) #endif // !defined(QT_NO_WEBKIT) +void HelpViewer::home() +{ + TRACE_OBJ + setSource(helpEngine.homePage()); +} + +bool HelpViewer::canOpenPage(const QString &url) +{ + TRACE_OBJ + return url.endsWith(QLatin1String(".html"), Qt::CaseInsensitive) + || url.endsWith(QLatin1String(".htm"), Qt::CaseInsensitive) + || url == QLatin1String("blank"); +} + +bool HelpViewer::isLocalUrl(const QUrl &url) +{ + TRACE_OBJ + const QString scheme = url.scheme(); + return scheme.isEmpty() + || scheme == QLatin1String("file") + || scheme == QLatin1String("qrc") + || scheme == QLatin1String("data") + || scheme == QLatin1String("qthelp") + || scheme == QLatin1String("about"); +} + + QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer.h b/tools/assistant/tools/assistant/helpviewer.h index 3618a73..4dd8064 100644 --- a/tools/assistant/tools/assistant/helpviewer.h +++ b/tools/assistant/tools/assistant/helpviewer.h @@ -53,8 +53,8 @@ QT_BEGIN_NAMESPACE -class QHelpEngine; class CentralWidget; +class HelpEngineWrapper; class QPoint; class QString; @@ -69,7 +69,7 @@ class HelpViewer : public QWebView Q_OBJECT public: - HelpViewer(QHelpEngine *helpEngine, CentralWidget *parent); + HelpViewer(CentralWidget *parent); void setSource(const QUrl &url); inline QUrl source() const @@ -97,6 +97,9 @@ public: inline qreal zoom() const { return textSizeMultiplier(); } + static bool canOpenPage(const QString &url); + static bool isLocalUrl(const QUrl &url); + public Q_SLOTS: void home(); void backward() { back(); } @@ -118,9 +121,9 @@ private Q_SLOTS: void setLoadFinished(bool ok); private: - QHelpEngine *helpEngine; CentralWidget* parentWidget; bool loadFinished; + HelpEngineWrapper &helpEngine; }; #else @@ -130,7 +133,7 @@ class HelpViewer : public QTextBrowser Q_OBJECT public: - HelpViewer(QHelpEngine *helpEngine, CentralWidget *parent); + HelpViewer(CentralWidget *parent); void setSource(const QUrl &url); void resetZoom(); @@ -143,6 +146,8 @@ public: { return textCursor().hasSelection(); } bool launchedWithExternalApp(const QUrl &url); + static bool canOpenPage(const QString &url); + static bool isLocalUrl(const QUrl &url); public Q_SLOTS: void home(); @@ -165,8 +170,8 @@ private: int zoomCount; bool controlPressed; QString lastAnchor; - QHelpEngine *helpEngine; CentralWidget* parentWidget; + HelpEngineWrapper &helpEngine; }; #endif diff --git a/tools/assistant/tools/assistant/images/bookmark.png b/tools/assistant/tools/assistant/images/bookmark.png Binary files differnew file mode 100644 index 0000000..57e57e3 --- /dev/null +++ b/tools/assistant/tools/assistant/images/bookmark.png diff --git a/tools/assistant/tools/assistant/indexwindow.cpp b/tools/assistant/tools/assistant/indexwindow.cpp index 24a212e..82242e5 100644 --- a/tools/assistant/tools/assistant/indexwindow.cpp +++ b/tools/assistant/tools/assistant/indexwindow.cpp @@ -38,9 +38,12 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "indexwindow.h" #include "centralwidget.h" +#include "helpenginewrapper.h" +#include "helpviewer.h" #include "topicchooser.h" #include <QtGui/QLayout> @@ -51,22 +54,20 @@ #include <QtGui/QContextMenuEvent> #include <QtGui/QListWidgetItem> -#include <QtHelp/QHelpEngine> #include <QtHelp/QHelpIndexWidget> QT_BEGIN_NAMESPACE -IndexWindow::IndexWindow(QHelpEngine *helpEngine, QWidget *parent) +IndexWindow::IndexWindow(QWidget *parent) : QWidget(parent) - , m_searchLineEdit(0) - , m_indexWidget(0) - , m_helpEngine(helpEngine) + , m_searchLineEdit(new QLineEdit) + , m_indexWidget(HelpEngineWrapper::instance().indexWidget()) { + TRACE_OBJ QVBoxLayout *layout = new QVBoxLayout(this); QLabel *l = new QLabel(tr("&Look for:")); layout->addWidget(l); - m_searchLineEdit = new QLineEdit(); l->setBuddy(m_searchLineEdit); connect(m_searchLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterIndices(QString))); @@ -74,11 +75,11 @@ IndexWindow::IndexWindow(QHelpEngine *helpEngine, QWidget *parent) layout->setMargin(4); layout->addWidget(m_searchLineEdit); - m_indexWidget = m_helpEngine->indexWidget(); + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); m_indexWidget->installEventFilter(this); - connect(m_helpEngine->indexModel(), SIGNAL(indexCreationStarted()), this, + connect(helpEngine.indexModel(), SIGNAL(indexCreationStarted()), this, SLOT(disableSearchLineEdit())); - connect(m_helpEngine->indexModel(), SIGNAL(indexCreated()), this, + connect(helpEngine.indexModel(), SIGNAL(indexCreated()), this, SLOT(enableSearchLineEdit())); connect(m_indexWidget, SIGNAL(linkActivated(QUrl,QString)), this, SIGNAL(linkActivated(QUrl))); @@ -93,10 +94,12 @@ IndexWindow::IndexWindow(QHelpEngine *helpEngine, QWidget *parent) IndexWindow::~IndexWindow() { + TRACE_OBJ } void IndexWindow::filterIndices(const QString &filter) { + TRACE_OBJ if (filter.contains(QLatin1Char('*'))) m_indexWidget->filterIndices(filter, filter); else @@ -105,6 +108,7 @@ void IndexWindow::filterIndices(const QString &filter) bool IndexWindow::eventFilter(QObject *obj, QEvent *e) { + TRACE_OBJ if (obj == m_searchLineEdit && e->type() == QEvent::KeyPress) { QKeyEvent *ke = static_cast<QKeyEvent*>(e); QModelIndex idx = m_indexWidget->currentIndex(); @@ -170,22 +174,26 @@ bool IndexWindow::eventFilter(QObject *obj, QEvent *e) void IndexWindow::enableSearchLineEdit() { + TRACE_OBJ m_searchLineEdit->setDisabled(false); filterIndices(m_searchLineEdit->text()); } void IndexWindow::disableSearchLineEdit() { + TRACE_OBJ m_searchLineEdit->setDisabled(true); } void IndexWindow::setSearchLineEditText(const QString &text) { + TRACE_OBJ m_searchLineEdit->setText(text); } void IndexWindow::focusInEvent(QFocusEvent *e) { + TRACE_OBJ if (e->reason() != Qt::MouseFocusReason) { m_searchLineEdit->selectAll(); m_searchLineEdit->setFocus(); @@ -194,6 +202,7 @@ void IndexWindow::focusInEvent(QFocusEvent *e) void IndexWindow::open(QHelpIndexWidget* indexWidget, const QModelIndex &index) { + TRACE_OBJ QHelpIndexModel *model = qobject_cast<QHelpIndexModel*>(indexWidget->model()); if (model) { QString keyword = model->data(index, Qt::DisplayRole).toString(); @@ -210,7 +219,7 @@ void IndexWindow::open(QHelpIndexWidget* indexWidget, const QModelIndex &index) return; } - if (url.path().endsWith(QLatin1String(".pdf"), Qt::CaseInsensitive)) + if (!HelpViewer::canOpenPage(url.path())) CentralWidget::instance()->setSource(url); else CentralWidget::instance()->setSourceInNewTab(url); diff --git a/tools/assistant/tools/assistant/indexwindow.h b/tools/assistant/tools/assistant/indexwindow.h index 4343d0e..eb587b1 100644 --- a/tools/assistant/tools/assistant/indexwindow.h +++ b/tools/assistant/tools/assistant/indexwindow.h @@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE class QHelpIndexWidget; -class QHelpEngine; class QModelIndex; class IndexWindow : public QWidget @@ -57,7 +56,7 @@ class IndexWindow : public QWidget Q_OBJECT public: - IndexWindow(QHelpEngine *helpEngine, QWidget *parent = 0); + IndexWindow(QWidget *parent = 0); ~IndexWindow(); void setSearchLineEditText(const QString &text); @@ -84,7 +83,6 @@ private: QLineEdit *m_searchLineEdit; QHelpIndexWidget *m_indexWidget; - QHelpEngine *m_helpEngine; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/installdialog.cpp b/tools/assistant/tools/assistant/installdialog.cpp index 95a1226..f3bf6f6 100644 --- a/tools/assistant/tools/assistant/installdialog.cpp +++ b/tools/assistant/tools/assistant/installdialog.cpp @@ -38,6 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "installdialog.h" @@ -66,6 +67,7 @@ InstallDialog::InstallDialog(QHelpEngineCore *helpEngine, QWidget *parent, const QString &host, int port) : QDialog(parent), m_helpEngine(helpEngine), m_host(host), m_port(port) { + TRACE_OBJ m_ui.setupUi(this); m_ui.installButton->setEnabled(false); @@ -94,15 +96,18 @@ InstallDialog::InstallDialog(QHelpEngineCore *helpEngine, QWidget *parent, InstallDialog::~InstallDialog() { + TRACE_OBJ } QStringList InstallDialog::installedDocumentations() const { + TRACE_OBJ return m_installedDocumentations; } void InstallDialog::init() { + TRACE_OBJ m_ui.statusLabel->setText(tr("Downloading documentation info...")); m_ui.progressBar->show(); @@ -122,6 +127,7 @@ void InstallDialog::init() void InstallDialog::updateInstallButton() { + TRACE_OBJ QListWidgetItem *item = 0; for (int i=0; i<m_ui.listWidget->count(); ++i) { item = m_ui.listWidget->item(i); @@ -136,6 +142,7 @@ void InstallDialog::updateInstallButton() void InstallDialog::updateDocItemList() { + TRACE_OBJ QStringList registeredDocs = m_helpEngine->registeredDocumentations(); QListWidgetItem *item = 0; for (int i=0; i<m_ui.listWidget->count(); ++i) { @@ -151,6 +158,7 @@ void InstallDialog::updateDocItemList() void InstallDialog::cancelDownload() { + TRACE_OBJ m_ui.statusLabel->setText(tr("Download canceled.")); m_httpAborted = true; m_itemsToInstall.clear(); @@ -162,6 +170,7 @@ void InstallDialog::cancelDownload() void InstallDialog::install() { + TRACE_OBJ QListWidgetItem *item = 0; for (int i=0; i<m_ui.listWidget->count(); ++i) { item = m_ui.listWidget->item(i); @@ -174,6 +183,7 @@ void InstallDialog::install() void InstallDialog::downloadNextFile() { + TRACE_OBJ if (!m_itemsToInstall.count()) { m_ui.cancelButton->setEnabled(false); m_ui.closeButton->setEnabled(true); @@ -226,6 +236,7 @@ void InstallDialog::downloadNextFile() void InstallDialog::httpRequestFinished(int requestId, bool error) { + TRACE_OBJ if (requestId == m_docInfoId && m_buffer) { m_ui.progressBar->hide(); if (error) { @@ -296,6 +307,7 @@ void InstallDialog::httpRequestFinished(int requestId, bool error) void InstallDialog::installFile(const QString &fileName) { + TRACE_OBJ if (m_helpEngine->registerDocumentation(fileName)) { m_installedDocumentations .append(QHelpEngineCore::namespaceName(fileName)); @@ -308,6 +320,7 @@ void InstallDialog::installFile(const QString &fileName) void InstallDialog::readResponseHeader(const QHttpResponseHeader &responseHeader) { + TRACE_OBJ if (responseHeader.statusCode() != 200) { QMessageBox::information(this, m_windowTitle, tr("Download failed: %1.") @@ -321,6 +334,7 @@ void InstallDialog::readResponseHeader(const QHttpResponseHeader &responseHeader void InstallDialog::updateDataReadProgress(int bytesRead, int totalBytes) { + TRACE_OBJ if (m_httpAborted) return; @@ -330,6 +344,7 @@ void InstallDialog::updateDataReadProgress(int bytesRead, int totalBytes) void InstallDialog::browseDirectories() { + TRACE_OBJ QString dir = QFileDialog::getExistingDirectory(this, m_windowTitle, m_ui.pathLineEdit->text()); if (!dir.isEmpty()) diff --git a/tools/assistant/tools/assistant/main.cpp b/tools/assistant/tools/assistant/main.cpp index 7a957e2..77e5e7c 100644 --- a/tools/assistant/tools/assistant/main.cpp +++ b/tools/assistant/tools/assistant/main.cpp @@ -38,27 +38,34 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include <QtCore/QDir> #include <QtCore/QFileInfo> +#include <QtCore/QLibraryInfo> #include <QtCore/QLocale> +#include <QtCore/QScopedPointer> +#include <QtCore/QStringList> #include <QtCore/QTranslator> -#include <QtCore/QLibraryInfo> #include <QtCore/QUrl> -#include <QtCore/QStringList> #include <QtGui/QApplication> #include <QtGui/QDesktopServices> -#include <QtHelp/QHelpEngineCore> +#include <QtHelp/QHelpEngine> +#include <QtHelp/QHelpSearchEngine> #include <QtNetwork/QLocalSocket> #include <QtSql/QSqlDatabase> +#include "../shared/collectionconfiguration.h" +#include "helpenginewrapper.h" #include "mainwindow.h" #include "cmdlineparser.h" +// #define TRACING_REQUESTED + QT_USE_NAMESPACE #if defined(USE_STATIC_SQLITE_PLUGIN) @@ -66,118 +73,57 @@ QT_USE_NAMESPACE Q_IMPORT_PLUGIN(qsqlite) #endif +namespace { + void updateLastPagesOnUnregister(QHelpEngineCore& helpEngine, const QString& nsName) { - int lastPage = helpEngine.customValue(QLatin1String("LastTabPage")).toInt(); - - QLatin1String sep("|"); - QLatin1String pages("LastShownPages"); -#if !defined(QT_NO_WEBKIT) - QLatin1String zoom("LastPagesZoomWebView"); -#else - QLatin1String zoom("LastPagesZoomTextBrowser"); -#endif - - QStringList currentPages = - helpEngine.customValue(pages).toString(). - split(QLatin1Char('|'), QString::SkipEmptyParts); - + TRACE_OBJ + int lastPage = CollectionConfiguration::lastTabPage(helpEngine); + QStringList currentPages = CollectionConfiguration::lastShownPages(helpEngine); if (!currentPages.isEmpty()) { - QVector<QString>zoomList = helpEngine.customValue(zoom).toString(). - split(sep, QString::SkipEmptyParts).toVector(); - if (zoomList.isEmpty()) - zoomList.fill(QLatin1String("0.0"), currentPages.size()); - else if(zoomList.count() < currentPages.count()) { - zoomList.insert(zoomList.count(), - currentPages.count() - zoomList.count(), QLatin1String("0.0")); - } + QStringList zoomList = CollectionConfiguration::lastZoomFactors(helpEngine); + while (zoomList.count() < currentPages.count()) + zoomList.append(CollectionConfiguration::DefaultZoomFactor); for (int i = currentPages.count(); --i >= 0;) { if (QUrl(currentPages.at(i)).host() == nsName) { - zoomList.remove(i); + zoomList.removeAt(i); currentPages.removeAt(i); lastPage = (lastPage == (i + 1)) ? 1 : lastPage; } } - helpEngine.setCustomValue(pages, currentPages.join(sep)); - helpEngine.setCustomValue(QLatin1String("LastTabPage"), lastPage); - helpEngine.setCustomValue(zoom, QStringList(zoomList.toList()).join(sep)); + CollectionConfiguration::setLastShownPages(helpEngine, currentPages); + CollectionConfiguration::setLastTabPage(helpEngine, lastPage); + CollectionConfiguration::setLastZoomFactors(helpEngine, zoomList); } } bool updateUserCollection(QHelpEngineCore& user, const QHelpEngineCore& caller) { - const uint callerCollectionCreationTime = caller. - customValue(QLatin1String("CreationTime"), 0).toUInt(); - const uint userCollectionCreationTime = user. - customValue(QLatin1String("CreationTime"), 1).toUInt(); - - if (callerCollectionCreationTime <= userCollectionCreationTime) + TRACE_OBJ + if (!CollectionConfiguration::isNewer(caller, user)) return false; - - user.setCustomValue(QLatin1String("CreationTime"), - callerCollectionCreationTime); - user.setCustomValue(QLatin1String("WindowTitle"), - caller.customValue(QLatin1String("WindowTitle"))); - user.setCustomValue(QLatin1String("LastShownPages"), - caller.customValue(QLatin1String("LastShownPages"))); -#if !defined(QT_NO_WEBKIT) - const QLatin1String zoomKey("LastPagesZoomWebView"); -#else - const QLatin1String zoomKey("LastPagesZoomTextBrowser"); -#endif - user.setCustomValue(zoomKey, caller.customValue(zoomKey)); - user.setCustomValue(QLatin1String("CurrentFilter"), - caller.customValue(QLatin1String("CurrentFilter"))); - user.setCustomValue(QLatin1String("CacheDirectory"), - caller.customValue(QLatin1String("CacheDirectory"))); - user.setCustomValue(QLatin1String("EnableFilterFunctionality"), - caller.customValue(QLatin1String("EnableFilterFunctionality"))); - user.setCustomValue(QLatin1String("HideFilterFunctionality"), - caller.customValue(QLatin1String("HideFilterFunctionality"))); - user.setCustomValue(QLatin1String("EnableDocumentationManager"), - caller.customValue(QLatin1String("EnableDocumentationManager"))); - user.setCustomValue(QLatin1String("EnableAddressBar"), - caller.customValue(QLatin1String("EnableAddressBar"))); - user.setCustomValue(QLatin1String("HideAddressBar"), - caller.customValue(QLatin1String("HideAddressBar"))); - user.setCustomValue(QLatin1String("ApplicationIcon"), - caller.customValue(QLatin1String("ApplicationIcon"))); - user.setCustomValue(QLatin1String("AboutMenuTexts"), - caller.customValue(QLatin1String("AboutMenuTexts"))); - user.setCustomValue(QLatin1String("AboutIcon"), - caller.customValue(QLatin1String("AboutIcon"))); - user.setCustomValue(QLatin1String("AboutTexts"), - caller.customValue(QLatin1String("AboutTexts"))); - user.setCustomValue(QLatin1String("AboutImages"), - caller.customValue(QLatin1String("AboutImages"))); - user.setCustomValue(QLatin1String("defaultHomepage"), - caller.customValue(QLatin1String("defaultHomepage"))); - + CollectionConfiguration::copyConfiguration(caller, user); return true; } -bool -referencedHelpFilesExistAll(QHelpEngineCore& user, QStringList& nameSpaces) +void stripNonexistingDocs(QHelpEngineCore& collection) { - QFileInfo fi; - int counter = nameSpaces.count(); - for (int i = counter; --i >= 0;) { - const QString& nameSpace = nameSpaces.at(i); - fi.setFile(user.documentationFileName(nameSpace)); - if (!fi.exists() || !fi.isFile()) { - user.unregisterDocumentation(nameSpace); - nameSpaces.removeAll(nameSpace); - } + TRACE_OBJ + const QStringList &namespaces = collection.registeredDocumentations(); + foreach (const QString &ns, namespaces) { + QFileInfo fi(collection.documentationFileName(ns)); + if (!fi.exists() || !fi.isFile()) + collection.unregisterDocumentation(ns); } - return (counter != nameSpaces.count()) ? false : true; } QString indexFilesFolder(const QString &collectionFile) { + TRACE_OBJ QString indexFilesFolder = QLatin1String(".fulltextsearch"); if (!collectionFile.isEmpty()) { QFileInfo fi(collectionFile); @@ -187,192 +133,306 @@ QString indexFilesFolder(const QString &collectionFile) return indexFilesFolder; } -int main(int argc, char *argv[]) +/* + * Returns the expected absolute file path of the cached collection file + * correspondinging to the given collection's file. + * It may or may not exist yet. + */ +QString constructCachedCollectionFilePath(const QHelpEngineCore &collection) +{ + TRACE_OBJ + const QString &filePath = collection.collectionFile(); + const QString &fileName = QFileInfo(filePath).fileName(); + const QString &cacheDir = CollectionConfiguration::cacheDir(collection); + const QString &dir = !cacheDir.isEmpty() + && CollectionConfiguration::cacheDirIsRelativeToCollection(collection) + ? QFileInfo(filePath).dir().absolutePath() + + QDir::separator() + cacheDir + : MainWindow::collectionFileDirectory(false, cacheDir); + return dir + QDir::separator() + fileName; +} + +bool synchronizeDocs(QHelpEngineCore &collection, + QHelpEngineCore &cachedCollection, + CmdLineParser &cmd) { -#ifndef Q_OS_WIN - // First do a quick search for arguments that imply command-line mode. + TRACE_OBJ + const QDateTime &lastCollectionRegisterTime = + CollectionConfiguration::lastRegisterTime(collection); + if (!lastCollectionRegisterTime.isValid() || lastCollectionRegisterTime + < CollectionConfiguration::lastRegisterTime(cachedCollection)) + return true; + + const QStringList &docs = collection.registeredDocumentations(); + const QStringList &cachedDocs = cachedCollection.registeredDocumentations(); + + /* + * Ensure that the cached collection contains all docs that + * the collection contains. + */ + foreach (const QString &doc, docs) { + if (!cachedDocs.contains(doc)) { + const QString &docFile = collection.documentationFileName(doc); + if (!cachedCollection.registerDocumentation(docFile)) { + cmd.showMessage(QCoreApplication::translate("Assistant", + "Error registering documentation file '%1': %2"). + arg(docFile).arg(cachedCollection.error()), true); + return false; + } + } + } + + CollectionConfiguration::updateLastRegisterTime(cachedCollection); + + return true; +} + +bool removeSearchIndex(const QString &collectionFile) +{ + TRACE_OBJ + QString path = QFileInfo(collectionFile).path(); + path += QLatin1Char('/') + indexFilesFolder(collectionFile); + + QLocalSocket localSocket; + localSocket.connectToServer(QString(QLatin1String("QtAssistant%1")) + .arg(QLatin1String(QT_VERSION_STR))); + + QDir dir(path); // check if there is no other instance ruinning + if (!dir.exists() || localSocket.waitForConnected()) + return false; + + QStringList lst = dir.entryList(QDir::Files | QDir::Hidden); + foreach (const QString &item, lst) + dir.remove(item); + return true; +} + +bool rebuildSearchIndex(QCoreApplication &app, const QString &collectionFile, + CmdLineParser &cmd) +{ + TRACE_OBJ + QHelpEngine engine(collectionFile); + if (!engine.setupData()) { + cmd.showMessage(QCoreApplication::translate("Assistant", "Error: %1") + .arg(engine.error()), true); + return false; + } + + QHelpSearchEngine * const searchEngine = engine.searchEngine(); + QObject::connect(searchEngine, SIGNAL(indexingFinished()), &app, + SLOT(quit())); + searchEngine->reindexDocumentation(); + return app.exec() == 0; +} + +bool useGui(int argc, char *argv[]) +{ + TRACE_OBJ + bool gui = true; +#ifndef Q_OS_WIN + // Look for arguments that imply command-line mode. const char * cmdModeArgs[] = { - "-help", "-register", "-unregister", "-remove-search-index" + "-help", "-register", "-unregister", "-remove-search-index", + "-rebuild-search-index" }; - bool useGui = true; for (int i = 1; i < argc; ++i) { for (size_t j = 0; j < sizeof cmdModeArgs/sizeof *cmdModeArgs; ++j) { if(strcmp(argv[i], cmdModeArgs[j]) == 0) { - useGui = false; + gui = false; break; } } } - QApplication a(argc, argv, useGui); #else - QApplication a(argc, argv); + Q_UNUSED(argc) + Q_UNUSED(argv) #endif + return gui; +} + +bool registerDocumentation(QHelpEngineCore &collection, CmdLineParser &cmd, + bool printSuccess) +{ + TRACE_OBJ + if (!collection.registerDocumentation(cmd.helpFile())) { + cmd.showMessage(QCoreApplication::translate("Assistant", + "Could not register documentation file\n%1\n\nReason:\n%2") + .arg(cmd.helpFile()).arg(collection.error()), true); + return false; + } + if (printSuccess) + cmd.showMessage(QCoreApplication::translate("Assistant", + "Documentation successfully registered."), + false); + CollectionConfiguration::updateLastRegisterTime(collection); + return true; +} + +bool unregisterDocumentation(QHelpEngineCore &collection, + const QString &namespaceName, CmdLineParser &cmd, bool printSuccess) +{ + TRACE_OBJ + if (!collection.unregisterDocumentation(namespaceName)) { + cmd.showMessage(QCoreApplication::translate("Assistant", + "Could not unregister documentation" + " file\n%1\n\nReason:\n%2"). + arg(cmd.helpFile()).arg(collection.error()), true); + return false; + } + updateLastPagesOnUnregister(collection, namespaceName); + if (printSuccess) + cmd.showMessage(QCoreApplication::translate("Assistant", + "Documentation successfully unregistered."), + false); + return true; +} + +void setupTranslation(const QString &fileName, const QString &dir) +{ + QTranslator *translator = new QTranslator(QCoreApplication::instance()); + if (translator->load(fileName, dir)) { + QCoreApplication::installTranslator(translator); + } else { + qWarning("Could not load translation file %s in directory %s.", + qPrintable(fileName), qPrintable(dir)); + } +} + +void setupTranslations() +{ + TRACE_OBJ + const QString& locale = QLocale::system().name(); + const QString &resourceDir + = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + setupTranslation(QLatin1String("assistant_") + locale, resourceDir); + setupTranslation(QLatin1String("qt_") + locale, resourceDir); + setupTranslation(QLatin1String("qt_help_") + locale, resourceDir); +} + +} // Anonymous namespace. + +int main(int argc, char *argv[]) +{ + TRACE_OBJ + QApplication a(argc, argv, useGui(argc, argv)); a.addLibraryPath(a.applicationDirPath() + QLatin1String("/plugins")); - CmdLineParser cmd; - CmdLineParser::Result res = cmd.parse(a.arguments()); + // Parse arguments. + CmdLineParser cmd(a.arguments()); + CmdLineParser::Result res = cmd.parse(); if (res == CmdLineParser::Help) return 0; else if (res == CmdLineParser::Error) return -1; - QString cmdCollectionFile = cmd.collectionFile(); - if (cmd.registerRequest() != CmdLineParser::None) { - if (cmdCollectionFile.isEmpty()) - cmdCollectionFile = MainWindow::defaultHelpCollectionFileName(); - QHelpEngineCore help(cmdCollectionFile); - help.setupData(); - if (cmd.registerRequest() == CmdLineParser::Register) { - if (!help.registerDocumentation(cmd.helpFile())) { - cmd.showMessage( - QObject::tr("Could not register documentation file\n%1\n\nReason:\n%2") - .arg(cmd.helpFile()).arg(help.error()), true); - return -1; - } else { - cmd.showMessage(QObject::tr("Documentation successfully registered."), - false); - } - } else { - QString nsName = QHelpEngineCore::namespaceName(cmd.helpFile()); - if (help.unregisterDocumentation(nsName)) { - updateLastPagesOnUnregister(help, nsName); - cmd.showMessage( - QObject::tr("Documentation successfully unregistered."), - false); - } else { - cmd.showMessage(QObject::tr("Could not unregister documentation" - " file\n%1\n\nReason:\n%2").arg(cmd.helpFile()). - arg(help.error()), true); - return -1; - } + /* + * Create the collection objects that we need. We always have the + * cached collection file. Depending on whether the user specified + * one, we also may have an input collection file. + */ + const QString collectionFile = cmd.collectionFile(); + const bool collectionFileGiven = !collectionFile.isEmpty(); + QScopedPointer<QHelpEngineCore> collection; + if (collectionFileGiven) { + collection.reset(new QHelpEngineCore(collectionFile)); + if (!collection->setupData()) { + cmd.showMessage(QCoreApplication::translate("Assistant", + "Error reading collection file '%1': %2."). + arg(collectionFile).arg(collection->error()), true); + return EXIT_FAILURE; } - help.setCustomValue(QLatin1String("DocUpdate"), true); - return 0; } - - if (cmd.removeSearchIndex()) { - QString file = cmdCollectionFile; - if (file.isEmpty()) - file = MainWindow::defaultHelpCollectionFileName(); - QString path = QFileInfo(file).path(); - path += QLatin1Char('/') + indexFilesFolder(file); - - QLocalSocket localSocket; - localSocket.connectToServer(QString(QLatin1String("QtAssistant%1")) - .arg(QLatin1String(QT_VERSION_STR))); - - QDir dir(path); // check if there is no other instance ruinning - if (!localSocket.waitForConnected() && dir.exists()) { - QStringList lst = dir.entryList(QDir::Files | QDir::Hidden); - foreach (const QString &item, lst) - dir.remove(item); - return 0; - } else { - return -1; - } + const QString &cachedCollectionFile = collectionFileGiven + ? constructCachedCollectionFilePath(*collection) + : MainWindow::defaultHelpCollectionFileName(); + if (collectionFileGiven && !QFileInfo(cachedCollectionFile).exists() + && !collection->copyCollectionFile(cachedCollectionFile)) { + cmd.showMessage(QCoreApplication::translate("Assistant", + "Error creating collection file '%1': %2."). + arg(cachedCollectionFile).arg(collection->error()), true); + return EXIT_FAILURE; } - - { - QSqlDatabase db; - QStringList sqlDrivers(db.drivers()); - if (sqlDrivers.isEmpty() - || !sqlDrivers.contains(QLatin1String("QSQLITE"))) { - cmd.showMessage(QObject::tr("Cannot load sqlite database driver!"), - true); - return -1; - } + QHelpEngineCore cachedCollection(cachedCollectionFile); + if (!cachedCollection.setupData()) { + cmd.showMessage(QCoreApplication::translate("Assistant", + "Error reading collection file '%1': %2"). + arg(cachedCollectionFile). + arg(cachedCollection.error()), true); + return EXIT_FAILURE; } - if (!cmdCollectionFile.isEmpty()) { - QHelpEngineCore caller(cmdCollectionFile); - if (!caller.setupData()) { - cmd.showMessage(QObject::tr("The specified collection file could " - "not be read!"), true); - return -1; - } + stripNonexistingDocs(cachedCollection); + if (collectionFileGiven) { + if (CollectionConfiguration::isNewer(*collection, cachedCollection)) + CollectionConfiguration::copyConfiguration(*collection, + cachedCollection); + if (!synchronizeDocs(*collection, cachedCollection, cmd)) + return EXIT_FAILURE; + } - QString fileName = QFileInfo(cmdCollectionFile).fileName(); - QString dir = MainWindow::collectionFileDirectory(false, - caller.customValue(QLatin1String("CacheDirectory"), - QString()).toString()); - - bool collectionFileExists = true; - QFileInfo fi(dir + QDir::separator() + fileName); - if (!fi.exists()) { - collectionFileExists = false; - if (!caller.copyCollectionFile(fi.absoluteFilePath())) { - cmd.showMessage(caller.error(), true); - return -1; - } + if (cmd.registerRequest() != CmdLineParser::None) { + const QStringList &cachedDocs = + cachedCollection.registeredDocumentations(); + const QString &namespaceName = + QHelpEngineCore::namespaceName(cmd.helpFile()); + if (cmd.registerRequest() == CmdLineParser::Register) { + if (collectionFileGiven + && !registerDocumentation(*collection, cmd, true)) + return EXIT_FAILURE; + if (!cachedDocs.contains(namespaceName) + && !registerDocumentation(cachedCollection, cmd, !collectionFileGiven)) + return EXIT_FAILURE; + return EXIT_SUCCESS; } - - if (collectionFileExists) { - QHelpEngineCore user(fi.absoluteFilePath()); - if (user.setupData()) { - // some docs might have been un/registered - bool docUpdate = caller. - customValue(QLatin1String("DocUpdate"), false).toBool(); - - // update in case the passed collection file changed - if (updateUserCollection(user, caller)) - docUpdate = true; - - QStringList userDocs = user.registeredDocumentations(); - // update user collection file, docs might have been (re)moved - if (!referencedHelpFilesExistAll(user, userDocs)) - docUpdate = true; - - if (docUpdate) { - QStringList callerDocs = caller.registeredDocumentations(); - foreach (const QString &doc, callerDocs) { - if (!userDocs.contains(doc)) { - user.registerDocumentation( - caller.documentationFileName(doc)); - } - } - - QLatin1String intern("com.trolltech.com.assistantinternal-"); - foreach (const QString &doc, userDocs) { - if (!callerDocs.contains(doc) && !doc.startsWith(intern)) - user.unregisterDocumentation(doc); - } - - caller.setCustomValue(QLatin1String("DocUpdate"), false); - } - } + if (cmd.registerRequest() == CmdLineParser::Unregister) { + if (collectionFileGiven + && !unregisterDocumentation(*collection, namespaceName, cmd, true)) + return EXIT_FAILURE; + if (cachedDocs.contains(namespaceName) + && !unregisterDocumentation(cachedCollection, namespaceName, + cmd, !collectionFileGiven)) + return EXIT_FAILURE; + return EXIT_SUCCESS; } - cmd.setCollectionFile(fi.absoluteFilePath()); } - if (!cmd.currentFilter().isEmpty()) { - QString collectionFile; - if (cmdCollectionFile.isEmpty()) { - MainWindow::collectionFileDirectory(true); - cmdCollectionFile = MainWindow::defaultHelpCollectionFileName(); - } - - QHelpEngineCore user(cmdCollectionFile); - if (user.setupData()) - user.setCurrentFilter(cmd.currentFilter()); + if (cmd.removeSearchIndex()) { + return removeSearchIndex(cachedCollectionFile) + ? EXIT_SUCCESS : EXIT_FAILURE; } - const QString& locale = QLocale::system().name(); - QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath); - - QTranslator translator(0); - translator.load(QLatin1String("assistant_") + locale, resourceDir); - a.installTranslator(&translator); + if (cmd.rebuildSearchIndex()) { + return rebuildSearchIndex(a, cachedCollectionFile, cmd) + ? EXIT_SUCCESS : EXIT_FAILURE; + } - QTranslator qtTranslator(0); - qtTranslator.load(QLatin1String("qt_") + locale, resourceDir); - a.installTranslator(&qtTranslator); + if (!QSqlDatabase::isDriverAvailable(QLatin1String("QSQLITE"))) { + cmd.showMessage(QCoreApplication::translate("Assistant", + "Cannot load sqlite database driver!"), + true); + return EXIT_FAILURE; + } - QTranslator qtHelpTranslator(0); - qtHelpTranslator.load(QLatin1String("qt_help_") + locale, resourceDir); - a.installTranslator(&qtHelpTranslator); + if (!cmd.currentFilter().isEmpty()) { + if (collectionFileGiven) + collection->setCurrentFilter(cmd.currentFilter()); + cachedCollection.setCurrentFilter(cmd.currentFilter()); + } - MainWindow w(&cmd); - w.show(); + setupTranslations(); + + /* + * We need to be careful here: The main window has to be deleted before + * the help engine wrapper, which has to be deleted before the + * QApplication. + */ + if (collectionFileGiven) + cmd.setCollectionFile(cachedCollectionFile); + MainWindow *w = new MainWindow(&cmd); + w->show(); a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); - return a.exec(); + const int retval = a.exec(); + delete w; + HelpEngineWrapper::removeInstance(); + return retval; } diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp index 0dbf813..2ff6b5e 100644 --- a/tools/assistant/tools/assistant/mainwindow.cpp +++ b/tools/assistant/tools/assistant/mainwindow.cpp @@ -38,24 +38,32 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "mainwindow.h" + +#include "bookmarkmanager.h" #include "centralwidget.h" #include "helpviewer.h" #include "indexwindow.h" #include "topicchooser.h" #include "contentwindow.h" #include "preferencesdialog.h" -#include "bookmarkmanager.h" +#include "helpenginewrapper.h" #include "remotecontrol.h" #include "cmdlineparser.h" #include "aboutdialog.h" #include "searchwidget.h" #include "qtdocinstaller.h" +// #define TRACING_REQUESTED + #include <QtCore/QDir> #include <QtCore/QTimer> +#include <QtCore/QDateTime> #include <QtCore/QDebug> +#include <QtCore/QFileSystemWatcher> +#include <QtCore/QPair> #include <QtCore/QResource> #include <QtCore/QByteArray> #include <QtCore/QTextStream> @@ -76,8 +84,9 @@ #include <QtGui/QProgressBar> #include <QtGui/QDesktopServices> #include <QtGui/QToolButton> +#include <QtGui/QFileDialog> -#include <QtHelp/QHelpEngine> +#include <QtHelp/QHelpEngineCore> #include <QtHelp/QHelpSearchEngine> #include <QtHelp/QHelpContentModel> #include <QtHelp/QHelpIndexModel> @@ -86,6 +95,7 @@ QT_BEGIN_NAMESPACE MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) : QMainWindow(parent) + , m_bookmarkWidget(0) , m_filterCombo(0) , m_toolBarMenu(0) , m_cmdLine(cmdLine) @@ -93,37 +103,53 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) , m_qtDocInstaller(0) , m_connectedInitSignals(false) { + TRACE_OBJ + setToolButtonStyle(Qt::ToolButtonFollowStyle); + QString collectionFile; if (usesDefaultCollection()) { MainWindow::collectionFileDirectory(true); - m_helpEngine = new QHelpEngine(MainWindow::defaultHelpCollectionFileName(), - this); + collectionFile = MainWindow::defaultHelpCollectionFileName(); } else { - m_helpEngine = new QHelpEngine(cmdLine->collectionFile(), this); + collectionFile = cmdLine->collectionFile(); } + HelpEngineWrapper &helpEngineWrapper = + HelpEngineWrapper::instance(collectionFile); - m_centralWidget = new CentralWidget(m_helpEngine, this); + m_centralWidget = new CentralWidget(this); setCentralWidget(m_centralWidget); - m_indexWindow = new IndexWindow(m_helpEngine); + m_indexWindow = new IndexWindow(this); QDockWidget *indexDock = new QDockWidget(tr("Index"), this); indexDock->setObjectName(QLatin1String("IndexWindow")); indexDock->setWidget(m_indexWindow); addDockWidget(Qt::LeftDockWidgetArea, indexDock); - m_contentWindow = new ContentWindow(m_helpEngine); + m_contentWindow = new ContentWindow; QDockWidget *contentDock = new QDockWidget(tr("Contents"), this); contentDock->setObjectName(QLatin1String("ContentWindow")); contentDock->setWidget(m_contentWindow); addDockWidget(Qt::LeftDockWidgetArea, contentDock); - QDockWidget *bookmarkDock = new QDockWidget(tr("Bookmarks"), this); - bookmarkDock->setObjectName(QLatin1String("BookmarkWindow")); - bookmarkDock->setWidget(setupBookmarkWidget()); - addDockWidget(Qt::LeftDockWidgetArea, bookmarkDock); + 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, + SLOT(activateCurrentCentralWidgetTab())); + connect(manager, 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))); + } - QHelpSearchEngine *searchEngine = m_helpEngine->searchEngine(); + QHelpSearchEngine *searchEngine = helpEngineWrapper.searchEngine(); connect(searchEngine, SIGNAL(indexingStarted()), this, SLOT(indexingStarted())); connect(searchEngine, SIGNAL(indexingFinished()), this, SLOT(indexingFinished())); @@ -140,18 +166,9 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) setupFilterToolbar(); setupAddressToolbar(); - m_bookmarkManager->setupBookmarkModels(); - m_bookmarkMenu->addSeparator(); - m_bookmarkManager->fillBookmarkMenu(m_bookmarkMenu); - connect(m_bookmarkMenu, SIGNAL(triggered(QAction*)), this, - SLOT(showBookmark(QAction*))); - connect(m_bookmarkManager, SIGNAL(bookmarksChanged()), this, - SLOT(updateBookmarkMenu())); - - setWindowTitle(m_helpEngine->customValue(QLatin1String("WindowTitle"), - defWindowTitle).toString()); - QByteArray iconArray = m_helpEngine->customValue(QLatin1String("ApplicationIcon"), - QByteArray()).toByteArray(); + const QString windowTitle = helpEngineWrapper.windowTitle(); + setWindowTitle(windowTitle.isEmpty() ? defWindowTitle : windowTitle); + QByteArray iconArray = helpEngineWrapper.applicationIcon(); if (iconArray.size() > 0) { QPixmap pix; pix.loadFromData(iconArray); @@ -165,29 +182,28 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) // Show the widget here, otherwise the restore geometry and state won't work // on x11. show(); - QByteArray ba(m_helpEngine->customValue(QLatin1String("MainWindow")).toByteArray()); + QByteArray ba(helpEngineWrapper.mainWindow()); if (!ba.isEmpty()) restoreState(ba); - ba = m_helpEngine->customValue(QLatin1String("MainWindowGeometry")).toByteArray(); + ba = helpEngineWrapper.mainWindowGeometry(); if (!ba.isEmpty()) { restoreGeometry(ba); } else { tabifyDockWidget(contentDock, indexDock); - tabifyDockWidget(indexDock, bookmarkDock); + if (bookmarkDock) + tabifyDockWidget(indexDock, bookmarkDock); contentDock->raise(); resize(QSize(800, 600)); } - if (!m_helpEngine->customValue(QLatin1String("useAppFont")).isValid()) { - m_helpEngine->setCustomValue(QLatin1String("useAppFont"), false); - m_helpEngine->setCustomValue(QLatin1String("useBrowserFont"), false); - m_helpEngine->setCustomValue(QLatin1String("appFont"), qApp->font()); - m_helpEngine->setCustomValue(QLatin1String("appWritingSystem"), - QFontDatabase::Latin); - m_helpEngine->setCustomValue(QLatin1String("browserFont"), qApp->font()); - m_helpEngine->setCustomValue(QLatin1String("browserWritingSystem"), - QFontDatabase::Latin); + 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(); } @@ -196,7 +212,7 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) QTimer::singleShot(0, this, SLOT(insertLastPages())); if (m_cmdLine->enableRemoteControl()) - (void)new RemoteControl(this, m_helpEngine); + (void)new RemoteControl(this); if (m_cmdLine->contents() == CmdLineParser::Show) showContents(); @@ -209,9 +225,9 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) hideIndex(); if (m_cmdLine->bookmarks() == CmdLineParser::Show) - showBookmarks(); + showBookmarksDockWidget(); else if (m_cmdLine->bookmarks() == CmdLineParser::Hide) - hideBookmarks(); + hideBookmarksDockWidget(); if (m_cmdLine->search() == CmdLineParser::Show) showSearch(); @@ -223,51 +239,59 @@ MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent) else if (m_cmdLine->index() == CmdLineParser::Activate) showIndex(); else if (m_cmdLine->bookmarks() == CmdLineParser::Activate) - showBookmarks(); + showBookmarksDockWidget(); if (!m_cmdLine->currentFilter().isEmpty()) { const QString &curFilter = m_cmdLine->currentFilter(); - if (m_helpEngine->customFilters().contains(curFilter)) - m_helpEngine->setCurrentFilter(curFilter); + 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); } MainWindow::~MainWindow() { + TRACE_OBJ if (m_qtDocInstaller) delete m_qtDocInstaller; } bool MainWindow::usesDefaultCollection() const { + TRACE_OBJ return m_cmdLine->collectionFile().isEmpty(); } void MainWindow::closeEvent(QCloseEvent *e) { - m_bookmarkManager->saveBookmarks(); - m_helpEngine->setCustomValue(QLatin1String("MainWindow"), saveState()); - m_helpEngine->setCustomValue(QLatin1String("MainWindowGeometry"), - saveGeometry()); - + TRACE_OBJ + BookmarkManager::destroy(); + HelpEngineWrapper::instance().setMainWindow(saveState()); + HelpEngineWrapper::instance().setMainWindowGeometry(saveGeometry()); QMainWindow::closeEvent(e); } bool MainWindow::initHelpDB() { - if (!m_helpEngine->setupData()) + TRACE_OBJ + HelpEngineWrapper &helpEngineWrapper = HelpEngineWrapper::instance(); + if (!helpEngineWrapper.setupData()) return false; bool assistantInternalDocRegistered = false; QString intern(QLatin1String("com.trolltech.com.assistantinternal-")); - foreach (const QString &ns, m_helpEngine->registeredDocumentations()) { + foreach (const QString &ns, helpEngineWrapper.registeredDocumentations()) { if (ns.startsWith(intern)) { intern = ns; assistantInternalDocRegistered = true; @@ -275,8 +299,7 @@ bool MainWindow::initHelpDB() } } - const QString &collectionFile = m_helpEngine->collectionFile(); - + const QString &collectionFile = helpEngineWrapper.collectionFile(); QFileInfo fi(collectionFile); QString helpFile; QTextStream(&helpFile) << fi.absolutePath() << QDir::separator() @@ -293,109 +316,79 @@ bool MainWindow::initHelpDB() file.close(); } - QHelpEngineCore hc(fi.absoluteFilePath()); - hc.setupData(); - hc.unregisterDocumentation(intern); - hc.registerDocumentation(helpFile); - needsSetup = true; - } - - const QLatin1String unfiltered("UnfilteredFilterInserted"); - if (1 != m_helpEngine->customValue(unfiltered).toInt()) { - { - QHelpEngineCore hc(collectionFile); - hc.setupData(); - hc.addCustomFilter(tr("Unfiltered"), QStringList()); - hc.setCustomValue(unfiltered, 1); - } - - m_helpEngine->blockSignals(true); - m_helpEngine->setCurrentFilter(tr("Unfiltered")); - m_helpEngine->blockSignals(false); + helpEngineWrapper.unregisterDocumentation(intern); + helpEngineWrapper.registerDocumentation(helpFile); needsSetup = true; } if (needsSetup) - m_helpEngine->setupData(); + helpEngineWrapper.setupData(); return true; } void MainWindow::lookForNewQtDocumentation() { - m_qtDocInstaller = new QtDocInstaller(m_helpEngine->collectionFile()); - connect(m_qtDocInstaller, SIGNAL(errorMessage(QString)), this, - SLOT(displayInstallationError(QString))); + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + QStringList docs; + docs << QLatin1String("assistant") + << QLatin1String("designer") + << QLatin1String("linguist") + << QLatin1String("qmake") + << QLatin1String("qt"); + QList<QtDocInstaller::DocInfo> qtDocInfos; + foreach (const QString &doc, docs) + qtDocInfos.append(QtDocInstaller::DocInfo(doc, helpEngine.qtDocInfo(doc))); + + m_qtDocInstaller = new QtDocInstaller(qtDocInfos); connect(m_qtDocInstaller, SIGNAL(docsInstalled(bool)), this, SLOT(qtDocumentationInstalled(bool))); - - QString versionKey = QString(QLatin1String("qtVersion%1$$$qt")). - arg(QLatin1String(QT_VERSION_STR)); - if (m_helpEngine->customValue(versionKey, 0).toInt() != 1) + connect(m_qtDocInstaller, SIGNAL(qchFileNotFound(QString)), this, + SLOT(resetQtDocInfo(QString))); + connect(m_qtDocInstaller, SIGNAL(registerDocumentation(QString, QString)), + this, SLOT(registerDocumentation(QString, QString))); + if (helpEngine.qtDocInfo(QLatin1String("qt")).count() != 2) statusBar()->showMessage(tr("Looking for Qt Documentation...")); m_qtDocInstaller->installDocs(); } -void MainWindow::displayInstallationError(const QString &errorMessage) -{ - QMessageBox::warning(this, tr("Qt Assistant"), errorMessage); -} - void MainWindow::qtDocumentationInstalled(bool newDocsInstalled) { + TRACE_OBJ if (newDocsInstalled) - m_helpEngine->setupData(); + HelpEngineWrapper::instance().setupData(); statusBar()->clearMessage(); checkInitState(); } void MainWindow::checkInitState() { + TRACE_OBJ if (!m_cmdLine->enableRemoteControl()) return; - if (m_helpEngine->contentModel()->isCreatingContents() - || m_helpEngine->indexModel()->isCreatingIndex()) { + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + if (helpEngine.contentModel()->isCreatingContents() + || helpEngine.indexModel()->isCreatingIndex()) { if (!m_connectedInitSignals) { - connect(m_helpEngine->contentModel(), SIGNAL(contentsCreated()), + connect(helpEngine.contentModel(), SIGNAL(contentsCreated()), this, SLOT(checkInitState())); - connect(m_helpEngine->indexModel(), SIGNAL(indexCreated()), this, + connect(helpEngine.indexModel(), SIGNAL(indexCreated()), this, SLOT(checkInitState())); m_connectedInitSignals = true; } } else { if (m_connectedInitSignals) { - disconnect(m_helpEngine->contentModel(), 0, this, 0); - disconnect(m_helpEngine->indexModel(), 0, this, 0); + disconnect(helpEngine.contentModel(), 0, this, 0); + disconnect(helpEngine.indexModel(), 0, this, 0); } emit initDone(); } } -void MainWindow::updateBookmarkMenu() -{ - if (m_bookmarkManager) { - m_bookmarkMenu->removeAction(m_bookmarkMenuAction); - - m_bookmarkMenu->clear(); - - m_bookmarkMenu->addAction(m_bookmarkMenuAction); - m_bookmarkMenu->addSeparator(); - - m_bookmarkManager->fillBookmarkMenu(m_bookmarkMenu); - } -} - -void MainWindow::showBookmark(QAction *action) -{ - if (m_bookmarkManager) { - const QUrl &url = m_bookmarkManager->urlForAction(action); - if (url.isValid()) - m_centralWidget->setSource(url); - } -} - void MainWindow::insertLastPages() { + TRACE_OBJ if (m_cmdLine->url().isValid()) m_centralWidget->setSource(m_cmdLine->url()); else @@ -407,6 +400,7 @@ void MainWindow::insertLastPages() void MainWindow::setupActions() { + TRACE_OBJ QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); #ifdef Q_OS_MAC setUnifiedTitleAndToolBarOnMac(true); @@ -437,8 +431,12 @@ void MainWindow::setupActions() m_closeTabAction->setShortcuts(QKeySequence::Close); QAction *tmp = menu->addAction(tr("&Quit"), this, SLOT(close())); - tmp->setShortcut(QKeySequence::Quit); tmp->setMenuRole(QAction::QuitRole); +#ifdef Q_OS_WIN + tmp->setShortcut(QKeySequence(tr("CTRL+Q"))); +#else + tmp->setShortcut(QKeySequence::Quit); +#endif menu = menuBar()->addMenu(tr("&Edit")); m_copyAction = menu->addAction(tr("&Copy selected Text"), m_centralWidget, @@ -492,7 +490,7 @@ void MainWindow::setupActions() QKeySequence(tr("ALT+C"))); m_viewMenu->addAction(tr("Index"), this, SLOT(showIndex()), QKeySequence(tr("ALT+I"))); - m_viewMenu->addAction(tr("Bookmarks"), this, SLOT(showBookmarks()), + m_viewMenu->addAction(tr("Bookmarks"), this, SLOT(showBookmarksDockWidget()), QKeySequence(tr("ALT+O"))); m_viewMenu->addAction(tr("Search"), this, SLOT(showSearchWidget()), QKeySequence(tr("ALT+S"))); @@ -528,10 +526,8 @@ void MainWindow::setupActions() tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Left")) << QKeySequence(Qt::CTRL + Qt::Key_PageUp)); - m_bookmarkMenu = menuBar()->addMenu(tr("&Bookmarks")); - m_bookmarkMenuAction = m_bookmarkMenu->addAction(tr("Add Bookmark..."), - this, SLOT(addBookmark())); - m_bookmarkMenuAction->setShortcut(tr("CTRL+D")); + if (BookmarkManager *manager = BookmarkManager::instance()) + manager->takeBookmarksMenu(menuBar()->addMenu(tr("&Bookmarks"))); menu = menuBar()->addMenu(tr("&Help")); m_aboutAction = menu->addAction(tr("About..."), this, SLOT(showAboutDialog())); @@ -592,14 +588,6 @@ void MainWindow::setupActions() SLOT(updateNavigationItems())); connect(m_centralWidget, SIGNAL(highlighted(QString)), statusBar(), SLOT(showMessage(QString))); - connect(m_centralWidget, SIGNAL(addNewBookmark(QString,QString)), this, - SLOT(addNewBookmark(QString,QString))); - - // bookmarks - connect(m_bookmarkWidget, SIGNAL(requestShowLink(QUrl)), m_centralWidget, - SLOT(setSource(QUrl))); - connect(m_bookmarkWidget, SIGNAL(escapePressed()), this, - SLOT(activateCurrentCentralWidgetTab())); // index window connect(m_indexWindow, SIGNAL(linkActivated(QUrl)), m_centralWidget, @@ -624,6 +612,7 @@ void MainWindow::setupActions() QMenu *MainWindow::toolBarMenu() { + TRACE_OBJ if (!m_toolBarMenu) { m_viewMenu->addSeparator(); m_toolBarMenu = m_viewMenu->addMenu(tr("Toolbars")); @@ -633,8 +622,9 @@ QMenu *MainWindow::toolBarMenu() void MainWindow::setupFilterToolbar() { - if (!m_helpEngine-> - customValue(QLatin1String("EnableFilterFunctionality"), true).toBool()) + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + if (!helpEngine.filterFunctionalityEnabled()) return; m_filterCombo = new QComboBox(this); @@ -647,16 +637,15 @@ void MainWindow::setupFilterToolbar() this)); filterToolBar->addWidget(m_filterCombo); - const QLatin1String hideFilter("HideFilterFunctionality"); - if (m_helpEngine->customValue(hideFilter, true).toBool()) + if (!helpEngine.filterToolbarVisible()) filterToolBar->hide(); toolBarMenu()->addAction(filterToolBar->toggleViewAction()); - connect(m_helpEngine, SIGNAL(setupFinished()), this, - SLOT(setupFilterCombo())); + connect(&helpEngine, SIGNAL(setupFinished()), this, + SLOT(setupFilterCombo()), Qt::QueuedConnection); connect(m_filterCombo, SIGNAL(activated(QString)), this, SLOT(filterDocumentation(QString))); - connect(m_helpEngine, SIGNAL(currentFilterChanged(QString)), this, + connect(&helpEngine, SIGNAL(currentFilterChanged(QString)), this, SLOT(currentFilterChanged(QString))); setupFilterCombo(); @@ -664,7 +653,9 @@ void MainWindow::setupFilterToolbar() void MainWindow::setupAddressToolbar() { - if (!m_helpEngine->customValue(QLatin1String("EnableAddressBar"), true).toBool()) + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + if (!helpEngine.addressBarEnabled()) return; m_addressLineEdit = new QLineEdit(this); @@ -676,7 +667,7 @@ void MainWindow::setupAddressToolbar() this)); addressToolBar->addWidget(m_addressLineEdit); - if (m_helpEngine->customValue(QLatin1String("HideAddressBar"), true).toBool()) + if (!helpEngine.addressBarVisible()) addressToolBar->hide(); toolBarMenu()->addAction(addressToolBar->toggleViewAction()); @@ -691,57 +682,53 @@ void MainWindow::setupAddressToolbar() void MainWindow::updateAboutMenuText() { - if (m_helpEngine) { - QByteArray ba = m_helpEngine->customValue(QLatin1String("AboutMenuTexts"), - QByteArray()).toByteArray(); - if (ba.size() > 0) { - QString lang; - QString str; - QString trStr; - QString currentLang = QLocale::system().name(); - int i = currentLang.indexOf(QLatin1Char('_')); - if (i > -1) - currentLang = currentLang.left(i); - QDataStream s(&ba, QIODevice::ReadOnly); - while (!s.atEnd()) { - s >> lang; - s >> str; - if (lang == QLatin1String("default") && trStr.isEmpty()) { - trStr = str; - } else if (lang == currentLang) { - trStr = str; - break; - } + TRACE_OBJ + QByteArray ba = HelpEngineWrapper::instance().aboutMenuTexts(); + if (ba.size() > 0) { + QString lang; + QString str; + QString trStr; + QString currentLang = QLocale::system().name(); + int i = currentLang.indexOf(QLatin1Char('_')); + if (i > -1) + currentLang = currentLang.left(i); + QDataStream s(&ba, QIODevice::ReadOnly); + while (!s.atEnd()) { + s >> lang; + s >> str; + if (lang == QLatin1String("default") && trStr.isEmpty()) { + trStr = str; + } else if (lang == currentLang) { + trStr = str; + break; } - if (!trStr.isEmpty()) - m_aboutAction->setText(trStr); } + if (!trStr.isEmpty()) + m_aboutAction->setText(trStr); } } void MainWindow::showNewAddress() { + TRACE_OBJ showNewAddress(m_centralWidget->currentSource()); } void MainWindow::showNewAddress(const QUrl &url) { + TRACE_OBJ m_addressLineEdit->setText(url.toString()); } -void MainWindow::addBookmark() -{ - addNewBookmark(m_centralWidget->currentTitle(), - m_centralWidget->currentSource().toString()); -} - void MainWindow::gotoAddress() { + TRACE_OBJ 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); @@ -755,12 +742,14 @@ void MainWindow::updateNavigationItems() void MainWindow::updateTabCloseAction() { + TRACE_OBJ m_closeTabAction->setEnabled(m_centralWidget->enableTabCloseAction()); } void MainWindow::showTopicChooser(const QMap<QString, QUrl> &links, const QString &keyword) { + TRACE_OBJ TopicChooser tc(this, keyword, links); if (tc.exec() == QDialog::Accepted) { m_centralWidget->setSource(tc.link()); @@ -769,7 +758,8 @@ void MainWindow::showTopicChooser(const QMap<QString, QUrl> &links, void MainWindow::showPreferences() { - PreferencesDialog dia(m_helpEngine, this); + TRACE_OBJ + PreferencesDialog dia(this); connect(&dia, SIGNAL(updateApplicationFont()), this, SLOT(updateApplicationFont())); @@ -781,6 +771,7 @@ void MainWindow::showPreferences() void MainWindow::syncContents() { + TRACE_OBJ qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); const QUrl url = m_centralWidget->currentSource(); showContents(); @@ -792,40 +783,32 @@ void MainWindow::syncContents() void MainWindow::copyAvailable(bool yes) { + TRACE_OBJ m_copyAction->setEnabled(yes); } -void MainWindow::addNewBookmark(const QString &title, const QString &url) -{ - if (url.isEmpty() || url == QLatin1String("about:blank")) - return; - - m_bookmarkManager->showBookmarkDialog(this, title, url); -} - void MainWindow::showAboutDialog() { + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); QByteArray contents; - if (m_helpEngine) { - QByteArray ba = m_helpEngine->customValue(QLatin1String("AboutTexts"), - QByteArray()).toByteArray(); - if (!ba.isEmpty()) { - QString lang; - QByteArray cba; - QString currentLang = QLocale::system().name(); - int i = currentLang.indexOf(QLatin1Char('_')); - if (i > -1) - currentLang = currentLang.left(i); - QDataStream s(&ba, QIODevice::ReadOnly); - while (!s.atEnd()) { - s >> lang; - s >> cba; - if (lang == QLatin1String("default") && contents.isEmpty()) { - contents = cba; - } else if (lang == currentLang) { - contents = cba; - break; - } + QByteArray ba = helpEngine.aboutTexts(); + if (!ba.isEmpty()) { + QString lang; + QByteArray cba; + QString currentLang = QLocale::system().name(); + int i = currentLang.indexOf(QLatin1Char('_')); + if (i > -1) + currentLang = currentLang.left(i); + QDataStream s(&ba, QIODevice::ReadOnly); + while (!s.atEnd()) { + s >> lang; + s >> cba; + if (lang == QLatin1String("default") && contents.isEmpty()) { + contents = cba; + } else if (lang == currentLang) { + contents = cba; + break; } } } @@ -834,11 +817,8 @@ void MainWindow::showAboutDialog() QByteArray iconArray; if (!contents.isEmpty()) { - iconArray = m_helpEngine->customValue(QLatin1String("AboutIcon"), - QByteArray()).toByteArray(); - QByteArray resources = - m_helpEngine->customValue(QLatin1String("AboutImages"), - QByteArray()).toByteArray(); + iconArray = helpEngine.aboutIcon(); + QByteArray resources = helpEngine.aboutImages(); QPixmap pix; pix.loadFromData(iconArray); aboutDia.setText(QString::fromUtf8(contents), resources); @@ -861,50 +841,109 @@ void MainWindow::showAboutDialog() aboutDia.exec(); } +void MainWindow::setContentsVisible(bool visible) +{ + TRACE_OBJ + if (visible) + showContents(); + else + hideContents(); +} + void MainWindow::showContents() { + TRACE_OBJ activateDockWidget(m_contentWindow); } +void MainWindow::hideContents() +{ + TRACE_OBJ + m_contentWindow->parentWidget()->hide(); +} + +void MainWindow::setIndexVisible(bool visible) +{ + TRACE_OBJ + if (visible) + showIndex(); + else + hideIndex(); +} + void MainWindow::showIndex() { + TRACE_OBJ activateDockWidget(m_indexWindow); } -void MainWindow::showBookmarks() +void MainWindow::hideIndex() { - activateDockWidget(m_bookmarkWidget); + TRACE_OBJ + m_indexWindow->parentWidget()->hide(); } -void MainWindow::activateDockWidget(QWidget *w) +void MainWindow::setBookmarksVisible(bool visible) { - w->parentWidget()->show(); - w->parentWidget()->raise(); - w->setFocus(); + TRACE_OBJ + if (visible) + showBookmarksDockWidget(); + else + hideBookmarksDockWidget(); } -void MainWindow::hideContents() +void MainWindow::showBookmarksDockWidget() { - m_contentWindow->parentWidget()->hide(); + TRACE_OBJ + if (m_bookmarkWidget) + activateDockWidget(m_bookmarkWidget); } -void MainWindow::hideIndex() +void MainWindow::hideBookmarksDockWidget() { - m_indexWindow->parentWidget()->hide(); + TRACE_OBJ + if (m_bookmarkWidget) + m_bookmarkWidget->parentWidget()->hide(); } -void MainWindow::hideBookmarks() +void MainWindow::setSearchVisible(bool visible) { - m_bookmarkWidget->parentWidget()->hide(); + TRACE_OBJ + if (visible) + showSearch(); + else + hideSearch(); +} + +void MainWindow::showSearch() +{ + TRACE_OBJ + m_centralWidget->activateSearchWidget(); +} + +void MainWindow::hideSearch() +{ + TRACE_OBJ + m_centralWidget->removeSearchWidget(); +} + +void MainWindow::activateDockWidget(QWidget *w) +{ + TRACE_OBJ + w->parentWidget()->show(); + w->parentWidget()->raise(); + w->setFocus(); } void MainWindow::setIndexString(const QString &str) { + TRACE_OBJ m_indexWindow->setSearchLineEditText(str); } void MainWindow::activateCurrentBrowser() { + TRACE_OBJ CentralWidget *cw = CentralWidget::instance(); if (cw) { cw->activateTab(true); @@ -913,40 +952,36 @@ void MainWindow::activateCurrentBrowser() void MainWindow::activateCurrentCentralWidgetTab() { + TRACE_OBJ m_centralWidget->activateTab(); } -void MainWindow::showSearch() -{ - m_centralWidget->activateSearchWidget(); -} - void MainWindow::showSearchWidget() { + TRACE_OBJ m_centralWidget->activateSearchWidget(true); } -void MainWindow::hideSearch() -{ - m_centralWidget->removeSearchWidget(); -} - void MainWindow::updateApplicationFont() { + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); QFont font = qApp->font(); - if (m_helpEngine->customValue(QLatin1String("useAppFont")).toBool()) - font = qVariantValue<QFont>(m_helpEngine->customValue(QLatin1String("appFont"))); + if (helpEngine.usesAppFont()) + font = helpEngine.appFont(); qApp->setFont(font, "QWidget"); } void MainWindow::setupFilterCombo() { + TRACE_OBJ + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); QString curFilter = m_filterCombo->currentText(); if (curFilter.isEmpty()) - curFilter = m_helpEngine->currentFilter(); + curFilter = helpEngine.currentFilter(); m_filterCombo->clear(); - m_filterCombo->addItems(m_helpEngine->customFilters()); + m_filterCombo->addItems(helpEngine.customFilters()); int idx = m_filterCombo->findText(curFilter); if (idx < 0) idx = 0; @@ -955,16 +990,20 @@ void MainWindow::setupFilterCombo() void MainWindow::filterDocumentation(const QString &customFilter) { - m_helpEngine->setCurrentFilter(customFilter); + TRACE_OBJ + HelpEngineWrapper::instance().setCurrentFilter(customFilter); } void MainWindow::expandTOC(int depth) { + TRACE_OBJ + Q_ASSERT(depth >= -1); m_contentWindow->expandToDepth(depth); } void MainWindow::indexingStarted() { + TRACE_OBJ if (!m_progressWidget) { m_progressWidget = new QWidget(); QLayout* hlayout = new QHBoxLayout(m_progressWidget); @@ -990,21 +1029,15 @@ void MainWindow::indexingStarted() void MainWindow::indexingFinished() { + TRACE_OBJ statusBar()->removeWidget(m_progressWidget); delete m_progressWidget; m_progressWidget = 0; } -QWidget* MainWindow::setupBookmarkWidget() -{ - m_bookmarkManager = new BookmarkManager(m_helpEngine); - m_bookmarkWidget = new BookmarkWidget(m_bookmarkManager, this); - connect(m_bookmarkWidget, SIGNAL(addBookmark()), this, SLOT(addBookmark())); - return m_bookmarkWidget; -} - QString MainWindow::collectionFileDirectory(bool createDir, const QString &cacheDir) { + TRACE_OBJ QString collectionPath = QDesktopServices::storageLocation(QDesktopServices::DataLocation); if (collectionPath.isEmpty()) { @@ -1030,16 +1063,65 @@ QString MainWindow::collectionFileDirectory(bool createDir, const QString &cache QString MainWindow::defaultHelpCollectionFileName() { - return collectionFileDirectory() + QDir::separator() + + TRACE_OBJ + // forces creation of the default collection file path + return collectionFileDirectory(true) + QDir::separator() + QString(QLatin1String("qthelpcollection_%1.qhc")). arg(QLatin1String(QT_VERSION_STR)); } void MainWindow::currentFilterChanged(const QString &filter) { + TRACE_OBJ const int index = m_filterCombo->findText(filter); Q_ASSERT(index != -1); m_filterCombo->setCurrentIndex(index); } +void MainWindow::documentationRemoved(const QString &namespaceName) +{ + TRACE_OBJ + CentralWidget* widget = CentralWidget::instance(); + widget->closeOrReloadTabs(widget->currentSourceFileList(). + keys(namespaceName), false); +} + +void MainWindow::documentationUpdated(const QString &namespaceName) +{ + TRACE_OBJ + CentralWidget* widget = CentralWidget::instance(); + widget->closeOrReloadTabs(widget->currentSourceFileList(). + keys(namespaceName), true); +} + +void MainWindow::resetQtDocInfo(const QString &component) +{ + TRACE_OBJ + HelpEngineWrapper::instance().setQtDocInfo(component, + QStringList(QDateTime().toString(Qt::ISODate))); +} + +void MainWindow::registerDocumentation(const QString &component, + const QString &absFileName) +{ + TRACE_OBJ + QString ns = QHelpEngineCore::namespaceName(absFileName); + if (ns.isEmpty()) + return; + + HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + if (helpEngine.registeredDocumentations().contains(ns)) + helpEngine.unregisterDocumentation(ns); + if (!helpEngine.registerDocumentation(absFileName)) { + QMessageBox::warning(this, tr("Qt Assistant"), + tr("Could not register file '%1': %2"). + arg(absFileName).arg(helpEngine.error())); + } else { + QStringList docInfo; + docInfo << QFileInfo(absFileName).lastModified().toString(Qt::ISODate) + << absFileName; + helpEngine.setQtDocInfo(component, docInfo); + } +} + QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/mainwindow.h b/tools/assistant/tools/assistant/mainwindow.h index 8a9b572..40ca624 100644 --- a/tools/assistant/tools/assistant/mainwindow.h +++ b/tools/assistant/tools/assistant/mainwindow.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE class QAction; +class QFileSystemWatcher; class QLineEdit; class QComboBox; class QMenu; @@ -57,8 +58,6 @@ class QHelpEngineCore; class QHelpEngine; class CentralWidget; class ContentWindow; -class BookmarkManager; -class BookmarkWidget; class CmdLineParser; class QtDocInstaller; @@ -76,10 +75,6 @@ public: static QString defaultHelpCollectionFileName(); public: - void hideContents(); - void hideIndex(); - void hideBookmarks(); - void hideSearch(); void setIndexString(const QString &str); void expandTOC(int depth); bool usesDefaultCollection() const; @@ -88,18 +83,20 @@ signals: void initDone(); public slots: - void showContents(); - void showIndex(); - void showBookmarks(); - void showSearch(); + void setContentsVisible(bool visible); + void setIndexVisible(bool visible); + void setBookmarksVisible(bool visible); + void setSearchVisible(bool visible); void showSearchWidget(); void syncContents(); void activateCurrentCentralWidgetTab(); void currentFilterChanged(const QString &filter); private slots: + void showContents(); + void showIndex(); + void showSearch(); void insertLastPages(); - void addBookmark(); void gotoAddress(); void showPreferences(); void showNewAddress(); @@ -108,7 +105,6 @@ private slots: void updateNavigationItems(); void updateTabCloseAction(); void showNewAddress(const QUrl &url); - void addNewBookmark(const QString &title, const QString &url); void showTopicChooser(const QMap<QString, QUrl> &links, const QString &keyword); void updateApplicationFont(); void filterDocumentation(const QString &customFilter); @@ -116,12 +112,13 @@ private slots: void lookForNewQtDocumentation(); void indexingStarted(); void indexingFinished(); - void displayInstallationError(const QString &errorMessage); void qtDocumentationInstalled(bool newDocsInstalled); + void registerDocumentation(const QString &component, + const QString &absFileName); + void resetQtDocInfo(const QString &component); void checkInitState(); - - void updateBookmarkMenu(); - void showBookmark(QAction *action); + void documentationRemoved(const QString &namespaceName); + void documentationUpdated(const QString &namespaceName); private: bool initHelpDB(); @@ -132,14 +129,21 @@ private: void setupFilterToolbar(); void setupAddressToolbar(); QMenu *toolBarMenu(); - QWidget *setupBookmarkWidget(); + void hideContents(); + void hideIndex(); + void hideSearch(); - QHelpEngine *m_helpEngine; +private slots: + void showBookmarksDockWidget(); + void hideBookmarksDockWidget(); + +private: + QWidget *m_bookmarkWidget; + +private: CentralWidget *m_centralWidget; IndexWindow *m_indexWindow; ContentWindow *m_contentWindow; - BookmarkWidget *m_bookmarkWidget; - BookmarkManager *m_bookmarkManager; QLineEdit *m_addressLineEdit; QComboBox *m_filterCombo; @@ -161,8 +165,6 @@ private: QMenu *m_viewMenu; QMenu *m_toolBarMenu; - QMenu *m_bookmarkMenu; - QAction *m_bookmarkMenuAction; CmdLineParser *m_cmdLine; diff --git a/tools/assistant/tools/assistant/preferencesdialog.cpp b/tools/assistant/tools/assistant/preferencesdialog.cpp index ca12d8f..f0ef054 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.cpp +++ b/tools/assistant/tools/assistant/preferencesdialog.cpp @@ -38,6 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "preferencesdialog.h" #include "filternamedialog.h" @@ -45,8 +46,10 @@ #include "fontpanel.h" #include "centralwidget.h" #include "aboutdialog.h" +#include "helpenginewrapper.h" -#include <QtAlgorithms> +#include <QtCore/QtAlgorithms> +#include <QtCore/QFileSystemWatcher> #include <QtGui/QHeaderView> #include <QtGui/QFileDialog> @@ -60,12 +63,13 @@ QT_BEGIN_NAMESPACE -PreferencesDialog::PreferencesDialog(QHelpEngineCore *helpEngine, QWidget *parent) +PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) - , m_helpEngine(helpEngine) , m_appFontChanged(false) , m_browserFontChanged(false) + , helpEngine(HelpEngineWrapper::instance()) { + TRACE_OBJ m_ui.setupUi(this); connect(m_ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), @@ -73,11 +77,8 @@ PreferencesDialog::PreferencesDialog(QHelpEngineCore *helpEngine, QWidget *paren connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject())); - QLatin1String key("EnableFilterFunctionality"); - m_hideFiltersTab = !m_helpEngine->customValue(key, true).toBool(); - - key = QLatin1String("EnableDocumentationManager"); - m_hideDocsTab = !m_helpEngine->customValue(key, true).toBool(); + m_hideFiltersTab = !helpEngine.filterFunctionalityEnabled(); + m_hideDocsTab = !helpEngine.documentationManagerEnabled(); if (!m_hideFiltersTab) { m_ui.attributeWidget->header()->hide(); @@ -106,7 +107,7 @@ PreferencesDialog::PreferencesDialog(QHelpEngineCore *helpEngine, QWidget *paren connect(m_ui.docRemoveButton, SIGNAL(clicked()), this, SLOT(removeDocumentation())); - m_docsBackup = m_helpEngine->registeredDocumentations(); + m_docsBackup = helpEngine.registeredDocumentations(); m_ui.registeredDocsListWidget->addItems(m_docsBackup); } else { m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.docsTab)); @@ -118,27 +119,17 @@ PreferencesDialog::PreferencesDialog(QHelpEngineCore *helpEngine, QWidget *paren PreferencesDialog::~PreferencesDialog() { - QLatin1String key(""); + TRACE_OBJ if (m_appFontChanged) { - key = QLatin1String("appFont"); - m_helpEngine->setCustomValue(key, m_appFontPanel->selectedFont()); - - key = QLatin1String("useAppFont"); - m_helpEngine->setCustomValue(key, m_appFontPanel->isChecked()); - - key = QLatin1String("appWritingSystem"); - m_helpEngine->setCustomValue(key, m_appFontPanel->writingSystem()); + helpEngine.setAppFont(m_appFontPanel->selectedFont()); + helpEngine.setUseAppFont(m_appFontPanel->isChecked()); + helpEngine.setAppWritingSystem(m_appFontPanel->writingSystem()); } if (m_browserFontChanged) { - key = QLatin1String("browserFont"); - m_helpEngine->setCustomValue(key, m_browserFontPanel->selectedFont()); - - key = QLatin1String("useBrowserFont"); - m_helpEngine->setCustomValue(key, m_browserFontPanel->isChecked()); - - key = QLatin1String("browserWritingSystem"); - m_helpEngine->setCustomValue(key, m_browserFontPanel->writingSystem()); + helpEngine.setBrowserFont(m_browserFontPanel->selectedFont()); + helpEngine.setUseBrowserFont(m_browserFontPanel->isChecked()); + helpEngine.setBrowserWritingSystem(m_browserFontPanel->writingSystem()); } if (m_appFontChanged || m_browserFontChanged) { @@ -149,32 +140,31 @@ PreferencesDialog::~PreferencesDialog() QString homePage = m_ui.homePageLineEdit->text(); if (homePage.isEmpty()) homePage = QLatin1String("help"); - m_helpEngine->setCustomValue(QLatin1String("homepage"), homePage); + helpEngine.setHomePage(homePage); int option = m_ui.helpStartComboBox->currentIndex(); - m_helpEngine->setCustomValue(QLatin1String("StartOption"), option); + helpEngine.setStartOption(option); } void PreferencesDialog::showDialog() { + TRACE_OBJ if (exec() != Accepted) m_appFontChanged = m_browserFontChanged = false; } void PreferencesDialog::updateFilterPage() { - if (!m_helpEngine) - return; - + TRACE_OBJ m_ui.filterWidget->clear(); m_ui.attributeWidget->clear(); - QHelpEngineCore help(m_helpEngine->collectionFile(), 0); - help.setupData(); m_filterMapBackup.clear(); - const QStringList filters = help.customFilters(); + const QStringList &filters = helpEngine.customFilters(); foreach (const QString &filter, filters) { - QStringList atts = help.filterAttributes(filter); + if (filter == HelpEngineWrapper::TrUnfiltered) + continue; + QStringList atts = helpEngine.filterAttributes(filter); m_filterMapBackup.insert(filter, atts); if (!m_filterMap.contains(filter)) m_filterMap.insert(filter, atts); @@ -182,15 +172,16 @@ void PreferencesDialog::updateFilterPage() m_ui.filterWidget->addItems(m_filterMap.keys()); - foreach (const QString &a, help.filterAttributes()) + foreach (const QString &a, helpEngine.filterAttributes()) new QTreeWidgetItem(m_ui.attributeWidget, QStringList() << a); - if (m_filterMap.keys().count()) + if (!m_filterMap.keys().isEmpty()) m_ui.filterWidget->setCurrentRow(0); } void PreferencesDialog::updateAttributes(QListWidgetItem *item) { + TRACE_OBJ QStringList checkedList; if (item) checkedList = m_filterMap.value(item->text()); @@ -206,6 +197,7 @@ void PreferencesDialog::updateAttributes(QListWidgetItem *item) void PreferencesDialog::updateFilterMap() { + TRACE_OBJ if (!m_ui.filterWidget->currentItem()) return; QString filter = m_ui.filterWidget->currentItem()->text(); @@ -224,6 +216,7 @@ void PreferencesDialog::updateFilterMap() void PreferencesDialog::addFilter() { + TRACE_OBJ FilterNameDialog dia(this); if (dia.exec() == QDialog::Rejected) return; @@ -241,6 +234,7 @@ void PreferencesDialog::addFilter() void PreferencesDialog::removeFilter() { + TRACE_OBJ QListWidgetItem *item = m_ui.filterWidget ->takeItem(m_ui.filterWidget->currentRow()); if (!item) @@ -255,6 +249,7 @@ void PreferencesDialog::removeFilter() void PreferencesDialog::addDocumentationLocal() { + TRACE_OBJ const QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Add Documentation"), QString(), tr("Qt Compressed Help Files (*.qch)")); if (fileNames.isEmpty()) @@ -275,10 +270,11 @@ void PreferencesDialog::addDocumentationLocal() continue; } - m_helpEngine->registerDocumentation(fileName); - m_ui.registeredDocsListWidget->addItem(nameSpace); - m_regDocs.append(nameSpace); - m_unregDocs.removeAll(nameSpace); + if (helpEngine.registerDocumentation(fileName)) { + m_ui.registeredDocsListWidget->addItem(nameSpace); + m_regDocs.append(nameSpace); + m_unregDocs.removeAll(nameSpace); + } } if (!invalidFiles.isEmpty() || !alreadyRegistered.isEmpty()) { @@ -307,6 +303,7 @@ void PreferencesDialog::addDocumentationLocal() void PreferencesDialog::removeDocumentation() { + TRACE_OBJ bool foundBefore = false; CentralWidget* widget = CentralWidget::instance(); QMap<int, QString> openedDocList = widget->currentSourceFileList(); @@ -338,6 +335,7 @@ void PreferencesDialog::removeDocumentation() void PreferencesDialog::applyChanges() { + TRACE_OBJ bool filtersWereChanged = false; if (!m_hideFiltersTab) { if (m_filterMap.count() != m_filterMapBackup.count()) { @@ -370,34 +368,28 @@ void PreferencesDialog::applyChanges() if (filtersWereChanged) { foreach (const QString &filter, m_removedFilters) - m_helpEngine->removeCustomFilter(filter); + helpEngine.removeCustomFilter(filter); QMapIterator<QString, QStringList> it(m_filterMap); while (it.hasNext()) { it.next(); - m_helpEngine->addCustomFilter(it.key(), it.value()); + helpEngine.addCustomFilter(it.key(), it.value()); } } - qSort(m_TabsToClose); - CentralWidget* widget = CentralWidget::instance(); - for (int i = m_TabsToClose.count(); --i >= 0;) - widget->closeTabAt(m_TabsToClose.at(i)); - if (widget->availableHelpViewer()== 0) - widget->setSource(QUrl(QLatin1String("about:blank"))); - - if (m_unregDocs.count()) { - foreach (const QString &doc, m_unregDocs) - m_helpEngine->unregisterDocumentation(doc); - } + CentralWidget::instance()->closeOrReloadTabs(m_TabsToClose, false); + + foreach (const QString &doc, m_unregDocs) + helpEngine.unregisterDocumentation(doc); - if (filtersWereChanged || m_regDocs.count() || m_unregDocs.count()) - m_helpEngine->setupData(); + if (filtersWereChanged || !m_regDocs.isEmpty() || !m_unregDocs.isEmpty()) + helpEngine.setupData(); accept(); } void PreferencesDialog::updateFontSettingsPage() { + TRACE_OBJ m_browserFontPanel = new FontPanel(this); m_browserFontPanel->setCheckable(true); m_ui.stackedWidget_2->insertWidget(0, m_browserFontPanel); @@ -411,31 +403,23 @@ void PreferencesDialog::updateFontSettingsPage() const QString customSettings(tr("Use custom settings")); m_appFontPanel->setTitle(customSettings); - QLatin1String key = QLatin1String("appFont"); - QFont font = qVariantValue<QFont>(m_helpEngine->customValue(key)); + QFont font = helpEngine.appFont(); m_appFontPanel->setSelectedFont(font); - key = QLatin1String("appWritingSystem"); - QFontDatabase::WritingSystem system = static_cast<QFontDatabase::WritingSystem> - (m_helpEngine->customValue(key).toInt()); + QFontDatabase::WritingSystem system = helpEngine.appWritingSystem(); m_appFontPanel->setWritingSystem(system); - key = QLatin1String("useAppFont"); - m_appFontPanel->setChecked(m_helpEngine->customValue(key).toBool()); + m_appFontPanel->setChecked(helpEngine.usesAppFont()); m_browserFontPanel->setTitle(customSettings); - key = QLatin1String("browserFont"); - font = qVariantValue<QFont>(m_helpEngine->customValue(key)); + font = helpEngine.browserFont(); m_browserFontPanel->setSelectedFont(font); - key = QLatin1String("browserWritingSystem"); - system = static_cast<QFontDatabase::WritingSystem> - (m_helpEngine->customValue(key).toInt()); + system = helpEngine.browserWritingSystem(); m_browserFontPanel->setWritingSystem(system); - key = QLatin1String("useBrowserFont"); - m_browserFontPanel->setChecked(m_helpEngine->customValue(key).toBool()); + m_browserFontPanel->setChecked(helpEngine.usesBrowserFont()); connect(m_appFontPanel, SIGNAL(toggled(bool)), this, SLOT(appFontSettingToggled(bool))); @@ -457,41 +441,38 @@ void PreferencesDialog::updateFontSettingsPage() void PreferencesDialog::appFontSettingToggled(bool on) { + TRACE_OBJ Q_UNUSED(on) m_appFontChanged = true; } void PreferencesDialog::appFontSettingChanged(int index) { + TRACE_OBJ Q_UNUSED(index) m_appFontChanged = true; } void PreferencesDialog::browserFontSettingToggled(bool on) { + TRACE_OBJ Q_UNUSED(on) m_browserFontChanged = true; } void PreferencesDialog::browserFontSettingChanged(int index) { + TRACE_OBJ Q_UNUSED(index) m_browserFontChanged = true; } void PreferencesDialog::updateOptionsPage() { - QString homepage = m_helpEngine->customValue(QLatin1String("homepage"), - QLatin1String("")).toString(); + TRACE_OBJ + m_ui.homePageLineEdit->setText(helpEngine.homePage()); - if (homepage.isEmpty()) { - homepage = m_helpEngine->customValue(QLatin1String("defaultHomepage"), - QLatin1String("help")).toString(); - } - m_ui.homePageLineEdit->setText(homepage); - - int option = m_helpEngine->customValue(QLatin1String("StartOption"), - ShowLastPages).toInt(); + int option = helpEngine.startOption(); m_ui.helpStartComboBox->setCurrentIndex(option); connect(m_ui.blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage())); @@ -501,11 +482,13 @@ void PreferencesDialog::updateOptionsPage() void PreferencesDialog::setBlankPage() { + TRACE_OBJ m_ui.homePageLineEdit->setText(QLatin1String("about:blank")); } void PreferencesDialog::setCurrentPage() { + TRACE_OBJ QString homepage = CentralWidget::instance()->currentSource().toString(); if (homepage.isEmpty()) homepage = QLatin1String("help"); @@ -515,9 +498,8 @@ void PreferencesDialog::setCurrentPage() void PreferencesDialog::setDefaultPage() { - QString homepage = m_helpEngine->customValue(QLatin1String("defaultHomepage"), - QLatin1String("help")).toString(); - m_ui.homePageLineEdit->setText(homepage); + TRACE_OBJ + m_ui.homePageLineEdit->setText(helpEngine.defaultHomePage()); } QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/preferencesdialog.h b/tools/assistant/tools/assistant/preferencesdialog.h index 9ad6b6a..2894494 100644 --- a/tools/assistant/tools/assistant/preferencesdialog.h +++ b/tools/assistant/tools/assistant/preferencesdialog.h @@ -48,20 +48,15 @@ QT_BEGIN_NAMESPACE class FontPanel; -class QHelpEngineCore; - -enum { - ShowHomePage = 0, - ShowBlankPage = 1, - ShowLastPages = 2 -}; +class HelpEngineWrapper; +class QFileSystemWatcher; class PreferencesDialog : public QDialog { Q_OBJECT public: - PreferencesDialog(QHelpEngineCore *helpEngine, QWidget *parent = 0); + PreferencesDialog(QWidget *parent = 0); ~PreferencesDialog(); void showDialog(); @@ -93,7 +88,6 @@ private: void updateOptionsPage(); Ui::PreferencesDialogClass m_ui; - QHelpEngineCore *m_helpEngine; bool m_hideFiltersTab; bool m_hideDocsTab; QMap<QString, QStringList> m_filterMapBackup; @@ -107,6 +101,7 @@ private: FontPanel *m_browserFontPanel; bool m_appFontChanged; bool m_browserFontChanged; + HelpEngineWrapper &helpEngine; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/qtdocinstaller.cpp b/tools/assistant/tools/assistant/qtdocinstaller.cpp index 652f630..5a501bf 100644 --- a/tools/assistant/tools/assistant/qtdocinstaller.cpp +++ b/tools/assistant/tools/assistant/qtdocinstaller.cpp @@ -38,23 +38,27 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include <QtCore/QDir> #include <QtCore/QLibraryInfo> #include <QtCore/QDateTime> +#include <QtCore/QFileSystemWatcher> #include <QtHelp/QHelpEngineCore> +#include "helpenginewrapper.h" #include "qtdocinstaller.h" QT_BEGIN_NAMESPACE -QtDocInstaller::QtDocInstaller(const QString &collectionFile) +QtDocInstaller::QtDocInstaller(const QList<DocInfo> &docInfos) + : m_abort(false), m_docInfos(docInfos) { - m_abort = false; - m_collectionFile = collectionFile; + TRACE_OBJ } QtDocInstaller::~QtDocInstaller() { + TRACE_OBJ if (!isRunning()) return; m_mutex.lock(); @@ -65,86 +69,59 @@ QtDocInstaller::~QtDocInstaller() void QtDocInstaller::installDocs() { + TRACE_OBJ start(LowPriority); } void QtDocInstaller::run() { - QHelpEngineCore *helpEngine = new QHelpEngineCore(m_collectionFile); - helpEngine->setupData(); - bool changes = false; - - QStringList docs; - docs << QLatin1String("assistant") - << QLatin1String("designer") - << QLatin1String("linguist") - << QLatin1String("qmake") - << QLatin1String("qt"); + TRACE_OBJ + m_qchDir = QLibraryInfo::location(QLibraryInfo::DocumentationPath) + + QDir::separator() + QLatin1String("qch"); + m_qchFiles = m_qchDir.entryList(QStringList() << QLatin1String("*.qch")); - foreach (const QString &doc, docs) { - changes |= installDoc(doc, helpEngine); + bool changes = false; + foreach (const DocInfo &docInfo, m_docInfos) { + changes |= installDoc(docInfo); m_mutex.lock(); if (m_abort) { - delete helpEngine; m_mutex.unlock(); return; } m_mutex.unlock(); } - delete helpEngine; emit docsInstalled(changes); } -bool QtDocInstaller::installDoc(const QString &name, QHelpEngineCore *helpEngine) +bool QtDocInstaller::installDoc(const DocInfo &docInfo) { - QString versionKey = QString(QLatin1String("qtVersion%1$$$%2")). - arg(QLatin1String(QT_VERSION_STR)).arg(name); - - QString info = helpEngine->customValue(versionKey, QString()).toString(); - QStringList lst = info.split(QLatin1String("|")); - + TRACE_OBJ + const QString &component = docInfo.first; + const QStringList &info = docInfo.second; QDateTime dt; - if (lst.count() && !lst.first().isEmpty()) - dt = QDateTime::fromString(lst.first(), Qt::ISODate); + if (!info.isEmpty() && !info.first().isEmpty()) + dt = QDateTime::fromString(info.first(), Qt::ISODate); QString qchFile; - if (lst.count() == 2) - qchFile = lst.last(); - - QDir dir(QLibraryInfo::location(QLibraryInfo::DocumentationPath) - + QDir::separator() + QLatin1String("qch")); + if (info.count() == 2) + qchFile = info.last(); - const QStringList files = dir.entryList(QStringList() << QLatin1String("*.qch")); - if (files.isEmpty()) { - helpEngine->setCustomValue(versionKey, QDateTime().toString(Qt::ISODate) - + QLatin1String("|")); + if (m_qchFiles.isEmpty()) { + emit qchFileNotFound(component); return false; } - foreach (const QString &f, files) { - if (f.startsWith(name)) { - QFileInfo fi(dir.absolutePath() + QDir::separator() + f); - if (dt.isValid() && fi.lastModified().toString(Qt::ISODate) == dt.toString(Qt::ISODate) + foreach (const QString &f, m_qchFiles) { + if (f.startsWith(component)) { + QFileInfo fi(m_qchDir.absolutePath() + QDir::separator() + f); + if (dt.isValid() && fi.lastModified().toTime_t() == dt.toTime_t() && qchFile == fi.absoluteFilePath()) return false; - - QString namespaceName = QHelpEngineCore::namespaceName(fi.absoluteFilePath()); - if (namespaceName.isEmpty()) - continue; - - if (helpEngine->registeredDocumentations().contains(namespaceName)) - helpEngine->unregisterDocumentation(namespaceName); - - if (!helpEngine->registerDocumentation(fi.absoluteFilePath())) { - emit errorMessage( - tr("The file %1 could not be registered successfully!\n\nReason: %2") - .arg(fi.absoluteFilePath()).arg(helpEngine->error())); - } - - helpEngine->setCustomValue(versionKey, fi.lastModified().toString(Qt::ISODate) - + QLatin1String("|") + fi.absoluteFilePath()); + emit registerDocumentation(component, fi.absoluteFilePath()); return true; } } + + emit qchFileNotFound(component); return false; } diff --git a/tools/assistant/tools/assistant/qtdocinstaller.h b/tools/assistant/tools/assistant/qtdocinstaller.h index 05606f9..92a707b 100644 --- a/tools/assistant/tools/assistant/qtdocinstaller.h +++ b/tools/assistant/tools/assistant/qtdocinstaller.h @@ -42,34 +42,41 @@ #ifndef QTDOCINSTALLER #define QTDOCINSTALLER -#include <QtCore/QThread> +#include <QtCore/QDir> #include <QtCore/QMutex> +#include <QtCore/QPair> +#include <QtCore/QStringList> +#include <QtCore/QThread> QT_BEGIN_NAMESPACE -class QHelpEngineCore; +class HelpEngineWrapper; class QtDocInstaller : public QThread { Q_OBJECT public: - QtDocInstaller(const QString &collectionFile); + typedef QPair<QString, QStringList> DocInfo; + QtDocInstaller(const QList<DocInfo> &docInfos); ~QtDocInstaller(); void installDocs(); signals: - void errorMessage(const QString &msg); + void qchFileNotFound(const QString &component); + void registerDocumentation(const QString &component, + const QString &absFileName); void docsInstalled(bool newDocsInstalled); private: void run(); - bool installDoc(const QString &name, - QHelpEngineCore *helpEngine); + bool installDoc(const DocInfo &docInfo); bool m_abort; - QString m_collectionFile; QMutex m_mutex; + QStringList m_qchFiles; + QDir m_qchDir; + QList<DocInfo> m_docInfos; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/remotecontrol.cpp b/tools/assistant/tools/assistant/remotecontrol.cpp index 5fa7432..5ecdd69 100644 --- a/tools/assistant/tools/assistant/remotecontrol.cpp +++ b/tools/assistant/tools/assistant/remotecontrol.cpp @@ -38,12 +38,16 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "remotecontrol.h" #include "mainwindow.h" #include "centralwidget.h" +#include "helpenginewrapper.h" #include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QFileSystemWatcher> #include <QtCore/QThread> #include <QtCore/QTextStream> #include <QtCore/QSocketNotifier> @@ -65,16 +69,19 @@ QT_BEGIN_NAMESPACE StdInListenerWin::StdInListenerWin(QObject *parent) : QThread(parent) { + TRACE_OBJ } StdInListenerWin::~StdInListenerWin() { + TRACE_OBJ terminate(); wait(); } void StdInListenerWin::run() { + TRACE_OBJ bool ok = true; char chBuf[4096]; DWORD dwRead; @@ -97,23 +104,24 @@ void StdInListenerWin::run() #endif while (ok) { - ok = ReadFile(hStdinDup, chBuf, 4096, &dwRead, NULL); + ok = ReadFile(hStdinDup, chBuf, sizeof(chBuf), &dwRead, NULL); if (ok && dwRead != 0) - emit receivedCommand(QString::fromLocal8Bit(chBuf)); + emit receivedCommand(QString::fromLocal8Bit(chBuf, dwRead)); } } #endif -RemoteControl::RemoteControl(MainWindow *mainWindow, QHelpEngine *helpEngine) +RemoteControl::RemoteControl(MainWindow *mainWindow) : QObject(mainWindow) , m_mainWindow(mainWindow) - , m_helpEngine(helpEngine) , m_debug(false) , m_caching(true) , m_syncContents(false) - , m_expandTOC(-3) + , m_expandTOC(-2) + , helpEngine(HelpEngineWrapper::instance()) { + TRACE_OBJ connect(m_mainWindow, SIGNAL(initDone()), this, SLOT(applyCache())); #ifdef Q_OS_WIN StdInListenerWin *l = new StdInListenerWin(this); @@ -130,6 +138,7 @@ RemoteControl::RemoteControl(MainWindow *mainWindow, QHelpEngine *helpEngine) void RemoteControl::receivedData() { + TRACE_OBJ QByteArray ba; while (true) { char c = getc(stdin); @@ -145,135 +154,204 @@ void RemoteControl::receivedData() void RemoteControl::handleCommandString(const QString &cmdString) { + TRACE_OBJ QStringList cmds = cmdString.split(QLatin1Char(';')); QStringList::const_iterator it = cmds.constBegin(); - QString cmdLine, cmd, arg; while (it != cmds.constEnd()) { - cmdLine = (*it).trimmed(); - cmd = cmdLine; - arg.clear(); - int i = cmdLine.indexOf(QLatin1Char(' ')); - if (i > 0) { - cmd = cmdLine.left(i); - arg = cmdLine.mid(i+1); - } - cmd = cmd.toLower(); + QString cmd, arg; + splitInputString(*it, cmd, arg); if (m_debug) QMessageBox::information(0, tr("Debugging Remote Control"), tr("Received Command: %1 %2").arg(cmd).arg(arg)); - if (cmd == QLatin1String("debug")) { - if (arg == QLatin1String("on")) - m_debug = true; - else - m_debug = false; - } else if (cmd == QLatin1String("show")) { - if (arg.toLower() == QLatin1String("contents")) { - m_mainWindow->showContents(); - } else if (arg.toLower() == QLatin1String("index")) { - m_mainWindow->showIndex(); - } else if (arg.toLower() == QLatin1String("bookmarks")) { - m_mainWindow->showBookmarks(); - } else if (arg.toLower() == QLatin1String("search")) { - m_mainWindow->showSearch(); - } - } else if (cmd == QLatin1String("hide")) { - if (arg.toLower() == QLatin1String("contents")) { - m_mainWindow->hideContents(); - } else if (arg.toLower() == QLatin1String("index")) { - m_mainWindow->hideIndex(); - } else if (arg.toLower() == QLatin1String("bookmarks")) { - m_mainWindow->hideBookmarks(); - } else if (arg.toLower() == QLatin1String("search")) { - m_mainWindow->hideSearch(); - } - } else if (cmd == QLatin1String("setsource")) { - QUrl url(arg); - if (url.isValid()) { - if (url.isRelative()) - url = CentralWidget::instance()->currentSource().resolved(url); - if (m_caching) { - clearCache(); - m_setSource = url; - } else { - CentralWidget::instance()->setSource(url); - } - } - } else if (cmd == QLatin1String("synccontents")) { - if (m_caching) - m_syncContents = true; - else - m_mainWindow->syncContents(); - } else if (cmd == QLatin1String("activatekeyword")) { - if (m_caching) { - clearCache(); - m_activateKeyword = arg; - } else { - m_mainWindow->setIndexString(arg); - if (!arg.isEmpty()) - m_helpEngine->indexWidget()->activateCurrentItem(); - } - } else if (cmd == QLatin1String("activateidentifier")) { - if (m_caching) { - clearCache(); - m_activateIdentifier = arg; - } else { - QMap<QString, QUrl> links = - m_helpEngine->linksForIdentifier(arg); - if (links.count()) - CentralWidget::instance()->setSource(links.constBegin().value()); - } - } else if (cmd == QLatin1String("expandtoc")) { - bool ok = false; - int depth = -1; - if (!arg.isEmpty()) - depth = arg.toInt(&ok); - if (!ok) - depth = -1; - - if (m_caching) - m_expandTOC = depth; - else - m_mainWindow->expandTOC(depth); - } else if (cmd == QLatin1String("setcurrentfilter")) { - if (!m_helpEngine->customFilters().contains(arg)) - return; - if (m_caching) { - clearCache(); - m_currentFilter = arg; - } else { - m_helpEngine->setCurrentFilter(arg); - } - } else { + if (cmd == QLatin1String("debug")) + handleDebugCommand(arg); + else if (cmd == QLatin1String("show")) + handleShowOrHideCommand(arg, true); + else if (cmd == QLatin1String("hide")) + handleShowOrHideCommand(arg, false); + else if (cmd == QLatin1String("setsource")) + handleSetSourceCommand(arg); + else if (cmd == QLatin1String("synccontents")) + handleSyncContentsCommand(); + else if (cmd == QLatin1String("activatekeyword")) + handleActivateKeywordCommand(arg); + else if (cmd == QLatin1String("activateidentifier")) + handleActivateIdentifierCommand(arg); + else if (cmd == QLatin1String("expandtoc")) + handleExpandTocCommand(arg); + else if (cmd == QLatin1String("setcurrentfilter")) + handleSetCurrentFilterCommand(arg); + else if (cmd == QLatin1String("register")) + handleRegisterCommand(arg); + else if (cmd == QLatin1String("unregister")) + handleUnregisterCommand(arg); + else return; - } + ++it; } m_mainWindow->raise(); m_mainWindow->activateWindow(); } +void RemoteControl::splitInputString(const QString &input, QString &cmd, + QString &arg) +{ + TRACE_OBJ + QString cmdLine = input.trimmed(); + int i = cmdLine.indexOf(QLatin1Char(' ')); + cmd = cmdLine.left(i); + arg = cmdLine.mid(i+1); + cmd = cmd.toLower(); +} + +void RemoteControl::handleDebugCommand(const QString &arg) +{ + TRACE_OBJ + m_debug = arg == QLatin1String("on"); +} + +void RemoteControl::handleShowOrHideCommand(const QString &arg, bool show) +{ + TRACE_OBJ + if (arg.toLower() == QLatin1String("contents")) + m_mainWindow->setContentsVisible(show); + else if (arg.toLower() == QLatin1String("index")) + m_mainWindow->setIndexVisible(show); + else if (arg.toLower() == QLatin1String("bookmarks")) + m_mainWindow->setBookmarksVisible(show); + else if (arg.toLower() == QLatin1String("search")) + m_mainWindow->setSearchVisible(show); +} + +void RemoteControl::handleSetSourceCommand(const QString &arg) +{ + TRACE_OBJ + QUrl url(arg); + if (url.isValid()) { + if (url.isRelative()) + url = CentralWidget::instance()->currentSource().resolved(url); + if (m_caching) { + clearCache(); + m_setSource = url; + } else { + CentralWidget::instance()->setSource(url); + } + } +} + +void RemoteControl::handleSyncContentsCommand() +{ + TRACE_OBJ + if (m_caching) + m_syncContents = true; + else + m_mainWindow->syncContents(); +} + +void RemoteControl::handleActivateKeywordCommand(const QString &arg) +{ + TRACE_OBJ + if (m_caching) { + clearCache(); + m_activateKeyword = arg; + } else { + m_mainWindow->setIndexString(arg); + if (!arg.isEmpty()) + helpEngine.indexWidget()->activateCurrentItem(); + } +} + +void RemoteControl::handleActivateIdentifierCommand(const QString &arg) +{ + TRACE_OBJ + if (m_caching) { + clearCache(); + m_activateIdentifier = arg; + } else { + const QMap<QString, QUrl> &links = helpEngine.linksForIdentifier(arg); + if (!links.isEmpty()) + CentralWidget::instance()->setSource(links.constBegin().value()); + } +} + +void RemoteControl::handleExpandTocCommand(const QString &arg) +{ + TRACE_OBJ + bool ok = false; + int depth = -2; + if (!arg.isEmpty()) + depth = arg.toInt(&ok); + if (!ok || depth < -2) + depth = -2; + + if (m_caching) + m_expandTOC = depth; + else if (depth != -2) + m_mainWindow->expandTOC(depth); +} + +void RemoteControl::handleSetCurrentFilterCommand(const QString &arg) +{ + TRACE_OBJ + if (helpEngine.customFilters().contains(arg)) { + if (m_caching) { + clearCache(); + m_currentFilter = arg; + } else { + helpEngine.setCurrentFilter(arg); + } + } +} + +void RemoteControl::handleRegisterCommand(const QString &arg) +{ + TRACE_OBJ + const QString &absFileName = QFileInfo(arg).absoluteFilePath(); + if (helpEngine.registeredDocumentations(). + contains(QHelpEngineCore::namespaceName(absFileName))) + return; + if (helpEngine.registerDocumentation(absFileName)) + helpEngine.setupData(); +} + +void RemoteControl::handleUnregisterCommand(const QString &arg) +{ + TRACE_OBJ + 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); + if (helpEngine.unregisterDocumentation(ns)) + helpEngine.setupData(); + } +} + void RemoteControl::applyCache() { + TRACE_OBJ if (m_setSource.isValid()) { CentralWidget::instance()->setSource(m_setSource); } else if (!m_activateKeyword.isEmpty()) { m_mainWindow->setIndexString(m_activateKeyword); - m_helpEngine->indexWidget()->activateCurrentItem(); + helpEngine.indexWidget()->activateCurrentItem(); } else if (!m_activateIdentifier.isEmpty()) { QMap<QString, QUrl> links = - m_helpEngine->linksForIdentifier(m_activateIdentifier); - if (links.count()) + helpEngine.linksForIdentifier(m_activateIdentifier); + if (!links.isEmpty()) CentralWidget::instance()->setSource(links.constBegin().value()); } else if (!m_currentFilter.isEmpty()) { - m_helpEngine->setCurrentFilter(m_currentFilter); + helpEngine.setCurrentFilter(m_currentFilter); } if (m_syncContents) m_mainWindow->syncContents(); - if (m_expandTOC != -3) + Q_ASSERT(m_expandTOC >= -2); + if (m_expandTOC != -2) m_mainWindow->expandTOC(m_expandTOC); m_caching = false; @@ -281,6 +359,7 @@ void RemoteControl::applyCache() void RemoteControl::clearCache() { + TRACE_OBJ m_currentFilter.clear(); m_setSource.clear(); m_syncContents = false; diff --git a/tools/assistant/tools/assistant/remotecontrol.h b/tools/assistant/tools/assistant/remotecontrol.h index b888b40..0777878 100644 --- a/tools/assistant/tools/assistant/remotecontrol.h +++ b/tools/assistant/tools/assistant/remotecontrol.h @@ -43,19 +43,20 @@ #define REMOTECONTROL_H #include <QtCore/QObject> +#include <QtCore/QString> #include <QtCore/QUrl> QT_BEGIN_NAMESPACE +class HelpEngineWrapper; class MainWindow; -class QHelpEngine; class RemoteControl : public QObject { Q_OBJECT public: - RemoteControl(MainWindow *mainWindow, QHelpEngine *helpEngine); + RemoteControl(MainWindow *mainWindow); private slots: void receivedData(); @@ -64,10 +65,20 @@ private slots: private: void clearCache(); + void splitInputString(const QString &input, QString &cmd, QString &arg); + void handleDebugCommand(const QString &arg); + void handleShowOrHideCommand(const QString &arg, bool show); + void handleSetSourceCommand(const QString &arg); + void handleSyncContentsCommand(); + void handleActivateKeywordCommand(const QString &arg); + void handleActivateIdentifierCommand(const QString &arg); + void handleExpandTocCommand(const QString &arg); + void handleSetCurrentFilterCommand(const QString &arg); + void handleRegisterCommand(const QString &arg); + void handleUnregisterCommand(const QString &arg); private: MainWindow *m_mainWindow; - QHelpEngine *m_helpEngine; bool m_debug; bool m_caching; @@ -77,6 +88,7 @@ private: QString m_activateIdentifier; int m_expandTOC; QString m_currentFilter; + HelpEngineWrapper &helpEngine; }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/searchwidget.cpp b/tools/assistant/tools/assistant/searchwidget.cpp index ad24231..d83790d 100644 --- a/tools/assistant/tools/assistant/searchwidget.cpp +++ b/tools/assistant/tools/assistant/searchwidget.cpp @@ -38,6 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "tracer.h" #include "mainwindow.h" #include "searchwidget.h" @@ -65,6 +66,7 @@ SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent) , attached(false) , searchEngine(engine) { + TRACE_OBJ QVBoxLayout *vLayout = new QVBoxLayout(this); resultWidget = searchEngine->resultWidget(); @@ -91,11 +93,13 @@ SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent) SearchWidget::~SearchWidget() { + TRACE_OBJ // nothing todo } void SearchWidget::zoomIn() { + TRACE_OBJ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); if (browser && zoomCount != 10) { zoomCount++; @@ -105,6 +109,7 @@ void SearchWidget::zoomIn() void SearchWidget::zoomOut() { + TRACE_OBJ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); if (browser && zoomCount != -5) { zoomCount--; @@ -114,6 +119,7 @@ void SearchWidget::zoomOut() void SearchWidget::resetZoom() { + TRACE_OBJ if (zoomCount == 0) return; @@ -126,33 +132,39 @@ void SearchWidget::resetZoom() bool SearchWidget::isAttached() const { + TRACE_OBJ return attached; } void SearchWidget::setAttached(bool state) { + TRACE_OBJ attached = state; } void SearchWidget::search() const { + TRACE_OBJ QList<QHelpSearchQuery> query = searchEngine->queryWidget()->query(); searchEngine->search(query); } void SearchWidget::searchingStarted() { + TRACE_OBJ qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); } void SearchWidget::searchingFinished(int hits) { + TRACE_OBJ Q_UNUSED(hits) qApp->restoreOverrideCursor(); } bool SearchWidget::eventFilter(QObject* o, QEvent *e) { + TRACE_OBJ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget); if (browser && o == browser->viewport() && e->type() == QEvent::MouseButtonRelease){ @@ -171,6 +183,7 @@ bool SearchWidget::eventFilter(QObject* o, QEvent *e) void SearchWidget::keyPressEvent(QKeyEvent *keyEvent) { + TRACE_OBJ if (keyEvent->key() == Qt::Key_Escape) MainWindow::activateCurrentBrowser(); else @@ -179,6 +192,7 @@ void SearchWidget::keyPressEvent(QKeyEvent *keyEvent) void SearchWidget::contextMenuEvent(QContextMenuEvent *contextMenuEvent) { + TRACE_OBJ QMenu menu; QPoint point = contextMenuEvent->globalPos(); diff --git a/tools/assistant/tools/assistant/topicchooser.cpp b/tools/assistant/tools/assistant/topicchooser.cpp index 5c04244..262fea8 100644 --- a/tools/assistant/tools/assistant/topicchooser.cpp +++ b/tools/assistant/tools/assistant/topicchooser.cpp @@ -38,9 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - -#include <QtCore/QMap> -#include <QtCore/QUrl> +#include "tracer.h" #include "topicchooser.h" @@ -50,37 +48,40 @@ TopicChooser::TopicChooser(QWidget *parent, const QString &keyword, const QMap<QString, QUrl> &links) : QDialog(parent) { + TRACE_OBJ ui.setupUi(this); ui.label->setText(tr("Choose a topic for <b>%1</b>:").arg(keyword)); - m_links = links; - QMap<QString, QUrl>::const_iterator it = m_links.constBegin(); - for (; it != m_links.constEnd(); ++it) + QMap<QString, QUrl>::const_iterator it = links.constBegin(); + for (; it != links.constEnd(); ++it) { ui.listWidget->addItem(it.key()); + m_links.append(it.value()); + } if (ui.listWidget->count() != 0) ui.listWidget->setCurrentRow(0); ui.listWidget->setFocus(); - connect(ui.buttonDisplay, SIGNAL(clicked()), - this, SLOT(accept())); - connect(ui.buttonCancel, SIGNAL(clicked()), - this, SLOT(reject())); - connect(ui.listWidget, SIGNAL(itemActivated(QListWidgetItem*)), - this, SLOT(accept())); + connect(ui.buttonDisplay, SIGNAL(clicked()), this, SLOT(accept())); + connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(reject())); + connect(ui.listWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, + SLOT(accept())); } QUrl TopicChooser::link() const { + TRACE_OBJ QListWidgetItem *item = ui.listWidget->currentItem(); if (!item) return QUrl(); QString title = item->text(); - if (title.isEmpty() || !m_links.contains(title)) + if (title.isEmpty()) return QUrl(); - return m_links.value(title); + const int row = ui.listWidget->row(item); + Q_ASSERT(row < m_links.count()); + return m_links.at(row); } QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/topicchooser.h b/tools/assistant/tools/assistant/topicchooser.h index 4dba726..4113cee 100644 --- a/tools/assistant/tools/assistant/topicchooser.h +++ b/tools/assistant/tools/assistant/topicchooser.h @@ -44,9 +44,10 @@ #include "ui_topicchooser.h" -#include <QUrl> -#include <QMap> -#include <QString> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QUrl> #include <QtGui/QDialog> @@ -64,7 +65,7 @@ public: private: Ui::TopicChooser ui; - QMap<QString, QUrl> m_links; + QList<QUrl> m_links; }; QT_END_NAMESPACE diff --git a/tools/assistant/compat/lib/qassistantclient_global.h b/tools/assistant/tools/assistant/tracer.h index 6b58736..66d450a 100644 --- a/tools/assistant/compat/lib/qassistantclient_global.h +++ b/tools/assistant/tools/assistant/tracer.h @@ -39,25 +39,37 @@ ** ****************************************************************************/ -#ifndef QASSISTANTCLIENT_GLOBAL_H -#define QASSISTANTCLIENT_GLOBAL_H +#ifndef TRACER_H +#define TRACER_H -#include <QtCore/qglobal.h> - -QT_BEGIN_HEADER +#include <QtCore/QtGlobal> QT_BEGIN_NAMESPACE -#if defined(QT_ASSISTANT_CLIENT_STATIC) || (!defined(QT_SHARED) && !defined(QT_DLL)) -# define QT_ASSISTANT_CLIENT_EXPORT -#elif defined(QT_ASSISTANT_CLIENT_LIBRARY) -# define QT_ASSISTANT_CLIENT_EXPORT Q_DECL_EXPORT -#else -# define QT_ASSISTANT_CLIENT_EXPORT Q_DECL_IMPORT -#endif +class Tracer +{ +public: + Tracer(const char *func) : m_func(func) + { + qDebug("Entering function %s.", m_func); + } -QT_END_NAMESPACE + ~Tracer() + { + qDebug("Leaving function %s.", m_func); + } -QT_END_HEADER +private: + const char * const m_func; +}; +QT_END_NAMESPACE + +// #define TRACING_REQUESTED +#ifdef TRACING_REQUESTED +#define TRACE_OBJ Tracer traceObj__(Q_FUNC_INFO); +#else +#define TRACE_OBJ #endif + +#endif // TRACER_H diff --git a/tools/assistant/tools/assistant/xbelsupport.cpp b/tools/assistant/tools/assistant/xbelsupport.cpp new file mode 100644 index 0000000..7d5a08b --- /dev/null +++ b/tools/assistant/tools/assistant/xbelsupport.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "tracer.h" + +#include "xbelsupport.h" + +#include "bookmarkitem.h" +#include "bookmarkmodel.h" + +#include <QtCore/QDate> +#include <QtCore/QModelIndex> + +QT_BEGIN_NAMESPACE + +struct Bookmark { + QString title; + QString url; + bool folded; +}; + +XbelWriter::XbelWriter(BookmarkModel *model) + : QXmlStreamWriter() + , bookmarkModel(model) +{ + TRACE_OBJ + setAutoFormatting(true); +} + +void XbelWriter::writeToFile(QIODevice *device) +{ + TRACE_OBJ + setDevice(device); + + writeStartDocument(); + writeDTD(QLatin1String("<!DOCTYPE xbel>")); + writeStartElement(QLatin1String("xbel")); + writeAttribute(QLatin1String("version"), QLatin1String("1.0")); + + const QModelIndex &root = bookmarkModel->index(0,0, QModelIndex()); + for (int i = 0; i < bookmarkModel->rowCount(root); ++i) + writeData(bookmarkModel->index(i, 0, root)); + writeEndDocument(); +} + +void XbelWriter::writeData(const QModelIndex &index) +{ + TRACE_OBJ + if (index.isValid()) { + Bookmark entry; + entry.title = index.data().toString(); + entry.url = index.data(UserRoleUrl).toString(); + + if (index.data(UserRoleFolder).toBool()) { + writeStartElement(QLatin1String("folder")); + entry.folded = !index.data(UserRoleExpanded).toBool(); + writeAttribute(QLatin1String("folded"), entry.folded + ? QLatin1String("yes") : QLatin1String("no")); + writeTextElement(QLatin1String("title"), entry.title); + + for (int i = 0; i < bookmarkModel->rowCount(index); ++i) + writeData(bookmarkModel->index(i, 0 , index)); + writeEndElement(); + } else { + writeStartElement(QLatin1String("bookmark")); + writeAttribute(QLatin1String("href"), entry.url); + writeTextElement(QLatin1String("title"), entry.title); + writeEndElement(); + } + } +} + +// -- XbelReader + +XbelReader::XbelReader(BookmarkModel *model) + : QXmlStreamReader() + , bookmarkModel(model) +{ + TRACE_OBJ +} + +bool XbelReader::readFromFile(QIODevice *device) +{ + TRACE_OBJ + setDevice(device); + + while (!atEnd()) { + readNext(); + + if (isStartElement()) { + if (name() == QLatin1String("xbel") + && attributes().value(QLatin1String("version")) + == QLatin1String("1.0")) { + const QModelIndex &root = bookmarkModel->index(0,0, QModelIndex()); + parents.append(bookmarkModel->addItem(root, true)); + readXBEL(); + bookmarkModel->setData(parents.first(), + QDate::currentDate().toString(Qt::ISODate), Qt::EditRole); + } else { + raiseError(QLatin1String("The file is not an XBEL version 1.0 file.")); + } + } + } + + return !error(); +} + +void XbelReader::readXBEL() +{ + TRACE_OBJ + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + if (name() == QLatin1String("folder")) + readFolder(); + else if (name() == QLatin1String("bookmark")) + readBookmark(); + else + readUnknownElement(); + } + } +} + +void XbelReader::readFolder() +{ + TRACE_OBJ + parents.append(bookmarkModel->addItem(parents.last(), true)); + bookmarkModel->setData(parents.last(), + attributes().value(QLatin1String("folded")) == QLatin1String("no"), + UserRoleExpanded); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + if (name() == QLatin1String("title")) { + bookmarkModel->setData(parents.last(), readElementText(), + Qt::EditRole); + } else if (name() == QLatin1String("folder")) + readFolder(); + else if (name() == QLatin1String("bookmark")) + readBookmark(); + else + readUnknownElement(); + } + } + + parents.removeLast(); +} + +void XbelReader::readBookmark() +{ + TRACE_OBJ + const QModelIndex &index = bookmarkModel->addItem(parents.last(), false); + if (BookmarkItem* item = bookmarkModel->itemFromIndex(index)) { + item->setData(UserRoleUrl, attributes().value(QLatin1String("href")) + .toString()); + } + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + if (name() == QLatin1String("title")) + bookmarkModel->setData(index, readElementText(), Qt::EditRole); + else + readUnknownElement(); + } + } +} + +void XbelReader::readUnknownElement() +{ + TRACE_OBJ + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) + readUnknownElement(); + } +} + +QT_END_NAMESPACE diff --git a/tools/assistant/compat/topicchooser.h b/tools/assistant/tools/assistant/xbelsupport.h index fef57df..037415f 100644 --- a/tools/assistant/compat/topicchooser.h +++ b/tools/assistant/tools/assistant/xbelsupport.h @@ -39,39 +39,49 @@ ** ****************************************************************************/ -#ifndef TOPICCHOOSER_H -#define TOPICCHOOSER_H +#ifndef XBELSUPPORT_H +#define XBELSUPPORT_H -#include "ui_topicchooser.h" +#include <QtXml/QXmlStreamReader> +#include <QtCore/QPersistentModelIndex> -#include <QDialog> -#include <QStringList> +QT_FORWARD_DECLARE_CLASS(QIODevice) +QT_FORWARD_DECLARE_CLASS(QModelIndex) QT_BEGIN_NAMESPACE -class TopicChooser : public QDialog +class BookmarkModel; + +class XbelWriter : public QXmlStreamWriter { - Q_OBJECT public: - TopicChooser(QWidget *parent, const QStringList &lnkNames, - const QStringList &lnks, const QString &title); + XbelWriter(BookmarkModel *model); + void writeToFile(QIODevice *device); + +private: + void writeData(const QModelIndex &index); - QString link() const; +private: + BookmarkModel *bookmarkModel; +}; - static QString getLink(QWidget *parent, const QStringList &lnkNames, - const QStringList &lnks, const QString &title); +class XbelReader : public QXmlStreamReader +{ +public: + XbelReader(BookmarkModel *model); + bool readFromFile(QIODevice *device); -private slots: - void on_buttonDisplay_clicked(); - void on_buttonCancel_clicked(); - void on_listbox_itemActivated(QListWidgetItem *item); +private: + void readXBEL(); + void readFolder(); + void readBookmark(); + void readUnknownElement(); private: - Ui::TopicChooser ui; - QString theLink; - QStringList links, linkNames; + BookmarkModel *bookmarkModel; + QList<QPersistentModelIndex> parents; }; -#endif // TOPICCHOOSER_H - QT_END_NAMESPACE + +#endif // XBELSUPPORT_H diff --git a/tools/assistant/tools/qcollectiongenerator/main.cpp b/tools/assistant/tools/qcollectiongenerator/main.cpp index 2339c50..7fcb4e1 100644 --- a/tools/assistant/tools/qcollectiongenerator/main.cpp +++ b/tools/assistant/tools/qcollectiongenerator/main.cpp @@ -39,21 +39,23 @@ ** ****************************************************************************/ +#include "../shared/collectionconfiguration.h" #include "../shared/helpgenerator.h" +#include <private/qhelpgenerator_p.h> +#include <private/qhelpprojectdata_p.h> + +#include <QtCore/QCoreApplication> #include <QtCore/QDir> #include <QtCore/QMap> #include <QtCore/QFileInfo> #include <QtCore/QCoreApplication> #include <QtCore/QDateTime> #include <QtCore/QBuffer> - -#include <private/qhelpgenerator_p.h> -#include <private/qhelpprojectdata_p.h> #include <QtHelp/QHelpEngineCore> - #include <QtXml/QXmlStreamReader> + QT_USE_NAMESPACE class CollectionConfigReader : public QXmlStreamReader @@ -87,6 +89,7 @@ public: QStringList filesToRegister() const { return m_filesToRegister; } QString cacheDirectory() const { return m_cacheDirectory; } + bool cacheDirRelativeToCollection() const { return m_cacheDirRelativeToCollection; } private: void raiseErrorWithLine(); @@ -115,11 +118,13 @@ private: QMap<QString, QString> m_filesToGenerate; QStringList m_filesToRegister; QString m_cacheDirectory; + bool m_cacheDirRelativeToCollection; }; void CollectionConfigReader::raiseErrorWithLine() { - raiseError(QObject::tr("Unknown token at line %1.") + raiseError(QCoreApplication::translate("QCollectionGenerator", + "Unknown token at line %1.") .arg(lineNumber())); } @@ -139,8 +144,10 @@ void CollectionConfigReader::readData(const QByteArray &contents) && attributes().value(QLatin1String("version")) == QLatin1String("1.0")) readConfig(); else - raiseError(QObject::tr("Unknown token at line %1. Expected \"QtHelpCollectionProject\"!") - .arg(lineNumber())); + raiseError(QCoreApplication::translate("QCollectionGenerator", + "Unknown token at line %1. " + "Expected \"QtHelpCollectionProject\"!") + .arg(lineNumber())); } } } @@ -198,6 +205,9 @@ void CollectionConfigReader::readAssistantSettings() } else if (name() == QLatin1String("aboutDialog")) { readAboutDialog(); } else if (name() == "cacheDirectory") { + m_cacheDirRelativeToCollection = + attributes().value(QLatin1String("base")) + == QLatin1String("collection"); m_cacheDirectory = readElementText(); } else { raiseErrorWithLine(); @@ -322,6 +332,14 @@ void CollectionConfigReader::readRegister() } } +namespace { + QString absoluteFileName(const QString &basePath, const QString &fileName) + { + return QFileInfo(fileName).isAbsolute() ? + fileName : basePath + QDir::separator() + fileName; + } +} + int main(int argc, char *argv[]) { QString error; @@ -339,7 +357,8 @@ int main(int argc, char *argv[]) QFileInfo fi(QString::fromLocal8Bit(argv[i])); collectionFile = fi.absoluteFilePath(); } else { - error = QObject::tr("Missing output file name!"); + error = QCoreApplication::translate("QCollectionGenerator", + "Missing output file name!"); } } else if (arg == QLatin1String("-h")) { showHelp = true; @@ -353,14 +372,16 @@ int main(int argc, char *argv[]) } if (showVersion) { - fprintf(stdout, "Qt Collection Generator version 1.0 (Qt %s)\n", QT_VERSION_STR); + fprintf(stdout, "Qt Collection Generator version 1.0 (Qt %s)\n", + QT_VERSION_STR); return 0; } if (configFile.isEmpty() && !showHelp) - error = QObject::tr("Missing collection config file!"); + error = QCoreApplication::translate("QCollectionGenerator", + "Missing collection config file!"); - QString help = QObject::tr("\nUsage:\n\n" + QString help = QCoreApplication::translate("QCollectionGenerator", "\nUsage:\n\n" "qcollectiongenerator <collection-config-file> [options]\n\n" " -o <collection-file> Generates a collection file\n" " called <collection-file>. If\n" @@ -403,13 +424,13 @@ int main(int argc, char *argv[]) while (it != config.filesToGenerate().constEnd()) { fprintf(stdout, "Generating help for %s...\n", qPrintable(it.key())); QHelpProjectData helpData; - if (!helpData.readData(basePath + QDir::separator() + it.key())) { + if (!helpData.readData(absoluteFileName(basePath, it.key()))) { fprintf(stderr, "%s\n", qPrintable(helpData.errorMessage())); return -1; } HelpGenerator helpGenerator; - if (!helpGenerator.generate(&helpData, basePath + QDir::separator() + it.value())) { + if (!helpGenerator.generate(&helpData, absoluteFileName(basePath, it.value()))) { fprintf(stderr, "%s\n", qPrintable(helpGenerator.error())); return -1; } @@ -433,49 +454,54 @@ int main(int argc, char *argv[]) } foreach (const QString &file, config.filesToRegister()) { - if (!helpEngine.registerDocumentation(basePath + QDir::separator() + file)) { + if (!helpEngine.registerDocumentation(absoluteFileName(basePath, file))) { fprintf(stderr, "%s\n", qPrintable(helpEngine.error())); return -1; } } if (!config.title().isEmpty()) - helpEngine.setCustomValue(QLatin1String("WindowTitle"), config.title()); + CollectionConfiguration::setWindowTitle(helpEngine, config.title()); if (!config.homePage().isEmpty()) { - helpEngine.setCustomValue(QLatin1String("defaultHomepage"), - config.homePage()); + CollectionConfiguration::setDefaultHomePage(helpEngine, + config.homePage()); } - if (!config.startPage().isEmpty()) - helpEngine.setCustomValue(QLatin1String("LastShownPages"), config.startPage()); + if (!config.startPage().isEmpty()) { + CollectionConfiguration::setLastShownPages(helpEngine, + QStringList(config.startPage())); + } - if (!config.currentFilter().isEmpty()) - helpEngine.setCustomValue(QLatin1String("CurrentFilter"), config.currentFilter()); + if (!config.currentFilter().isEmpty()) { + helpEngine.setCurrentFilter(config.currentFilter()); + } - if (!config.cacheDirectory().isEmpty()) - helpEngine.setCustomValue(QLatin1String("CacheDirectory"), config.cacheDirectory()); + if (!config.cacheDirectory().isEmpty()) { + CollectionConfiguration::setCacheDir(helpEngine, config.cacheDirectory(), + config.cacheDirRelativeToCollection()); + } - helpEngine.setCustomValue(QLatin1String("EnableFilterFunctionality"), + CollectionConfiguration::setFilterFunctionalityEnabled(helpEngine, config.enableFilterFunctionality()); - helpEngine.setCustomValue(QLatin1String("HideFilterFunctionality"), - config.hideFilterFunctionality()); - helpEngine.setCustomValue(QLatin1String("EnableDocumentationManager"), + CollectionConfiguration::setFilterToolbarVisible(helpEngine, + !config.hideFilterFunctionality()); + CollectionConfiguration::setDocumentationManagerEnabled(helpEngine, config.enableDocumentationManager()); - helpEngine.setCustomValue(QLatin1String("EnableAddressBar"), + CollectionConfiguration::setAddressBarEnabled(helpEngine, config.enableAddressBar()); - helpEngine.setCustomValue(QLatin1String("HideAddressBar"), - config.hideAddressBar()); - helpEngine.setCustomValue(QLatin1String("CreationTime"), + CollectionConfiguration::setAddressBarVisible(helpEngine, + !config.hideAddressBar()); + CollectionConfiguration::setCreationTime(helpEngine, QDateTime::currentDateTime().toTime_t()); if (!config.applicationIcon().isEmpty()) { - QFile icon(basePath + QDir::separator() + config.applicationIcon()); + QFile icon(absoluteFileName(basePath, config.applicationIcon())); if (!icon.open(QIODevice::ReadOnly)) { fprintf(stderr, "Cannot open %s!\n", qPrintable(icon.fileName())); return -1; } - helpEngine.setCustomValue(QLatin1String("ApplicationIcon"), icon.readAll()); + CollectionConfiguration::setApplicationIcon(helpEngine, icon.readAll()); } if (config.aboutMenuTexts().count()) { @@ -487,16 +513,16 @@ int main(int argc, char *argv[]) s << it.value(); ++it; } - helpEngine.setCustomValue(QLatin1String("AboutMenuTexts"), ba); + CollectionConfiguration::setAboutMenuTexts(helpEngine, ba); } if (!config.aboutIcon().isEmpty()) { - QFile icon(basePath + QDir::separator() + config.aboutIcon()); + QFile icon(absoluteFileName(basePath, config.aboutIcon())); if (!icon.open(QIODevice::ReadOnly)) { fprintf(stderr, "Cannot open %s!\n", qPrintable(icon.fileName())); return -1; } - helpEngine.setCustomValue(QLatin1String("AboutIcon"), icon.readAll()); + CollectionConfiguration::setAboutIcon(helpEngine, icon.readAll()); } if (config.aboutTextFiles().count()) { @@ -512,7 +538,7 @@ int main(int argc, char *argv[]) while (it != config.aboutTextFiles().constEnd()) { s << it.key(); - QFileInfo fi(basePath + QDir::separator() + it.value()); + QFileInfo fi(absoluteFileName(basePath, it.value())); QFile f(fi.absoluteFilePath()); if (!f.open(QIODevice::ReadOnly)) { fprintf(stderr, "Cannot open %s!\n", qPrintable(f.fileName())); @@ -544,14 +570,14 @@ int main(int argc, char *argv[]) } ++it; } - helpEngine.setCustomValue(QLatin1String("AboutTexts"), ba); + CollectionConfiguration::setAboutTexts(helpEngine, ba); if (imgData.count()) { QByteArray imageData; QBuffer buffer(&imageData); buffer.open(QIODevice::WriteOnly); QDataStream out(&buffer); out << imgData; - helpEngine.setCustomValue(QLatin1String("AboutImages"), imageData); + CollectionConfiguration::setAboutImages(helpEngine, imageData); } } diff --git a/tools/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro b/tools/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro index cf70e48..98e6a31 100644 --- a/tools/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro +++ b/tools/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro @@ -1,14 +1,17 @@ -QT += xml network +QT += xml \ + network TEMPLATE = app DESTDIR = ../../../../bin TARGET = qcollectiongenerator -CONFIG += qt warn_on help console +CONFIG += qt \ + warn_on \ + help \ + console CONFIG -= app_bundle - -target.path=$$[QT_INSTALL_BINS] +target.path = $$[QT_INSTALL_BINS] INSTALLS += target - SOURCES += ../shared/helpgenerator.cpp \ - main.cpp - -HEADERS += ../shared/helpgenerator.h + main.cpp \ + ../shared/collectionconfiguration.cpp +HEADERS += ../shared/helpgenerator.h \ + ../shared/collectionconfiguration.h diff --git a/tools/assistant/tools/qhelpgenerator/main.cpp b/tools/assistant/tools/qhelpgenerator/main.cpp index 6245e33..a309f42 100644 --- a/tools/assistant/tools/qhelpgenerator/main.cpp +++ b/tools/assistant/tools/qhelpgenerator/main.cpp @@ -58,6 +58,7 @@ int main(int argc, char *argv[]) QString basePath; bool showHelp = false; bool showVersion = false; + bool checkLinks = false; for (int i = 1; i < argc; ++i) { arg = QString::fromLocal8Bit(argv[i]); @@ -66,12 +67,15 @@ int main(int argc, char *argv[]) QFileInfo fi(QString::fromLocal8Bit(argv[i])); compressedFile = fi.absoluteFilePath(); } else { - error = QObject::tr("Missing output file name!"); + error = QCoreApplication::translate("QHelpGenerator", + "Missing output file name!"); } } else if (arg == QLatin1String("-v")) { showVersion = true; } else if (arg == QLatin1String("-h")) { showHelp = true; + } else if (arg == QLatin1String("-c")) { + checkLinks = true; } else { QFileInfo fi(arg); projectFile = fi.absoluteFilePath(); @@ -80,19 +84,23 @@ int main(int argc, char *argv[]) } if (showVersion) { - fprintf(stdout, "Qt Help Generator version 1.0 (Qt %s)\n", QT_VERSION_STR); + fprintf(stdout, "Qt Help Generator version 1.0 (Qt %s)\n", + QT_VERSION_STR); return 0; } if (projectFile.isEmpty() && !showHelp) - error = QObject::tr("Missing Qt help project file!"); + error = QCoreApplication::translate("QHelpGenerator", + "Missing Qt help project file!"); - QString help = QObject::tr("\nUsage:\n\n" + QString help = QCoreApplication::translate("QHelpGenerator", "\nUsage:\n\n" "qhelpgenerator <help-project-file> [options]\n\n" " -o <compressed-file> Generates a Qt compressed help\n" " file called <compressed-file>.\n" " If this option is not specified\n" " a default name will be used.\n" + " -c Checks whether all links in HTML files\n" + " point to files in this help project.\n" " -v Displays the version of \n" " qhelpgenerator.\n\n"); @@ -111,9 +119,11 @@ int main(int argc, char *argv[]) } if (compressedFile.isEmpty()) { - QFileInfo fi(projectFile); - compressedFile = basePath + QDir::separator() - + fi.baseName() + QLatin1String(".qch"); + if (!checkLinks) { + QFileInfo fi(projectFile); + compressedFile = basePath + QDir::separator() + + fi.baseName() + QLatin1String(".qch"); + } } else { // check if the output dir exists -- create if it doesn't QFileInfo fi(compressedFile); @@ -134,7 +144,11 @@ int main(int argc, char *argv[]) QCoreApplication app(argc, argv); HelpGenerator generator; - bool success = generator.generate(helpData, compressedFile); + bool success = true; + if (checkLinks) + success = generator.checkLinks(*helpData); + if (success && !compressedFile.isEmpty()) + success = generator.generate(helpData, compressedFile); delete helpData; if (!success) { fprintf(stderr, "%s\n", qPrintable(generator.error())); diff --git a/tools/assistant/tools/shared/collectionconfiguration.cpp b/tools/assistant/tools/shared/collectionconfiguration.cpp new file mode 100644 index 0000000..896afaf --- /dev/null +++ b/tools/assistant/tools/shared/collectionconfiguration.cpp @@ -0,0 +1,313 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "collectionconfiguration.h" + +#include <QtHelp/QHelpEngineCore> + +QT_BEGIN_NAMESPACE + +namespace { + const QString AboutIconKey(QLatin1String("AboutIcon")); + const QString AboutImagesKey(QLatin1String("AboutImages")); + const QString AboutMenuTextsKey(QLatin1String("AboutMenuTexts")); + const QString AboutTextsKey(QLatin1String("AboutTexts")); + const QString ApplicationIconKey(QLatin1String("ApplicationIcon")); + const QString CacheDirKey(QLatin1String("CacheDirectory")); + const QString CacheDirRelativeToCollectionKey(QLatin1String("CacheDirRelativeToCollection")); + const QString CreationTimeKey(QLatin1String("CreationTime")); + const QString DefaultHomePageKey(QLatin1String("defaultHomepage")); + const QString EnableAddressBarKey(QLatin1String("EnableAddressBar")); + const QString EnableDocManagerKey(QLatin1String("EnableDocumentationManager")); + const QString EnableFilterKey(QLatin1String("EnableFilterFunctionality")); + const QString HideAddressBarKey(QLatin1String("HideAddressBar")); + const QString FilterToolbarHiddenKey(QLatin1String("HideFilterFunctionality")); + const QString LastPageKey(QLatin1String("LastTabPage")); + const QString LastRegisterTime(QLatin1String("LastRegisterTime")); + const QString LastShownPagesKey(QLatin1String("LastShownPages")); + const QString LastZoomFactorsKey(QLatin1String( +#if !defined(QT_NO_WEBKIT) + "LastPagesZoomWebView" +#else + "LastPagesZoomTextBrowser" +#endif + )); + const QString WindowTitleKey(QLatin1String("WindowTitle")); +} // anonymous namespace + +const QString CollectionConfiguration::DefaultZoomFactor(QLatin1String("0.0")); +const QString CollectionConfiguration::ListSeparator(QLatin1String("|")); + +uint CollectionConfiguration::creationTime(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(CreationTimeKey, 0).toUInt(); +} + +void CollectionConfiguration::setCreationTime(QHelpEngineCore &helpEngine, uint time) +{ + helpEngine.setCustomValue(CreationTimeKey, time); +} + +const QString CollectionConfiguration::windowTitle(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(WindowTitleKey).toString(); +} + +void CollectionConfiguration::setWindowTitle(QHelpEngineCore &helpEngine, + const QString &windowTitle) +{ + helpEngine.setCustomValue(WindowTitleKey, windowTitle); +} + +bool CollectionConfiguration::filterFunctionalityEnabled(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(EnableFilterKey, true).toBool(); +} + +void CollectionConfiguration::setFilterFunctionalityEnabled(QHelpEngineCore &helpEngine, + bool enabled) +{ + helpEngine.setCustomValue(EnableFilterKey, enabled); +} + +bool CollectionConfiguration::filterToolbarVisible(const QHelpEngineCore &helpEngine) +{ + return !helpEngine.customValue(FilterToolbarHiddenKey, true).toBool(); +} + +void CollectionConfiguration::setFilterToolbarVisible(QHelpEngineCore &helpEngine, + bool visible) +{ + helpEngine.setCustomValue(FilterToolbarHiddenKey, !visible); +} + +bool CollectionConfiguration::addressBarEnabled(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(EnableAddressBarKey, true).toBool(); +} + +void CollectionConfiguration::setAddressBarEnabled(QHelpEngineCore &helpEngine, + bool enabled) +{ + helpEngine.setCustomValue(EnableAddressBarKey, enabled); +} + +bool CollectionConfiguration::addressBarVisible(const QHelpEngineCore &helpEngine) +{ + return !helpEngine.customValue(HideAddressBarKey, true).toBool(); +} + +void CollectionConfiguration::setAddressBarVisible(QHelpEngineCore &helpEngine, + bool visible) +{ + helpEngine.setCustomValue(HideAddressBarKey, !visible); +} + +const QString CollectionConfiguration::cacheDir(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(CacheDirKey).toString(); +} + +bool CollectionConfiguration::cacheDirIsRelativeToCollection(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(CacheDirRelativeToCollectionKey).toBool(); +} + +void CollectionConfiguration::setCacheDir(QHelpEngineCore &helpEngine, + const QString &cacheDir, bool relativeToCollection) +{ + helpEngine.setCustomValue(CacheDirKey, cacheDir); + helpEngine.setCustomValue(CacheDirRelativeToCollectionKey, + relativeToCollection); +} + +bool CollectionConfiguration::documentationManagerEnabled(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(EnableDocManagerKey, true).toBool(); +} + +void CollectionConfiguration::setDocumentationManagerEnabled(QHelpEngineCore &helpEngine, + bool enabled) +{ + helpEngine.setCustomValue(EnableDocManagerKey, enabled); +} + +const QByteArray CollectionConfiguration::applicationIcon(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(ApplicationIconKey).toByteArray(); +} + +void CollectionConfiguration::setApplicationIcon(QHelpEngineCore &helpEngine, + const QByteArray &icon) +{ + helpEngine.setCustomValue(ApplicationIconKey, icon); +} + +const QByteArray CollectionConfiguration::aboutMenuTexts(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(AboutMenuTextsKey).toByteArray(); +} + +void CollectionConfiguration::setAboutMenuTexts(QHelpEngineCore &helpEngine, + const QByteArray &texts) +{ + helpEngine.setCustomValue(AboutMenuTextsKey, texts); +} + +const QByteArray CollectionConfiguration::aboutIcon(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(AboutIconKey).toByteArray(); +} + +void CollectionConfiguration::setAboutIcon(QHelpEngineCore &helpEngine, + const QByteArray &icon) +{ + helpEngine.setCustomValue(AboutIconKey, icon); +} + +const QByteArray CollectionConfiguration::aboutTexts(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(AboutTextsKey).toByteArray(); +} + +void CollectionConfiguration::setAboutTexts(QHelpEngineCore &helpEngine, + const QByteArray &texts) +{ + helpEngine.setCustomValue(AboutTextsKey, texts); +} + +const QByteArray CollectionConfiguration::aboutImages(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(AboutImagesKey).toByteArray(); +} + +void CollectionConfiguration::setAboutImages(QHelpEngineCore &helpEngine, + const QByteArray &images) +{ + helpEngine.setCustomValue(AboutImagesKey, images); +} + +const QString CollectionConfiguration::defaultHomePage(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(DefaultHomePageKey, QLatin1String("help")). + toString(); +} + +void CollectionConfiguration::setDefaultHomePage(QHelpEngineCore &helpEngine, + const QString &page) +{ + helpEngine.setCustomValue(DefaultHomePageKey, page); +} + +const QStringList CollectionConfiguration::lastShownPages(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(LastShownPagesKey).toString(). + split(ListSeparator, QString::SkipEmptyParts); +} + +void CollectionConfiguration::setLastShownPages(QHelpEngineCore &helpEngine, + const QStringList &lastShownPages) +{ + helpEngine.setCustomValue(LastShownPagesKey, + lastShownPages.join(ListSeparator)); +} + +const QStringList CollectionConfiguration::lastZoomFactors(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(LastZoomFactorsKey).toString(). + split(ListSeparator, QString::SkipEmptyParts); +} + +void CollectionConfiguration::setLastZoomFactors(QHelpEngineCore &helpEngine, + const QStringList &lastZoomFactors) +{ + helpEngine.setCustomValue(LastZoomFactorsKey, + lastZoomFactors.join(ListSeparator)); +} + +int CollectionConfiguration::lastTabPage(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(LastPageKey, 1).toInt(); +} + +void CollectionConfiguration::setLastTabPage(QHelpEngineCore &helpEngine, + int lastPage) +{ + helpEngine.setCustomValue(LastPageKey, lastPage); +} + +const QDateTime CollectionConfiguration::lastRegisterTime(const QHelpEngineCore &helpEngine) +{ + return helpEngine.customValue(LastRegisterTime, QDateTime()).toDateTime(); +} + +void CollectionConfiguration::updateLastRegisterTime(QHelpEngineCore &helpEngine) +{ + helpEngine.setCustomValue(LastRegisterTime, QDateTime::currentDateTime()); +} + +bool CollectionConfiguration::isNewer(const QHelpEngineCore &newer, + const QHelpEngineCore &older) +{ + return creationTime(newer) > creationTime(older); +} + +void CollectionConfiguration::copyConfiguration(const QHelpEngineCore &source, + QHelpEngineCore &target) +{ + setCreationTime(target, creationTime(source)); + setWindowTitle(target, windowTitle(source)); + target.setCurrentFilter(source.currentFilter()); + setCacheDir(target, cacheDir(source), cacheDirIsRelativeToCollection(source)); + setFilterFunctionalityEnabled(target, filterFunctionalityEnabled(source)); + setFilterToolbarVisible(target, filterToolbarVisible(source)); + setAddressBarEnabled(target, addressBarEnabled(source)); + setAddressBarVisible(target, addressBarVisible(source)); + setDocumentationManagerEnabled(target, documentationManagerEnabled(source)); + setApplicationIcon(target, applicationIcon(source)); + setAboutMenuTexts(target, aboutMenuTexts(source)); + setAboutIcon(target, aboutIcon(source)); + setAboutTexts(target, aboutTexts(source)); + setAboutImages(target, aboutImages(source)); + setDefaultHomePage(target, defaultHomePage(source)); +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/shared/collectionconfiguration.h b/tools/assistant/tools/shared/collectionconfiguration.h new file mode 100644 index 0000000..d897adb --- /dev/null +++ b/tools/assistant/tools/shared/collectionconfiguration.h @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COLLECTIONCONFIGURATION_H +#define COLLECTIONCONFIGURATION_H + +#include <QtCore/QByteArray> +#include <QtCore/QCoreApplication> +#include <QtCore/QDateTime> +#include <QtCore/QString> +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE + +class QHelpEngineCore; + +class CollectionConfiguration +{ +public: + static const QString windowTitle(const QHelpEngineCore &helpEngine); + static void setWindowTitle(QHelpEngineCore &helpEngine, + const QString &windowTitle); + + static const QString cacheDir(const QHelpEngineCore &helpEngine); + static bool cacheDirIsRelativeToCollection(const QHelpEngineCore &helpEngine); + static void setCacheDir(QHelpEngineCore &helpEngine, + const QString &cacheDir, bool relativeToCollection); + + static uint creationTime(const QHelpEngineCore &helpEngine); + static void setCreationTime(QHelpEngineCore &helpEngine, uint time); + + static bool filterFunctionalityEnabled(const QHelpEngineCore &helpEngine); + static void setFilterFunctionalityEnabled(QHelpEngineCore &helpEngine, + bool enabled); + + static bool filterToolbarVisible(const QHelpEngineCore &helpEngine); + static void setFilterToolbarVisible(QHelpEngineCore &helpEngine, + bool visible); + + static bool addressBarEnabled(const QHelpEngineCore &helpEngine); + static void setAddressBarEnabled(QHelpEngineCore &helpEngine, bool enabled); + + static bool addressBarVisible(const QHelpEngineCore &helpEngine); + static void setAddressBarVisible(QHelpEngineCore &helpEngine, bool visible); + + + static bool documentationManagerEnabled(const QHelpEngineCore &helpEngine); + static void setDocumentationManagerEnabled(QHelpEngineCore &helpEngine, + bool enabled); + + static const QByteArray applicationIcon(const QHelpEngineCore &helpEngine); + static void setApplicationIcon(QHelpEngineCore &helpEngine, + const QByteArray &icon); + + // TODO: Encapsulate encoding from/to QByteArray here + static const QByteArray aboutMenuTexts(const QHelpEngineCore &helpEngine); + static void setAboutMenuTexts(QHelpEngineCore &helpEngine, + const QByteArray &texts); + + static const QByteArray aboutIcon(const QHelpEngineCore &helpEngine); + static void setAboutIcon(QHelpEngineCore &helpEngine, + const QByteArray &icon); + + // TODO: Encapsulate encoding from/to QByteArray here + static const QByteArray aboutTexts(const QHelpEngineCore &helpEngine); + static void setAboutTexts(QHelpEngineCore &helpEngine, + const QByteArray &texts); + + static const QByteArray aboutImages(const QHelpEngineCore &helpEngine); + static void setAboutImages(QHelpEngineCore &helpEngine, + const QByteArray &images); + + static const QString defaultHomePage(const QHelpEngineCore &helpEngine); + static void setDefaultHomePage(QHelpEngineCore &helpEngine, + const QString &page); + + // TODO: Don't allow last pages and zoom factors to be set in isolation + // Perhaps also fill up missing elements automatically or assert. + static const QStringList lastShownPages(const QHelpEngineCore &helpEngine); + static void setLastShownPages(QHelpEngineCore &helpEngine, + const QStringList &lastShownPages); + static const QStringList lastZoomFactors(const QHelpEngineCore &helpEngine); + static void setLastZoomFactors(QHelpEngineCore &helPEngine, + const QStringList &lastZoomFactors); + + static int lastTabPage(const QHelpEngineCore &helpEngine); + static void setLastTabPage(QHelpEngineCore &helpEngine, int lastPage); + + static bool isNewer(const QHelpEngineCore &newer, + const QHelpEngineCore &older); + static void copyConfiguration(const QHelpEngineCore &source, + QHelpEngineCore &target); + + /* + * Note that this only reflects register actions caused by the + * "-register" command line switch, not GUI or remote control actions. + */ + static const QDateTime lastRegisterTime(const QHelpEngineCore &helpEngine); + static void updateLastRegisterTime(QHelpEngineCore &helpEngine); + + static const QString DefaultZoomFactor; + static const QString ListSeparator; +}; + +QT_END_NAMESPACE + +#endif // COLLECTIONCONFIGURATION_H diff --git a/tools/assistant/tools/shared/helpgenerator.cpp b/tools/assistant/tools/shared/helpgenerator.cpp index fa183cd..12008e6 100644 --- a/tools/assistant/tools/shared/helpgenerator.cpp +++ b/tools/assistant/tools/shared/helpgenerator.cpp @@ -61,6 +61,11 @@ bool HelpGenerator::generate(QHelpDataInterface *helpData, return generator->generate(helpData, outputFileName); } +bool HelpGenerator::checkLinks(const QHelpDataInterface &helpData) +{ + return generator->checkLinks(helpData); +} + QString HelpGenerator::error() const { return generator->error(); diff --git a/tools/assistant/tools/shared/helpgenerator.h b/tools/assistant/tools/shared/helpgenerator.h index 903d588..6da1c2b 100644 --- a/tools/assistant/tools/shared/helpgenerator.h +++ b/tools/assistant/tools/shared/helpgenerator.h @@ -57,6 +57,7 @@ public: HelpGenerator(); bool generate(QHelpDataInterface *helpData, const QString &outputFileName); + bool checkLinks(const QHelpDataInterface &helpData); QString error() const; private slots: diff --git a/tools/assistant/translations/qt_help.pro b/tools/assistant/translations/qt_help.pro index 1012f3f..6f66876 100644 --- a/tools/assistant/translations/qt_help.pro +++ b/tools/assistant/translations/qt_help.pro @@ -44,6 +44,7 @@ TRANSLATIONS = \ $$TR_DIR/qt_help_cs.ts \ $$TR_DIR/qt_help_da.ts \ $$TR_DIR/qt_help_de.ts \ + $$TR_DIR/qt_help_hu.ts \ $$TR_DIR/qt_help_ja.ts \ $$TR_DIR/qt_help_pl.ts \ $$TR_DIR/qt_help_ru.ts \ diff --git a/tools/assistant/translations/translations.pro b/tools/assistant/translations/translations.pro index d29ffc3..c692262 100644 --- a/tools/assistant/translations/translations.pro +++ b/tools/assistant/translations/translations.pro @@ -46,6 +46,7 @@ TRANSLATIONS = \ $$TR_DIR/assistant_da.ts \ $$TR_DIR/assistant_de.ts \ $$TR_DIR/assistant_fr.ts \ + $$TR_DIR/assistant_hu.ts \ $$TR_DIR/assistant_ja.ts \ $$TR_DIR/assistant_pl.ts \ $$TR_DIR/assistant_ru.ts \ diff --git a/tools/assistant/translations/translations_adp.pro b/tools/assistant/translations/translations_adp.pro deleted file mode 100644 index f8da2e3..0000000 --- a/tools/assistant/translations/translations_adp.pro +++ /dev/null @@ -1,41 +0,0 @@ -# Include those manually as they do not contain any directory specification - -FORMS += ../compat/helpdialog.ui \ - ../compat/mainwindow.ui \ - ../compat/tabbedbrowser.ui \ - ../compat/topicchooser.ui - -SOURCES += ../compat/main.cpp \ - ../compat/helpwindow.cpp \ - ../compat/topicchooser.cpp \ - ../compat/docuparser.cpp \ - ../compat/index.cpp \ - ../compat/profile.cpp \ - ../compat/config.cpp \ - ../compat/helpdialog.cpp \ - ../compat/mainwindow.cpp \ - ../compat/tabbedbrowser.cpp \ - ../compat/fontsettingsdialog.cpp - -SOURCES += ../../shared/fontpanel/fontpanel.cpp - -HEADERS += ../compat/helpwindow.h \ - ../compat/topicchooser.h \ - ../compat/docuparser.h \ - ../compat/index.h \ - ../compat/profile.h \ - ../compat/helpdialog.h \ - ../compat/mainwindow.h \ - ../compat/tabbedbrowser.h \ - ../compat/config.h \ - ../compat/fontsettingsdialog.h - - -TR_DIR = $$PWD/../../../translations -TRANSLATIONS = \ - $$TR_DIR/assistant_adp_de.ts \ - $$TR_DIR/assistant_adp_ja.ts \ - $$TR_DIR/assistant_adp_pl.ts \ - $$TR_DIR/assistant_adp_ru.ts \ - $$TR_DIR/assistant_adp_zh_CN.ts \ - $$TR_DIR/assistant_adp_zh_TW.ts diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 83b4d9c..7154fd4 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -701,9 +701,6 @@ void Configure::parseCmdLine() } else if ( configCmdLine.at(i) == "-opengl-es-cm" ) { dictionary[ "OPENGL" ] = "yes"; dictionary[ "OPENGL_ES_CM" ] = "yes"; - } else if ( configCmdLine.at(i) == "-opengl-es-cl" ) { - dictionary[ "OPENGL" ] = "yes"; - dictionary[ "OPENGL_ES_CL" ] = "yes"; } else if ( configCmdLine.at(i) == "-opengl-es-2" ) { dictionary[ "OPENGL" ] = "yes"; dictionary[ "OPENGL_ES_2" ] = "yes"; @@ -1821,7 +1818,6 @@ bool Configure::displayHelp() desc("CETEST", "yes", "-cetest", "Compile Windows CE remote test application"); desc( "-signature <file>", "Use file for signing the target project"); desc("OPENGL_ES_CM", "no", "-opengl-es-cm", "Enable support for OpenGL ES Common"); - desc("OPENGL_ES_CL", "no", "-opengl-es-cl", "Enable support for OpenGL ES Common Lite"); desc("OPENGL_ES_2", "no", "-opengl-es-2", "Enable support for OpenGL ES 2.0"); desc("DIRECTSHOW", "no", "-phonon-wince-ds9", "Enable Phonon Direct Show 9 backend for Windows CE"); @@ -1871,8 +1867,16 @@ bool Configure::findFile( const QString &fileName ) QString paths; if (file.endsWith(".h")) { - if (!mingwPath.isNull() && !findFileInPaths(file, mingwPath + QLatin1String("/../include")).isNull()) - return true; + if (!mingwPath.isNull()) { + if (!findFileInPaths(file, mingwPath + QLatin1String("/../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; + } + } paths = QString::fromLocal8Bit(getenv("INCLUDE")); } else if ( file.endsWith( ".lib" ) || file.endsWith( ".a" ) ) { if (!mingwPath.isNull() && !findFileInPaths(file, mingwPath + QLatin1String("/../lib")).isNull()) @@ -2002,18 +2006,16 @@ bool Configure::checkAvailability(const QString &part) available = (dictionary[ "ARCHITECTURE" ] == "windowsce"); else if (part == "OPENGL_ES_CM") available = (dictionary[ "ARCHITECTURE" ] == "windowsce"); - else if (part == "OPENGL_ES_CL") - available = (dictionary[ "ARCHITECTURE" ] == "windowsce"); else if (part == "OPENGL_ES_2") available = (dictionary[ "ARCHITECTURE" ] == "windowsce"); else if (part == "DIRECTSHOW") available = (dictionary[ "ARCHITECTURE" ] == "windowsce"); else if (part == "SSE2") - available = (dictionary.value("QMAKESPEC") != "win32-msvc") && (dictionary.value("QMAKESPEC") != "win32-g++"); + available = (dictionary.value("QMAKESPEC") != "win32-msvc"); else if (part == "3DNOW" ) - available = (dictionary.value("QMAKESPEC") != "win32-msvc") && (dictionary.value("QMAKESPEC") != "win32-icc") && findFile("mm3dnow.h") && (dictionary.value("QMAKESPEC") != "win32-g++"); + available = (dictionary.value("QMAKESPEC") != "win32-msvc") && (dictionary.value("QMAKESPEC") != "win32-icc") && findFile("mm3dnow.h"); else if (part == "MMX" || part == "SSE") - available = (dictionary.value("QMAKESPEC") != "win32-msvc") && (dictionary.value("QMAKESPEC") != "win32-g++"); + available = (dictionary.value("QMAKESPEC") != "win32-msvc"); else if (part == "OPENSSL") available = findFile("openssl\\ssl.h"); else if (part == "DBUS") @@ -2481,11 +2483,6 @@ void Configure::generateOutputVars() qtConfig += "egl"; } - if ( dictionary["OPENGL_ES_CL"] == "yes" ) { - qtConfig += "opengles1cl"; - qtConfig += "egl"; - } - if ( dictionary["OPENVG"] == "yes" ) { qtConfig += "openvg"; qtConfig += "egl"; @@ -2939,13 +2936,10 @@ void Configure::generateConfigfiles() if(dictionary["NATIVE_GESTURES"] == "no") qconfigList += "QT_NO_NATIVE_GESTURES"; if(dictionary["OPENGL_ES_CM"] == "yes" || - dictionary["OPENGL_ES_CL"] == "yes" || dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES"; if(dictionary["OPENGL_ES_CM"] == "yes") qconfigList += "QT_OPENGL_ES_1"; if(dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES_2"; - if(dictionary["OPENGL_ES_CL"] == "yes") qconfigList += "QT_OPENGL_ES_1_CL"; - if(dictionary["SQL_MYSQL"] == "yes") qconfigList += "QT_SQL_MYSQL"; if(dictionary["SQL_ODBC"] == "yes") qconfigList += "QT_SQL_ODBC"; if(dictionary["SQL_OCI"] == "yes") qconfigList += "QT_SQL_OCI"; diff --git a/tools/designer/src/components/formeditor/formwindow.cpp b/tools/designer/src/components/formeditor/formwindow.cpp index 9fd084d..3a7cd83 100644 --- a/tools/designer/src/components/formeditor/formwindow.cpp +++ b/tools/designer/src/components/formeditor/formwindow.cpp @@ -484,6 +484,7 @@ void FormWindow::setMainContainer(QWidget *w) sheet->setVisible(sheet->indexOf(QLatin1String("windowTitle")), true); sheet->setVisible(sheet->indexOf(QLatin1String("windowIcon")), true); sheet->setVisible(sheet->indexOf(QLatin1String("windowModality")), true); + sheet->setVisible(sheet->indexOf(QLatin1String("windowOpacity")), true); sheet->setVisible(sheet->indexOf(QLatin1String("windowFilePath")), true); // ### generalize } diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.cpp b/tools/designer/src/components/propertyeditor/propertyeditor.cpp index b171ddc..512cc82 100644 --- a/tools/designer/src/components/propertyeditor/propertyeditor.cpp +++ b/tools/designer/src/components/propertyeditor/propertyeditor.cpp @@ -1175,11 +1175,11 @@ void PropertyEditor::slotValueChanged(QtProperty *property, const QVariant &valu Q_ASSERT(ok); QVariant v; qVariantSetValue(v, e); - emit propertyValueChanged(property->propertyName(), v, true); + emitPropertyValueChanged(property->propertyName(), v, true); return; } - emit propertyValueChanged(property->propertyName(), value, enableSubPropertyHandling); + emitPropertyValueChanged(property->propertyName(), value, enableSubPropertyHandling); } bool PropertyEditor::isDynamicProperty(const QtBrowserItem* item) const diff --git a/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp index 674c3a8..1a8611c 100644 --- a/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp +++ b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp @@ -88,11 +88,15 @@ namespace qdesigner_internal { struct WidgetBoxCategoryEntry { WidgetBoxCategoryEntry(); - explicit WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable); + explicit WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &widget, + const QString &filter, + const QIcon &icon, + bool editable); QDesignerWidgetBoxInterface::Widget widget; QString toolTip; QString whatsThis; + QString filter; QIcon icon; bool editable; }; @@ -103,8 +107,11 @@ WidgetBoxCategoryEntry::WidgetBoxCategoryEntry() : { } -WidgetBoxCategoryEntry::WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &w, const QIcon &i, bool e) : +WidgetBoxCategoryEntry::WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &w, + const QString &filterIn, + const QIcon &i, bool e) : widget(w), + filter(filterIn), icon(i), editable(e) { @@ -142,6 +149,7 @@ public: private: typedef QList<WidgetBoxCategoryEntry> WidgetBoxCategoryEntrys; + QRegExp m_classNameRegExp; QDesignerFormEditorInterface *m_core; WidgetBoxCategoryEntrys m_items; QListView::ViewMode m_viewMode; @@ -149,9 +157,11 @@ private: WidgetBoxCategoryModel::WidgetBoxCategoryModel(QDesignerFormEditorInterface *core, QObject *parent) : QAbstractListModel(parent), + m_classNameRegExp(QLatin1String("<widget +class *= *\"([^\"]+)\"")), m_core(core), m_viewMode(QListView::ListMode) { + Q_ASSERT(m_classNameRegExp.isValid()); } QListView::ViewMode WidgetBoxCategoryModel::viewMode() const @@ -205,8 +215,14 @@ bool WidgetBoxCategoryModel::removeCustomWidgets() void WidgetBoxCategoryModel::addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon,bool editable) { - // build item - WidgetBoxCategoryEntry item(widget, icon, editable); + // build item. Filter on name + class name if it is different and not a layout. + QString filter = widget.name(); + if (!filter.contains(QLatin1String("Layout")) && m_classNameRegExp.indexIn(widget.domXml()) != -1) { + const QString className = m_classNameRegExp.cap(1); + if (!filter.contains(className)) + filter += className; + } + WidgetBoxCategoryEntry item(widget, filter, icon, editable); const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase(); const int dbIndex = db->indexOfClassName(widget.name()); if (dbIndex != -1) { @@ -255,7 +271,7 @@ QVariant WidgetBoxCategoryModel::data(const QModelIndex &index, int role) const case Qt::WhatsThisRole: return QVariant(item.whatsThis); case FilterRole: - return item.widget.name(); + return item.filter; } return QVariant(); } diff --git a/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp b/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp index e89c47c..9a1739e 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp +++ b/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp @@ -92,7 +92,8 @@ static const PropertyNameTypeMap &stringPropertyTypes() } QDesignerPropertyEditor::QDesignerPropertyEditor(QWidget *parent, Qt::WindowFlags flags) : - QDesignerPropertyEditorInterface(parent, flags) + QDesignerPropertyEditorInterface(parent, flags), + m_propertyChangedForwardingBlocked(false) { // Make old signal work for compatibility connect(this, SIGNAL(propertyChanged(QString,QVariant)), this, SLOT(slotPropertyChanged(QString,QVariant))); @@ -147,9 +148,20 @@ QDesignerPropertyEditor::StringPropertyParameters QDesignerPropertyEditor::textP return StringPropertyParameters(ValidationSingleLine, true); } +void QDesignerPropertyEditor::emitPropertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling) +{ + // Avoid duplicate signal emission - see below + m_propertyChangedForwardingBlocked = true; + emit propertyValueChanged(name, value, enableSubPropertyHandling); + emit propertyChanged(name, value); + m_propertyChangedForwardingBlocked = false; +} + void QDesignerPropertyEditor::slotPropertyChanged(const QString &name, const QVariant &value) { - emit propertyValueChanged(name, value, true); + // Forward signal from Integration using the old interfaces. + if (!m_propertyChangedForwardingBlocked) + emit propertyValueChanged(name, value, true); } } diff --git a/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h b/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h index cdd53f0..27078f2 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h +++ b/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h @@ -79,7 +79,6 @@ public: static StringPropertyParameters textPropertyValidationMode(QDesignerFormEditorInterface *core, const QObject *object, const QString &propertyName, bool isMainContainer); - Q_SIGNALS: void propertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling); void resetProperty(const QString &name); @@ -97,6 +96,13 @@ public Q_SLOTS: private Q_SLOTS: void slotPropertyChanged(const QString &name, const QVariant &value); + +protected: + void emitPropertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling); + +private: + bool m_propertyChangedForwardingBlocked; + }; } // namespace qdesigner_internal diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp index b4b962c..13bb1d7 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp +++ b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp @@ -610,8 +610,9 @@ QDesignerPropertySheet::QDesignerPropertySheet(QObject *object, QObject *parent) createFakeProperty(QLatin1String("whatsThis")); createFakeProperty(QLatin1String("acceptDrops")); createFakeProperty(QLatin1String("dragEnabled")); - // windowModality is visible only for the main container, in which case the form windows enables it on loading + // windowModality/Opacity is visible only for the main container, in which case the form windows enables it on loading setVisible(createFakeProperty(QLatin1String("windowModality")), false); + setVisible(createFakeProperty(QLatin1String("windowOpacity"), double(1.0)), false); if (qobject_cast<const QToolBar *>(d->m_object)) { // prevent toolbars from being dragged off createFakeProperty(QLatin1String("floatable"), QVariant(true)); } else { @@ -1451,8 +1452,13 @@ bool QDesignerPropertySheet::isVisible(int index) const } if (isFakeProperty(index)) { - if (type == PropertyWindowModality) // Hidden for child widgets + switch (type) { + case PropertyWindowModality: // Hidden for child widgets + case PropertyWindowOpacity: return d->m_info.value(index).visible; + default: + break; + } return true; } diff --git a/tools/designer/translations/translations.pro b/tools/designer/translations/translations.pro index a1b99fd..103c1fe 100644 --- a/tools/designer/translations/translations.pro +++ b/tools/designer/translations/translations.pro @@ -132,6 +132,7 @@ TRANSLATIONS = \ $$TR_DIR/designer_cs.ts \ $$TR_DIR/designer_de.ts \ $$TR_DIR/designer_fr.ts \ + $$TR_DIR/designer_hu.ts \ $$TR_DIR/designer_ja.ts \ $$TR_DIR/designer_pl.ts \ $$TR_DIR/designer_ru.ts \ diff --git a/tools/linguist/linguist/linguist.pro b/tools/linguist/linguist/linguist.pro index 693bc71..4f7ed8a 100644 --- a/tools/linguist/linguist/linguist.pro +++ b/tools/linguist/linguist/linguist.pro @@ -9,7 +9,7 @@ CONFIG += qt \ uitools DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII -build_all:!build_pass { +build_all:!build_pass { CONFIG -= build_all CONFIG += release } @@ -42,7 +42,7 @@ SOURCES += \ statistics.cpp \ translatedialog.cpp \ translationsettingsdialog.cpp \ - ../shared/simtexth.cpp + ../shared/simtexth.cpp HEADERS += \ batchtranslationdialog.h \ @@ -71,7 +71,7 @@ contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE DEFINES += QT_KEYWORDS TARGET = linguist win32:RC_FILE = linguist.rc -mac { +mac { static:CONFIG -= global_init_link_order ICON = linguist.icns TARGET = Linguist @@ -100,6 +100,7 @@ TRANSLATIONS = \ $$TR_DIR/linguist_cs.ts \ $$TR_DIR/linguist_de.ts \ $$TR_DIR/linguist_fr.ts \ + $$TR_DIR/linguist_hu.ts \ $$TR_DIR/linguist_ja.ts \ $$TR_DIR/linguist_pl.ts \ $$TR_DIR/linguist_ru.ts \ diff --git a/tools/linguist/linguist/mainwindow.ui b/tools/linguist/linguist/mainwindow.ui index 450ce89..4edde5e 100644 --- a/tools/linguist/linguist/mainwindow.ui +++ b/tools/linguist/linguist/mainwindow.ui @@ -679,7 +679,7 @@ <string>About Qt</string> </property> <property name="whatsThis"> - <string>Display information about the Qt toolkit by Trolltech.</string> + <string>Display information about the Qt toolkit by Nokia.</string> </property> <property name="menuRole"> <enum>QAction::AboutQtRole</enum> diff --git a/tools/linguist/lupdate/lupdate.h b/tools/linguist/lupdate/lupdate.h index 70332cd..136884b 100644 --- a/tools/linguist/lupdate/lupdate.h +++ b/tools/linguist/lupdate/lupdate.h @@ -79,6 +79,7 @@ void loadCPP(Translator &translator, const QStringList &filenames, ConversionDat bool loadJava(Translator &translator, const QString &filename, ConversionData &cd); bool loadQScript(Translator &translator, const QString &filename, ConversionData &cd); bool loadUI(Translator &translator, const QString &filename, ConversionData &cd); +bool loadQml(Translator &translator, const QString &filename, ConversionData &cd); QT_END_NAMESPACE diff --git a/tools/linguist/lupdate/lupdate.pro b/tools/linguist/lupdate/lupdate.pro index ccc2d47..283d69f 100644 --- a/tools/linguist/lupdate/lupdate.pro +++ b/tools/linguist/lupdate/lupdate.pro @@ -15,6 +15,9 @@ build_all:!build_pass { include(../shared/formats.pri) include(../shared/proparser.pri) +include($$QT_SOURCE_TREE/src/declarative/qml/parser/parser.pri) +INCLUDEPATH += $$QT_SOURCE_TREE/src/declarative/qml + SOURCES += \ main.cpp \ merge.cpp \ @@ -23,6 +26,7 @@ SOURCES += \ cpp.cpp \ java.cpp \ qscript.cpp \ + qml.cpp \ ui.cpp HEADERS += \ diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp index b2bfd7c..0003baa 100644 --- a/tools/linguist/lupdate/main.cpp +++ b/tools/linguist/lupdate/main.cpp @@ -83,7 +83,7 @@ static void printUsage() printOut(QObject::tr( "Usage:\n" " lupdate [options] [project-file]...\n" - " lupdate [options] [source-file|path]... -ts ts-files\n\n" + " lupdate [options] [source-file|path|@lst-file]... -ts ts-files|@lst-file\n\n" "lupdate is part of Qt's Linguist tool chain. It extracts translatable\n" "messages from Qt UI files, C++, Java and JavaScript/QtScript source code.\n" "Extracted messages are stored in textual translation source files (typically\n" @@ -132,6 +132,8 @@ static void printUsage() " Specify the codec assumed for tr() calls. Effective only with -ts.\n" " -version\n" " Display the version of lupdate and exit.\n" + " @lst-file\n" + " Read additional file names (one per line) from lst-file.\n" ).arg(m_defaultExtensions)); } @@ -267,6 +269,8 @@ static void processSources(Translator &fetchedTor, else if (it->endsWith(QLatin1String(".js"), Qt::CaseInsensitive) || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive)) loadQScript(fetchedTor, *it, cd); + else if (it->endsWith(QLatin1String(".qml"), Qt::CaseInsensitive)) + loadQml(fetchedTor, *it, cd); else sourceFilesCpp << *it; } @@ -560,73 +564,92 @@ int main(int argc, char **argv) return 1; } + QStringList files; + if (arg.startsWith(QLatin1String("@"))) { + QFile lstFile(arg.mid(1)); + if (!lstFile.open(QIODevice::ReadOnly)) { + qWarning("lupdate error: List file '%s' is not readable", + qPrintable(lstFile.fileName())); + return 1; + } + while (!lstFile.atEnd()) + files << QString::fromLocal8Bit(lstFile.readLine().trimmed()); + } else { + files << arg; + } if (metTsFlag) { - bool found = false; - foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) { - if (arg.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive)) { - QFileInfo fi(arg); - if (!fi.exists() || fi.isWritable()) { - tsFileNames.append(QFileInfo(arg).absoluteFilePath()); - } else { - qWarning("lupdate warning: For some reason, '%s' is not writable.\n", - qPrintable(arg)); + foreach (const QString &file, files) { + bool found = false; + foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) { + if (file.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive)) { + QFileInfo fi(file); + if (!fi.exists() || fi.isWritable()) { + tsFileNames.append(QFileInfo(file).absoluteFilePath()); + } else { + qWarning("lupdate warning: For some reason, '%s' is not writable.\n", + qPrintable(file)); + } + found = true; + break; } - found = true; - break; + } + if (!found) { + qWarning("lupdate error: File '%s' has no recognized extension\n", + qPrintable(file)); + return 1; } } - if (!found) { - qWarning("lupdate error: File '%s' has no recognized extension\n", - qPrintable(arg)); - return 1; - } - } else if (arg.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive) - || arg.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) { - proFiles << arg; numFiles++; } else { - QFileInfo fi(arg); - if (!fi.exists()) { - qWarning("lupdate error: File '%s' does not exists\n", qPrintable(arg)); - return 1; - } else if (fi.isDir()) { - if (options & Verbose) - printOut(QObject::tr("Scanning directory '%1'...").arg(arg)); - QDir dir = QDir(fi.filePath()); - projectRoots.insert(dir.absolutePath() + QLatin1Char('/')); - if (extensionsNameFilters.isEmpty()) { - foreach (QString ext, extensions.split(QLatin1Char(','))) { - ext = ext.trimmed(); - if (ext.startsWith(QLatin1Char('.'))) - ext.remove(0, 1); - extensionsNameFilters.insert(ext); - } + foreach (const QString &file, files) { + QFileInfo fi(file); + if (!fi.exists()) { + qWarning("lupdate error: File '%s' does not exists\n", qPrintable(file)); + return 1; } - QDir::Filters filters = QDir::Files | QDir::NoSymLinks; - if (recursiveScan) - filters |= QDir::AllDirs | QDir::NoDotAndDotDot; - QFileInfoList fileinfolist; - recursiveFileInfoList(dir, extensionsNameFilters, filters, &fileinfolist); - int scanRootLen = dir.absolutePath().length(); - foreach (const QFileInfo &fi, fileinfolist) { - QString fn = QDir::cleanPath(fi.absoluteFilePath()); - sourceFiles << fn; - - if (!fn.endsWith(QLatin1String(".java")) - && !fn.endsWith(QLatin1String(".ui")) - && !fn.endsWith(QLatin1String(".js")) - && !fn.endsWith(QLatin1String(".qs"))) { - int offset = 0; - int depth = 0; - do { - offset = fn.lastIndexOf(QLatin1Char('/'), offset - 1); - QString ffn = fn.mid(offset + 1); - allCSources.insert(ffn, fn); - } while (++depth < 3 && offset > scanRootLen); + if (file.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive) + || file.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) { + proFiles << file; + } else if (fi.isDir()) { + if (options & Verbose) + printOut(QObject::tr("Scanning directory '%1'...").arg(file)); + QDir dir = QDir(fi.filePath()); + projectRoots.insert(dir.absolutePath() + QLatin1Char('/')); + if (extensionsNameFilters.isEmpty()) { + foreach (QString ext, extensions.split(QLatin1Char(','))) { + ext = ext.trimmed(); + if (ext.startsWith(QLatin1Char('.'))) + ext.remove(0, 1); + extensionsNameFilters.insert(ext); + } + } + QDir::Filters filters = QDir::Files | QDir::NoSymLinks; + if (recursiveScan) + filters |= QDir::AllDirs | QDir::NoDotAndDotDot; + QFileInfoList fileinfolist; + recursiveFileInfoList(dir, extensionsNameFilters, filters, &fileinfolist); + int scanRootLen = dir.absolutePath().length(); + foreach (const QFileInfo &fi, fileinfolist) { + QString fn = QDir::cleanPath(fi.absoluteFilePath()); + sourceFiles << fn; + + if (!fn.endsWith(QLatin1String(".java")) + && !fn.endsWith(QLatin1String(".ui")) + && !fn.endsWith(QLatin1String(".js")) + && !fn.endsWith(QLatin1String(".qs")) + && !fn.endsWith(QLatin1String(".qml"))) { + int offset = 0; + int depth = 0; + do { + offset = fn.lastIndexOf(QLatin1Char('/'), offset - 1); + QString ffn = fn.mid(offset + 1); + allCSources.insert(ffn, fn); + } while (++depth < 3 && offset > scanRootLen); + } } + } else { + sourceFiles << QDir::cleanPath(fi.absoluteFilePath());; } - } else { - sourceFiles << QDir::cleanPath(fi.absoluteFilePath());; } numFiles++; } diff --git a/tools/linguist/lupdate/qml.cpp b/tools/linguist/lupdate/qml.cpp new file mode 100644 index 0000000..860d87c --- /dev/null +++ b/tools/linguist/lupdate/qml.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lupdate.h" + +#include <translator.h> + +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include <QtCore/QString> + +#include "parser/qmljsengine_p.h" +#include "parser/qmljsparser_p.h" +#include "parser/qmljslexer_p.h" +#include "parser/qmljsnodepool_p.h" +#include "parser/qmljsastvisitor_p.h" +#include "parser/qmljsast_p.h" + +#include <QCoreApplication> +#include <QFile> +#include <QFileInfo> +#include <QtDebug> +#include <QStringList> + +#include <iostream> +#include <cstdlib> + +QT_BEGIN_NAMESPACE + +using namespace QmlJS; + +class FindTrCalls: protected AST::Visitor +{ +public: + void operator()(Translator *translator, const QString &fileName, AST::Node *node) + { + m_translator = translator; + m_fileName = fileName; + m_component = QFileInfo(fileName).baseName(); //matches qsTr usage in QScriptEngine + accept(node); + } + +protected: + using AST::Visitor::visit; + using AST::Visitor::endVisit; + + void accept(AST::Node *node) + { AST::Node::acceptChild(node, this); } + + virtual void endVisit(AST::CallExpression *node) + { + if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(node->base)) { + if (idExpr->name->asString() == QLatin1String("qsTr") || + idExpr->name->asString() == QLatin1String("QT_TR_NOOP")) { + if (node->arguments && AST::cast<AST::StringLiteral *>(node->arguments->expression)) { + AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression); + const QString source = literal->value->asString(); + + QString comment; + bool plural = false; + AST::ArgumentList *commentNode = node->arguments->next; + if (commentNode) { + literal = AST::cast<AST::StringLiteral *>(commentNode->expression); + comment = literal->value->asString(); + + AST::ArgumentList *nNode = commentNode->next; + if (nNode) { + AST::NumericLiteral *numLiteral = AST::cast<AST::NumericLiteral *>(nNode->expression); + if (numLiteral) { + plural = true; + } + } + } + + TranslatorMessage msg(m_component, source, + comment, QString(), m_fileName, + node->firstSourceLocation().startLine, QStringList(), + TranslatorMessage::Unfinished, plural); + m_translator->extend(msg); + } + } else if (idExpr->name->asString() == QLatin1String("qsTranslate") || + idExpr->name->asString() == QLatin1String("QT_TRANSLATE_NOOP")) { + if (node->arguments && AST::cast<AST::StringLiteral *>(node->arguments->expression)) { + AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression); + const QString context = literal->value->asString(); + + QString source; + QString comment; + bool plural = false; + AST::ArgumentList *sourceNode = node->arguments->next; + if (sourceNode) { + literal = AST::cast<AST::StringLiteral *>(sourceNode->expression); + source = literal->value->asString(); + AST::ArgumentList *commentNode = sourceNode->next; + if (commentNode) { + literal = AST::cast<AST::StringLiteral *>(commentNode->expression); + comment = literal->value->asString(); + + AST::ArgumentList *nNode = commentNode->next; + if (nNode) { + AST::NumericLiteral *numLiteral = AST::cast<AST::NumericLiteral *>(nNode->expression); + if (numLiteral) { + plural = true; + } + } + } + } + + TranslatorMessage msg(context, source, + comment, QString(), m_fileName, + node->firstSourceLocation().startLine, QStringList(), + TranslatorMessage::Unfinished, plural); + m_translator->extend(msg); + } + + } + } + } + +private: + Translator *m_translator; + QString m_fileName; + QString m_component; +}; + +QString createErrorString(const QString &filename, const QString &code, Parser &parser) +{ + // print out error + QStringList lines = code.split(QLatin1Char('\n')); + lines.append(QLatin1String("\n")); // sentinel. + QString errorString; + + foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) { + + if (m.isWarning()) + continue; + + QString error = filename + QLatin1Char(':') + QString::number(m.loc.startLine) + + QLatin1Char(':') + QString::number(m.loc.startColumn) + QLatin1String(": error: ") + + m.message + QLatin1Char('\n'); + + int line = 0; + if (m.loc.startLine > 0) + line = m.loc.startLine - 1; + + const QString textLine = lines.at(line); + + error += textLine + QLatin1Char('\n'); + + int column = m.loc.startColumn - 1; + if (column < 0) + column = 0; + + column = qMin(column, textLine.length()); + + for (int i = 0; i < column; ++i) { + const QChar ch = textLine.at(i); + if (ch.isSpace()) + error += ch.unicode(); + else + error += QLatin1Char(' '); + } + error += QLatin1String("^\n"); + errorString += error; + } + return errorString; +} + +bool loadQml(Translator &translator, const QString &filename, ConversionData &cd) +{ + cd.m_sourceFileName = filename; + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) { + cd.appendError(QString::fromLatin1("Cannot open %1: %2") + .arg(filename, file.errorString())); + return false; + } + + const QString code = QTextStream(&file).readAll(); + + Engine driver; + Parser parser(&driver); + + NodePool nodePool(filename, &driver); + driver.setNodePool(&nodePool); + + Lexer lexer(&driver); + lexer.setCode(code, /*line = */ 1); + driver.setLexer(&lexer); + + if (parser.parse()) { + FindTrCalls trCalls; + trCalls(&translator, filename, parser.ast()); + } else { + QString error = createErrorString(filename, code, parser); + cd.appendError(error); + return false; + } + return true; +} + +QT_END_NAMESPACE diff --git a/tools/porting/src/q3porting.xml b/tools/porting/src/q3porting.xml index 7a31d6e..39f341f 100644 --- a/tools/porting/src/q3porting.xml +++ b/tools/porting/src/q3porting.xml @@ -1626,10 +1626,6 @@ <Name>Q3Wizard</Name> </item> <item Type="Qt4Class" > - <Library>QtAssistant</Library> - <Name>QAssistantClient</Name> - </item> - <item Type="Qt4Class" > <Library>QtCore</Library> <Name>QAbstractEventDispatcher</Name> </item> diff --git a/tools/qdbus/qdbus/qdbus.cpp b/tools/qdbus/qdbus/qdbus.cpp index 48b0dad..b08910a 100644 --- a/tools/qdbus/qdbus/qdbus.cpp +++ b/tools/qdbus/qdbus/qdbus.cpp @@ -248,8 +248,8 @@ static QStringList readList(QStringList &args) return retval; } -static void placeCall(const QString &service, const QString &path, const QString &interface, - const QString &member, QStringList args) +static int placeCall(const QString &service, const QString &path, const QString &interface, + const QString &member, QStringList args, bool try_prop=true) { QDBusInterface iface(service, path, interface, connection); @@ -273,10 +273,22 @@ static void placeCall(const QString &service, const QString &path, const QString } if (midx == -1) { + // Failed to set property after falling back? + // Bail out without displaying an error + if (!try_prop) + return 1; + if (try_prop && args.size() == 1) { + QStringList proparg; + proparg += interface; + proparg += member; + proparg += args.first(); + if (!placeCall(service, path, "org.freedesktop.DBus.Properties", "Set", proparg, false)) + return 0; + } fprintf(stderr, "Cannot find '%s.%s' in object %s at %s\n", qPrintable(interface), qPrintable(member), qPrintable(path), qPrintable(service)); - exit(1); + return 1; } QMetaMethod mm = mo->method(midx); @@ -314,7 +326,7 @@ static void placeCall(const QString &service, const QString &path, const QString if (p.type() == QVariant::Invalid) { fprintf(stderr, "Could not convert '%s' to type '%s'.\n", qPrintable(argument), types.at(i).constData()); - exit(1); + return 1 ; } } else if (id == qMetaTypeId<QDBusVariant>()) { QDBusVariant tmp(p); @@ -324,7 +336,7 @@ static void placeCall(const QString &service, const QString &path, const QString if (path.path().isNull()) { fprintf(stderr, "Cannot pass argument '%s' because it is not a valid object path.\n", qPrintable(argument)); - exit(1); + return 1; } p = qVariantFromValue(path); } else if (id == qMetaTypeId<QDBusSignature>()) { @@ -332,39 +344,50 @@ static void placeCall(const QString &service, const QString &path, const QString if (sig.signature().isNull()) { fprintf(stderr, "Cannot pass argument '%s' because it is not a valid signature.\n", qPrintable(argument)); - exit(1); + return 1; } p = qVariantFromValue(sig); } else { fprintf(stderr, "Sorry, can't pass arg of type '%s'.\n", types.at(i).constData()); - exit(1); + return 1; } params += p; } if (params.count() != types.count() || !args.isEmpty()) { fprintf(stderr, "Invalid number of parameters\n"); - exit(1); + return 1; } } QDBusMessage reply = iface.callWithArgumentList(QDBus::Block, member, params); if (reply.type() == QDBusMessage::ErrorMessage) { QDBusError err = reply; + // Failed to retrieve property after falling back? + // Bail out without displaying an error + if (!try_prop) + return 1; + if (err.type() == QDBusError::UnknownMethod && try_prop) { + QStringList proparg; + proparg += interface; + proparg += member; + if (!placeCall(service, path, "org.freedesktop.DBus.Properties", "Get", proparg, false)) + return 0; + } if (err.type() == QDBusError::ServiceUnknown) fprintf(stderr, "Service '%s' does not exist.\n", qPrintable(service)); else printf("Error: %s\n%s\n", qPrintable(err.name()), qPrintable(err.message())); - exit(2); + return 2; } else if (reply.type() != QDBusMessage::ReplyMessage) { fprintf(stderr, "Invalid reply type %d\n", int(reply.type())); - exit(1); + return 1; } foreach (QVariant v, reply.arguments()) printArg(v); - exit(0); + return 0; } static bool globServices(QDBusConnectionInterface *bus, const QString &glob) @@ -483,6 +506,7 @@ int main(int argc, char **argv) exit(1); } - placeCall(service, path, interface, member, args); + int ret = placeCall(service, path, interface, member, args); + exit(ret); } diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index 6c33054..d9c767a 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -881,6 +881,7 @@ QString CppCodeMarker::addMarkUp(const QString& protectedCode, static QRegExp globalX("[\n{()=] *([a-zA-Z_][a-zA-Z_0-9]*)[ \n]*\\("); static QRegExp multiLineComment("/(?:( )?\\*(?:[^*]+|\\*(?! /))*\\*\\1/)"); multiLineComment.setMinimal(true); + static QRegExp singleLineCommentLine("(?:^|\n)(?:[^&]|&(?!quot;)|"(?:[^&\\\\]|&(?!quot;)|\\\\"|\\\\(?!"))*")*//(?!!)[^!\n]*"); static QRegExp singleLineComment("//(?!!)[^!\n]*"); static QRegExp preprocessor("(?:^|\n)(#[ \t]*(?:include|if|elif|endif|error|pragma|define" "|warning)(?:(?:\\\\\n|\\n#)[^\n]*)*)"); @@ -1056,7 +1057,8 @@ QString CppCodeMarker::addMarkUp(const QString& protectedCode, int mlpos; int slpos; int len; - slpos = singleLineComment.indexIn(result, pos); + int sllpos = singleLineCommentLine.indexIn(result, pos); + slpos = sllpos == -1 ? -1 : singleLineComment.indexIn(result, sllpos); mlpos = multiLineComment.indexIn(result, pos); if (slpos == -1 && mlpos == -1) @@ -1127,7 +1129,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, "signal", "signals"); FastSection qmlattachedsignals(qmlClassNode, - "QML Attached Signals", + "Attached Signals", "signal", "signals"); FastSection qmlmethods(qmlClassNode, @@ -1135,7 +1137,7 @@ QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, "method", "methods"); FastSection qmlattachedmethods(qmlClassNode, - "QML Attached Methods", + "Attached Methods", "method", "methods"); diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp index 9b6a516..7d08c77 100644 --- a/tools/qdoc3/cppcodeparser.cpp +++ b/tools/qdoc3/cppcodeparser.cpp @@ -95,6 +95,7 @@ QT_BEGIN_NAMESPACE #define COMMAND_QMLMETHOD Doc::alias("qmlmethod") #define COMMAND_QMLATTACHEDMETHOD Doc::alias("qmlattachedmethod") #define COMMAND_QMLDEFAULT Doc::alias("default") +#define COMMAND_QMLBASICTYPE Doc::alias("qmlbasictype") #endif QStringList CppCodeParser::exampleFiles; @@ -536,7 +537,8 @@ QSet<QString> CppCodeParser::topicCommands() << COMMAND_QMLSIGNAL << COMMAND_QMLATTACHEDSIGNAL << COMMAND_QMLMETHOD - << COMMAND_QMLATTACHEDMETHOD; + << COMMAND_QMLATTACHEDMETHOD + << COMMAND_QMLBASICTYPE; #else << COMMAND_VARIABLE; #endif @@ -728,6 +730,20 @@ Node *CppCodeParser::processTopicCommand(const Doc& doc, } return new QmlClassNode(tre->root(), names[0], classNode); } + else if (command == COMMAND_QMLBASICTYPE) { +#if 0 + QStringList parts = arg.split(" "); + qDebug() << command << parts; + if (parts.size() > 1) { + FakeNode* pageNode = static_cast<FakeNode*>(tre->root()->findNode(parts[1], Node::Fake)); + if (pageNode) { + qDebug() << "FOUND"; + return new QmlBasicTypeNode(pageNode, parts[0]); + } + } +#endif + return new QmlBasicTypeNode(tre->root(), arg); + } else if ((command == COMMAND_QMLSIGNAL) || (command == COMMAND_QMLMETHOD) || (command == COMMAND_QMLATTACHEDSIGNAL) || diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index a3cdae6..15386f1 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -1428,14 +1428,19 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) QList<Section> sections; QList<Section>::const_iterator s; - QString htmlTitle = fake->fullTitle(); + QString fullTitle = fake->fullTitle(); + QString htmlTitle = fullTitle; if (fake->subType() == Node::File && !fake->subTitle().isEmpty()) { subTitleSize = SmallSubTitle; htmlTitle += " (" + fake->subTitle() + ")"; } + else if (fake->subType() == Node::QmlBasicType) { + fullTitle = "QML Basic Type: " + fullTitle; + htmlTitle = fullTitle; + } generateHeader(htmlTitle, fake, marker, true); - generateTitle(fake->fullTitle(), + generateTitle(fullTitle, Text() << fake->subTitle(), subTitleSize, fake, diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index 5796ea4..9357671 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -85,6 +85,9 @@ void Node::setDoc(const Doc& doc, bool replace) } /*! + Construct a node with the given \a type and having the + given \a parent and \a name. The new node is added to the + parent's child list. */ Node::Node(Type type, InnerNode *parent, const QString& name) : typ(type), @@ -490,6 +493,8 @@ NodeList InnerNode::overloads(const QString &funcName) const } /*! + Construct an inner node (i.e., not a leaf node) of the + given \a type and having the given \a parent and \a name. */ InnerNode::InnerNode(Type type, InnerNode *parent, const QString& name) : Node(type, parent, name) @@ -547,6 +552,7 @@ bool InnerNode::isSameSignature(const FunctionNode *f1, const FunctionNode *f2) } /*! + Adds the \a child to this node's child list. */ void InnerNode::addChild(Node *child) { @@ -564,7 +570,7 @@ void InnerNode::addChild(Node *child) else { if (child->type() == Enum) enumChildren.append(child); - childMap.insert(child->name(), child); + childMap.insert(child->name(), child); } } @@ -1207,7 +1213,11 @@ bool TargetNode::isInnerNode() const bool QmlClassNode::qmlOnly = false; /*! - Constructor for the Qml class node. + Constructs a Qml class node (i.e. a Fake node with the + subtype QmlClass. The new node has the given \a parent + and \a name and is associated with the C++ class node + specified by \a cn which may be null if the the Qml + class node is not associated with a C++ class node. */ QmlClassNode::QmlClassNode(InnerNode *parent, const QString& name, @@ -1234,6 +1244,18 @@ QString QmlClassNode::fileBase() const } /*! + Constructs a Qml basic type node (i.e. a Fake node with + the subtype QmlBasicType. The new node has the given + \a parent and \a name. + */ +QmlBasicTypeNode::QmlBasicTypeNode(InnerNode *parent, + const QString& name) + : FakeNode(parent, name, QmlBasicType) +{ + setTitle(name); +} + +/*! Constructor for the Qml property group node. \a parent is always a QmlClassNode. */ diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index c77fbeb..077aeb8 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -96,7 +96,8 @@ class Node #ifdef QDOC_QML ExternalPage, QmlClass, - QmlPropertyGroup + QmlPropertyGroup, + QmlBasicType #else ExternalPage #endif @@ -373,6 +374,14 @@ class QmlClassNode : public FakeNode const ClassNode* cnode; }; +class QmlBasicTypeNode : public FakeNode +{ + public: + QmlBasicTypeNode(InnerNode *parent, + const QString& name); + virtual ~QmlBasicTypeNode() { } +}; + class QmlPropGroupNode : public FakeNode { public: diff --git a/tools/qdoc3/pagegenerator.cpp b/tools/qdoc3/pagegenerator.cpp index a001c10..07edcc4 100644 --- a/tools/qdoc3/pagegenerator.cpp +++ b/tools/qdoc3/pagegenerator.cpp @@ -104,7 +104,8 @@ QString PageGenerator::fileBase(const Node *node) we prepend "qml-" to the file name of QML element doc files. */ - if (p->subType() == Node::QmlClass) { + if ((p->subType() == Node::QmlClass) || + (p->subType() == Node::QmlBasicType)) { base.prepend("qml-"); } #endif @@ -209,6 +210,10 @@ void PageGenerator::generateInnerNode(const InnerNode *node, if (fakeNode->subType() == Node::QmlPropertyGroup) return; #endif + if (fakeNode->subType() == Node::Page) { + if (node->count() > 0) + qDebug() << "PAGE" << fakeNode->title() << "HAS CHILDREN"; + } } if (node->parent() != 0) { diff --git a/tools/qdoc3/test/assistant.qdocconf b/tools/qdoc3/test/assistant.qdocconf index 38da552..63455f1 100644 --- a/tools/qdoc3/test/assistant.qdocconf +++ b/tools/qdoc3/test/assistant.qdocconf @@ -6,18 +6,18 @@ include(qt-defines.qdocconf) project = Qt Assistant description = Qt Assistant Manual -url = http://qt.nokia.com/doc/4.6 +url = http://qt.nokia.com/doc/4.7 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Assistant qhp.Assistant.file = assistant.qhp -qhp.Assistant.namespace = com.trolltech.assistant.460 +qhp.Assistant.namespace = com.trolltech.assistant.470 qhp.Assistant.virtualFolder = qdoc qhp.Assistant.indexTitle = Qt Assistant Manual qhp.Assistant.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png -qhp.Assistant.filterAttributes = qt 4.6.2 tools assistant +qhp.Assistant.filterAttributes = qt 4.7.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/designer.qdocconf b/tools/qdoc3/test/designer.qdocconf index 57d21a9..b0c88f1 100644 --- a/tools/qdoc3/test/designer.qdocconf +++ b/tools/qdoc3/test/designer.qdocconf @@ -6,18 +6,18 @@ include(qt-defines.qdocconf) project = Qt Designer description = Qt Designer Manual -url = http://qt.nokia.com/doc/4.6 +url = http://qt.nokia.com/doc/4.7 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Designer qhp.Designer.file = designer.qhp -qhp.Designer.namespace = com.trolltech.designer.460 +qhp.Designer.namespace = com.trolltech.designer.470 qhp.Designer.virtualFolder = qdoc qhp.Designer.indexTitle = Qt Designer Manual qhp.Designer.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png -qhp.Designer.filterAttributes = qt 4.6.2 tools designer +qhp.Designer.filterAttributes = qt 4.7.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/linguist.qdocconf b/tools/qdoc3/test/linguist.qdocconf index 5860b33..6acd2c6 100644 --- a/tools/qdoc3/test/linguist.qdocconf +++ b/tools/qdoc3/test/linguist.qdocconf @@ -6,18 +6,18 @@ include(qt-defines.qdocconf) project = Qt Linguist description = Qt Linguist Manual -url = http://qt.nokia.com/doc/4.6 +url = http://qt.nokia.com/doc/4.7 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Linguist qhp.Linguist.file = linguist.qhp -qhp.Linguist.namespace = com.trolltech.linguist.460 +qhp.Linguist.namespace = com.trolltech.linguist.470 qhp.Linguist.virtualFolder = qdoc qhp.Linguist.indexTitle = Qt Linguist Manual qhp.Linguist.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png -qhp.Linguist.filterAttributes = qt 4.6.2 tools linguist +qhp.Linguist.filterAttributes = qt 4.7.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/qmake.qdocconf b/tools/qdoc3/test/qmake.qdocconf index 0e7d960..76e7012 100644 --- a/tools/qdoc3/test/qmake.qdocconf +++ b/tools/qdoc3/test/qmake.qdocconf @@ -6,18 +6,18 @@ include(qt-defines.qdocconf) project = QMake description = QMake Manual -url = http://qt.nokia.com/doc/4.6 +url = http://qt.nokia.com/doc/4.7 indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = qmake qhp.qmake.file = qmake.qhp -qhp.qmake.namespace = com.trolltech.qmake.460 +qhp.qmake.namespace = com.trolltech.qmake.470 qhp.qmake.virtualFolder = qdoc qhp.qmake.indexTitle = QMake Manual qhp.qmake.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png -qhp.qmake.filterAttributes = qt 4.6.2 tools qmake +qhp.qmake.filterAttributes = qt 4.7.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/qml.qdocconf b/tools/qdoc3/test/qml.qdocconf new file mode 100644 index 0000000..3b5d8dc --- /dev/null +++ b/tools/qdoc3/test/qml.qdocconf @@ -0,0 +1,80 @@ +include(compat.qdocconf) +include(macros.qdocconf) +include(qt-cpp-ignore.qdocconf) +include(qt-html-templates.qdocconf) +include(qt-defines.qdocconf) + +project = Qml +description = Qml Reference Documentation +url = http://doc.qtsoftware.com/4.6 +qmlonly = true + +edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ + QtXmlPatterns QtTest +edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtSql QtSvg \ + QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \ + QtDesigner QtAssistant QAxContainer Phonon \ + QAxServer QtUiTools QtTest QtDBus +edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest +edition.DesktopLight.groups = -graphicsview-api + +qhp.projects = Qml + +qhp.Qml.file = qml.qhp +qhp.Qml.namespace = com.trolltech.qml.460 +qhp.Qml.virtualFolder = qdoc +qhp.Qml.indexTitle = Qml Reference + +# Files not referenced in any qdoc file +# See also extraimages.HTML +qhp.Qml.extraFiles = classic.css \ + images/qt-logo.png + +qhp.Qml.filterAttributes = qt 4.6.0 qtrefdoc +qhp.Qml.customFilters.Qt.name = Qt 4.6.0 +qhp.Qml.customFilters.Qt.filterAttributes = qt 4.6.0 +qhp.Qml.subprojects = classes +qhp.Qml.subprojects.classes.title = Elements +qhp.Qml.subprojects.classes.indexTitle = Qml Elements +qhp.Qml.subprojects.classes.selectors = fake:qmlclass +qhp.Qml.subprojects.classes.sortPages = true + +language = Cpp + +headerdirs = $QT_SOURCE_TREE/src/declarative +sourcedirs = $QT_SOURCE_TREE/src/declarative \ + $QT_SOURCE_TREE/doc/src/declarative + +sources += $QT_SOURCE_TREE/doc/src/tutorials/declarative.qdoc + +sources.fileextensions = "*.cpp *.qdoc" +examples.fileextensions = "*.cpp *.h *.js *.qml" + +exampledirs = $QT_SOURCE_TREE/doc/src \ + $QT_SOURCE_TREE/examples \ + $QT_SOURCE_TREE/examples/tutorials \ + $QT_SOURCE_TREE \ + $QT_SOURCE_TREE/qmake/examples \ + $QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs +imagedirs = $QT_SOURCE_TREE/doc/src/images \ + $QT_SOURCE_TREE/examples \ + $QT_SOURCE_TREE/doc/src/declarative/pics +outputdir = $QT_BUILD_TREE/doc-build/html-qml +tagfile = $QT_BUILD_TREE/doc-build/html-qml/qt.tags +base = file:$QT_BUILD_TREE/doc/html-qml + +HTML.stylesheets = classic.css + +HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n" \ + "<tr>\n" \ + "<td align=\"left\" valign=\"top\">" \ + "<img src=\"images/qt-logo.png\" align=\"left\" border=\"0\"/>" \ + "</td>\n" \ + "<td width=\"1\"> </td>" \ + "<td class=\"postheader\" valign=\"center\" align=\"left\">" \ + "<a href=\"qmlreference.html\">" \ + "<font color=\"#004faf\">Home</font></a> ·" \ + " <a href=\"qmlelements.html\">" \ + "<font color=\"#004faf\">Elements</font></a>" \ + "</td>\n" \ + "</tr></table>" diff --git a/tools/qdoc3/test/qt-build-docs.qdocconf b/tools/qdoc3/test/qt-build-docs.qdocconf index def4e67..6cc27b6 100644 --- a/tools/qdoc3/test/qt-build-docs.qdocconf +++ b/tools/qdoc3/test/qt-build-docs.qdocconf @@ -6,19 +6,20 @@ include(qt-defines.qdocconf) project = Qt description = Qt Reference Documentation -url = http://qt.nokia.com/doc/4.6 +url = http://qt.nokia.com/doc/4.7 edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtScriptTools QtSql QtSvg \ QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \ QtDesigner QtAssistant QAxContainer Phonon \ QAxServer QtUiTools QtTest QtDBus + edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.460 +qhp.Qt.namespace = com.trolltech.qt.470 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = @@ -32,9 +33,9 @@ qhp.Qt.extraFiles = classic.css \ images/dynamiclayouts-example.png \ images/stylesheet-coffee-plastique.png -qhp.Qt.filterAttributes = qt 4.6.2 qtrefdoc -qhp.Qt.customFilters.Qt.name = Qt 4.6.2 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.6.2 +qhp.Qt.filterAttributes = qt 4.7.0 qtrefdoc +qhp.Qt.customFilters.Qt.name = Qt 4.7.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0 qhp.Qt.subprojects = classes overviews examples qhp.Qt.subprojects.classes.title = Classes qhp.Qt.subprojects.classes.indexTitle = Qt's Classes @@ -96,7 +97,7 @@ excludedirs = $QT_SOURCE_TREE/src/3rdparty/clucene \ $QT_SOURCE_TREE/src/3rdparty/phonon/waveout sources.fileextensions = "*.cpp *.qdoc *.mm" -examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp" +examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml" examples.imageextensions = "*.png" exampledirs = $QT_SOURCE_TREE/doc/src \ @@ -106,7 +107,8 @@ exampledirs = $QT_SOURCE_TREE/doc/src \ $QT_SOURCE_TREE/qmake/examples \ $QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs imagedirs = $QT_SOURCE_TREE/doc/src/images \ - $QT_SOURCE_TREE/examples + $QT_SOURCE_TREE/examples \ + $QT_SOURCE_TREE/doc/src/declarative/pics outputdir = $QT_BUILD_TREE/doc/html tagfile = $QT_BUILD_TREE/doc/html/qt.tags base = file:$QT_BUILD_TREE/doc/html diff --git a/tools/qdoc3/test/qt.qdocconf b/tools/qdoc3/test/qt.qdocconf index 1aefa98..b65ac56 100644 --- a/tools/qdoc3/test/qt.qdocconf +++ b/tools/qdoc3/test/qt.qdocconf @@ -8,11 +8,11 @@ project = Qt versionsym = version = %VERSION% description = Qt Reference Documentation -url = http://qt.nokia.com/doc/4.6 +url = http://qt.nokia.com/doc/4.7 -edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtScriptTools QtSql QtSvg \ - QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \ - QtDesigner QtAssistant QAxContainer Phonon \ +edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript \ + QtScriptTools QtSql QtSvg QtWebKit QtXml QtXmlPatterns \ + Qt3Support QtHelp QtDesigner QAxContainer Phonon \ QAxServer QtUiTools QtTest QtDBus edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest edition.DesktopLight.groups = -graphicsview-api @@ -20,7 +20,7 @@ edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.460 +qhp.Qt.namespace = com.trolltech.qt.470 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = @@ -34,9 +34,9 @@ qhp.Qt.extraFiles = classic.css \ images/dynamiclayouts-example.png \ images/stylesheet-coffee-plastique.png -qhp.Qt.filterAttributes = qt 4.6.2 qtrefdoc -qhp.Qt.customFilters.Qt.name = Qt 4.6.2 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.6.2 +qhp.Qt.filterAttributes = qt 4.7.0 qtrefdoc +qhp.Qt.customFilters.Qt.name = Qt 4.7.0 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.0 qhp.Qt.subprojects = classes overviews examples qhp.Qt.subprojects.classes.title = Classes qhp.Qt.subprojects.classes.indexTitle = Qt's Classes @@ -99,7 +99,7 @@ excludedirs = $QTDIR/src/3rdparty/clucene \ $QTDIR/src/3rdparty/phonon/waveout sources.fileextensions = "*.cpp *.qdoc *.mm" -examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp" +examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml" examples.imageextensions = "*.png" exampledirs = $QTDIR/doc/src \ @@ -109,7 +109,8 @@ exampledirs = $QTDIR/doc/src \ $QTDIR/qmake/examples \ $QTDIR/src/3rdparty/webkit/WebKit/qt/docs imagedirs = $QTDIR/doc/src/images \ - $QTDIR/examples + $QTDIR/examples \ + $QTDIR/doc/src/declarative/pics outputdir = $QTDIR/doc/html tagfile = $QTDIR/doc/html/qt.tags base = file:$QTDIR/doc/html diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index d46da95..6c2502d 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -1914,7 +1914,8 @@ QString Tree::fullDocumentLocation(const Node *node) const } else if (node->type() == Node::Fake) { #ifdef QDOC_QML - if (node->subType() == Node::QmlClass) + if ((node->subType() == Node::QmlClass) || + (node->subType() == Node::QmlBasicType)) return "qml-" + node->fileBase() + ".html"; else #endif diff --git a/tools/qmldebugger/qmldebugger.pro b/tools/qmldebugger/qmldebugger.pro new file mode 100644 index 0000000..679cae6 --- /dev/null +++ b/tools/qmldebugger/qmldebugger.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS = standalone + diff --git a/tools/qmldebugger/standalone/canvasframerate.cpp b/tools/qmldebugger/standalone/canvasframerate.cpp new file mode 100644 index 0000000..d956029 --- /dev/null +++ b/tools/qmldebugger/standalone/canvasframerate.cpp @@ -0,0 +1,581 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCore/qdebug.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qdatastream.h> +#include <QtCore/qmargins.h> + +#include <QtGui/qapplication.h> +#include <QtGui/qpainter.h> +#include <QtGui/qtooltip.h> +#include <QtGui/qslider.h> +#include <QtGui/qscrollbar.h> +#include <QtGui/qspinbox.h> +#include <QtGui/qgroupbox.h> +#include <QtGui/qboxlayout.h> +#include <QtGui/qlabel.h> +#include <QtGui/qlineedit.h> +#include <QtGui/qpushbutton.h> +#include <QtGui/qtabwidget.h> + +#include <QResizeEvent> +#include <QShowEvent> + +#include <private/qmldebugclient_p.h> +#include "canvasframerate.h" + +QT_BEGIN_NAMESPACE + +class QLineGraph : public QWidget +{ +Q_OBJECT +public: + QLineGraph(QAbstractSlider *slider, QWidget * = 0); + + void setPosition(int); + +public slots: + void addSample(int, int, int, bool); + void setResolutionForHeight(int); + void clear(); + +protected: + virtual void paintEvent(QPaintEvent *); + virtual void mouseMoveEvent(QMouseEvent *); + virtual void leaveEvent(QEvent *); + virtual void wheelEvent(QWheelEvent *event); + +private slots: + void sliderChanged(int); + +private: + void updateSlider(); + void drawSample(QPainter *, int, const QRect &, QList<QRect> *); + void drawTime(QPainter *, const QRect &); + QRect findContainingRect(const QList<QRect> &rects, const QPoint &pos) const; + struct Sample { + int sample[3]; + bool isBreak; + }; + QList<Sample> _samples; + + QAbstractSlider *slider; + int position; + int samplesPerWidth; + int resolutionForHeight; + bool ignoreScroll; + QMargins graphMargins; + + QList<QRect> rectsPaintTime; // time to do a paintEvent() + QList<QRect> rectsTimeBetween; // time between frames + QRect highlightedBar; +}; + +QLineGraph::QLineGraph(QAbstractSlider *slider, QWidget *parent) +: QWidget(parent), slider(slider), position(-1), samplesPerWidth(99), resolutionForHeight(50), + ignoreScroll(false), graphMargins(65, 10, 71, 35) +{ + setMouseTracking(true); + + slider->setMaximum(0); + slider->setMinimum(0); + slider->setSingleStep(1); + + connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int))); +} + +void QLineGraph::sliderChanged(int v) +{ + if(ignoreScroll) + return; + + if (v == slider->maximum()) + position = -1; + else + position = v; + + update(); + + // update highlightedRect + QPoint pos = mapFromGlobal(QCursor::pos()); + if (geometry().contains(pos)) { + QMouseEvent *me = new QMouseEvent(QEvent::MouseMove, pos, + Qt::NoButton, Qt::NoButton, Qt::NoModifier); + QApplication::postEvent(this, me); + } +} + +void QLineGraph::clear() +{ + _samples.clear(); + rectsPaintTime.clear(); + rectsTimeBetween.clear(); + highlightedBar = QRect(); + position = -1; + + updateSlider(); + update(); +} + +void QLineGraph::updateSlider() +{ + ignoreScroll = true; + slider->setMaximum(qMax(0, _samples.count() - samplesPerWidth - 1)); + + if(position == -1) { + slider->setValue(slider->maximum()); + } else { + slider->setValue(position); + } + ignoreScroll = false; +} + +void QLineGraph::addSample(int a, int b, int d, bool isBreak) +{ + Sample s; + s.isBreak = isBreak; + s.sample[0] = a; + s.sample[1] = b; + s.sample[2] = d; + _samples << s; + updateSlider(); + update(); +} + +void QLineGraph::setPosition(int p) +{ + sliderChanged(p); +} + +void QLineGraph::drawTime(QPainter *p, const QRect &rect) +{ + if(_samples.isEmpty()) + return; + + int first = position; + if(first == -1) + first = qMax(0, _samples.count() - samplesPerWidth - 1); + int last = qMin(_samples.count() - 1, first + samplesPerWidth); + + qreal scaleX = qreal(rect.width()) / qreal(samplesPerWidth); + + int t = 0; + + for(int ii = first; ii <= last; ++ii) { + int sampleTime = _samples.at(ii).sample[2] / 1000; + if(sampleTime != t) { + + int xEnd = rect.left() + scaleX * (ii - first); + p->drawLine(xEnd, rect.bottom(), xEnd, rect.bottom() + 7); + + QRect text(xEnd - 30, rect.bottom() + 10, 60, 30); + + p->drawText(text, Qt::AlignHCenter | Qt::AlignTop, QString::number(_samples.at(ii).sample[2])); + + t = sampleTime; + } + } + +} + +void QLineGraph::drawSample(QPainter *p, int s, const QRect &rect, QList<QRect> *record) +{ + if(_samples.isEmpty()) + return; + + int first = position; + if(first == -1) + first = qMax(0, _samples.count() - samplesPerWidth - 1); + int last = qMin(_samples.count() - 1, first + samplesPerWidth); + + qreal scaleY = qreal(rect.height()) / resolutionForHeight; + qreal scaleX = qreal(rect.width()) / qreal(samplesPerWidth); + + int xEnd; + int lastXEnd = rect.left(); + + p->save(); + p->setPen(Qt::NoPen); + for(int ii = first + 1; ii <= last; ++ii) { + + xEnd = rect.left() + scaleX * (ii - first); + int yEnd = rect.bottom() - _samples.at(ii).sample[s] * scaleY; + + if (!(s == 0 && _samples.at(ii).isBreak)) { + QRect bar(lastXEnd, yEnd, scaleX, _samples.at(ii).sample[s] * scaleY); + record->append(bar); + p->drawRect(bar); + } + + lastXEnd = xEnd; + } + p->restore(); +} + +void QLineGraph::paintEvent(QPaintEvent *) +{ + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + QRect r(graphMargins.left(), graphMargins.top(), + width() - graphMargins.right(), height() - graphMargins.bottom()); + + p.save(); + p.rotate(-90); + p.translate(-r.height()/2 - r.width()/2 - graphMargins.right(), -r.height()/2); + p.drawText(r, Qt::AlignCenter, tr("Frame rate")); + p.restore(); + + p.setBrush(QColor("lightsteelblue")); + rectsTimeBetween.clear(); + drawSample(&p, 0, r, &rectsTimeBetween); + + p.setBrush(QColor("pink")); + rectsPaintTime.clear(); + drawSample(&p, 1, r, &rectsPaintTime); + + if (!highlightedBar.isNull()) { + p.setBrush(Qt::darkGreen); + p.drawRect(highlightedBar); + } + + p.setBrush(Qt::NoBrush); + p.drawRect(r); + + slider->setGeometry(x() + r.x(), slider->y(), r.width(), slider->height()); + + for(int ii = 0; ii <= resolutionForHeight; ++ii) { + int y = 1 + r.bottom() - ii * r.height() / resolutionForHeight; + + if((ii % 10) == 0) { + p.drawLine(r.left() - 20, y, r.left(), y); + QRect text(r.left() - 20 - 53, y - 10, 50, 20); + p.drawText(text, Qt::AlignRight | Qt::AlignVCenter, QString::number(ii)); + } else { + p.drawLine(r.left() - 7, y, r.left(), y); + } + } + + drawTime(&p, r); +} + +void QLineGraph::mouseMoveEvent(QMouseEvent *event) +{ + QPoint pos = event->pos(); + + QRect rect = findContainingRect(rectsPaintTime, pos); + if (rect.isNull()) + rect = findContainingRect(rectsTimeBetween, pos); + + if (!highlightedBar.isNull()) + update(highlightedBar.adjusted(-1, -1, 1, 1)); + highlightedBar = rect; + + if (!rect.isNull()) { + QRect graph(graphMargins.left(), graphMargins.top(), + width() - graphMargins.right(), height() - graphMargins.bottom()); + qreal scaleY = qreal(graph.height()) / resolutionForHeight; + QToolTip::showText(event->globalPos(), QString::number(qRound(rect.height() / scaleY)), this, rect); + update(rect.adjusted(-1, -1, 1, 1)); + } +} + +void QLineGraph::leaveEvent(QEvent *) +{ + if (!highlightedBar.isNull()) { + QRect bar = highlightedBar.adjusted(-1, -1, 1, 1); + highlightedBar = QRect(); + update(bar); + } +} + +void QLineGraph::wheelEvent(QWheelEvent *event) +{ + QWheelEvent we(QPoint(0,0), event->delta(), event->buttons(), event->modifiers(), event->orientation()); + QApplication::sendEvent(slider, &we); +} + +void QLineGraph::setResolutionForHeight(int resolution) +{ + resolutionForHeight = resolution; + update(); +} + +QRect QLineGraph::findContainingRect(const QList<QRect> &rects, const QPoint &pos) const +{ + for (int i=0; i<rects.count(); i++) { + if (rects[i].contains(pos)) + return rects[i]; + } + return QRect(); +} + + +class GraphWindow : public QWidget +{ + Q_OBJECT +public: + GraphWindow(QWidget *parent = 0); + + virtual QSize sizeHint() const; + +public slots: + void addSample(int, int, int, bool); + void setResolutionForHeight(int); + void clear(); + +private: + QLineGraph *m_graph; +}; + +GraphWindow::GraphWindow(QWidget *parent) + : QWidget(parent) +{ + QSlider *scroll = new QSlider(Qt::Horizontal); + scroll->setFocusPolicy(Qt::WheelFocus); + m_graph = new QLineGraph(scroll); + + setFocusPolicy(Qt::WheelFocus); + setFocusProxy(scroll); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 5, 0); + layout->setSpacing(0); + layout->addWidget(m_graph, 2); + layout->addWidget(new QLabel(tr("Total time elapsed (ms)")), 0, Qt::AlignHCenter); + layout->addWidget(scroll); +} + +void GraphWindow::addSample(int a, int b, int d, bool isBreak) +{ + m_graph->addSample(a, b, d, isBreak); +} + +void GraphWindow::setResolutionForHeight(int res) +{ + m_graph->setResolutionForHeight(res); +} + +void GraphWindow::clear() +{ + m_graph->clear(); +} + +QSize GraphWindow::sizeHint() const +{ + return QSize(400, 220); +} + + +class CanvasFrameRatePlugin : public QmlDebugClient +{ + Q_OBJECT +public: + CanvasFrameRatePlugin(QmlDebugConnection *client); + +signals: + void sample(int, int, int, bool); + +protected: + virtual void messageReceived(const QByteArray &); + +private: + int lb; + int ld; +}; + +CanvasFrameRatePlugin::CanvasFrameRatePlugin(QmlDebugConnection *client) +: QmlDebugClient(QLatin1String("CanvasFrameRate"), client), lb(-1) +{ +} + +void CanvasFrameRatePlugin::messageReceived(const QByteArray &data) +{ + QByteArray rwData = data; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + int b; int c; int d; bool isBreak; + stream >> b >> c >> d >> isBreak; + + if (lb != -1) + emit sample(c, lb, ld, isBreak); + + lb = b; + ld = d; +} + +CanvasFrameRate::CanvasFrameRate(QWidget *parent) +: QWidget(parent), + m_plugin(0) +{ + m_tabs = new QTabWidget(this); + + QHBoxLayout *bottom = new QHBoxLayout; + bottom->setMargin(0); + bottom->setSpacing(10); + + m_res = new QSpinBox; + m_res->setRange(30, 200); + m_res->setValue(m_res->minimum()); + m_res->setSingleStep(10); + m_res->setSuffix(QLatin1String("ms")); + bottom->addWidget(new QLabel(tr("Resolution:"))); + bottom->addWidget(m_res); + + bottom->addStretch(); + + m_clearButton = new QPushButton(tr("Clear")); + connect(m_clearButton, SIGNAL(clicked()), SLOT(clearGraph())); + bottom->addWidget(m_clearButton); + + QPushButton *pb = new QPushButton(tr("New Graph"), this); + connect(pb, SIGNAL(clicked()), this, SLOT(newTab())); + bottom->addWidget(pb); + + m_group = new QGroupBox(tr("Enabled")); + m_group->setCheckable(true); + m_group->setChecked(false); + connect(m_group, SIGNAL(toggled(bool)), SLOT(enabledToggled(bool))); + + QVBoxLayout *groupLayout = new QVBoxLayout(m_group); + groupLayout->setContentsMargins(5, 0, 5, 0); + groupLayout->setSpacing(2); + groupLayout->addWidget(m_tabs); + groupLayout->addLayout(bottom); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setContentsMargins(0, 10, 0, 0); + layout->setSpacing(0); + layout->addWidget(m_group); + setLayout(layout); +} + +void CanvasFrameRate::reset(QmlDebugConnection *conn) +{ + delete m_plugin; + m_plugin = 0; + + QWidget *w; + for (int i=0; i<m_tabs->count(); i++) { + w = m_tabs->widget(i); + m_tabs->removeTab(i); + delete w; + } + + if (conn) { + connect(conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + SLOT(connectionStateChanged(QAbstractSocket::SocketState))); + if (conn->state() == QAbstractSocket::ConnectedState) + handleConnected(conn); + } +} + +void CanvasFrameRate::connectionStateChanged(QAbstractSocket::SocketState state) +{ + if (state == QAbstractSocket::UnconnectedState) { + delete m_plugin; + m_plugin = 0; + } else if (state == QAbstractSocket::ConnectedState) { + handleConnected(qobject_cast<QmlDebugConnection*>(sender())); + } +} + +void CanvasFrameRate::handleConnected(QmlDebugConnection *conn) +{ + delete m_plugin; + m_plugin = new CanvasFrameRatePlugin(conn); + enabledToggled(m_group->isChecked()); + newTab(); +} + +void CanvasFrameRate::setSizeHint(const QSize &size) +{ + m_sizeHint = size; +} + +QSize CanvasFrameRate::sizeHint() const +{ + return m_sizeHint; +} + +void CanvasFrameRate::clearGraph() +{ + if (m_tabs->count()) { + GraphWindow *w = qobject_cast<GraphWindow*>(m_tabs->currentWidget()); + if (w) + w->clear(); + } +} + +void CanvasFrameRate::newTab() +{ + if (!m_plugin) + return; + + if (m_tabs->count()) { + QWidget *w = m_tabs->widget(m_tabs->count() - 1); + QObject::disconnect(m_plugin, SIGNAL(sample(int,int,int,bool)), + w, SLOT(addSample(int,int,int,bool))); + } + + int count = m_tabs->count(); + + GraphWindow *graph = new GraphWindow; + graph->setResolutionForHeight(m_res->value()); + connect(m_plugin, SIGNAL(sample(int,int,int,bool)), + graph, SLOT(addSample(int,int,int,bool))); + connect(m_res, SIGNAL(valueChanged(int)), + graph, SLOT(setResolutionForHeight(int))); + + QString name = QLatin1String("Graph ") + QString::number(count + 1); + m_tabs->addTab(graph, name); + m_tabs->setCurrentIndex(count); +} + +void CanvasFrameRate::enabledToggled(bool checked) +{ + if (m_plugin) + static_cast<QmlDebugClient *>(m_plugin)->setEnabled(checked); +} + +QT_END_NAMESPACE + +#include "canvasframerate.moc" diff --git a/tools/qmldebugger/standalone/canvasframerate.h b/tools/qmldebugger/standalone/canvasframerate.h new file mode 100644 index 0000000..f8eec59 --- /dev/null +++ b/tools/qmldebugger/standalone/canvasframerate.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef CANVASFRAMERATE_H +#define CANVASFRAMERATE_H + +#include <QtCore/qpointer.h> +#include <QtGui/qwidget.h> + +#include <private/qmldebugclient_p.h> + +QT_BEGIN_NAMESPACE + +class QTabWidget; +class QSlider; +class QGroupBox; +class QLabel; +class QSpinBox; +class QPushButton; + +class CanvasFrameRatePlugin; + +class CanvasFrameRate : public QWidget +{ + Q_OBJECT +public: + CanvasFrameRate(QWidget *parent = 0); + + void reset(QmlDebugConnection *conn); + + void setSizeHint(const QSize &); + virtual QSize sizeHint() const; + +private slots: + void clearGraph(); + void newTab(); + void enabledToggled(bool); + void connectionStateChanged(QAbstractSocket::SocketState state); + +private: + void handleConnected(QmlDebugConnection *conn); + + QGroupBox *m_group; + QTabWidget *m_tabs; + QSpinBox *m_res; + QPushButton *m_clearButton; + CanvasFrameRatePlugin *m_plugin; + QSize m_sizeHint; +}; + +QT_END_NAMESPACE + +#endif // CANVASFRAMERATE_H + diff --git a/tools/qmldebugger/standalone/engine.cpp b/tools/qmldebugger/standalone/engine.cpp new file mode 100644 index 0000000..6cfd82b --- /dev/null +++ b/tools/qmldebugger/standalone/engine.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QSplitter> +#include <QTabWidget> +#include <QFile> + +#include <private/qmlenginedebug_p.h> +#include <private/qmldebugclient_p.h> +#include <QtDeclarative/qmlcomponent.h> +#include <QtDeclarative/qmlgraphicsitem.h> +#include <private/qmldebugservice_p.h> + +#include "engine.h" +#include "objectpropertiesview.h" +#include "expressionquerywidget.h" +#include "objecttree.h" +#include "watchtable.h" + +QT_BEGIN_NAMESPACE + + +class DebuggerEngineItem : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name CONSTANT); + Q_PROPERTY(int engineId READ engineId CONSTANT); + +public: + DebuggerEngineItem(const QString &name, int id) + : m_name(name), m_engineId(id) {} + + QString name() const { return m_name; } + int engineId() const { return m_engineId; } + +private: + QString m_name; + int m_engineId; +}; + +EnginePane::EnginePane(QmlDebugConnection *conn, QWidget *parent) +: QWidget(parent), m_client(new QmlEngineDebug(conn, this)), m_engines(0), m_context(0), m_watchTableModel(0), m_exprQueryWidget(0) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + + QFile enginesFile(":/engines.qml"); + enginesFile.open(QFile::ReadOnly); + Q_ASSERT(enginesFile.isOpen()); + + m_engineView = new QmlView(this); + m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems)); + m_engineView->setContentResizable(true); + m_engineView->setQml(enginesFile.readAll()); + m_engineView->execute(); + m_engineView->setFixedHeight(100); + QObject::connect(m_engineView->root(), SIGNAL(engineClicked(int)), + this, SLOT(engineSelected(int))); + QObject::connect(m_engineView->root(), SIGNAL(refreshEngines()), + this, SLOT(refreshEngines())); + + m_engineView->setVisible(false); + layout->addWidget(m_engineView); + + QSplitter *splitter = new QSplitter; + + m_objTree = new ObjectTree(m_client, this); + m_propertiesView = new ObjectPropertiesView(m_client); + m_watchTableModel = new WatchTableModel(m_client, this); + + m_watchTableView = new WatchTableView(m_watchTableModel); + m_watchTableView->setModel(m_watchTableModel); + WatchTableHeaderView *header = new WatchTableHeaderView(m_watchTableModel); + m_watchTableView->setHorizontalHeader(header); + + connect(m_objTree, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), + m_propertiesView, SLOT(reload(QmlDebugObjectReference))); + connect(m_objTree, SIGNAL(expressionWatchRequested(QmlDebugObjectReference,QString)), + m_watchTableModel, SLOT(expressionWatchRequested(QmlDebugObjectReference,QString))); + + connect(m_propertiesView, SIGNAL(activated(QmlDebugObjectReference,QmlDebugPropertyReference)), + m_watchTableModel, SLOT(togglePropertyWatch(QmlDebugObjectReference,QmlDebugPropertyReference))); + + connect(m_watchTableModel, SIGNAL(watchCreated(QmlDebugWatch*)), + m_propertiesView, SLOT(watchCreated(QmlDebugWatch*))); + + connect(m_watchTableView, SIGNAL(objectActivated(int)), + m_objTree, SLOT(setCurrentObject(int))); + + m_exprQueryWidget = new ExpressionQueryWidget(ExpressionQueryWidget::SeparateEntryMode, m_client); + connect(m_objTree, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), + m_exprQueryWidget, SLOT(setCurrentObject(QmlDebugObjectReference))); + + QSplitter *propertiesTab = new QSplitter(Qt::Vertical); + propertiesTab->addWidget(m_propertiesView); + propertiesTab->addWidget(m_exprQueryWidget); + propertiesTab->setStretchFactor(0, 2); + propertiesTab->setStretchFactor(1, 1); + + m_tabs = new QTabWidget(this); + m_tabs->addTab(propertiesTab, tr("Properties")); + m_tabs->addTab(m_watchTableView, tr("Watched")); + + splitter->addWidget(m_objTree); + splitter->addWidget(m_tabs); + splitter->setStretchFactor(1, 2); + layout->addWidget(splitter); +} + +void EnginePane::engineSelected(int id) +{ + qWarning() << "Engine selected" << id; + queryContext(id); +} + +void EnginePane::queryContext(int id) +{ + if (m_context) { + delete m_context; + m_context = 0; + } + + m_context = m_client->queryRootContexts(QmlDebugEngineReference(id), this); + if (!m_context->isWaiting()) + contextChanged(); + else + QObject::connect(m_context, SIGNAL(stateChanged(QmlDebugQuery::State)), + this, SLOT(contextChanged())); +} + +void EnginePane::contextChanged() +{ + //dump(m_context->rootContext(), 0); + + foreach (const QmlDebugObjectReference &object, m_context->rootContext().objects()) + m_objTree->reload(object.debugId()); + + delete m_context; m_context = 0; +} + +void EnginePane::refreshEngines() +{ + if (m_engines) + return; + + m_engines = m_client->queryAvailableEngines(this); + if (!m_engines->isWaiting()) + enginesChanged(); + else + QObject::connect(m_engines, SIGNAL(stateChanged(QmlDebugQuery::State)), + this, SLOT(enginesChanged())); +} + +void EnginePane::enginesChanged() +{ + qDeleteAll(m_engineItems); + m_engineItems.clear(); + + QList<QmlDebugEngineReference> engines = m_engines->engines(); + delete m_engines; m_engines = 0; + + if (engines.isEmpty()) + qWarning("qmldebugger: no engines found!"); + + for (int ii = 0; ii < engines.count(); ++ii) + m_engineItems << new DebuggerEngineItem(engines.at(ii).name(), + engines.at(ii).debugId()); + + m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems)); + + m_engineView->setVisible(m_engineItems.count() > 1); + if (m_engineItems.count() == 1) + engineSelected(qobject_cast<DebuggerEngineItem*>(m_engineItems.at(0))->engineId()); +} + + +#include "engine.moc" + +QT_END_NAMESPACE + diff --git a/tools/assistant/compat/lib/qassistantclient.h b/tools/qmldebugger/standalone/engine.h index fc8bb5b..f4c4275 100644 --- a/tools/assistant/compat/lib/qassistantclient.h +++ b/tools/qmldebugger/standalone/engine.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2009 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. +** This file is part of the Qt QML Debugger of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -38,63 +38,64 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef ENGINE_H +#define ENGINE_H -#ifndef QASSISTANTCLIENT_H -#define QASSISTANTCLIENT_H - -#include <QtCore/QObject> -#include <QtCore/QStringList> -#include <QtCore/QProcess> -#include <QtCore/qglobal.h> -#include <QtAssistant/qassistantclient_global.h> - -QT_BEGIN_HEADER +#include <QWidget> +#include <QtCore/qpointer.h> +#include <QtDeclarative/qmlengine.h> +#include <QtDeclarative/qmlcontext.h> +#include <QtDeclarative/qmlview.h> +#include <private/qmldebug_p.h> QT_BEGIN_NAMESPACE -class QTcpSocket; +class ObjectPropertiesView; +class QmlDebugConnection; +class QmlDebugPropertyReference; +class QmlDebugWatch; +class ObjectTree; +class WatchTableModel; +class WatchTableView; +class ExpressionQueryWidget; -class QT_ASSISTANT_CLIENT_EXPORT QAssistantClient : public QObject -{ - Q_OBJECT - Q_PROPERTY( bool open READ isOpen ) +class QTabWidget; +class EnginePane : public QWidget +{ +Q_OBJECT public: - QAssistantClient( const QString &path, QObject *parent = 0); - ~QAssistantClient(); + EnginePane(QmlDebugConnection *, QWidget *parent = 0); - bool isOpen() const; +public slots: + void refreshEngines(); - void setArguments( const QStringList &args ); +private slots: + void enginesChanged(); -public Q_SLOTS: - virtual void openAssistant(); - virtual void closeAssistant(); - virtual void showPage( const QString &page ); + void queryContext(int); + void contextChanged(); -Q_SIGNALS: - void assistantOpened(); - void assistantClosed(); - void error( const QString &msg ); - -private Q_SLOTS: - void socketConnected(); - void socketConnectionClosed(); - void readPort(); - void procError(QProcess::ProcessError err); - void socketError(); - void readStdError(); + void engineSelected(int); private: - QTcpSocket *socket; - QProcess *proc; - quint16 port; - QString host, assistantCommand, pageBuffer; - bool opened; + QmlEngineDebug *m_client; + QmlDebugEnginesQuery *m_engines; + QmlDebugRootContextQuery *m_context; + + ObjectTree *m_objTree; + QTabWidget *m_tabs; + WatchTableView *m_watchTableView; + WatchTableModel *m_watchTableModel; + ExpressionQueryWidget *m_exprQueryWidget; + + QmlView *m_engineView; + QList<QObject *> m_engineItems; + + ObjectPropertiesView *m_propertiesView; }; QT_END_NAMESPACE -QT_END_HEADER +#endif // ENGINE_H -#endif diff --git a/tools/qmldebugger/standalone/engine.png b/tools/qmldebugger/standalone/engine.png Binary files differnew file mode 100644 index 0000000..a0a8a04 --- /dev/null +++ b/tools/qmldebugger/standalone/engine.png diff --git a/tools/qmldebugger/standalone/engines.qml b/tools/qmldebugger/standalone/engines.qml new file mode 100644 index 0000000..0b2b7ac --- /dev/null +++ b/tools/qmldebugger/standalone/engines.qml @@ -0,0 +1,46 @@ +import Qt 4.6 + +Item { + height: 100 + id: root + signal engineClicked(int id) + signal refreshEngines() + + Row { + anchors.fill: parent + Repeater { + model: engines + Item { + width: 100; height: 100; + Image { + id: engineIcon; + source: "qrc:/engine.png" + anchors.horizontalCenter: parent.horizontalCenter + } + Text { + anchors.top: engineIcon.bottom; + text: modelData.name + "(" + modelData.engineId + ")" + anchors.horizontalCenter: parent.horizontalCenter + } + MouseRegion { + anchors.fill: parent + onClicked: root.engineClicked(modelData.engineId); + } + } + } + } + + + Image { + y: 15 + source: "qrc:/refresh.png"; + width: 75; + height: 63; + smooth: true + anchors.right: parent.right + MouseRegion { + anchors.fill: parent + onClicked: root.refreshEngines() + } + } +} diff --git a/tools/qmldebugger/standalone/expressionquerywidget.cpp b/tools/qmldebugger/standalone/expressionquerywidget.cpp new file mode 100644 index 0000000..cd59871 --- /dev/null +++ b/tools/qmldebugger/standalone/expressionquerywidget.cpp @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCore/qdebug.h> + +#include <QtGui/qlabel.h> +#include <QtGui/qtextedit.h> +#include <QtGui/qlineedit.h> +#include <QtGui/qpushbutton.h> +#include <QtGui/qevent.h> +#include <QtGui/qgroupbox.h> +#include <QtGui/qtextobject.h> +#include <QtGui/qlayout.h> + +#include "expressionquerywidget.h" + +ExpressionQueryWidget::ExpressionQueryWidget(Mode mode, QmlEngineDebug *client, QWidget *parent) + : QWidget(parent), + m_mode(mode), + m_client(client), + m_query(0), + m_textEdit(new QTextEdit), + m_lineEdit(0) +{ + m_prompt = QLatin1String(">> "); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(m_textEdit); + + updateTitle(); + + if (m_mode == SeparateEntryMode) { + m_lineEdit = new QLineEdit; + connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(executeExpression())); + QHBoxLayout *hbox = new QHBoxLayout; + hbox->setMargin(5); + hbox->setSpacing(5); + hbox->addWidget(new QLabel(tr("Expression:"))); + hbox->addWidget(m_lineEdit); + layout->addLayout(hbox); + + m_textEdit->setReadOnly(true); + m_lineEdit->installEventFilter(this); + } else { + m_textEdit->installEventFilter(this); + appendPrompt(); + } +} + +void ExpressionQueryWidget::setEngineDebug(QmlEngineDebug *client) +{ + m_client = client; +} + +void ExpressionQueryWidget::clear() +{ + m_textEdit->clear(); + if (m_lineEdit) + m_lineEdit->clear(); + if (m_mode == ShellMode) + appendPrompt(); +} + +void ExpressionQueryWidget::updateTitle() +{ + if (m_currObject.debugId() < 0) { + m_title = tr("Expression queries"); + } else { + QString desc = QLatin1String("<") + + m_currObject.className() + QLatin1String(": ") + + (m_currObject.name().isEmpty() ? QLatin1String("<unnamed>") : m_currObject.name()) + + QLatin1String(">"); + m_title = tr("Expression queries (using context for %1)" , "Selected object").arg(desc); + } +} + +void ExpressionQueryWidget::appendPrompt() +{ + m_textEdit->moveCursor(QTextCursor::End); + + if (m_mode == SeparateEntryMode) { + m_textEdit->insertPlainText("\n"); + } else { + m_textEdit->setTextColor(Qt::gray); + m_textEdit->append(m_prompt); + } +} + +void ExpressionQueryWidget::setCurrentObject(const QmlDebugObjectReference &obj) +{ + m_currObject = obj; + updateTitle(); +} + +void ExpressionQueryWidget::checkCurrentContext() +{ + m_textEdit->moveCursor(QTextCursor::End); + + if (m_currObject.debugId() != -1 && m_currObject.debugId() != m_objectAtLastFocus.debugId()) + showCurrentContext(); + m_objectAtLastFocus = m_currObject; +} + +void ExpressionQueryWidget::showCurrentContext() +{ + if (m_mode == ShellMode) { + // clear the initial prompt + if (m_textEdit->document()->lineCount() == 1) + m_textEdit->clear(); + } + + m_textEdit->moveCursor(QTextCursor::End); + m_textEdit->setTextColor(Qt::darkGreen); + m_textEdit->append(m_currObject.className() + + QLatin1String(": ") + + (m_currObject.name().isEmpty() ? QLatin1String("<unnamed object>") : m_currObject.name())); + appendPrompt(); +} + +void ExpressionQueryWidget::executeExpression() +{ + if (!m_client) + return; + + if (m_mode == SeparateEntryMode) + m_expr = m_lineEdit->text().trimmed(); + else + m_expr = m_expr.trimmed(); + + if (!m_expr.isEmpty() && m_currObject.debugId() != -1) { + if (m_query) + delete m_query; + m_query = m_client->queryExpressionResult(m_currObject.debugId(), m_expr, this); + if (!m_query->isWaiting()) + showResult(); + else + QObject::connect(m_query, SIGNAL(stateChanged(QmlDebugQuery::State)), + this, SLOT(showResult())); + + m_lastExpr = m_expr; + if (m_lineEdit) + m_lineEdit->clear(); + } +} + +void ExpressionQueryWidget::showResult() +{ + if (m_query) { + m_textEdit->moveCursor(QTextCursor::End); + QVariant value = m_query->result(); + QString result; + + if (value.type() == QVariant::List || value.type() == QVariant::StringList) { + result = tr("<%1 items>", "%1 = number of items").arg(value.toList().count()); + } else if (value.isNull()) { + result = QLatin1String("<no value>"); + } else { + result = value.toString(); + } + + if (m_mode == SeparateEntryMode) { + m_textEdit->setTextColor(Qt::black); + m_textEdit->setFontWeight(QFont::Bold); + m_textEdit->insertPlainText(m_expr + " : "); + m_textEdit->setFontWeight(QFont::Normal); + m_textEdit->insertPlainText(result); + } else { + m_textEdit->setTextColor(Qt::darkGreen); + m_textEdit->insertPlainText(" => "); + m_textEdit->setTextColor(Qt::black); + m_textEdit->insertPlainText(result); + } + appendPrompt(); + m_expr.clear(); + } +} + +bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == m_textEdit) { + switch (event->type()) { + case QEvent::KeyPress: + { + QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); + int key = keyEvent->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter) { + executeExpression(); + return true; + } else if (key == Qt::Key_Backspace) { + // ensure m_expr doesn't contain backspace characters + QTextCursor cursor = m_textEdit->textCursor(); + bool atLastLine = !(cursor.block().next().isValid()); + if (!atLastLine) + return true; + if (cursor.columnNumber() <= m_prompt.count()) + return true; + cursor.deletePreviousChar(); + m_expr = cursor.block().text().mid(m_prompt.count()); + return true; + } else { + m_textEdit->moveCursor(QTextCursor::End); + m_textEdit->setTextColor(Qt::black); + m_expr += keyEvent->text(); + } + break; + } + case QEvent::FocusIn: + checkCurrentContext(); + m_textEdit->moveCursor(QTextCursor::End); + break; + default: + break; + } + } else if (obj == m_lineEdit) { + switch (event->type()) { + case QEvent::KeyPress: + { + QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); + int key = keyEvent->key(); + if (key == Qt::Key_Up && m_lineEdit->text() != m_lastExpr) { + m_expr = m_lineEdit->text(); + if (!m_lastExpr.isEmpty()) + m_lineEdit->setText(m_lastExpr); + } else if (key == Qt::Key_Down) { + m_lineEdit->setText(m_expr); + } + break; + } + case QEvent::FocusIn: + checkCurrentContext(); + break; + default: + break; + } + } + return QWidget::eventFilter(obj, event); +} diff --git a/tools/qmldebugger/standalone/expressionquerywidget.h b/tools/qmldebugger/standalone/expressionquerywidget.h new file mode 100644 index 0000000..8c224f8 --- /dev/null +++ b/tools/qmldebugger/standalone/expressionquerywidget.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef EXPRESSIONQUERYWIDGET_H +#define EXPRESSIONQUERYWIDGET_H + +#include <QWidget> + +#include <private/qmldebug_p.h> + +QT_BEGIN_NAMESPACE + +class QGroupBox; +class QTextEdit; +class QLineEdit; +class QPushButton; + +class ExpressionQueryWidget : public QWidget +{ + Q_OBJECT +public: + enum Mode { + SeparateEntryMode, + ShellMode + }; + + ExpressionQueryWidget(Mode mode = SeparateEntryMode, QmlEngineDebug *client = 0, QWidget *parent = 0); + + void setEngineDebug(QmlEngineDebug *client); + void clear(); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +public slots: + void setCurrentObject(const QmlDebugObjectReference &obj); + +private slots: + void executeExpression(); + void showResult(); + +private: + void appendPrompt(); + void checkCurrentContext(); + void showCurrentContext(); + void updateTitle(); + + Mode m_mode; + + QmlEngineDebug *m_client; + QmlDebugExpressionQuery *m_query; + QTextEdit *m_textEdit; + QLineEdit *m_lineEdit; + QPushButton *m_button; + QString m_prompt; + QString m_expr; + QString m_lastExpr; + + QString m_title; + + QmlDebugObjectReference m_currObject; + QmlDebugObjectReference m_objectAtLastFocus; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/tools/qmldebugger/standalone/main.cpp b/tools/qmldebugger/standalone/main.cpp new file mode 100644 index 0000000..715837e --- /dev/null +++ b/tools/qmldebugger/standalone/main.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtGui/qapplication.h> + +#include "qmldebugger.h" + +int main(int argc, char ** argv) +{ + QApplication app(argc, argv); + app.setApplicationName("QtQmlDebugger"); + app.setOrganizationName("Nokia"); + app.setOrganizationDomain("nokia.com"); + + QStringList args = app.arguments(); + + QmlDebugger win; + if (args.contains("--engine")) + win.showEngineTab(); + + for (int i=0; i<args.count(); i++) { + if (!args[i].contains(':')) + continue; + QStringList hostAndPort = args[i].split(':'); + bool ok = false; + quint16 port = hostAndPort.value(1).toInt(&ok); + if (ok) { + qWarning() << "qmldebugger connecting to" + << hostAndPort[0] << port << "..."; + win.setHost(hostAndPort[0]); + win.setPort(port); + win.connectToHost(); + break; + } + } + + win.show(); + + return app.exec(); +} diff --git a/tools/qmldebugger/standalone/objectpropertiesview.cpp b/tools/qmldebugger/standalone/objectpropertiesview.cpp new file mode 100644 index 0000000..3a8d8c8 --- /dev/null +++ b/tools/qmldebugger/standalone/objectpropertiesview.cpp @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCore/qdebug.h> + +#include <QtGui/qtreewidget.h> +#include <QtGui/qlayout.h> +#include <QtGui/qheaderview.h> + +#include <private/qmldebugservice_p.h> +#include <private/qmldebug_p.h> +#include <private/qmldebugclient_p.h> + +#include "objectpropertiesview.h" + +QT_BEGIN_NAMESPACE + +class PropertiesViewItem : public QObject, public QTreeWidgetItem +{ + Q_OBJECT +public: + enum Type { + BindingType, + OtherType + }; + + PropertiesViewItem(QTreeWidget *widget, Type type = OtherType); + PropertiesViewItem(QTreeWidgetItem *parent, Type type = OtherType); + + QmlDebugPropertyReference property; + Type type; +}; + +PropertiesViewItem::PropertiesViewItem(QTreeWidget *widget, Type type) + : QTreeWidgetItem(widget), type(type) +{ +} + +PropertiesViewItem::PropertiesViewItem(QTreeWidgetItem *parent, Type type) + : QTreeWidgetItem(parent), type(type) +{ +} + +ObjectPropertiesView::ObjectPropertiesView(QmlEngineDebug *client, QWidget *parent) + : QWidget(parent), + m_client(client), + m_query(0), + m_watch(0) +{ + QVBoxLayout *layout = new QVBoxLayout; + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + setLayout(layout); + + m_tree = new QTreeWidget(this); + m_tree->setAlternatingRowColors(true); + m_tree->setExpandsOnDoubleClick(false); + m_tree->setHeaderLabels(QStringList() + << tr("Name") << tr("Value") << tr("Type")); + QObject::connect(m_tree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), + this, SLOT(itemActivated(QTreeWidgetItem *))); + + m_tree->setColumnCount(3); + m_tree->header()->setDefaultSectionSize(150); + + layout->addWidget(m_tree); +} + +void ObjectPropertiesView::setEngineDebug(QmlEngineDebug *client) +{ + m_client = client; +} + +void ObjectPropertiesView::clear() +{ + setObject(QmlDebugObjectReference()); +} + +void ObjectPropertiesView::reload(const QmlDebugObjectReference &obj) +{ + if (!m_client) + return; + if (m_query) + delete m_query; + + m_query = m_client->queryObjectRecursive(obj, this); + if (!m_query->isWaiting()) + queryFinished(); + else + QObject::connect(m_query, SIGNAL(stateChanged(QmlDebugQuery::State)), + this, SLOT(queryFinished())); +} + +void ObjectPropertiesView::queryFinished() +{ + if (!m_client || !m_query) + return; + + QmlDebugObjectReference obj = m_query->object(); + + QmlDebugWatch *watch = m_client->addWatch(obj, this); + if (watch->state() == QmlDebugWatch::Dead) { + delete watch; + watch = 0; + } else { + if (m_watch) { + m_client->removeWatch(m_watch); + delete m_watch; + } + m_watch = watch; + QObject::connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), + this, SLOT(valueChanged(QByteArray,QVariant))); + } + + delete m_query; + m_query = 0; + + setObject(obj); +} + +void ObjectPropertiesView::setPropertyValue(PropertiesViewItem *item, const QVariant &value, bool makeGray) +{ + if (value.type() == QVariant::List || value.type() == QVariant::StringList) { + PropertiesViewItem *bindingItem = static_cast<PropertiesViewItem*>(item->takeChild(item->childCount() - 1)); + if (bindingItem && bindingItem->type != PropertiesViewItem::BindingType) { + delete bindingItem; + bindingItem = 0; + } + + qDeleteAll(item->takeChildren()); + + QVariantList variants = value.toList(); + item->setText(1, tr("<%1 items>", "%1 = number of items").arg(variants.count())); + item->setText(2, QString::fromUtf8(value.typeName())); + + PropertiesViewItem *child; + for (int i=0; i<variants.count(); i++) { + child = new PropertiesViewItem(item); + setPropertyValue(child, variants[i], makeGray); + } + + if (bindingItem) + item->addChild(bindingItem); + + item->setExpanded(false); + } else { + item->setText(1, (value.isNull() ? QLatin1String("<no value>") : value.toString())); + item->setExpanded(true); + } + + if (makeGray) { + for (int i=0; i<m_tree->columnCount(); i++) + item->setForeground(i, Qt::gray); + } +} + +void ObjectPropertiesView::setObject(const QmlDebugObjectReference &object) +{ + m_object = object; + m_tree->clear(); + + QList<QmlDebugPropertyReference> properties = object.properties(); + for (int i=0; i<properties.count(); i++) { + const QmlDebugPropertyReference &p = properties[i]; + + PropertiesViewItem *item = new PropertiesViewItem(m_tree); + item->property = p; + + item->setText(0, p.name()); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + + setPropertyValue(item, p.value(), !p.hasNotifySignal()); + item->setText(2, p.valueTypeName()); + + // binding is set after property value to ensure it is added to the end of the + // list, if the value is a list + if (!p.binding().isEmpty()) { + PropertiesViewItem *binding = new PropertiesViewItem(item, PropertiesViewItem::BindingType); + binding->setText(1, p.binding()); + binding->setForeground(1, Qt::darkGreen); + } + } +} + +void ObjectPropertiesView::watchCreated(QmlDebugWatch *watch) +{ + if (watch->objectDebugId() == m_object.debugId() + && qobject_cast<QmlDebugPropertyWatch*>(watch)) { + connect(watch, SIGNAL(stateChanged(QmlDebugWatch::State)), SLOT(watchStateChanged())); + setWatched(qobject_cast<QmlDebugPropertyWatch*>(watch)->name(), true); + } +} + +void ObjectPropertiesView::watchStateChanged() +{ + QmlDebugWatch *watch = qobject_cast<QmlDebugWatch*>(sender()); + + if (watch->objectDebugId() == m_object.debugId() + && qobject_cast<QmlDebugPropertyWatch*>(watch) + && watch->state() == QmlDebugWatch::Inactive) { + setWatched(qobject_cast<QmlDebugPropertyWatch*>(watch)->name(), false); + } +} + +void ObjectPropertiesView::setWatched(const QString &property, bool watched) +{ + for (int i=0; i<m_tree->topLevelItemCount(); i++) { + PropertiesViewItem *item = static_cast<PropertiesViewItem *>(m_tree->topLevelItem(i)); + if (item->property.name() == property && item->property.hasNotifySignal()) { + QFont font = m_tree->font(); + font.setBold(watched); + item->setFont(0, font); + } + } +} + +void ObjectPropertiesView::valueChanged(const QByteArray &name, const QVariant &value) +{ + for (int i=0; i<m_tree->topLevelItemCount(); i++) { + PropertiesViewItem *item = static_cast<PropertiesViewItem *>(m_tree->topLevelItem(i)); + if (item->property.name() == name) { + setPropertyValue(item, value, !item->property.hasNotifySignal()); + return; + } + } +} + +void ObjectPropertiesView::itemActivated(QTreeWidgetItem *i) +{ + PropertiesViewItem *item = static_cast<PropertiesViewItem *>(i); + if (!item->property.name().isEmpty()) + emit activated(m_object, item->property); +} + +QT_END_NAMESPACE + +#include "objectpropertiesview.moc" diff --git a/tools/qmldebugger/standalone/objectpropertiesview.h b/tools/qmldebugger/standalone/objectpropertiesview.h new file mode 100644 index 0000000..43413dc --- /dev/null +++ b/tools/qmldebugger/standalone/objectpropertiesview.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef PROPERTIESTABLEMODEL_H +#define PROPERTIESTABLEMODEL_H + +#include <private/qmldebug_p.h> + +#include <QtGui/qwidget.h> + +QT_BEGIN_NAMESPACE + +class QTreeWidget; +class QTreeWidgetItem; +class QmlDebugConnection; +class PropertiesViewItem; + +class ObjectPropertiesView : public QWidget +{ + Q_OBJECT +public: + ObjectPropertiesView(QmlEngineDebug *client = 0, QWidget *parent = 0); + + void setEngineDebug(QmlEngineDebug *client); + void clear(); + +signals: + void activated(const QmlDebugObjectReference &, const QmlDebugPropertyReference &); + +public slots: + void reload(const QmlDebugObjectReference &); + void watchCreated(QmlDebugWatch *); + +private slots: + void queryFinished(); + void watchStateChanged(); + void valueChanged(const QByteArray &name, const QVariant &value); + void itemActivated(QTreeWidgetItem *i); + +private: + void setObject(const QmlDebugObjectReference &object); + void setWatched(const QString &property, bool watched); + void setPropertyValue(PropertiesViewItem *item, const QVariant &value, bool makeGray); + + QmlEngineDebug *m_client; + QmlDebugObjectQuery *m_query; + QmlDebugWatch *m_watch; + + QTreeWidget *m_tree; + QmlDebugObjectReference m_object; +}; + + +QT_END_NAMESPACE + +#endif diff --git a/tools/qmldebugger/standalone/objecttree.cpp b/tools/qmldebugger/standalone/objecttree.cpp new file mode 100644 index 0000000..cf467f2 --- /dev/null +++ b/tools/qmldebugger/standalone/objecttree.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtGui/qevent.h> +#include <QtGui/qmenu.h> +#include <QtGui/qaction.h> + +#include <QInputDialog> + +#include <private/qmldebugservice_p.h> +#include <private/qmldebug_p.h> +#include <private/qmldebugclient_p.h> + +#include "objecttree.h" + +Q_DECLARE_METATYPE(QmlDebugObjectReference) + +ObjectTree::ObjectTree(QmlEngineDebug *client, QWidget *parent) + : QTreeWidget(parent), + m_client(client), + m_query(0) +{ + setHeaderHidden(true); + setMinimumWidth(250); + setExpandsOnDoubleClick(false); + + connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), + SLOT(currentItemChanged(QTreeWidgetItem *))); + connect(this, SIGNAL(itemActivated(QTreeWidgetItem *, int)), + SLOT(activated(QTreeWidgetItem *))); +} + +void ObjectTree::setEngineDebug(QmlEngineDebug *client) +{ + m_client = client; +} + +void ObjectTree::reload(int objectDebugId) +{ + if (!m_client) + return; + + if (m_query) { + delete m_query; + m_query = 0; + } + + m_query = m_client->queryObjectRecursive(QmlDebugObjectReference(objectDebugId), this); + if (!m_query->isWaiting()) + objectFetched(); + else + QObject::connect(m_query, SIGNAL(stateChanged(QmlDebugQuery::State)), + this, SLOT(objectFetched())); +} + +void ObjectTree::setCurrentObject(int debugId) +{ + QTreeWidgetItem *item = findItemByObjectId(debugId); + if (item) { + setCurrentItem(item); + scrollToItem(item); + item->setExpanded(true); + } +} + +void ObjectTree::objectFetched() +{ + dump(m_query->object(), 0); + buildTree(m_query->object(), 0); + setCurrentItem(topLevelItem(0)); + + delete m_query; + m_query = 0; +} + +void ObjectTree::currentItemChanged(QTreeWidgetItem *item) +{ + if (!item) + return; + + QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value<QmlDebugObjectReference>(); + if (obj.debugId() >= 0) + emit currentObjectChanged(obj); +} + +void ObjectTree::activated(QTreeWidgetItem *item) +{ + if (!item) + return; + + QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value<QmlDebugObjectReference>(); + if (obj.debugId() >= 0) + emit activated(obj); +} + +void ObjectTree::buildTree(const QmlDebugObjectReference &obj, QTreeWidgetItem *parent) +{ + if (!parent) + clear(); + + QTreeWidgetItem *item = parent ? new QTreeWidgetItem(parent) : new QTreeWidgetItem(this); + item->setText(0, obj.className()); + item->setData(0, Qt::UserRole, qVariantFromValue(obj)); + + if (parent && obj.contextDebugId() >= 0 + && obj.contextDebugId() != parent->data(0, Qt::UserRole + ).value<QmlDebugObjectReference>().contextDebugId()) { + QmlDebugFileReference source = obj.source(); + if (!source.url().isEmpty()) { + QString toolTipString = QLatin1String("URL: ") + source.url().toString(); + item->setToolTip(0, toolTipString); + } + item->setForeground(0, QColor("orange")); + } else { + item->setExpanded(true); + } + + if (obj.contextDebugId() < 0) + item->setForeground(0, Qt::lightGray); + + for (int ii = 0; ii < obj.children().count(); ++ii) + buildTree(obj.children().at(ii), item); +} + +void ObjectTree::dump(const QmlDebugContextReference &ctxt, int ind) +{ + QByteArray indent(ind * 4, ' '); + qWarning().nospace() << indent.constData() << ctxt.debugId() << " " + << qPrintable(ctxt.name()); + + for (int ii = 0; ii < ctxt.contexts().count(); ++ii) + dump(ctxt.contexts().at(ii), ind + 1); + + for (int ii = 0; ii < ctxt.objects().count(); ++ii) + dump(ctxt.objects().at(ii), ind); +} + +void ObjectTree::dump(const QmlDebugObjectReference &obj, int ind) +{ + QByteArray indent(ind * 4, ' '); + qWarning().nospace() << indent.constData() << qPrintable(obj.className()) + << " " << qPrintable(obj.name()) << " " + << obj.debugId(); + + for (int ii = 0; ii < obj.children().count(); ++ii) + dump(obj.children().at(ii), ind + 1); +} + +QTreeWidgetItem *ObjectTree::findItemByObjectId(int debugId) const +{ + for (int i=0; i<topLevelItemCount(); i++) { + QTreeWidgetItem *item = findItem(topLevelItem(i), debugId); + if (item) + return item; + } + + return 0; +} + +QTreeWidgetItem *ObjectTree::findItem(QTreeWidgetItem *item, int debugId) const +{ + if (item->data(0, Qt::UserRole).value<QmlDebugObjectReference>().debugId() == debugId) + return item; + + QTreeWidgetItem *child; + for (int i=0; i<item->childCount(); i++) { + child = findItem(item->child(i), debugId); + if (child) + return child; + } + + return 0; +} + +void ObjectTree::mousePressEvent(QMouseEvent *me) +{ + QTreeWidget::mousePressEvent(me); + if (!currentItem()) + return; + if(me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) { + QAction action(tr("Add watch..."), 0); + QList<QAction *> actions; + actions << &action; + QmlDebugObjectReference obj = + currentItem()->data(0, Qt::UserRole).value<QmlDebugObjectReference>(); + if (QMenu::exec(actions, me->globalPos())) { + bool ok = false; + QString watch = QInputDialog::getText(this, tr("Watch expression"), + tr("Expression:"), QLineEdit::Normal, QString(), &ok); + if (ok && !watch.isEmpty()) + emit expressionWatchRequested(obj, watch); + } + } +} diff --git a/tools/qmldebugger/standalone/objecttree.h b/tools/qmldebugger/standalone/objecttree.h new file mode 100644 index 0000000..c8d625c --- /dev/null +++ b/tools/qmldebugger/standalone/objecttree.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef OBJECTTREE_H +#define OBJECTTREE_H + +#include <QtGui/qtreewidget.h> + +QT_BEGIN_NAMESPACE + +class QTreeWidgetItem; + +class QmlEngineDebug; +class QmlDebugObjectReference; +class QmlDebugObjectQuery; +class QmlDebugContextReference; +class QmlDebugConnection; + + +class ObjectTree : public QTreeWidget +{ + Q_OBJECT +public: + ObjectTree(QmlEngineDebug *client = 0, QWidget *parent = 0); + + void setEngineDebug(QmlEngineDebug *client); + +signals: + void currentObjectChanged(const QmlDebugObjectReference &); + void activated(const QmlDebugObjectReference &); + void expressionWatchRequested(const QmlDebugObjectReference &, const QString &); + +public slots: + void reload(int objectDebugId); // set the root object + void setCurrentObject(int debugId); // select an object in the tree + +protected: + virtual void mousePressEvent(QMouseEvent *); + +private slots: + void objectFetched(); + void currentItemChanged(QTreeWidgetItem *); + void activated(QTreeWidgetItem *); + +private: + QTreeWidgetItem *findItemByObjectId(int debugId) const; + QTreeWidgetItem *findItem(QTreeWidgetItem *item, int debugId) const; + void dump(const QmlDebugContextReference &, int); + void dump(const QmlDebugObjectReference &, int); + void buildTree(const QmlDebugObjectReference &, QTreeWidgetItem *parent); + + QmlEngineDebug *m_client; + QmlDebugObjectQuery *m_query; +}; + +QT_END_NAMESPACE + + +#endif diff --git a/tools/qmldebugger/standalone/qmldebugger.cpp b/tools/qmldebugger/standalone/qmldebugger.cpp new file mode 100644 index 0000000..4d86377 --- /dev/null +++ b/tools/qmldebugger/standalone/qmldebugger.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCore/qtimer.h> +#include <QtCore/qdebug.h> +#include <QtCore/qsettings.h> + +#include <QtGui/qlayout.h> +#include <QtGui/qpushbutton.h> +#include <QtGui/qlineedit.h> +#include <QtGui/qtabwidget.h> +#include <QtGui/qspinbox.h> +#include <QtGui/qlabel.h> + +#include "canvasframerate.h" +#include "engine.h" +#include "qmldebugger.h" + +QmlDebugger::QmlDebugger(QWidget *parent) +: QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + + QHBoxLayout *connectLayout = new QHBoxLayout; + layout->addLayout(connectLayout); + connectLayout->addStretch(2); + + m_connectionState = new QLabel(this); + connectLayout->addWidget(m_connectionState); + m_host = new QLineEdit(this); + connectLayout->addWidget(m_host); + m_port = new QSpinBox(this); + m_port->setMinimum(1024); + m_port->setMaximum(20000); + connectLayout->addWidget(m_port); + m_connectButton = new QPushButton(tr("Connect"), this); + QObject::connect(m_connectButton, SIGNAL(clicked()), + this, SLOT(connectToHost())); + connectLayout->addWidget(m_connectButton); + m_disconnectButton = new QPushButton(tr("Disconnect"), this); + QObject::connect(m_disconnectButton, SIGNAL(clicked()), + this, SLOT(disconnectFromHost())); + m_disconnectButton->setEnabled(false); + connectLayout->addWidget(m_disconnectButton); + + m_tabs = new QTabWidget(this); + layout->addWidget(m_tabs); + + CanvasFrameRate *cfr = new CanvasFrameRate(this); + cfr->reset(&client); + cfr->setSizeHint(QSize(800, 600)); + m_tabs->addTab(cfr, tr("Frame Rate")); + + m_enginePane = new EnginePane(&client, this); + m_tabs->addTab(m_enginePane, tr("QML Engine")); + + QObject::connect(&client, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + this, SLOT(connectionStateChanged())); + connectionStateChanged(); + + QObject::connect(&client, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(connectionError(QAbstractSocket::SocketError))); + + QSettings settings; + m_host->setText(settings.value("Host", "127.0.0.1").toString()); + m_port->setValue(settings.value("Port", 3768).toInt()); + + connectToHost(); +} + +void QmlDebugger::setHost(const QString &host) +{ + m_host->setText(host); +} + +void QmlDebugger::setPort(quint16 port) +{ + m_port->setValue(port); +} + +void QmlDebugger::showEngineTab() +{ + m_tabs->setCurrentWidget(m_enginePane); +} + +void QmlDebugger::closeEvent(QCloseEvent *event) +{ + QSettings settings; + settings.setValue("Host", m_host->text()); + settings.setValue("Port", m_port->value()); + + QWidget::closeEvent(event); +} + +void QmlDebugger::connectionStateChanged() +{ + switch (client.state()) { + default: + case QAbstractSocket::UnconnectedState: + m_connectionState->setText(tr("Disconnected")); + m_connectButton->setEnabled(true); + m_disconnectButton->setEnabled(false); + break; + case QAbstractSocket::HostLookupState: + m_connectionState->setText(tr("Resolving")); + m_connectButton->setEnabled(false); + m_disconnectButton->setEnabled(true); + break; + case QAbstractSocket::ConnectingState: + m_connectionState->setText(tr("Connecting")); + m_connectButton->setEnabled(false); + m_disconnectButton->setEnabled(true); + break; + case QAbstractSocket::ConnectedState: + m_connectionState->setText(tr("Connected")); + m_connectButton->setEnabled(false); + m_disconnectButton->setEnabled(true); + + QTimer::singleShot(0, m_enginePane, SLOT(refreshEngines())); + break; + case QAbstractSocket::ClosingState: + m_connectionState->setText(tr("Closing")); + m_connectButton->setEnabled(false); + m_disconnectButton->setEnabled(false); + break; + } +} + +void QmlDebugger::connectionError(QAbstractSocket::SocketError socketError) +{ + qWarning() << "qmldebugger cannot connect:" << socketError + << client.errorString(); +} + +void QmlDebugger::connectToHost() +{ + client.connectToHost(m_host->text(), m_port->value()); +} + +void QmlDebugger::disconnectFromHost() +{ + client.disconnectFromHost(); +} diff --git a/tools/qmldebugger/standalone/qmldebugger.h b/tools/qmldebugger/standalone/qmldebugger.h new file mode 100644 index 0000000..da95ef9 --- /dev/null +++ b/tools/qmldebugger/standalone/qmldebugger.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QMLDEBUGGER_H +#define QMLDEBUGGER_H + +#include <private/qmldebugclient_p.h> +#include <QtNetwork/qtcpsocket.h> +#include <QtGui/qwidget.h> + +class QLabel; +class QLineEdit; +class QSpinBox; +class QPushButton; +class QTabWidget; + +class EnginePane; + +class QmlDebugger : public QWidget +{ + Q_OBJECT +public: + QmlDebugger(QWidget * = 0); + + void setHost(const QString &host); + void setPort(quint16 port); + void showEngineTab(); + +public slots: + void connectToHost(); + void disconnectFromHost(); + +protected: + void closeEvent(QCloseEvent *); + +private slots: + void connectionStateChanged(); + void connectionError(QAbstractSocket::SocketError socketError); + +private: + QmlDebugConnection client; + + QLabel *m_connectionState; + QLineEdit *m_host; + QSpinBox *m_port; + QPushButton *m_connectButton; + QPushButton *m_disconnectButton; + + EnginePane *m_enginePane; + QTabWidget *m_tabs; +}; + +#endif diff --git a/tools/qmldebugger/standalone/qmldebugger.pri b/tools/qmldebugger/standalone/qmldebugger.pri new file mode 100644 index 0000000..ede7d31 --- /dev/null +++ b/tools/qmldebugger/standalone/qmldebugger.pri @@ -0,0 +1,18 @@ +QT += network declarative +contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl + +INCLUDEPATH += ../../../src/declarative/debugger + +# Input +HEADERS += $$PWD/canvasframerate.h \ + $$PWD/watchtable.h \ + $$PWD/objecttree.h \ + $$PWD/objectpropertiesview.h \ + $$PWD/expressionquerywidget.h + +SOURCES += $$PWD/canvasframerate.cpp \ + $$PWD/watchtable.cpp \ + $$PWD/objecttree.cpp \ + $$PWD/objectpropertiesview.cpp \ + $$PWD/expressionquerywidget.cpp + diff --git a/tools/qmldebugger/standalone/qmldebugger.qrc b/tools/qmldebugger/standalone/qmldebugger.qrc new file mode 100644 index 0000000..cb53ad5 --- /dev/null +++ b/tools/qmldebugger/standalone/qmldebugger.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>engines.qml</file> + <file>engine.png</file> + <file>refresh.png</file> + </qresource> +</RCC> diff --git a/tools/qmldebugger/standalone/refresh.png b/tools/qmldebugger/standalone/refresh.png Binary files differnew file mode 100644 index 0000000..8befc80 --- /dev/null +++ b/tools/qmldebugger/standalone/refresh.png diff --git a/tools/qmldebugger/standalone/standalone.pro b/tools/qmldebugger/standalone/standalone.pro new file mode 100644 index 0000000..72d051f --- /dev/null +++ b/tools/qmldebugger/standalone/standalone.pro @@ -0,0 +1,19 @@ +DESTDIR = ../../../bin +TARGET = qmldebugger + +include(qmldebugger.pri) + +HEADERS += $$PWD/qmldebugger.h \ + $$PWD/engine.h + +SOURCES += $$PWD/qmldebugger.cpp \ + $$PWD/engine.cpp \ + $$PWD/main.cpp + +RESOURCES += $$PWD/qmldebugger.qrc +OTHER_FILES += $$PWD/engines.qml + +target.path=$$[QT_INSTALL_BINS] +INSTALLS += target + +CONFIG += console diff --git a/tools/qmldebugger/standalone/watchtable.cpp b/tools/qmldebugger/standalone/watchtable.cpp new file mode 100644 index 0000000..6f9f99a --- /dev/null +++ b/tools/qmldebugger/standalone/watchtable.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "watchtable.h" + +#include <QtCore/qdebug.h> +#include <QtGui/qevent.h> +#include <QtGui/qaction.h> +#include <QtGui/qmenu.h> + +#include <private/qmldebug_p.h> +#include <QtDeclarative/qmlmetatype.h> + +QT_BEGIN_NAMESPACE + + +WatchTableModel::WatchTableModel(QmlEngineDebug *client, QObject *parent) + : QAbstractTableModel(parent), + m_client(client) +{ +} + +WatchTableModel::~WatchTableModel() +{ + for (int i=0; i<m_columns.count(); i++) + delete m_columns[i].watch; +} + +void WatchTableModel::setEngineDebug(QmlEngineDebug *client) +{ + m_client = client; +} + +void WatchTableModel::addWatch(QmlDebugWatch *watch, const QString &title) +{ + QString property; + if (qobject_cast<QmlDebugPropertyWatch *>(watch)) + property = qobject_cast<QmlDebugPropertyWatch *>(watch)->name(); + + connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), + SLOT(watchedValueChanged(QByteArray,QVariant))); + + connect(watch, SIGNAL(stateChanged(QmlDebugWatch::State)), SLOT(watchStateChanged())); + + int col = columnCount(QModelIndex()); + beginInsertColumns(QModelIndex(), col, col); + + WatchedEntity e; + e.title = title; + e.hasFirstValue = false; + e.property = property; + e.watch = watch; + m_columns.append(e); + + endInsertColumns(); +} + +void WatchTableModel::removeWatch(QmlDebugWatch *watch) +{ + int column = columnForWatch(watch); + if (column == -1) + return; + + WatchedEntity entity = m_columns.takeAt(column); + + for (QList<Value>::Iterator iter = m_values.begin(); iter != m_values.end();) { + if (iter->column == column) { + iter = m_values.erase(iter); + } else { + if(iter->column > column) + --iter->column; + ++iter; + } + } + + reset(); +} + +void WatchTableModel::updateWatch(QmlDebugWatch *watch, const QVariant &value) +{ + int column = columnForWatch(watch); + if (column == -1) + return; + + addValue(column, value); + + if (!m_columns[column].hasFirstValue) { + m_columns[column].hasFirstValue = true; + m_values[m_values.count() - 1].first = true; + } +} + +QmlDebugWatch *WatchTableModel::findWatch(int column) const +{ + if (column < m_columns.count()) + return m_columns.at(column).watch; + return 0; +} + +QmlDebugWatch *WatchTableModel::findWatch(int objectDebugId, const QString &property) const +{ + for (int i=0; i<m_columns.count(); i++) { + if (m_columns[i].watch->objectDebugId() == objectDebugId + && m_columns[i].property == property) { + return m_columns[i].watch; + } + } + return 0; +} + +int WatchTableModel::rowCount(const QModelIndex &) const +{ + return m_values.count(); +} + +int WatchTableModel::columnCount(const QModelIndex &) const +{ + return m_columns.count(); +} + +QVariant WatchTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal) { + if (section < m_columns.count() && role == Qt::DisplayRole) + return m_columns.at(section).title; + } else { + if (role == Qt::DisplayRole) + return section + 1; + } + return QVariant(); +} + +QVariant WatchTableModel::data(const QModelIndex &idx, int role) const +{ + if (m_values.at(idx.row()).column == idx.column()) { + if (role == Qt::DisplayRole) { + const QVariant &value = m_values.at(idx.row()).variant; + QString str = value.toString(); + + if (str.isEmpty() && QmlMetaType::isQObject(value.userType())) { + QObject *o = QmlMetaType::toQObject(value); + if(o) { + QString objectName = o->objectName(); + if(objectName.isEmpty()) + objectName = QLatin1String("<unnamed>"); + str = QLatin1String(o->metaObject()->className()) + + QLatin1String(": ") + objectName; + } + } + + if(str.isEmpty()) { + QDebug d(&str); + d << value; + } + return QVariant(str); + } else if(role == Qt::BackgroundRole) { + if(m_values.at(idx.row()).first) + return QColor(Qt::green); + else + return QVariant(); + } else { + return QVariant(); + } + } else { + return QVariant(); + } +} + +void WatchTableModel::watchStateChanged() +{ + QmlDebugWatch *watch = qobject_cast<QmlDebugWatch*>(sender()); + + if (watch && watch->state() == QmlDebugWatch::Inactive) { + removeWatch(watch); + watch->deleteLater(); + } +} + +int WatchTableModel::columnForWatch(QmlDebugWatch *watch) const +{ + for (int i=0; i<m_columns.count(); i++) { + if (m_columns.at(i).watch == watch) + return i; + } + return -1; +} + +void WatchTableModel::addValue(int column, const QVariant &value) +{ + int row = columnCount(QModelIndex()); + beginInsertRows(QModelIndex(), row, row); + + Value v; + v.column = column; + v.variant = value; + v.first = false; + m_values.append(v); + + endInsertRows(); +} + +void WatchTableModel::togglePropertyWatch(const QmlDebugObjectReference &object, const QmlDebugPropertyReference &property) +{ + if (!m_client || !property.hasNotifySignal()) + return; + + QmlDebugWatch *watch = findWatch(object.debugId(), property.name()); + if (watch) { + // watch will be deleted in watchStateChanged() + m_client->removeWatch(watch); + return; + } + + watch = m_client->addWatch(property, this); + if (watch->state() == QmlDebugWatch::Dead) { + delete watch; + watch = 0; + } else { + QString desc = property.name() + + QLatin1String(" on\n") + + object.className() + + QLatin1String(":\n") + + (object.name().isEmpty() ? QLatin1String("<unnamed object>") : object.name()); + addWatch(watch, desc); + emit watchCreated(watch); + } +} + +void WatchTableModel::watchedValueChanged(const QByteArray &propertyName, const QVariant &value) +{ + Q_UNUSED(propertyName); + QmlDebugWatch *watch = qobject_cast<QmlDebugWatch*>(sender()); + if (watch) + updateWatch(watch, value); +} + +void WatchTableModel::expressionWatchRequested(const QmlDebugObjectReference &obj, const QString &expr) +{ + if (!m_client) + return; + + QmlDebugWatch *watch = m_client->addWatch(obj, expr, this); + + if (watch->state() == QmlDebugWatch::Dead) { + delete watch; + watch = 0; + } else { + addWatch(watch, expr); + emit watchCreated(watch); + } +} + +void WatchTableModel::removeWatchAt(int column) +{ + if (!m_client) + return; + + QmlDebugWatch *watch = findWatch(column); + if (watch) { + m_client->removeWatch(watch); + delete watch; + watch = 0; + } +} + +void WatchTableModel::removeAllWatches() +{ + for (int i=0; i<m_columns.count(); i++) { + if (m_client) + m_client->removeWatch(m_columns[i].watch); + else + delete m_columns[i].watch; + } + m_columns.clear(); + m_values.clear(); + reset(); +} + +//---------------------------------------------- + +WatchTableHeaderView::WatchTableHeaderView(WatchTableModel *model, QWidget *parent) + : QHeaderView(Qt::Horizontal, parent), + m_model(model) +{ + setClickable(true); +} + +void WatchTableHeaderView::mousePressEvent(QMouseEvent *me) +{ + QHeaderView::mousePressEvent(me); + + if (me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) { + int col = logicalIndexAt(me->pos()); + if (col >= 0) { + QAction action(tr("Stop watching"), 0); + QList<QAction *> actions; + actions << &action; + if (QMenu::exec(actions, me->globalPos())) + m_model->removeWatchAt(col); + } + } +} + + +//---------------------------------------------- + +WatchTableView::WatchTableView(WatchTableModel *model, QWidget *parent) + : QTableView(parent), + m_model(model) +{ + setAlternatingRowColors(true); + connect(model, SIGNAL(watchCreated(QmlDebugWatch*)), SLOT(watchCreated(QmlDebugWatch*))); + connect(this, SIGNAL(activated(QModelIndex)), SLOT(indexActivated(QModelIndex))); +} + +void WatchTableView::indexActivated(const QModelIndex &index) +{ + QmlDebugWatch *watch = m_model->findWatch(index.column()); + if (watch) + emit objectActivated(watch->objectDebugId()); +} + +void WatchTableView::watchCreated(QmlDebugWatch *watch) +{ + int column = m_model->columnForWatch(watch); + resizeColumnToContents(column); +} + +QT_END_NAMESPACE diff --git a/tools/qmldebugger/standalone/watchtable.h b/tools/qmldebugger/standalone/watchtable.h new file mode 100644 index 0000000..fd12d3d --- /dev/null +++ b/tools/qmldebugger/standalone/watchtable.h @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt QML Debugger of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef WATCHTABLEMODEL_H +#define WATCHTABLEMODEL_H + +#include <QtCore/qpointer.h> +#include <QtCore/qlist.h> + +#include <QWidget> +#include <QHeaderView> +#include <QAbstractTableModel> +#include <QTableView> + +QT_BEGIN_NAMESPACE + +class QmlDebugWatch; +class QmlEngineDebug; +class QmlDebugConnection; +class QmlDebugPropertyReference; +class QmlDebugObjectReference; + +class WatchTableModel : public QAbstractTableModel +{ + Q_OBJECT +public: + WatchTableModel(QmlEngineDebug *client = 0, QObject *parent = 0); + ~WatchTableModel(); + + void setEngineDebug(QmlEngineDebug *client); + + QmlDebugWatch *findWatch(int column) const; + int columnForWatch(QmlDebugWatch *watch) const; + + void removeWatchAt(int column); + void removeAllWatches(); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + +signals: + void watchCreated(QmlDebugWatch *watch); + +public slots: + void togglePropertyWatch(const QmlDebugObjectReference &obj, const QmlDebugPropertyReference &prop); + void expressionWatchRequested(const QmlDebugObjectReference &, const QString &); + +private slots: + void watchStateChanged(); + void watchedValueChanged(const QByteArray &propertyName, const QVariant &value); + +private: + void addWatch(QmlDebugWatch *watch, const QString &title); + void removeWatch(QmlDebugWatch *watch); + void updateWatch(QmlDebugWatch *watch, const QVariant &value); + + QmlDebugWatch *findWatch(int objectDebugId, const QString &property) const; + + void addValue(int column, const QVariant &value); + + struct WatchedEntity + { + QString title; + bool hasFirstValue; + QString property; + QPointer<QmlDebugWatch> watch; + }; + + struct Value { + int column; + QVariant variant; + bool first; + }; + + QmlEngineDebug *m_client; + QList<WatchedEntity> m_columns; + QList<Value> m_values; +}; + + +class WatchTableHeaderView : public QHeaderView +{ + Q_OBJECT +public: + WatchTableHeaderView(WatchTableModel *model, QWidget *parent = 0); + +protected: + void mousePressEvent(QMouseEvent *me); + +private: + WatchTableModel *m_model; +}; + + +class WatchTableView : public QTableView +{ + Q_OBJECT +public: + WatchTableView(WatchTableModel *model, QWidget *parent = 0); + +signals: + void objectActivated(int objectDebugId); + +private slots: + void indexActivated(const QModelIndex &index); + void watchCreated(QmlDebugWatch *watch); + +private: + WatchTableModel *m_model; +}; + + +QT_END_NAMESPACE + +#endif // WATCHTABLEMODEL_H diff --git a/tools/qmlviewer/content/Browser.qml b/tools/qmlviewer/content/Browser.qml new file mode 100644 index 0000000..446045b --- /dev/null +++ b/tools/qmlviewer/content/Browser.qml @@ -0,0 +1,243 @@ +import Qt 4.6 + +Rectangle { + id: root + property bool keyPressed: false + property var folders: folders1 + property var view: view1 + width: 320 + height: 480 + color: palette.window + + FolderListModel { + id: folders1 + nameFilters: [ "*.qml" ] + folder: qmlViewerFolder + } + FolderListModel { + id: folders2 + nameFilters: [ "*.qml" ] + folder: qmlViewerFolder + } + + SystemPalette { id: palette } + + Script { + function down(path) { + if (folders == folders1) { + view = view2 + folders = folders2; + view1.state = "exitLeft"; + } else { + view = view1 + folders = folders1; + view2.state = "exitLeft"; + } + view.x = root.width; + view.state = "current"; + view.focus = true; + folders.folder = path; + } + function up() { + var path = folders.parentFolder; + if (folders == folders1) { + view = view2 + folders = folders2; + view1.state = "exitRight"; + } else { + view = view1 + folders = folders1; + view2.state = "exitRight"; + } + view.x = -root.width; + view.state = "current"; + view.focus = true; + folders.folder = path; + } + } + + Component { + id: folderDelegate + Rectangle { + id: wrapper + function launch() { + if (folders.isFolder(index)) { + down(filePath); + } else { + qmlViewer.launch(filePath); + } + } + width: root.width + height: 52 + color: "transparent" + Rectangle { + id: highlight; visible: false + anchors.fill: parent + gradient: Gradient { + GradientStop { id: t1; position: 0.0; color: palette.highlight } + GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) } + } + } + Item { + width: 48; height: 48 + Image { source: "images/folder.png"; anchors.centerIn: parent; visible: folders.isFolder(index)} + } + Text { + id: nameText + anchors.fill: parent; verticalAlignment: Text.AlignVCenter + text: fileName + anchors.leftMargin: 54 + font.pixelSize: 32 + color: (wrapper.ListView.isCurrentItem && root.keyPressed) ? palette.highlightedText : palette.windowText + } + MouseRegion { + id: mouseRegion + anchors.fill: parent + onClicked: { launch() } + } + states: [ + State { + name: "pressed" + when: mouseRegion.pressed + PropertyChanges { target: highlight; visible: true } + PropertyChanges { target: nameText; color: palette.highlightedText } + } + ] + } + } + + ListView { + id: view1 + anchors.top: titleBar.bottom + anchors.bottom: parent.bottom + x: 0 + width: parent.width + model: folders1 + delegate: folderDelegate + highlight: Rectangle { color: palette.highlight; visible: root.keyPressed && view1.count != 0 } + highlightMoveSpeed: 1000 + pressDelay: 100 + focus: true + state: "current" + states: [ + State { + name: "current" + PropertyChanges { target: view1; x: 0 } + }, + State { + name: "exitLeft" + PropertyChanges { target: view1; x: -root.width } + }, + State { + name: "exitRight" + PropertyChanges { target: view1; x: root.width } + } + ] + transitions: [ + Transition { + to: "current" + SequentialAnimation { + NumberAnimation { matchProperties: "x"; duration: 250 } + } + }, + Transition { + NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { matchProperties: "x"; duration: 250 } + } + ] + Keys.onPressed: { root.keyPressed = true; } + } + + ListView { + id: view2 + anchors.top: titleBar.bottom + anchors.bottom: parent.bottom + x: parent.width + width: parent.width + model: folders2 + delegate: folderDelegate + highlight: Rectangle { color: palette.highlight; visible: root.keyPressed && view2.count != 0 } + highlightMoveSpeed: 1000 + pressDelay: 100 + states: [ + State { + name: "current" + PropertyChanges { target: view2; x: 0 } + }, + State { + name: "exitLeft" + PropertyChanges { target: view2; x: -root.width } + }, + State { + name: "exitRight" + PropertyChanges { target: view2; x: root.width } + } + ] + transitions: [ + Transition { + to: "current" + SequentialAnimation { + NumberAnimation { matchProperties: "x"; duration: 250 } + } + }, + Transition { + NumberAnimation { matchProperties: "x"; duration: 250 } + } + ] + Keys.onPressed: { root.keyPressed = true; } + } + + Keys.onPressed: { + root.keyPressed = true; + if (event.key == Qt.Key_Return || event.key == Qt.Key_Select || event.key == Qt.Key_Right) { + view.currentItem.launch(); + event.accepted = true; + } else if (event.key == Qt.Key_Left) { + up(); + } + } + + BorderImage { + source: "images/titlebar.sci"; + width: parent.width; + height: 52 + y: -7 + id: titleBar + + Rectangle { + id: upButton + width: 48 + height: titleBar.height - 7 + color: "transparent" + + Image { anchors.centerIn: parent; source: "images/up.png" } + MouseRegion { id: upRegion; anchors.centerIn: parent + width: 56 + height: 56 + onClicked: if (folders.parentFolder != "") up() + } + states: [ + State { + name: "pressed" + when: upRegion.pressed + PropertyChanges { target: upButton; color: palette.highlight } + } + ] + } + Rectangle { + color: "gray" + x: 48 + width: 1 + height: 44 + } + + Text { + anchors.left: upButton.right; anchors.right: parent.right; height: parent.height + anchors.leftMargin: 4; anchors.rightMargin: 4 + text: folders.folder + color: "white" + elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter + font.pixelSize: 32 + } + } +} diff --git a/tools/qmlviewer/content/images/folder.png b/tools/qmlviewer/content/images/folder.png Binary files differnew file mode 100644 index 0000000..e53e2ad --- /dev/null +++ b/tools/qmlviewer/content/images/folder.png diff --git a/tools/qmlviewer/content/images/titlebar.png b/tools/qmlviewer/content/images/titlebar.png Binary files differnew file mode 100644 index 0000000..51c9008 --- /dev/null +++ b/tools/qmlviewer/content/images/titlebar.png diff --git a/tools/qmlviewer/content/images/titlebar.sci b/tools/qmlviewer/content/images/titlebar.sci new file mode 100644 index 0000000..0418d94 --- /dev/null +++ b/tools/qmlviewer/content/images/titlebar.sci @@ -0,0 +1,5 @@ +border.left: 10 +border.top: 12 +border.bottom: 12 +border.right: 10 +source: titlebar.png diff --git a/tools/qmlviewer/content/images/up.png b/tools/qmlviewer/content/images/up.png Binary files differnew file mode 100644 index 0000000..b05f802 --- /dev/null +++ b/tools/qmlviewer/content/images/up.png diff --git a/tools/qmlviewer/deviceorientation.cpp b/tools/qmlviewer/deviceorientation.cpp new file mode 100644 index 0000000..c507479 --- /dev/null +++ b/tools/qmlviewer/deviceorientation.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "deviceorientation.h" + +class DefaultDeviceOrientation : public DeviceOrientation +{ + Q_OBJECT +public: + DefaultDeviceOrientation() : DeviceOrientation(), m_orientation(DeviceOrientation::Portrait) {} + + Orientation orientation() const { + return m_orientation; + } + + void setOrientation(Orientation o) { + if (o != m_orientation) { + m_orientation = o; + emit orientationChanged(); + } + } + + Orientation m_orientation; +}; + +DeviceOrientation* DeviceOrientation::instance() +{ + static DefaultDeviceOrientation *o = 0; + if (!o) + o = new DefaultDeviceOrientation; + return o; +} + +#include "deviceorientation.moc" + diff --git a/tools/qmlviewer/deviceorientation.h b/tools/qmlviewer/deviceorientation.h new file mode 100644 index 0000000..fa7758f --- /dev/null +++ b/tools/qmlviewer/deviceorientation.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ORIENTATION_H +#define ORIENTATION_H + +#include <QObject> + +class DeviceOrientationPrivate; +class DeviceOrientation : public QObject +{ + Q_OBJECT +public: + enum Orientation { UnknownOrientation, Portrait, Landscape }; + virtual Orientation orientation() const = 0; + virtual void setOrientation(Orientation) = 0; + + static DeviceOrientation *instance(); + +signals: + void orientationChanged(); + +protected: + DeviceOrientation() {} + +private: + DeviceOrientationPrivate *d_ptr; + friend class DeviceOrientationPrivate; +}; + +#endif diff --git a/tools/qmlviewer/deviceorientation_maemo.cpp b/tools/qmlviewer/deviceorientation_maemo.cpp new file mode 100644 index 0000000..9df9af4 --- /dev/null +++ b/tools/qmlviewer/deviceorientation_maemo.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "deviceorientation.h" +#include <stdio.h> +#include <stdlib.h> + +class MaemoOrientation : public DeviceOrientation +{ + Q_OBJECT +public: + MaemoOrientation() + : DeviceOrientation(),m_current(Portrait), m_lastSeen(Portrait), m_lastSeenCount(0) + { + startTimer(100); + } + + Orientation orientation() const { + return m_current; + } + + void setOrientation(Orientation orient) { + //XXX maybe better to just ignore + if (orient != m_current) { + m_current = orient; + emit orientationChanged(); + } + } + + +protected: + virtual void timerEvent(QTimerEvent *) + { + Orientation c = get(); + + if (c == m_lastSeen) { + m_lastSeenCount++; + } else { + m_lastSeenCount = 0; + m_lastSeen = c; + } + + if (m_lastSeen != UnknownOrientation && m_lastSeen != m_current && m_lastSeenCount > 4) { + m_current = m_lastSeen; + emit orientationChanged(); + printf("%d\n", m_current); + } + } + +signals: + void changed(); + +private: + Orientation m_current; + Orientation m_lastSeen; + int m_lastSeenCount; + + Orientation get() + { + Orientation o = UnknownOrientation; + + int ax, ay, az; + + read(&ax, &ay, &az); + + if (abs(az) > 850) { + o = UnknownOrientation; + } else if (ax < -750) { + o = Portrait; + } else if (ay < -750) { + o = Landscape; + } + + return o; + } + + int read(int *ax,int *ay,int *az) + { + static const char *accel_filename = "/sys/class/i2c-adapter/i2c-3/3-001d/coord"; + + FILE *fd; + int rs; + fd = fopen(accel_filename, "r"); + if(fd==NULL){ printf("liqaccel, cannot open for reading\n"); return -1;} + rs=fscanf((FILE*) fd,"%i %i %i",ax,ay,az); + fclose(fd); + if(rs != 3){ printf("liqaccel, cannot read information\n"); return -2;} + return 0; + } +}; + + +DeviceOrientation* DeviceOrientation::instance() +{ + static MaemoOrientation *o = 0; + if (!o) + o = new MaemoOrientation; + return o; +} + +#include "deviceorientation_maemo.moc" diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp new file mode 100644 index 0000000..b7a3f1a --- /dev/null +++ b/tools/qmlviewer/main.cpp @@ -0,0 +1,344 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qml.h" +#include "qmlviewer.h" +#include <QWidget> +#include <QDir> +#include <QApplication> +#include <QTranslator> +#include <QDebug> + +#if defined (Q_OS_SYMBIAN) +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +void myMessageOutput(QtMsgType type, const char *msg) +{ + static int fd = -1; + if (fd == -1) + fd = ::open("E:\\qmlviewer.log", O_WRONLY | O_CREAT); + + ::write(fd, msg, strlen(msg)); + ::write(fd, "\n", 1); + ::fsync(fd); + + switch (type) { + case QtFatalMsg: + abort(); + } +} +#endif + +void usage() +{ + qWarning("Usage: qmlviewer [options] <filename>"); + qWarning(" "); + qWarning(" options:"); + qWarning(" -v, -version ............................. display version"); + qWarning(" -frameless ............................... run with no window frame"); + qWarning(" -maximized................................ run maximized"); + qWarning(" -fullscreen............................... run fullscreen"); + qWarning(" -stayontop................................ keep viewer window on top"); + qWarning(" -skin <qvfbskindir> ...................... run with a skin window frame"); + qWarning(" \"list\" for a list of built-ins"); + qWarning(" -resizeview .............................. resize the view, not the skin"); + qWarning(" -qmlbrowser .............................. use a QML-based file browser"); + qWarning(" -recordfile <output> ..................... set video recording file"); + qWarning(" - ImageMagick 'convert' for GIF)"); + qWarning(" - png file for raw frames"); + qWarning(" - 'ffmpeg' for other formats"); + qWarning(" -recorddither ordered|threshold|floyd .... set GIF dither recording mode"); + qWarning(" -recordrate <fps> ........................ set recording frame rate"); + qWarning(" -record arg .............................. add a recording process argument"); + qWarning(" -autorecord [from-]<tomilliseconds> ...... set recording to start and stop"); + qWarning(" -devicekeys .............................. use numeric keys (see F1)"); + qWarning(" -netcache <size> ......................... set disk cache to size bytes"); + qWarning(" -translation <translationfile> ........... set the language to run in"); + qWarning(" -L <directory> ........................... prepend to the library search path"); + qWarning(" -opengl .................................. use a QGLWidget for the viewport"); + qWarning(" -script <path> ........................... set the script to use"); + qWarning(" -scriptopts <options>|help ............... set the script options to use"); + + qWarning(" "); + qWarning(" Press F1 for interactive help"); + exit(1); +} + +void scriptOptsUsage() +{ + qWarning("Usage: qmlviewer -scriptopts <option>[,<option>...] ..."); + qWarning(" options:"); + qWarning(" record ................................... record a new script"); + qWarning(" play ..................................... playback an existing script"); + qWarning(" testimages ............................... record images or compare images on playback"); + qWarning(" testerror ................................ test 'error' property of root item on playback"); + qWarning(" exitoncomplete ........................... cleanly exit the viewer on script completion"); + qWarning(" exitonfailure ............................ immediately exit the viewer on script failure"); + qWarning(" saveonexit ............................... save recording on viewer exit"); + qWarning(" "); + qWarning(" One of record, play or both must be specified."); + exit(1); +} + +int main(int argc, char ** argv) +{ +#if defined (Q_OS_SYMBIAN) + qInstallMsgHandler(myMessageOutput); +#endif + +#if defined (Q_WS_X11) + //### 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") { + gsSpecified = true; + break; + } + } + + if (!gsSpecified) + QApplication::setGraphicsSystem("raster"); +#endif + + QApplication app(argc, argv); + app.setApplicationName("viewer"); + app.setOrganizationName("Nokia"); + app.setOrganizationDomain("nokia.com"); + + bool frameless = false; + bool resizeview = false; + QString fileName; + double fps = 0; + int autorecord_from = 0; + int autorecord_to = 0; + QString dither = "none"; + QString recordfile; + QStringList recordargs; + QStringList libraries; + QString skin; + QString script; + QString scriptopts; + bool runScript = false; + bool devkeys = false; + int cache = 0; + QString translationFile; + bool useGL = false; + bool fullScreen = false; + bool stayOnTop = false; + bool maximized = false; + bool useNativeFileBrowser = true; + +#if defined(Q_OS_SYMBIAN) + maximized = true; + useNativeFileBrowser = false; +#endif + + for (int i = 1; i < argc; ++i) { + bool lastArg = (i == argc - 1); + QString arg = argv[i]; + if (arg == "-frameless") { + frameless = true; + } else if (arg == "-maximized") { + maximized = true; + } else if (arg == "-fullscreen") { + fullScreen = true; + } else if (arg == "-stayontop") { + stayOnTop = true; + } else if (arg == "-skin") { + if (lastArg) usage(); + skin = QString(argv[++i]); + } else if (arg == "-resizeview") { + resizeview = true; + } else if (arg == "-netcache") { + if (lastArg) usage(); + cache = QString(argv[++i]).toInt(); + } else if (arg == "-recordrate") { + if (lastArg) usage(); + fps = QString(argv[++i]).toDouble(); + } else if (arg == "-recordfile") { + if (lastArg) usage(); + recordfile = QString(argv[++i]); + } else if (arg == "-record") { + if (lastArg) usage(); + recordargs << QString(argv[++i]); + } else if (arg == "-recorddither") { + if (lastArg) usage(); + dither = QString(argv[++i]); + } else if (arg == "-autorecord") { + if (lastArg) usage(); + QString range = QString(argv[++i]); + int dash = range.indexOf('-'); + if (dash > 0) + autorecord_from = range.left(dash).toInt(); + autorecord_to = range.mid(dash+1).toInt(); + } else if (arg == "-devicekeys") { + devkeys = true; + } else if (arg == QLatin1String("-v") || arg == QLatin1String("-version")) { + fprintf(stderr, "Qt Declarative UI Viewer version %s\n", QT_VERSION_STR); + return 0; + } else if (arg == "-translation") { + if (lastArg) usage(); + translationFile = argv[++i]; + } else if (arg == "-opengl") { + useGL = true; + } else if (arg == "-qmlbrowser") { + useNativeFileBrowser = false; + } else if (arg == "-L") { + if (lastArg) usage(); + libraries << QString(argv[++i]); + } else if (arg == "-script") { + if (lastArg) usage(); + script = QString(argv[++i]); + } else if (arg == "-scriptopts") { + if (lastArg) usage(); + scriptopts = QString(argv[++i]); + } else if (arg == "-savescript") { + if (lastArg) usage(); + script = QString(argv[++i]); + runScript = false; + } else if (arg == "-playscript") { + if (lastArg) usage(); + script = QString(argv[++i]); + runScript = true; + } else if (arg[0] != '-') { + fileName = arg; + } else if (1 || arg == "-help") { + usage(); + } + } + + QTranslator qmlTranslator; + if (!translationFile.isEmpty()) { + qmlTranslator.load(translationFile); + app.installTranslator(&qmlTranslator); + } + + Qt::WFlags wflags = (frameless ? Qt::FramelessWindowHint : Qt::Widget); + if (stayOnTop) + wflags |= Qt::WindowStaysOnTopHint; + + QmlViewer viewer(0, wflags); + if (!scriptopts.isEmpty()) { + QStringList options = + scriptopts.split(QLatin1Char(','), QString::SkipEmptyParts); + + QmlViewer::ScriptOptions scriptOptions = 0; + for (int i = 0; i < options.count(); ++i) { + const QString &option = options.at(i); + if (option == QLatin1String("help")) { + scriptOptsUsage(); + } else if (option == QLatin1String("play")) { + scriptOptions |= QmlViewer::Play; + } else if (option == QLatin1String("record")) { + scriptOptions |= QmlViewer::Record; + } else if (option == QLatin1String("testimages")) { + scriptOptions |= QmlViewer::TestImages; + } else if (option == QLatin1String("testerror")) { + scriptOptions |= QmlViewer::TestErrorProperty; + } else if (option == QLatin1String("exitoncomplete")) { + scriptOptions |= QmlViewer::ExitOnComplete; + } else if (option == QLatin1String("exitonfailure")) { + scriptOptions |= QmlViewer::ExitOnFailure; + } else if (option == QLatin1String("saveonexit")) { + scriptOptions |= QmlViewer::SaveOnExit; + } else { + scriptOptsUsage(); + } + } + + if (script.isEmpty()) + usage(); + + if (!(scriptOptions & QmlViewer::Record) && !(scriptOptions & QmlViewer::Play)) + scriptOptsUsage(); + viewer.setScriptOptions(scriptOptions); + viewer.setScript(script); + } else if (!script.isEmpty()) { + usage(); + } + + foreach (QString lib, libraries) + viewer.addLibraryPath(lib); + viewer.setNetworkCacheSize(cache); + viewer.setRecordFile(recordfile); + if (resizeview) + viewer.setScaleView(); + if (fps>0) + viewer.setRecordRate(fps); + if (autorecord_to) + viewer.setAutoRecord(autorecord_from,autorecord_to); + if (!skin.isEmpty()) { + if (skin == "list") { + foreach (QString s, viewer.builtinSkins()) + qWarning(s.toUtf8()); + exit(0); + } else { + viewer.setSkin(skin); + } + } + if (devkeys) + viewer.setDeviceKeys(true); + viewer.setRecordDither(dither); + if (recordargs.count()) + viewer.setRecordArgs(recordargs); + + viewer.setUseNativeFileBrowser(useNativeFileBrowser); + if (fullScreen && maximized) + qWarning() << "Both -fullscreen and -maximized specified. Using -fullscreen."; + if (!fileName.isEmpty()) { + viewer.open(fileName); + fullScreen ? viewer.showFullScreen() : maximized ? viewer.showMaximized() : viewer.show(); + } else { + if (!useNativeFileBrowser) + viewer.openFile(); + fullScreen ? viewer.showFullScreen() : maximized ? viewer.showMaximized() : viewer.show(); + if (useNativeFileBrowser) + viewer.openFile(); + } + viewer.setUseGL(useGL); + viewer.raise(); + + return app.exec(); +} diff --git a/tools/qmlviewer/proxysettings.cpp b/tools/qmlviewer/proxysettings.cpp new file mode 100644 index 0000000..52fa74f --- /dev/null +++ b/tools/qmlviewer/proxysettings.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QIntValidator> +#include <QSettings> + +#include "proxysettings.h" + +ProxySettings::ProxySettings (QWidget * parent) + : QDialog (parent), Ui::ProxySettings() +{ + setupUi (this); + + proxyServerEdit->setInputMask ("000.000.000.000;_"); + QIntValidator *validator = new QIntValidator (0, 9999, this); + 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 ()); +} + +ProxySettings::~ProxySettings() +{ +} + +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 ()); + + QDialog::accept (); +} + +QNetworkProxy ProxySettings::httpProxy () +{ + QSettings settings; + QNetworkProxy proxy; + + bool proxyInUse = settings.value ("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 ()); + //QNetworkProxy::setApplicationProxy (proxy); + } + else { + proxy.setType (QNetworkProxy::NoProxy); + } + return proxy; +} + +bool ProxySettings::httpProxyInUse() +{ + QSettings settings; + return settings.value ("http_proxy/use", 0).toBool (); +} diff --git a/tools/qmlviewer/proxysettings.h b/tools/qmlviewer/proxysettings.h new file mode 100644 index 0000000..b2f3e25 --- /dev/null +++ b/tools/qmlviewer/proxysettings.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROXYSETTINGS_H +#define PROXYSETTINGS_H + +#include <QDialog> +#include <QNetworkProxy> +#include "ui_proxysettings.h" + +/** +*/ +class ProxySettings : public QDialog, public Ui::ProxySettings +{ + +Q_OBJECT + +public: + ProxySettings(QWidget * parent = 0); + + ~ProxySettings(); + + static QNetworkProxy httpProxy (); + static bool httpProxyInUse (); + +public slots: + virtual void accept (); +}; + +#endif // PROXYSETTINGS_H diff --git a/tools/qmlviewer/proxysettings.ui b/tools/qmlviewer/proxysettings.ui new file mode 100644 index 0000000..84e39fe --- /dev/null +++ b/tools/qmlviewer/proxysettings.ui @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ProxySettings</class> + <widget class="QDialog" name="ProxySettings"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>318</width> + <height>199</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <widget class="QCheckBox" name="proxyCheckBox"> + <property name="text"> + <string>Use http proxy</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="serverAddressLabel"> + <property name="text"> + <string>Server Address:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="proxyServerEdit"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Port:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="proxyPortEdit"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="usernameLabel"> + <property name="text"> + <string>Username:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="usernameEdit"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="passwordLabel"> + <property name="text"> + <string>Password:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="passwordEdit"> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="5" column="0" colspan="2"> + <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>ProxySettings</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ProxySettings</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/qmlviewer/qfxtester.cpp b/tools/qmlviewer/qfxtester.cpp new file mode 100644 index 0000000..bd96545 --- /dev/null +++ b/tools/qmlviewer/qfxtester.cpp @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qfxtester.h> +#include <QDebug> +#include <QApplication> +#include <qmlview.h> +#include <QFile> +#include <QmlComponent> +#include <QDir> +#include <QCryptographicHash> +#include <private/qabstractanimation_p.h> +#include <private/qmlgraphicsitem_p.h> + +QT_BEGIN_NAMESPACE + +QML_DEFINE_TYPE(Qt.VisualTest, 4,6, VisualTest, QmlGraphicsVisualTest); +QML_DEFINE_TYPE(Qt.VisualTest, 4,6, Frame, QmlGraphicsVisualTestFrame); +QML_DEFINE_TYPE(Qt.VisualTest, 4,6, Mouse, QmlGraphicsVisualTestMouse); +QML_DEFINE_TYPE(Qt.VisualTest, 4,6, Key, QmlGraphicsVisualTestKey); + +QmlGraphicsTester::QmlGraphicsTester(const QString &script, QmlViewer::ScriptOptions opts, + QmlView *parent) +: QAbstractAnimation(parent), m_script(script), m_view(parent), filterEvents(true), options(opts), + testscript(0), hasCompleted(false), hasFailed(false) +{ + parent->viewport()->installEventFilter(this); + parent->installEventFilter(this); + QUnifiedTimer::instance()->setConsistentTiming(true); + if (options & QmlViewer::Play) + this->run(); + start(); +} + +QmlGraphicsTester::~QmlGraphicsTester() +{ + if (!hasFailed && + options & QmlViewer::Record && + options & QmlViewer::SaveOnExit) + save(); +} + +int QmlGraphicsTester::duration() const +{ + return -1; +} + +void QmlGraphicsTester::addMouseEvent(Destination dest, QMouseEvent *me) +{ + MouseEvent e(me); + e.destination = dest; + m_mouseEvents << e; +} + +void QmlGraphicsTester::addKeyEvent(Destination dest, QKeyEvent *ke) +{ + KeyEvent e(ke); + e.destination = dest; + m_keyEvents << e; +} + +bool QmlGraphicsTester::eventFilter(QObject *o, QEvent *e) +{ + if (!filterEvents) + return false; + + Destination destination; + if (o == m_view) { + destination = View; + } else if (o == m_view->viewport()) { + destination = ViewPort; + } else { + return false; + } + + switch (e->type()) { + case QEvent::KeyPress: + case QEvent::KeyRelease: + addKeyEvent(destination, (QKeyEvent *)e); + return true; + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + case QEvent::MouseButtonDblClick: + addMouseEvent(destination, (QMouseEvent *)e); + return true; + default: + break; + } + return false; +} + +void QmlGraphicsTester::executefailure() +{ + hasFailed = true; + + if (options & QmlViewer::ExitOnFailure) + exit(-1); +} + +void QmlGraphicsTester::imagefailure() +{ + hasFailed = true; + + if (options & QmlViewer::ExitOnFailure) + exit(-1); +} + +void QmlGraphicsTester::complete() +{ + if ((options & QmlViewer::TestErrorProperty) && !hasFailed) { + QString e = m_view->root()->property("error").toString(); + if (!e.isEmpty()) { + qWarning() << "Test failed:" << e; + hasFailed = true; + } + } + if (options & QmlViewer::ExitOnComplete) + QApplication::exit(hasFailed?-1:0); + + if (hasCompleted) + return; + hasCompleted = true; + + if (options & QmlViewer::Play) + qWarning("Script playback complete"); +} + +void QmlGraphicsTester::run() +{ + QmlComponent c(m_view->engine(), m_script + QLatin1String(".qml")); + + testscript = qobject_cast<QmlGraphicsVisualTest *>(c.create()); + if (testscript) testscript->setParent(this); + else { executefailure(); exit(-1); } + testscriptidx = 0; +} + +void QmlGraphicsTester::save() +{ + QString filename = m_script + QLatin1String(".qml"); + QFileInfo filenameInfo(filename); + QDir saveDir = filenameInfo.absoluteDir(); + saveDir.mkpath("."); + + QFile file(filename); + file.open(QIODevice::WriteOnly); + QTextStream ts(&file); + + ts << "import Qt.VisualTest 4.6\n\n"; + ts << "VisualTest {\n"; + + int imgCount = 0; + QList<KeyEvent> keyevents = m_savedKeyEvents; + QList<MouseEvent> mouseevents = m_savedMouseEvents; + for (int ii = 0; ii < m_savedFrameEvents.count(); ++ii) { + const FrameEvent &fe = m_savedFrameEvents.at(ii); + ts << " Frame {\n"; + ts << " msec: " << fe.msec << "\n"; + 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"); + imgCount++; + ts << " image: \"" << filename << "\"\n"; + } + ts << " }\n"; + + while (!mouseevents.isEmpty() && + mouseevents.first().msec == fe.msec) { + MouseEvent me = mouseevents.takeFirst(); + + ts << " Mouse {\n"; + ts << " type: " << me.type << "\n"; + ts << " button: " << me.button << "\n"; + ts << " buttons: " << me.buttons << "\n"; + ts << " x: " << me.pos.x() << "; y: " << me.pos.y() << "\n"; + ts << " modifiers: " << me.modifiers << "\n"; + if (me.destination == ViewPort) + ts << " sendToViewport: true\n"; + ts << " }\n"; + } + + while (!keyevents.isEmpty() && + keyevents.first().msec == fe.msec) { + KeyEvent ke = keyevents.takeFirst(); + + ts << " Key {\n"; + ts << " type: " << ke.type << "\n"; + ts << " key: " << ke.key << "\n"; + ts << " modifiers: " << ke.modifiers << "\n"; + ts << " text: \"" << ke.text.toUtf8().toHex() << "\"\n"; + ts << " autorep: " << (ke.autorep?"true":"false") << "\n"; + ts << " count: " << ke.count << "\n"; + if (ke.destination == ViewPort) + ts << " sendToViewport: true\n"; + ts << " }\n"; + } + } + + ts << "}\n"; + file.close(); +} + +void QmlGraphicsTester::updateCurrentTime(int msec) +{ + QmlGraphicsItemPrivate::setConsistentTime(msec); + + QImage img(m_view->width(), m_view->height(), QImage::Format_RGB32); + + if (options & QmlViewer::TestImages) { + img.fill(qRgb(255,255,255)); + QPainter p(&img); + m_view->render(&p); + } + + FrameEvent fe; + fe.msec = msec; + if (msec == 0 || !(options & QmlViewer::TestImages)) { + // Skip first frame, skip if not doing images + } else if (0 == (m_savedFrameEvents.count() % 60)) { + fe.image = img; + } else { + QCryptographicHash hash(QCryptographicHash::Md5); + hash.addData((const char *)img.bits(), img.bytesPerLine() * img.height()); + fe.hash = hash.result(); + } + m_savedFrameEvents.append(fe); + + // Deliver mouse events + filterEvents = false; + + if (!testscript) { + for (int ii = 0; ii < m_mouseEvents.count(); ++ii) { + MouseEvent &me = m_mouseEvents[ii]; + me.msec = msec; + QMouseEvent event(me.type, me.pos, me.button, me.buttons, me.modifiers); + + if (me.destination == View) { + QCoreApplication::sendEvent(m_view, &event); + } else { + QCoreApplication::sendEvent(m_view->viewport(), &event); + } + } + + for (int ii = 0; ii < m_keyEvents.count(); ++ii) { + KeyEvent &ke = m_keyEvents[ii]; + ke.msec = msec; + QKeyEvent event(ke.type, ke.key, ke.modifiers, ke.text, ke.autorep, ke.count); + + if (ke.destination == View) { + QCoreApplication::sendEvent(m_view, &event); + } else { + QCoreApplication::sendEvent(m_view->viewport(), &event); + } + } + m_savedMouseEvents.append(m_mouseEvents); + m_savedKeyEvents.append(m_keyEvents); + } + + m_mouseEvents.clear(); + m_keyEvents.clear(); + + // Advance test script + static int imgCount = 0; + while (testscript && testscript->count() > testscriptidx) { + + QObject *event = testscript->event(testscriptidx); + + if (QmlGraphicsVisualTestFrame *frame = qobject_cast<QmlGraphicsVisualTestFrame *>(event)) { + if (frame->msec() < msec) { + if (options & QmlViewer::TestImages && !(options & QmlViewer::Record)) { + qWarning() << "QmlGraphicsTester: Extra frame. Seen:" + << msec << "Expected:" << frame->msec(); + imagefailure(); + } + } else if (frame->msec() == msec) { + if (!frame->hash().isEmpty() && frame->hash().toUtf8() != fe.hash.toHex()) { + if (options & QmlViewer::TestImages && !(options & QmlViewer::Record)) { + qWarning() << "QmlGraphicsTester: Mismatched frame hash. Seen:" + << fe.hash.toHex() << "Expected:" + << frame->hash().toUtf8(); + imagefailure(); + } + } + } else if (frame->msec() > msec) { + break; + } + + if (options & QmlViewer::TestImages && !(options & QmlViewer::Record) && !frame->image().isEmpty()) { + QImage goodImage(frame->image().toLocalFile()); + if (goodImage != img) { + QString reject(frame->image().toLocalFile() + ".reject.png"); + qWarning() << "QmlGraphicsTester: Image mismatch. Reject saved to:" + << reject; + img.save(reject); + imagefailure(); + } + } + } else if (QmlGraphicsVisualTestMouse *mouse = qobject_cast<QmlGraphicsVisualTestMouse *>(event)) { + QPoint pos(mouse->x(), mouse->y()); + QPoint globalPos = m_view->mapToGlobal(QPoint(0, 0)) + pos; + QMouseEvent event((QEvent::Type)mouse->type(), pos, globalPos, (Qt::MouseButton)mouse->button(), (Qt::MouseButtons)mouse->buttons(), (Qt::KeyboardModifiers)mouse->modifiers()); + + MouseEvent me(&event); + me.msec = msec; + if (!mouse->sendToViewport()) { + QCoreApplication::sendEvent(m_view, &event); + me.destination = View; + } else { + QCoreApplication::sendEvent(m_view->viewport(), &event); + me.destination = ViewPort; + } + m_savedMouseEvents.append(me); + } else if (QmlGraphicsVisualTestKey *key = qobject_cast<QmlGraphicsVisualTestKey *>(event)) { + + QKeyEvent event((QEvent::Type)key->type(), key->key(), (Qt::KeyboardModifiers)key->modifiers(), QString::fromUtf8(QByteArray::fromHex(key->text().toUtf8())), key->autorep(), key->count()); + + KeyEvent ke(&event); + ke.msec = msec; + if (!key->sendToViewport()) { + QCoreApplication::sendEvent(m_view, &event); + ke.destination = View; + } else { + QCoreApplication::sendEvent(m_view->viewport(), &event); + ke.destination = ViewPort; + } + m_savedKeyEvents.append(ke); + } + testscriptidx++; + } + + filterEvents = true; + + if (testscript && testscript->count() <= testscriptidx) + complete(); +} + +QT_END_NAMESPACE diff --git a/tools/qmlviewer/qfxtester.h b/tools/qmlviewer/qfxtester.h new file mode 100644 index 0000000..303ac3a --- /dev/null +++ b/tools/qmlviewer/qfxtester.h @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXTESTER_H +#define QFXTESTER_H + +#include <QEvent> +#include <QMouseEvent> +#include <QKeyEvent> +#include <qmlviewer.h> + +QT_BEGIN_NAMESPACE + +class QmlGraphicsVisualTest : public QObject +{ + Q_OBJECT + Q_PROPERTY(QList<QObject *>* events READ events CONSTANT) + Q_CLASSINFO("DefaultProperty", "events") +public: + QmlGraphicsVisualTest() {} + + QList<QObject *> *events() { return &m_events; } + + int count() const { return m_events.count(); } + QObject *event(int idx) { return m_events.at(idx); } + +private: + QList<QObject *> m_events; +}; +QML_DECLARE_TYPE(QmlGraphicsVisualTest) + +class QmlGraphicsVisualTestFrame : public QObject +{ + Q_OBJECT + Q_PROPERTY(int msec READ msec WRITE setMsec) + Q_PROPERTY(QString hash READ hash WRITE setHash) + Q_PROPERTY(QUrl image READ image WRITE setImage) +public: + QmlGraphicsVisualTestFrame() : m_msec(-1) {} + + int msec() const { return m_msec; } + void setMsec(int m) { m_msec = m; } + + QString hash() const { return m_hash; } + void setHash(const QString &hash) { m_hash = hash; } + + QUrl image() const { return m_image; } + void setImage(const QUrl &image) { m_image = image; } + +private: + int m_msec; + QString m_hash; + QUrl m_image; +}; +QML_DECLARE_TYPE(QmlGraphicsVisualTestFrame) + +class QmlGraphicsVisualTestMouse : public QObject +{ + Q_OBJECT + Q_PROPERTY(int type READ type WRITE setType) + Q_PROPERTY(int button READ button WRITE setButton) + Q_PROPERTY(int buttons READ buttons WRITE setButtons) + Q_PROPERTY(int x READ x WRITE setX) + Q_PROPERTY(int y READ y WRITE setY) + Q_PROPERTY(int modifiers READ modifiers WRITE setModifiers) + Q_PROPERTY(bool sendToViewport READ sendToViewport WRITE setSendToViewport) +public: + QmlGraphicsVisualTestMouse() : m_type(0), m_button(0), m_buttons(0), m_x(0), m_y(0), m_modifiers(0), m_viewport(false) {} + + int type() const { return m_type; } + void setType(int t) { m_type = t; } + + int button() const { return m_button; } + void setButton(int b) { m_button = b; } + + int buttons() const { return m_buttons; } + void setButtons(int b) { m_buttons = b; } + + int x() const { return m_x; } + void setX(int x) { m_x = x; } + + int y() const { return m_y; } + void setY(int y) { m_y = y; } + + int modifiers() const { return m_modifiers; } + void setModifiers(int modifiers) { m_modifiers = modifiers; } + + bool sendToViewport() const { return m_viewport; } + void setSendToViewport(bool v) { m_viewport = v; } +private: + int m_type; + int m_button; + int m_buttons; + int m_x; + int m_y; + int m_modifiers; + bool m_viewport; +}; +QML_DECLARE_TYPE(QmlGraphicsVisualTestMouse) + +class QmlGraphicsVisualTestKey : public QObject +{ + Q_OBJECT + Q_PROPERTY(int type READ type WRITE setType) + Q_PROPERTY(int key READ key WRITE setKey) + Q_PROPERTY(int modifiers READ modifiers WRITE setModifiers) + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(bool autorep READ autorep WRITE setAutorep) + Q_PROPERTY(int count READ count WRITE setCount) + Q_PROPERTY(bool sendToViewport READ sendToViewport WRITE setSendToViewport) +public: + QmlGraphicsVisualTestKey() : m_type(0), m_key(0), m_modifiers(0), m_autorep(false), m_count(0), m_viewport(false) {} + + int type() const { return m_type; } + void setType(int t) { m_type = t; } + + int key() const { return m_key; } + void setKey(int k) { m_key = k; } + + int modifiers() const { return m_modifiers; } + void setModifiers(int m) { m_modifiers = m; } + + QString text() const { return m_text; } + void setText(const QString &t) { m_text = t; } + + bool autorep() const { return m_autorep; } + void setAutorep(bool a) { m_autorep = a; } + + int count() const { return m_count; } + void setCount(int c) { m_count = c; } + + bool sendToViewport() const { return m_viewport; } + void setSendToViewport(bool v) { m_viewport = v; } +private: + int m_type; + int m_key; + int m_modifiers; + QString m_text; + bool m_autorep; + int m_count; + bool m_viewport; +}; +QML_DECLARE_TYPE(QmlGraphicsVisualTestKey) + +class QmlGraphicsTester : public QAbstractAnimation +{ +public: + QmlGraphicsTester(const QString &script, QmlViewer::ScriptOptions options, QmlView *parent); + ~QmlGraphicsTester(); + + virtual int duration() const; + + void run(); + void save(); + + void executefailure(); +protected: + virtual void updateCurrentTime(int msecs); + virtual bool eventFilter(QObject *, QEvent *); + +private: + QString m_script; + + void imagefailure(); + void complete(); + + enum Destination { View, ViewPort }; + void addKeyEvent(Destination, QKeyEvent *); + void addMouseEvent(Destination, QMouseEvent *); + QmlView *m_view; + + struct MouseEvent { + MouseEvent(QMouseEvent *e) + : type(e->type()), button(e->button()), buttons(e->buttons()), + pos(e->pos()), modifiers(e->modifiers()), destination(View) {} + + QEvent::Type type; + Qt::MouseButton button; + Qt::MouseButtons buttons; + QPoint pos; + Qt::KeyboardModifiers modifiers; + Destination destination; + + int msec; + }; + struct KeyEvent { + KeyEvent(QKeyEvent *e) + : type(e->type()), key(e->key()), modifiers(e->modifiers()), text(e->text()), + autorep(e->isAutoRepeat()), count(e->count()), destination(View) {} + QEvent::Type type; + int key; + Qt::KeyboardModifiers modifiers; + QString text; + bool autorep; + ushort count; + Destination destination; + + int msec; + }; + struct FrameEvent { + QImage image; + QByteArray hash; + int msec; + }; + QList<MouseEvent> m_mouseEvents; + QList<KeyEvent> m_keyEvents; + + QList<MouseEvent> m_savedMouseEvents; + QList<KeyEvent> m_savedKeyEvents; + QList<FrameEvent> m_savedFrameEvents; + bool filterEvents; + + QmlViewer::ScriptOptions options; + int testscriptidx; + QmlGraphicsVisualTest *testscript; + + bool hasCompleted; + bool hasFailed; +}; + + +QT_END_NAMESPACE + +#endif // QFXTESTER_H diff --git a/tools/qmlviewer/qmlfolderlistmodel.cpp b/tools/qmlviewer/qmlfolderlistmodel.cpp new file mode 100644 index 0000000..35c672d --- /dev/null +++ b/tools/qmlviewer/qmlfolderlistmodel.cpp @@ -0,0 +1,416 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlfolderlistmodel.h" +#include <QDirModel> +#include <QDebug> +#include <qmlcontext.h> + +class QmlFolderListModelPrivate +{ +public: + QmlFolderListModelPrivate() + : sortField(QmlFolderListModel::Name), sortReversed(false), count(0) { + nameFilters << QLatin1String("*"); + } + + void updateSorting() { + QDir::SortFlags flags = 0; + switch(sortField) { + case QmlFolderListModel::Unsorted: + flags |= QDir::Unsorted; + break; + case QmlFolderListModel::Name: + flags |= QDir::Name; + break; + case QmlFolderListModel::Time: + flags |= QDir::Time; + break; + case QmlFolderListModel::Size: + flags |= QDir::Size; + break; + case QmlFolderListModel::Type: + flags |= QDir::Type; + break; + } + + if (sortReversed) + flags |= QDir::Reversed; + + model.setSorting(flags); + } + + QDirModel model; + QUrl folder; + QStringList nameFilters; + QModelIndex folderIndex; + QmlFolderListModel::SortField sortField; + bool sortReversed; + int count; +}; + +/*! + \qmlclass FolderListModel + \brief The FolderListModel provides a model of the contents of a folder in a filesystem. + + FolderListModel provides access to the local filesystem. The \e folder property + specifies the folder to list. + + Qt uses "/" as a universal directory separator in the same way that "/" is + used as a path separator in URLs. If you always use "/" as a directory + separator, Qt will translate your paths to conform to the underlying + operating system. + + The roles available are: + \list + \o fileName + \o filePath + \endlist + + Additionally a file entry can be differentiated from a folder entry + via the \l isFolder() method. +*/ + +QmlFolderListModel::QmlFolderListModel(QObject *parent) + : QListModelInterface(parent) +{ + d = new QmlFolderListModelPrivate; + d->model.setFilter(QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot); + connect(&d->model, SIGNAL(rowsInserted(const QModelIndex&,int,int)) + , this, SLOT(inserted(const QModelIndex&,int,int))); + connect(&d->model, SIGNAL(rowsRemoved(const QModelIndex&,int,int)) + , this, SLOT(removed(const QModelIndex&,int,int))); + connect(&d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)) + , this, SLOT(dataChanged(const QModelIndex&,const QModelIndex&))); + connect(&d->model, SIGNAL(modelReset()), this, SLOT(refresh())); + connect(&d->model, SIGNAL(layoutChanged()), this, SLOT(refresh())); +} + +QmlFolderListModel::~QmlFolderListModel() +{ + delete d; +} + +QHash<int,QVariant> QmlFolderListModel::data(int index, const QList<int> &roles) const +{ + Q_UNUSED(roles); + QHash<int,QVariant> folderData; + QModelIndex modelIndex = d->model.index(index, 0, d->folderIndex); + if (modelIndex.isValid()) { + folderData[QDirModel::FileNameRole] = d->model.data(modelIndex, QDirModel::FileNameRole); + folderData[QDirModel::FilePathRole] = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString()); + } + + return folderData; +} + +QVariant QmlFolderListModel::data(int index, int role) const +{ + QVariant rv; + QModelIndex modelIndex = d->model.index(index, 0, d->folderIndex); + if (modelIndex.isValid()) { + if (role == QDirModel::FileNameRole) + rv = d->model.data(modelIndex, QDirModel::FileNameRole); + else if (role == QDirModel::FilePathRole) + rv = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString()); + } + + return rv; +} + +int QmlFolderListModel::count() const +{ + return d->count; +} + +QList<int> QmlFolderListModel::roles() const +{ + QList<int> r; + r << QDirModel::FileNameRole; + r << QDirModel::FilePathRole; + return r; +} + +QString QmlFolderListModel::toString(int role) const +{ + switch (role) { + case QDirModel::FileNameRole: + return QLatin1String("fileName"); + case QDirModel::FilePathRole: + return QLatin1String("filePath"); + } + + return QString(); +} + +/*! + \qmlproperty string FolderListModel::folder + + The \a folder property holds the folder the model is currently providing. + + It is a URL, but must be a file: or qrc: URL (or relative to such a URL). +*/ +QUrl QmlFolderListModel::folder() const +{ + return d->folder; +} + +void QmlFolderListModel::setFolder(const QUrl &folder) +{ + if (folder == d->folder) + return; + QModelIndex index = d->model.index(folder.toLocalFile()); + if (index.isValid() && d->model.isDir(index)) { + d->folder = folder; + QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection); + emit folderChanged(); + } +} + +QUrl QmlFolderListModel::parentFolder() const +{ + QUrl r; + QString localFile = d->folder.toLocalFile(); + if (!localFile.isEmpty()) { + QDir dir(localFile); +#if defined(Q_OS_SYMBIAN) + if (dir.isRoot()) + dir.setPath(""); + else +#endif + dir.cdUp(); + r = d->folder; + r.setPath(dir.path()); + } else { + int pos = d->folder.path().lastIndexOf(QLatin1Char('/')); + if (pos == -1) + return QUrl(); + r = d->folder; + r.setPath(d->folder.path().left(pos)); + } + return r; +} + +/*! + \qmlproperty list<string> FolderListModel::nameFilters + + The \a nameFilters property contains a list of filename filters. + The filters may include the ? and * wildcards. + + The example below filters on PNG and JPEG files: + + \code + FolderListModel { + nameFilters: [ "*.png", "*.jpg" ] + } + \endcode +*/ +QStringList QmlFolderListModel::nameFilters() const +{ + return d->nameFilters; +} + +void QmlFolderListModel::setNameFilters(const QStringList &filters) +{ + d->nameFilters = filters; + d->model.setNameFilters(d->nameFilters); +} + +void QmlFolderListModel::componentComplete() +{ + if (!d->folder.isValid() || !QDir().exists(d->folder.toLocalFile())) + setFolder(QUrl(QLatin1String("file://")+QDir::currentPath())); + + if (!d->folderIndex.isValid()) + QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection); +} + +QmlFolderListModel::SortField QmlFolderListModel::sortField() const +{ + return d->sortField; +} + +void QmlFolderListModel::setSortField(SortField field) +{ + if (field != d->sortField) { + d->sortField = field; + d->updateSorting(); + } +} + +bool QmlFolderListModel::sortReversed() const +{ + return d->sortReversed; +} + +void QmlFolderListModel::setSortReversed(bool rev) +{ + if (rev != d->sortReversed) { + d->sortReversed = rev; + d->updateSorting(); + } +} + +/*! + \qmlmethod bool FolderListModel::isFolder(int index) + + Returns true if the entry \a index is a folder; otherwise + returns false. +*/ +bool QmlFolderListModel::isFolder(int index) const +{ + if (index != -1) { + QModelIndex idx = d->model.index(index, 0, d->folderIndex); + if (idx.isValid()) + return d->model.isDir(idx); + } + return false; +} + +void QmlFolderListModel::refresh() +{ + d->folderIndex = QModelIndex(); + if (d->count) { + int tmpCount = d->count; + d->count = 0; + emit itemsRemoved(0, tmpCount); + } + d->folderIndex = d->model.index(d->folder.toLocalFile()); + d->count = d->model.rowCount(d->folderIndex); + if (d->count) { + emit itemsInserted(0, d->count); + } +} + +void QmlFolderListModel::inserted(const QModelIndex &index, int start, int end) +{ + if (index == d->folderIndex) { + d->count = d->model.rowCount(d->folderIndex); + emit itemsInserted(start, end - start + 1); + } +} + +void QmlFolderListModel::removed(const QModelIndex &index, int start, int end) +{ + if (index == d->folderIndex) { + d->count = d->model.rowCount(d->folderIndex); + emit itemsRemoved(start, end - start + 1); + } +} + +void QmlFolderListModel::dataChanged(const QModelIndex &start, const QModelIndex &end) +{ + qDebug() << "data changed"; + if (start.parent() == d->folderIndex) + emit itemsChanged(start.row(), end.row() - start.row() + 1, roles()); +} + +/*! + \qmlproperty bool FolderListModel::showDirs + + If true (the default), directories are included in the model. + + Note that the nameFilters are ignored for directories. +*/ +bool QmlFolderListModel::showDirs() const +{ + return d->model.filter() & QDir::AllDirs; +} + +void QmlFolderListModel::setShowDirs(bool on) +{ + if (!(d->model.filter() & QDir::AllDirs) == !on) + return; + if (on) + d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives); + else + d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives)); +} + +/*! + \qmlproperty bool FolderListModel::showDotAndDotDot + + If true, the "." and ".." directories are included in the model. + + The default is false. +*/ +bool QmlFolderListModel::showDotAndDotDot() const +{ + return !(d->model.filter() & QDir::NoDotAndDotDot); +} + +void QmlFolderListModel::setShowDotAndDotDot(bool on) +{ + if (!(d->model.filter() & QDir::NoDotAndDotDot) == on) + return; + if (on) + d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot); + else + d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot); +} + +/*! + \qmlproperty bool FolderListModel::showOnlyReadable + + If true, only readable files and directories are shown. + + The default is false. +*/ +bool QmlFolderListModel::showOnlyReadable() const +{ + return d->model.filter() & QDir::Readable; +} + +void QmlFolderListModel::setShowOnlyReadable(bool on) +{ + if (!(d->model.filter() & QDir::Readable) == !on) + return; + if (on) + d->model.setFilter(d->model.filter() | QDir::Readable); + else + d->model.setFilter(d->model.filter() & ~QDir::Readable); +} + + +QML_DEFINE_TYPE(Qt,4,6,FolderListModel,QmlFolderListModel) + +QT_END_NAMESPACE + diff --git a/tools/qmlviewer/qmlfolderlistmodel.h b/tools/qmlviewer/qmlfolderlistmodel.h new file mode 100644 index 0000000..7357954 --- /dev/null +++ b/tools/qmlviewer/qmlfolderlistmodel.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLFOLDERLISTMODEL_H +#define QMLFOLDERLISTMODEL_H + +#include <qml.h> +#include "../../src/declarative/3rdparty/qlistmodelinterface_p.h" + +class QmlContext; +class QModelIndex; + +class QmlFolderListModelPrivate; +class QmlFolderListModel : public QListModelInterface, public QmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QmlParserStatus) + + Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged) + Q_PROPERTY(QUrl parentFolder READ parentFolder NOTIFY folderChanged) + Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters) + Q_PROPERTY(SortField sortField READ sortField WRITE setSortField) + Q_PROPERTY(bool sortReversed READ sortReversed WRITE setSortReversed) + Q_PROPERTY(bool showDirs READ showDirs WRITE setShowDirs) + Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot) + Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable) + +public: + QmlFolderListModel(QObject *parent = 0); + ~QmlFolderListModel(); + + virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const; + virtual QVariant data(int index, int role) const; + virtual int count() const; + virtual QList<int> roles() const; + virtual QString toString(int role) const; + + QUrl folder() const; + void setFolder(const QUrl &folder); + + QUrl parentFolder() const; + + QStringList nameFilters() const; + void setNameFilters(const QStringList &filters); + + virtual void componentComplete(); + + Q_INVOKABLE bool isFolder(int index) const; + + enum SortField { Unsorted, Name, Time, Size, Type }; + SortField sortField() const; + void setSortField(SortField field); + Q_ENUMS(SortField) + + bool sortReversed() const; + void setSortReversed(bool rev); + + bool showDirs() const; + void setShowDirs(bool); + bool showDotAndDotDot() const; + void setShowDotAndDotDot(bool); + bool showOnlyReadable() const; + void setShowOnlyReadable(bool); + +Q_SIGNALS: + void folderChanged(); + +private Q_SLOTS: + void refresh(); + void inserted(const QModelIndex &index, int start, int end); + void removed(const QModelIndex &index, int start, int end); + void dataChanged(const QModelIndex &start, const QModelIndex &end); + +private: + Q_DISABLE_COPY(QmlFolderListModel) + QmlFolderListModelPrivate *d; +}; + +QML_DECLARE_TYPE(QmlFolderListModel) + +#endif // QMLFOLDERLISTMODEL_H diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp new file mode 100644 index 0000000..1566473 --- /dev/null +++ b/tools/qmlviewer/qmlviewer.cpp @@ -0,0 +1,1455 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qmlview.h> +#include "ui_recopts.h" + +#include "qmlviewer.h" +#include <qmlcontext.h> +#include <qmlengine.h> +#include <qmlnetworkaccessmanagerfactory.h> +#include "qml.h" +#include <private/qperformancelog_p_p.h> +#include <private/qabstractanimation_p.h> +#include <QAbstractAnimation> +#include "deviceskin.h" + +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) +#include <private/qzipreader_p.h> +#endif + +#include <QSettings> +#include <QXmlStreamReader> +#include <QBuffer> +#include <QNetworkReply> +#include <QNetworkCookieJar> +#include <QNetworkDiskCache> +#include <QNetworkAccessManager> +#include <QSignalMapper> +#include <QmlComponent> +#include <QWidget> +#include <QApplication> +#include <QDir> +#include <QTextBrowser> +#include <QFile> +#include <QFileInfo> +#include <QVBoxLayout> +#include <QProgressDialog> +#include <QProcess> +#include <QMenuBar> +#include <QMenu> +#include <QAction> +#include <QFileDialog> +#include <QTimer> +#include <QNetworkProxyFactory> +#include <QKeyEvent> +#include <QMutex> +#include <QMutexLocker> +#include "proxysettings.h" +#include "deviceorientation.h" + +#ifdef GL_SUPPORTED +#include <QGLWidget> +#endif + +#include <qfxtester.h> + +#if defined (Q_OS_SYMBIAN) +#define SYMBIAN_NETWORK_INIT +#endif + +#if defined (SYMBIAN_NETWORK_INIT) +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <QTextCodec> +#include "sym_iap_util.h" +#endif + +QT_BEGIN_NAMESPACE + + +class Screen : public QObject +{ + Q_OBJECT + + Q_PROPERTY(Orientation orientation READ orientation NOTIFY orientationChanged) + Q_ENUMS(Orientation) + +public: + Screen(QObject *parent=0) : QObject(parent) { + connect(DeviceOrientation::instance(), SIGNAL(orientationChanged()), + this, SIGNAL(orientationChanged())); + } + + enum Orientation { UnknownOrientation = DeviceOrientation::UnknownOrientation, + Portrait = DeviceOrientation::Portrait, + Landscape = DeviceOrientation::Landscape }; + Orientation orientation() const { return Orientation(DeviceOrientation::instance()->orientation()); } + +signals: + void orientationChanged(); +}; + +QML_DECLARE_TYPE(Screen) +QML_DEFINE_TYPE(QmlViewer, 1, 0, Screen, Screen) + +class SizedMenuBar : public QMenuBar +{ + Q_OBJECT +public: + SizedMenuBar(QWidget *parent, QWidget *referenceWidget) + : QMenuBar(parent), refWidget(referenceWidget) + { + } + + virtual QSize sizeHint() const + { + return QSize(refWidget->sizeHint().width(), QMenuBar::sizeHint().height()); + } + +private: + QWidget *refWidget; +}; + + +class PreviewDeviceSkin : public DeviceSkin +{ + Q_OBJECT +public: + explicit PreviewDeviceSkin(const DeviceSkinParameters ¶meters, QWidget *parent); + + void setPreview(QWidget *formWidget); + void setPreviewAndScale(QWidget *formWidget); + + void setScreenSize(const QSize& size) + { + QMatrix fit; + fit = fit.scale(qreal(size.width())/m_screenSize.width(), + qreal(size.height())/m_screenSize.height()); + setTransform(fit); + QApplication::syncX(); + } + + QSize standardScreenSize() const { return m_screenSize; } + + QMenu* menu; + +private slots: + void slotSkinKeyPressEvent(int code, const QString& text, bool autorep); + void slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep); + void slotPopupMenu(); + +private: + const QSize m_screenSize; +}; + + +PreviewDeviceSkin::PreviewDeviceSkin(const DeviceSkinParameters ¶meters, QWidget *parent) : + DeviceSkin(parameters, parent), + m_screenSize(parameters.screenSize()) +{ + menu = new QMenu(this); + connect(this, SIGNAL(skinKeyPressEvent(int,QString,bool)), + this, SLOT(slotSkinKeyPressEvent(int,QString,bool))); + connect(this, SIGNAL(skinKeyReleaseEvent(int,QString,bool)), + this, SLOT(slotSkinKeyReleaseEvent(int,QString,bool))); + connect(this, SIGNAL(popupMenu()), this, SLOT(slotPopupMenu())); +} + +void PreviewDeviceSkin::setPreview(QWidget *formWidget) +{ + formWidget->setFixedSize(m_screenSize); + formWidget->setParent(this, Qt::SubWindow); + formWidget->setAutoFillBackground(true); + setView(formWidget); +} + +void PreviewDeviceSkin::setPreviewAndScale(QWidget *formWidget) +{ + setScreenSize(formWidget->sizeHint()); + formWidget->setParent(this, Qt::SubWindow); + formWidget->setAutoFillBackground(true); + setView(formWidget); +} + +void PreviewDeviceSkin::slotSkinKeyPressEvent(int code, const QString& text, bool autorep) +{ + if (QWidget *focusWidget = QApplication::focusWidget()) { + QKeyEvent e(QEvent::KeyPress,code,0,text,autorep); + QApplication::sendEvent(focusWidget, &e); + } + +} + +void PreviewDeviceSkin::slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep) +{ + if (QWidget *focusWidget = QApplication::focusWidget()) { + QKeyEvent e(QEvent::KeyRelease,code,0,text,autorep); + QApplication::sendEvent(focusWidget, &e); + } +} + +void PreviewDeviceSkin::slotPopupMenu() +{ + menu->exec(QCursor::pos()); +} + +static struct { const char *name, *args; } ffmpegprofiles[] = { + {"Maximum Quality", "-sameq"}, + {"High Quality", "-qmax 2"}, + {"Medium Quality", "-qmax 6"}, + {"Low Quality", "-qmax 16"}, + {"Custom ffmpeg arguments", ""}, + {0,0} +}; + +class RecordingDialog : public QDialog, public Ui::RecordingOptions { + Q_OBJECT + +public: + RecordingDialog(QWidget *parent) : QDialog(parent) + { + setupUi(this); + hz->setValidator(new QDoubleValidator(hz)); + for (int i=0; ffmpegprofiles[i].name; ++i) { + profile->addItem(ffmpegprofiles[i].name); + } + } + + void setArguments(QString a) + { + int i; + for (i=0; ffmpegprofiles[i].args[0]; ++i) { + if (ffmpegprofiles[i].args == a) { + profile->setCurrentIndex(i); + args->setText(QLatin1String(ffmpegprofiles[i].args)); + return; + } + } + customargs = a; + args->setText(a); + profile->setCurrentIndex(i); + } + + QString arguments() const + { + int i = profile->currentIndex(); + return ffmpegprofiles[i].args[0] ? QLatin1String(ffmpegprofiles[i].args) : customargs; + } + +private slots: + void pickProfile(int i) + { + if (ffmpegprofiles[i].args[0]) { + args->setText(QLatin1String(ffmpegprofiles[i].args)); + } else { + args->setText(customargs); + } + } + + void storeCustomArgs(QString s) + { + setArguments(s); + } + +private: + QString customargs; +}; + +class PersistentCookieJar : public QNetworkCookieJar { +public: + PersistentCookieJar(QObject *parent) : QNetworkCookieJar(parent) { load(); } + ~PersistentCookieJar() { save(); } + + virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const + { + QMutexLocker lock(&mutex); + return QNetworkCookieJar::cookiesForUrl(url); + } + + virtual bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url) + { + QMutexLocker lock(&mutex); + return QNetworkCookieJar::setCookiesFromUrl(cookieList, url); + } + +private: + void save() + { + QMutexLocker lock(&mutex); + QList<QNetworkCookie> list = allCookies(); + QByteArray data; + foreach (QNetworkCookie cookie, list) { + if (!cookie.isSessionCookie()) { + data.append(cookie.toRawForm()); + data.append("\n"); + } + } + QSettings settings("Nokia", "QtQmlViewer"); + settings.setValue("Cookies",data); + } + + void load() + { + QMutexLocker lock(&mutex); + QSettings settings("Nokia", "QtQmlViewer"); + QByteArray data = settings.value("Cookies").toByteArray(); + setAllCookies(QNetworkCookie::parseCookies(data)); + } + + mutable QMutex mutex; +}; + +class NetworkAccessManagerFactory : public QmlNetworkAccessManagerFactory +{ +public: + NetworkAccessManagerFactory() : cookieJar(0), cacheSize(0) {} + ~NetworkAccessManagerFactory() { + delete cookieJar; + } + + QNetworkAccessManager *create(QObject *parent) { + QMutexLocker lock(&mutex); + QNetworkAccessManager *manager = new QNetworkAccessManager(parent); + if (!cookieJar) + cookieJar = new PersistentCookieJar(0); + manager->setCookieJar(cookieJar); + cookieJar->setParent(0); + setupProxy(manager); + if (cacheSize > 0) { + QNetworkDiskCache *cache = new QNetworkDiskCache; + cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-duiviewer-network-cache")); + cache->setMaximumCacheSize(cacheSize); + manager->setCache(cache); + } else { + manager->setCache(0); + } + qDebug() << "created new network access manager for" << parent; + return manager; + } + + void setupProxy(QNetworkAccessManager *nam) + { + class SystemProxyFactory : public QNetworkProxyFactory + { + public: + virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query) + { + QString protocolTag = query.protocolTag(); + if (httpProxyInUse && (protocolTag == "http" || protocolTag == "https")) { + QList<QNetworkProxy> ret; + ret << httpProxy; + return ret; + } + return QNetworkProxyFactory::systemProxyForQuery(query); + } + void setHttpProxy (QNetworkProxy proxy) + { + httpProxy = proxy; + httpProxyInUse = true; + } + void unsetHttpProxy () + { + httpProxyInUse = false; + } + private: + bool httpProxyInUse; + QNetworkProxy httpProxy; + }; + + SystemProxyFactory *proxyFactory = new SystemProxyFactory; + if (ProxySettings::httpProxyInUse()) + proxyFactory->setHttpProxy(ProxySettings::httpProxy()); + else + proxyFactory->unsetHttpProxy(); + nam->setProxyFactory(proxyFactory); + } + + void setCacheSize(int size) { + if (size != cacheSize) { + cacheSize = size; + } + } + + PersistentCookieJar *cookieJar; + QMutex mutex; + int cacheSize; +}; + + +QString QmlViewer::getVideoFileName() +{ + QString title = convertAvailable || ffmpegAvailable ? tr("Save Video File") : tr("Save PNG Frames"); + QStringList types; + if (ffmpegAvailable) types += tr("Common Video files")+QLatin1String(" (*.avi *.mpeg *.mov)"); + 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(";; ")); +} + + +QmlViewer::QmlViewer(QWidget *parent, Qt::WindowFlags flags) +#if defined(Q_OS_SYMBIAN) + : QMainWindow(parent, flags) +#else + : QWidget(parent, flags) +#endif + , frame_stream(0), scaleSkin(true), mb(0) + , portraitOrientation(0), landscapeOrientation(0) + , m_scriptOptions(0), tester(0), useQmlFileBrowser(true) +{ + devicemode = false; + skin = 0; + canvas = 0; + record_autotime = 0; + record_rate = 50; + record_args += QLatin1String("-sameq"); + + recdlg = new RecordingDialog(this); + connect(recdlg->pickfile, SIGNAL(clicked()), this, SLOT(pickRecordingFile())); + senseFfmpeg(); + senseImageMagick(); + if (!ffmpegAvailable) + recdlg->ffmpegOptions->hide(); + if (!ffmpegAvailable && !convertAvailable) + recdlg->rateOptions->hide(); + QString warn; + if (!ffmpegAvailable) { + if (!convertAvailable) + warn = tr("ffmpeg and ImageMagick not available - no video output"); + else + warn = tr("ffmpeg not available - GIF and PNG outputs only"); + recdlg->warning->setText(warn); + } else { + recdlg->warning->hide(); + } + + canvas = new QmlView(this); + canvas->setAttribute(Qt::WA_OpaquePaintEvent); + canvas->setAttribute(Qt::WA_NoSystemBackground); + canvas->setContentResizable(!skin || !scaleSkin); + canvas->setFocus(); + + QObject::connect(canvas, SIGNAL(sceneResized(QSize)), this, SLOT(sceneResized(QSize))); + QObject::connect(canvas, SIGNAL(initialSize(QSize)), this, SLOT(adjustSizeSlot())); + QObject::connect(canvas, SIGNAL(errors(QList<QmlError>)), this, SLOT(executeErrors())); + QObject::connect(canvas, SIGNAL(quit()), QCoreApplication::instance (), SLOT(quit())); + + if (!(flags & Qt::FramelessWindowHint)) { + createMenu(menuBar(),0); + setPortrait(); + } + +#if !defined(Q_OS_SYMBIAN) + QVBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + setLayout(layout); + if (mb) + layout->addWidget(mb); + layout->addWidget(canvas); +#else + setCentralWidget(canvas); +#endif + + namFactory = new NetworkAccessManagerFactory; + canvas->engine()->setNetworkAccessManagerFactory(namFactory); + + connect(&autoStartTimer, SIGNAL(triggered()), this, SLOT(autoStartRecording())); + connect(&autoStopTimer, SIGNAL(triggered()), this, SLOT(autoStopRecording())); + connect(&recordTimer, SIGNAL(triggered()), this, SLOT(recordFrame())); + autoStartTimer.setRunning(false); + autoStopTimer.setRunning(false); + recordTimer.setRunning(false); + recordTimer.setRepeating(true); +} + +QmlViewer::~QmlViewer() +{ + canvas->engine()->setNetworkAccessManagerFactory(0); + delete namFactory; +} + +void QmlViewer::adjustSizeSlot() +{ + resize(sizeHint()); +} + +QMenuBar *QmlViewer::menuBar() const +{ +#if !defined(Q_OS_SYMBIAN) + if (!mb) + mb = new SizedMenuBar((QWidget*)this, canvas); +#else + mb = QMainWindow::menuBar(); +#endif + + return mb; +} + +void QmlViewer::createMenu(QMenuBar *menu, QMenu *flatmenu) +{ + QObject *parent = flatmenu ? (QObject*)flatmenu : (QObject*)menu; + + QMenu *fileMenu = flatmenu ? flatmenu : menu->addMenu(tr("&File")); + + QAction *openAction = new QAction(tr("&Open..."), parent); + openAction->setShortcut(QKeySequence("Ctrl+O")); + connect(openAction, SIGNAL(triggered()), this, SLOT(openFile())); + fileMenu->addAction(openAction); + + QAction *reloadAction = new QAction(tr("&Reload"), parent); + reloadAction->setShortcut(QKeySequence("Ctrl+R")); + connect(reloadAction, SIGNAL(triggered()), this, SLOT(reload())); + fileMenu->addAction(reloadAction); + +#if defined(Q_OS_SYMBIAN) + QAction *networkAction = new QAction(tr("Start &Network"), parent); + connect(networkAction, SIGNAL(triggered()), this, SLOT(startNetwork())); + fileMenu->addAction(networkAction); +#endif + +#if !defined(Q_OS_SYMBIAN) + if (flatmenu) flatmenu->addSeparator(); + + QMenu *recordMenu = flatmenu ? flatmenu : menu->addMenu(tr("&Recording")); + + QAction *snapshotAction = new QAction(tr("&Take Snapshot\tF3"), parent); + connect(snapshotAction, SIGNAL(triggered()), this, SLOT(takeSnapShot())); + recordMenu->addAction(snapshotAction); + + recordAction = new QAction(tr("Start Recording &Video\tF9"), parent); + connect(recordAction, SIGNAL(triggered()), this, SLOT(toggleRecordingWithSelection())); + recordMenu->addAction(recordAction); + + QAction *recordOptions = new QAction(tr("Video &Options..."), parent); + connect(recordOptions, SIGNAL(triggered()), this, SLOT(chooseRecordingOptions())); + + if (flatmenu) + flatmenu->addAction(recordOptions); + + if (flatmenu) flatmenu->addSeparator(); + + QMenu *debugMenu = flatmenu ? flatmenu->addMenu(tr("&Debugging")) : menu->addMenu(tr("&Debugging")); + + QAction *slowAction = new QAction(tr("&Slow Down Animations"), parent); + slowAction->setShortcut(QKeySequence("Ctrl+.")); + slowAction->setCheckable(true); + connect(slowAction, SIGNAL(triggered(bool)), this, SLOT(setSlowMode(bool))); + debugMenu->addAction(slowAction); + + if (flatmenu) flatmenu->addSeparator(); + + QMenu *skinMenu = flatmenu ? flatmenu->addMenu(tr("&Skin")) : menu->addMenu(tr("&Skin")); + + QActionGroup *skinActions; + QAction *skinAction; + + skinActions = new QActionGroup(parent); + skinAction = new QAction(tr("Scale skin"), parent); + skinAction->setCheckable(true); + skinAction->setChecked(scaleSkin); + skinActions->addAction(skinAction); + skinMenu->addAction(skinAction); + connect(skinAction, SIGNAL(triggered()), this, SLOT(setScaleSkin())); + skinAction = new QAction(tr("Resize view"), parent); + skinAction->setCheckable(true); + skinAction->setChecked(!scaleSkin); + skinActions->addAction(skinAction); + skinMenu->addAction(skinAction); + connect(skinAction, SIGNAL(triggered()), this, SLOT(setScaleView())); + skinMenu->addSeparator(); + + skinActions = new QActionGroup(parent); + QSignalMapper *mapper = new QSignalMapper(parent); + skinAction = new QAction(tr("None"), parent); + skinAction->setCheckable(true); + if (currentSkin.isEmpty()) + skinAction->setChecked(true); + skinActions->addAction(skinAction); + skinMenu->addAction(skinAction); + mapper->setMapping(skinAction, ""); + connect(skinAction, SIGNAL(triggered()), mapper, SLOT(map())); + skinMenu->addSeparator(); + + foreach (QString name, builtinSkins()) { + skinAction = new QAction(name, parent); + skinActions->addAction(skinAction); + skinMenu->addAction(skinAction); + skinAction->setCheckable(true); + if (":skin/"+name+".skin" == currentSkin) + skinAction->setChecked(true); + mapper->setMapping(skinAction, name); + connect(skinAction, SIGNAL(triggered()), mapper, SLOT(map())); + } + connect(mapper, SIGNAL(mapped(QString)), this, SLOT(setSkin(QString))); + + if (flatmenu) flatmenu->addSeparator(); +#endif // Q_OS_SYMBIAN + + QMenu *settingsMenu = flatmenu ? flatmenu : menu->addMenu(tr("S&ettings")); + QAction *proxyAction = new QAction(tr("Http &proxy..."), parent); + connect(proxyAction, SIGNAL(triggered()), this, SLOT(showProxySettings())); + settingsMenu->addAction(proxyAction); +#if !defined(Q_OS_SYMBIAN) + if (!flatmenu) + settingsMenu->addAction(recordOptions); +#else + QAction *fullscreenAction = new QAction(tr("Full Screen"), parent); + fullscreenAction->setCheckable(true); + connect(fullscreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen())); + settingsMenu->addAction(fullscreenAction); +#endif + + QMenu *propertiesMenu = settingsMenu->addMenu(tr("Properties")); + QActionGroup *orientation = new QActionGroup(parent); + + QAction *toggleOrientation = new QAction(tr("&Toggle Orientation"), parent); + toggleOrientation->setCheckable(true); + toggleOrientation->setShortcut(QKeySequence("Ctrl+T")); + settingsMenu->addAction(toggleOrientation); + connect(toggleOrientation, SIGNAL(triggered()), this, SLOT(toggleOrientation())); + + orientation->setExclusive(true); + portraitOrientation = new QAction(tr("orientation: Portrait"), parent); + portraitOrientation->setCheckable(true); + connect(portraitOrientation, SIGNAL(triggered()), this, SLOT(setPortrait())); + orientation->addAction(portraitOrientation); + propertiesMenu->addAction(portraitOrientation); + + landscapeOrientation = new QAction(tr("orientation: Landscape"), parent); + landscapeOrientation->setCheckable(true); + connect(landscapeOrientation, SIGNAL(triggered()), this, SLOT(setLandscape())); + orientation->addAction(landscapeOrientation); + propertiesMenu->addAction(landscapeOrientation); + + if (flatmenu) flatmenu->addSeparator(); + + QMenu *helpMenu = flatmenu ? flatmenu : menu->addMenu(tr("&Help")); + QAction *aboutAction = new QAction(tr("&About Qt..."), parent); + connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + helpMenu->addAction(aboutAction); + + QAction *quitAction = new QAction(tr("&Quit"), parent); + quitAction->setShortcut(QKeySequence("Ctrl+Q")); + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + fileMenu->addSeparator(); + fileMenu->addAction(quitAction); + if (menu) { + menu->setFixedHeight(menu->sizeHint().height()); + menu->setMinimumWidth(10); + } +} + +void QmlViewer::showProxySettings() +{ + ProxySettings settingsDlg (this); + + connect (&settingsDlg, SIGNAL (accepted()), this, SLOT (proxySettingsChanged ())); + + settingsDlg.exec(); +} + +void QmlViewer::proxySettingsChanged() +{ + reload (); +} + +void QmlViewer::setPortrait() +{ + DeviceOrientation::instance()->setOrientation(DeviceOrientation::Portrait); + portraitOrientation->setChecked(true); +} + +void QmlViewer::setLandscape() +{ + DeviceOrientation::instance()->setOrientation(DeviceOrientation::Landscape); + landscapeOrientation->setChecked(true); +} + +void QmlViewer::toggleOrientation() +{ + DeviceOrientation::instance()->setOrientation(DeviceOrientation::instance()->orientation()==DeviceOrientation::Portrait?DeviceOrientation::Landscape:DeviceOrientation::Portrait); +} + +void QmlViewer::toggleFullScreen() +{ + if (isFullScreen()) + showMaximized(); + else + showFullScreen(); +} + +void QmlViewer::setScaleSkin() +{ + if (scaleSkin) + return; + scaleSkin = true; + canvas->setContentResizable(!skin || !scaleSkin); + if (skin) { + canvas->setFixedSize(canvas->sizeHint()); + skin->setScreenSize(canvas->sizeHint()); + } +} + +void QmlViewer::setScaleView() +{ + if (!scaleSkin) + return; + scaleSkin = false; + if (skin) { + canvas->setContentResizable(!skin || !scaleSkin); + canvas->setMinimumSize(QSize(0,0)); + canvas->setMaximumSize(QSize(16777215,16777215)); + canvas->resize(skin->standardScreenSize()); + skin->setScreenSize(skin->standardScreenSize()); + } +} + + +void QmlViewer::takeSnapShot() +{ + static int snapshotcount = 1; + QString snapFileName = QString(QLatin1String("snapshot%1.png")).arg(snapshotcount); + QPixmap::grabWidget(canvas).save(snapFileName); + qDebug() << "Wrote" << snapFileName; + ++snapshotcount; +} + +void QmlViewer::pickRecordingFile() +{ + QString fileName = getVideoFileName(); + if (!fileName.isEmpty()) + recdlg->file->setText(fileName); +} + +void QmlViewer::chooseRecordingOptions() +{ + // File + recdlg->file->setText(record_file); + + // Size + recdlg->sizeOriginal->setText(tr("Original (%1x%2)").arg(canvas->width()).arg(canvas->height())); + if (recdlg->sizeWidth->value()<=1) { + recdlg->sizeWidth->setValue(canvas->width()); + recdlg->sizeHeight->setValue(canvas->height()); + } + + // Rate + if (record_rate == 24) + recdlg->hz24->setChecked(true); + else if (record_rate == 25) + recdlg->hz25->setChecked(true); + else if (record_rate == 50) + recdlg->hz50->setChecked(true); + else if (record_rate == 60) + recdlg->hz60->setChecked(true); + else { + recdlg->hzCustom->setChecked(true); + recdlg->hz->setText(QString::number(record_rate)); + } + + // Profile + recdlg->setArguments(record_args.join(" ")); + if (recdlg->exec()) { + // File + record_file = recdlg->file->text(); + // Size + if (recdlg->sizeOriginal->isChecked()) + record_outsize = QSize(); + else if (recdlg->size720p->isChecked()) + record_outsize = QSize(1280,720); + else if (recdlg->sizeVGA->isChecked()) + record_outsize = QSize(640,480); + else if (recdlg->sizeQVGA->isChecked()) + record_outsize = QSize(320,240); + else + record_outsize = QSize(recdlg->sizeWidth->value(),recdlg->sizeHeight->value()); + // Rate + if (recdlg->hz24->isChecked()) + record_rate = 24; + else if (recdlg->hz25->isChecked()) + record_rate = 25; + else if (recdlg->hz50->isChecked()) + record_rate = 50; + else if (recdlg->hz60->isChecked()) + record_rate = 60; + else { + record_rate = recdlg->hz->text().toDouble(); + } + // Profile + record_args = recdlg->arguments().split(" ",QString::SkipEmptyParts); + } +} + +void QmlViewer::toggleRecordingWithSelection() +{ + if (!recordTimer.isRunning()) { + if (record_file.isEmpty()) { + QString fileName = getVideoFileName(); + if (fileName.isEmpty()) + return; + if (!fileName.contains(QRegExp(".[^\\/]*$"))) + fileName += ".avi"; + setRecordFile(fileName); + } + } + toggleRecording(); +} + +void QmlViewer::toggleRecording() +{ + if (record_file.isEmpty()) { + toggleRecordingWithSelection(); + return; + } + bool recording = !recordTimer.isRunning(); + recordAction->setText(recording ? tr("&Stop Recording Video\tF9") : tr("&Start Recording Video\tF9")); + setRecording(recording); +} + +void QmlViewer::setSlowMode(bool enable) +{ + QUnifiedTimer::instance()->setSlowModeEnabled(enable); +} + +void QmlViewer::addLibraryPath(const QString& lib) +{ + canvas->engine()->addImportPath(lib); +} + +void QmlViewer::reload() +{ + openQml(currentFileOrUrl); +} + +void QmlViewer::open(const QString& doc) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) + if (doc.endsWith(".wgt",Qt::CaseInsensitive) + || doc.endsWith(".wgz",Qt::CaseInsensitive) + || doc.endsWith(".zip",Qt::CaseInsensitive)) + openWgt(doc); + else +#endif + openQml(doc); +} + +void QmlViewer::openWgt(const QString& doc) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) + // XXX This functionality could be migrated to QmlView once refined + + QUrl url(doc); + if (url.isRelative()) + url = QUrl::fromLocalFile(doc); + canvas->reset(); + QNetworkAccessManager * nam = canvas->engine()->networkAccessManager(); + wgtreply = nam->get(QNetworkRequest(url)); + connect(wgtreply,SIGNAL(finished()),this,SLOT(unpackWgt())); +#endif +} + +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) +static void removeRecursive(const QString& dirname) +{ + QDir dir(dirname); + QFileInfoList entries(dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot)); + for (int i = 0; i < entries.count(); ++i) + if (entries[i].isDir()) + removeRecursive(entries[i].filePath()); + else + dir.remove(entries[i].fileName()); + QDir().rmdir(dirname); +} +#endif + +void QmlViewer::unpackWgt() +{ +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) + QByteArray all = wgtreply->readAll(); + QBuffer buf(&all); + buf.open(QIODevice::ReadOnly); + QZipReader zip(&buf); + /* + for (int i=0; i<zip.count(); ++i) { + QZipReader::FileInfo info = zip.entryInfoAt(i); + qDebug() << "zip:" << info.filePath; + } + */ + wgtdir = QDir::tempPath()+QDir::separator()+QLatin1String("qmlviewer-wgt"); + removeRecursive(wgtdir); + QDir().mkpath(wgtdir); + zip.extractAll(wgtdir); + + QString rootfile; + + if (wgtreply->header(QNetworkRequest::ContentTypeHeader).toString() == "application/widget" || wgtreply->url().path().endsWith(".wgt",Qt::CaseInsensitive)) { + // W3C Draft http://www.w3.org/TR/2009/CR-widgets-20091201 + QFile configfile(wgtdir+QDir::separator()+"config.xml"); + if (configfile.open(QIODevice::ReadOnly)) { + QXmlStreamReader config(&configfile); + if (config.readNextStartElement() && config.name() == "widget") { + while (config.readNextStartElement()) { + if (config.name() == "content") { + rootfile = wgtdir + QDir::separator(); + rootfile += config.attributes().value(QLatin1String("src")); + } + // XXX process other config + + config.skipCurrentElement(); + } + } + } else { + qWarning("No config.xml found - non-standard WGT file"); + } + if (rootfile.isEmpty()) { + QString def = wgtdir+QDir::separator()+"index.qml"; + if (QFile::exists(def)) + rootfile = def; + } + } else { + // Just find index.qml, preferably at the root + for (int i=0; i<zip.count(); ++i) { + QZipReader::FileInfo info = zip.entryInfoAt(i); + if (info.filePath.compare(QLatin1String("index.qml"),Qt::CaseInsensitive)==0) + rootfile = wgtdir+QDir::separator()+info.filePath; + if (rootfile.isEmpty() && info.filePath.endsWith("/index.qml",Qt::CaseInsensitive)) + rootfile = wgtdir+QDir::separator()+info.filePath; + } + } + + openQml(rootfile); +#endif +} + +void QmlViewer::openFile() +{ + QString cur = canvas->url().toLocalFile(); + if (useQmlFileBrowser) { + openQml("qrc:/content/Browser.qml"); + } else { + QString fileName = QFileDialog::getOpenFileName(this, tr("Open QML file"), cur, tr("QML Files (*.qml)")); + if (!fileName.isEmpty()) { + QFileInfo fi(fileName); + openQml(fi.absoluteFilePath()); + } + } +} + +void QmlViewer::executeErrors() +{ + if (tester) tester->executefailure(); +} + +void QmlViewer::launch(const QString& file_or_url) +{ + QMetaObject::invokeMethod(this, "openQml", Qt::QueuedConnection, Q_ARG(QString, file_or_url)); +} + +void QmlViewer::openQml(const QString& file_or_url) +{ + currentFileOrUrl = file_or_url; + + QUrl url; + QFileInfo fi(file_or_url); + if (fi.exists()) + url = QUrl::fromLocalFile(fi.absoluteFilePath()); + else + url = QUrl(file_or_url); + setWindowTitle(tr("%1 - Qt Declarative UI Viewer").arg(file_or_url)); + + if (!m_script.isEmpty()) + tester = new QmlGraphicsTester(m_script, m_scriptOptions, canvas); + + canvas->reset(); + QmlContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("qmlViewer", this); +#ifdef Q_OS_SYMBIAN + ctxt->setContextProperty("qmlViewerFolder", "E:\\"); // Documents on your S60 phone +#else + ctxt->setContextProperty("qmlViewerFolder", QDir::currentPath()); +#endif + + QString fileName = url.toLocalFile(); + if (!fileName.isEmpty()) { + QFileInfo fi(fileName); + if (fi.exists()) { + if (fi.suffix().toLower() != QLatin1String("qml")) { + qWarning() << "qmlviewer cannot open non-QML file" << fileName; + return; + } + + QDir dir(fi.path()+"/dummydata", "*.qml"); + QStringList list = dir.entryList(); + for (int i = 0; i < list.size(); ++i) { + QString qml = list.at(i); + QFile f(dir.filePath(qml)); + f.open(QIODevice::ReadOnly); + QByteArray data = f.readAll(); + QmlComponent comp(canvas->engine()); + comp.setData(data, QUrl()); + QObject *dummyData = comp.create(); + + if(comp.isError()) { + QList<QmlError> errors = comp.errors(); + foreach (const QmlError &error, errors) { + qWarning() << error; + } + if (tester) tester->executefailure(); + } + + if (dummyData) { + qWarning() << "Loaded dummy data:" << dir.filePath(qml); + qml.truncate(qml.length()-4); + ctxt->setContextProperty(qml, dummyData); + dummyData->setParent(this); + } + } + } else { + qWarning() << "qmlviewer cannot find file:" << fileName; + return; + } + } + + canvas->setUrl(url); + + QTime t; + t.start(); + canvas->execute(); + qWarning() << "Wall startup time:" << t.elapsed(); + + if (!skin) { + canvas->updateGeometry(); + if (mb) + mb->updateGeometry(); + if (!isFullScreen() && !isMaximized()) + resize(sizeHint()); + } else { + if (scaleSkin) + canvas->resize(canvas->sizeHint()); + else { + canvas->setFixedSize(skin->standardScreenSize()); + canvas->resize(skin->standardScreenSize()); + } + } + +#ifdef QTOPIA + show(); +#endif +} + +void QmlViewer::startNetwork() +{ +#if defined(SYMBIAN_NETWORK_INIT) + qt_SetDefaultIap(); +#endif +} + +QStringList QmlViewer::builtinSkins() const +{ + QDir dir(":/skins/","*.skin"); + const QFileInfoList l = dir.entryInfoList(); + QStringList r; + for (QFileInfoList::const_iterator it = l.begin(); it != l.end(); ++it) { + r += (*it).baseName(); + } + return r; +} + +void QmlViewer::setSkin(const QString& skinDirOrName) +{ + QString skinDirectory = skinDirOrName; + + if (!QDir(skinDirOrName).exists() && QDir(":/skins/"+skinDirOrName+".skin").exists()) + skinDirectory = ":/skins/"+skinDirOrName+".skin"; + + if (currentSkin == skinDirectory) + return; + + currentSkin = skinDirectory; + + // XXX QWidget::setMask does not handle changes well, and we may + // XXX have been signalled from an item in a menu we're replacing, + // XXX hence some rather convoluted resetting here... + + QString err; + if (skin) { + skin->hide(); + skin->deleteLater(); + } + + canvas->setContentResizable(!skin || !scaleSkin); + + DeviceSkinParameters parameters; + if (!skinDirectory.isEmpty() && parameters.read(skinDirectory,DeviceSkinParameters::ReadAll,&err)) { + layout()->setEnabled(false); + //setMenuBar(0); + if (mb) + mb->hide(); + if (!err.isEmpty()) + qWarning() << err; + skin = new PreviewDeviceSkin(parameters,this); + canvas->resize(canvas->sizeHint()); + if (scaleSkin) + skin->setPreviewAndScale(canvas); + else + skin->setPreview(canvas); + createMenu(0,skin->menu); + skin->show(); + } else { + skin = 0; + clearMask(); + menuBar()->clear(); + canvas->setParent(this, Qt::SubWindow); + createMenu(menuBar(),0); + mb->show(); + setMinimumSize(QSize(0,0)); + setMaximumSize(QSize(16777215,16777215)); + canvas->setMinimumSize(QSize(0,0)); + canvas->setMaximumSize(QSize(16777215,16777215)); + QRect g = geometry(); + g.setSize(sizeHint()); + setParent(0,windowFlags()); // recreate + canvas->move(0,menuBar()->sizeHint().height()); + setGeometry(g); + layout()->setEnabled(true); + show(); + } + canvas->show(); +} + +void QmlViewer::setAutoRecord(int from, int to) +{ + if (from==0) from=1; // ensure resized + record_autotime = to-from; + autoStartTimer.setInterval(from); + autoStartTimer.setRunning(true); +} + +void QmlViewer::setRecordArgs(const QStringList& a) +{ + record_args = a; +} + +void QmlViewer::setRecordFile(const QString& f) +{ + record_file = f; +} + +void QmlViewer::setRecordRate(int fps) +{ + record_rate = fps; +} + +void QmlViewer::sceneResized(QSize size) +{ + if (size.width() > 0 && size.height() > 0) { + if (skin && scaleSkin) + skin->setScreenSize(size); + } +} + +void QmlViewer::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_0 && devicemode) + exit(0); + else if (event->key() == Qt::Key_F1 || (event->key() == Qt::Key_1 && devicemode)) { + qDebug() << "F1 - help\n" + << "F2 - save test script\n" + << "F3 - take PNG snapshot\n" + << "F4 - show items and state\n" + << "F5 - reload QML\n" + << "F6 - show object tree\n" + << "F7 - show timing\n" + << "F8 - show performance (if available)\n" + << "F9 - toggle video recording\n" + << "F10 - toggle orientation\n" + << "device keys: 0=quit, 1..8=F1..F8" + ; + } else if (event->key() == Qt::Key_F2 || (event->key() == Qt::Key_2 && devicemode)) { + if (tester && m_scriptOptions & Record) + tester->save(); + } else if (event->key() == Qt::Key_F3 || (event->key() == Qt::Key_3 && devicemode)) { + takeSnapShot(); + } else if (event->key() == Qt::Key_F5 || (event->key() == Qt::Key_5 && devicemode)) { + reload(); + } else if (event->key() == Qt::Key_F8 || (event->key() == Qt::Key_8 && devicemode)) { + QPerformanceLog::displayData(); + QPerformanceLog::clear(); + } else if (event->key() == Qt::Key_F9 || (event->key() == Qt::Key_9 && devicemode)) { + toggleRecording(); + } else if (event->key() == Qt::Key_F10) { + if (portraitOrientation) { + if (portraitOrientation->isChecked()) + setLandscape(); + else + setPortrait(); + } + } + + QWidget::keyPressEvent(event); +} + +void QmlViewer::senseImageMagick() +{ + QProcess proc; + proc.start("convert", QStringList() << "-h"); + proc.waitForFinished(2000); + QString help = proc.readAllStandardOutput(); + convertAvailable = help.contains("ImageMagick"); +} + +void QmlViewer::senseFfmpeg() +{ + QProcess proc; + proc.start("ffmpeg", QStringList() << "-h"); + proc.waitForFinished(2000); + QString ffmpegHelp = proc.readAllStandardOutput(); + ffmpegAvailable = ffmpegHelp.contains("-s "); + ffmpegHelp = tr("Video recording uses ffmpeg:")+"\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"); + b->setFont(f); + b->setText(ffmpegHelp); + l->addWidget(b); + d->setLayout(l); + ffmpegHelpWindow = d; + connect(recdlg->ffmpegHelp,SIGNAL(clicked()), ffmpegHelpWindow, SLOT(show())); +} + +void QmlViewer::setRecording(bool on) +{ + if (on == recordTimer.isRunning()) + return; + + int period = int(1000/record_rate+0.5); + QUnifiedTimer::instance()->setTimingInterval(on ? period:16); + QUnifiedTimer::instance()->setConsistentTiming(on); + if (on) { + canvas->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + recordTimer.setInterval(period); + recordTimer.setRunning(true); + frame_fmt = record_file.right(4).toLower(); + frame = QImage(canvas->width(),canvas->height(),QImage::Format_RGB32); + if (frame_fmt != ".png" && (!convertAvailable || frame_fmt != ".gif")) { + // Stream video to ffmpeg + + QProcess *proc = new QProcess(this); + connect(proc, SIGNAL(finished(int)), this, SLOT(ffmpegFinished(int))); + 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" << "-"; + 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 += record_args; + args << record_file; + proc->start("ffmpeg",args); + + } else { + // Store frames, save to GIF/PNG + frame_stream = 0; + } + } else { + canvas->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate); + recordTimer.setRunning(false); + if (frame_stream) { + qDebug() << "Saving video..."; + frame_stream->close(); + qDebug() << "Wrote" << record_file; + } else { + QProgressDialog progress(tr("Saving frames..."), tr("Cancel"), 0, frames.count()+10, this); + progress.setWindowModality(Qt::WindowModal); + + int frame=0; + QStringList inputs; + qDebug() << "Saving frames..."; + + QString framename; + bool png_output = false; + if (record_file.right(4).toLower()==".png") { + if (record_file.contains('%')) + framename = record_file; + else + framename = record_file.left(record_file.length()-4)+"%04d"+record_file.right(4); + png_output = true; + } else { + framename = "tmp-frame%04d.png"; + png_output = false; + } + foreach (QImage* img, frames) { + progress.setValue(progress.value()+1); + if (progress.wasCanceled()) + break; + QString name; + name.sprintf(framename.toLocal8Bit(),frame++); + if (record_outsize.isValid()) + *img = img->scaled(record_outsize,Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + if (record_dither=="ordered") + img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::OrderedDither).save(name); + else if (record_dither=="threshold") + img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::ThresholdDither).save(name); + else if (record_dither=="floyd") + img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither).save(name); + else + img->save(name); + inputs << name; + delete img; + } + + if (!progress.wasCanceled()) { + if (png_output) { + framename.replace(QRegExp("%\\d*."),"*"); + 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 << inputs; + args << record_file; + qDebug() << "Converting..." << record_file << "(this may take a while)"; + if (0!=QProcess::execute("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") { + qDebug() << "Compressing..." << record_file; + if (0!=QProcess::execute("gifsicle", QStringList() << "-O2" << "-o" << record_file << record_file)) + qWarning() << "Cannot run 'gifsicle' - not compressed"; + } + qDebug() << "Wrote" << record_file; + } + } + } + + progress.setValue(progress.maximum()-1); + foreach (QString name, inputs) + QFile::remove(name); + + frames.clear(); + } + } + qDebug() << "Recording: " << (recordTimer.isRunning()?"ON":"OFF"); +} + +void QmlViewer::ffmpegFinished(int code) +{ + qDebug() << "ffmpeg returned" << code << frame_stream->readAllStandardError(); +} + +void QmlViewer::autoStartRecording() +{ + setRecording(true); + autoStopTimer.setInterval(record_autotime); + autoStopTimer.setRunning(true); +} + +void QmlViewer::autoStopRecording() +{ + setRecording(false); +} + +void QmlViewer::recordFrame() +{ + canvas->QWidget::render(&frame); + if (frame_stream) { + if (frame_fmt == ".gif") { + // ffmpeg can't do 32bpp with gif + QImage rgb24 = frame.convertToFormat(QImage::Format_RGB888); + frame_stream->write((char*)rgb24.bits(),rgb24.numBytes()); + } else { + frame_stream->write((char*)frame.bits(),frame.numBytes()); + } + } else { + frames.append(new QImage(frame)); + } +} + +void QmlViewer::setDeviceKeys(bool on) +{ + devicemode = on; +} + +void QmlViewer::setNetworkCacheSize(int size) +{ + namFactory->setCacheSize(size); +} + +void QmlViewer::setUseGL(bool useGL) +{ +#ifdef GL_SUPPORTED + if (useGL) { + QGLFormat format = QGLFormat::defaultFormat(); + format.setSampleBuffers(false); + + QGLWidget *glWidget = new QGLWidget(format); + glWidget->setAutoFillBackground(false); + canvas->setViewport(glWidget); + } +#endif +} + +void QmlViewer::setUseNativeFileBrowser(bool use) +{ + useQmlFileBrowser = !use; +} + +QT_END_NAMESPACE + +#include "qmlviewer.moc" diff --git a/tools/qmlviewer/qmlviewer.h b/tools/qmlviewer/qmlviewer.h new file mode 100644 index 0000000..6b05584 --- /dev/null +++ b/tools/qmlviewer/qmlviewer.h @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLVIEWER_H +#define QMLVIEWER_H + +#include <QMainWindow> +#include <QMenuBar> +#include <private/qmltimer_p.h> +#include <QTime> +#include <QList> + +QT_BEGIN_NAMESPACE + +class QmlView; +class PreviewDeviceSkin; +class QmlGraphicsTestEngine; +class QProcess; +class RecordingDialog; +class QmlGraphicsTester; +class QNetworkReply; +class QNetworkCookieJar; +class NetworkAccessManagerFactory; + +class QmlViewer +#if defined(Q_OS_SYMBIAN) + : public QMainWindow +#else + : public QWidget +#endif +{ +Q_OBJECT +public: + QmlViewer(QWidget *parent=0, Qt::WindowFlags flags=0); + ~QmlViewer(); + + enum ScriptOption { + Play = 0x00000001, + Record = 0x00000002, + TestImages = 0x00000004, + TestErrorProperty = 0x00000008, + SaveOnExit = 0x00000010, + ExitOnComplete = 0x00000020, + ExitOnFailure = 0x00000040 + }; + Q_DECLARE_FLAGS(ScriptOptions, ScriptOption) + void setScript(const QString &s) { m_script = s; } + void setScriptOptions(ScriptOptions opt) { m_scriptOptions = opt; } + void setRecordDither(const QString& s) { record_dither = s; } + void setRecordRate(int fps); + void setRecordFile(const QString&); + void setRecordArgs(const QStringList&); + void setRecording(bool on); + bool isRecording() const { return recordTimer.isRunning(); } + void setAutoRecord(int from, int to); + void setDeviceKeys(bool); + void setNetworkCacheSize(int size); + void addLibraryPath(const QString& lib); + void setUseGL(bool use); + void setUseNativeFileBrowser(bool); + + QStringList builtinSkins() const; + + QMenuBar *menuBar() const; + +public slots: + void sceneResized(QSize size); + void open(const QString&); + void openWgt(const QString&); + void openQml(const QString&); + void openFile(); + void reload(); + void takeSnapShot(); + void toggleRecording(); + void toggleRecordingWithSelection(); + void ffmpegFinished(int code); + void setSkin(const QString& skinDirectory); + void showProxySettings (); + void proxySettingsChanged (); + void setScaleView(); + void executeErrors(); + void setSlowMode(bool); + void launch(const QString &); + +protected: + virtual void keyPressEvent(QKeyEvent *); + + void createMenu(QMenuBar *menu, QMenu *flatmenu); + +private slots: + void autoStartRecording(); + void autoStopRecording(); + void recordFrame(); + void chooseRecordingOptions(); + void pickRecordingFile(); + void setScaleSkin(); + void adjustSizeSlot(); + void setPortrait(); + void setLandscape(); + void toggleOrientation(); + void startNetwork(); + void toggleFullScreen(); + void unpackWgt(); + +private: + QString getVideoFileName(); + + PreviewDeviceSkin *skin; + QSize skinscreensize; + QmlView *canvas; + QString currentFileOrUrl; + QmlTimer recordTimer; + QString frame_fmt; + QImage frame; + QList<QImage*> frames; + QProcess* frame_stream; + QmlTimer autoStartTimer; + QmlTimer autoStopTimer; + QString record_dither; + QString record_file; + QSize record_outsize; + QStringList record_args; + int record_rate; + int record_autotime; + bool devicemode; + QAction *recordAction; + QString currentSkin; + bool scaleSkin; + mutable QMenuBar *mb; + RecordingDialog *recdlg; + + void senseImageMagick(); + void senseFfmpeg(); + QWidget *ffmpegHelpWindow; + bool ffmpegAvailable; + bool convertAvailable; + + QAction *portraitOrientation; + QAction *landscapeOrientation; + + QString m_script; + ScriptOptions m_scriptOptions; + QmlGraphicsTester *tester; + + QNetworkReply *wgtreply; + QString wgtdir; + + NetworkAccessManagerFactory *namFactory; + + bool useQmlFileBrowser; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(QmlViewer::ScriptOptions) + +QT_END_NAMESPACE + +#endif diff --git a/tools/qmlviewer/qmlviewer.pro b/tools/qmlviewer/qmlviewer.pro new file mode 100644 index 0000000..35e4ba8 --- /dev/null +++ b/tools/qmlviewer/qmlviewer.pro @@ -0,0 +1,54 @@ +TEMPLATE = app +CONFIG += qt \ + uic +DESTDIR = ../../bin +QT += declarative \ + script \ + network \ + sql + +contains(QT_CONFIG, opengl) { + QT += opengl + DEFINES += GL_SUPPORTED +} + +# Input +HEADERS += qmlviewer.h \ + proxysettings.h \ + qfxtester.h \ + deviceorientation.h \ + qmlfolderlistmodel.h +SOURCES += main.cpp \ + qmlviewer.cpp \ + proxysettings.cpp \ + qfxtester.cpp \ + qmlfolderlistmodel.cpp +RESOURCES = qmlviewer.qrc +maemo5 { + SOURCES += deviceorientation_maemo.cpp +} else { + SOURCES += deviceorientation.cpp +} +FORMS = recopts.ui \ + proxysettings.ui +INCLUDEPATH += ../../include/QtDeclarative +INCLUDEPATH += ../../src/declarative/util +include(../shared/deviceskin/deviceskin.pri) +target.path = $$[QT_INSTALL_BINS] +INSTALLS += target + +wince* { +QT += scripttools \ + xml \ + xmlpatterns \ + webkit \ + phonon +} +symbian { +# TARGET.UID3 = + include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) + TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 + HEADERS += $$QT_SOURCE_TREE/examples/network/qftp/sym_iap_util.h + LIBS += -lesock -lconnmon -linsock + TARGET.CAPABILITY = NetworkServices +} diff --git a/tools/qmlviewer/qmlviewer.qrc b/tools/qmlviewer/qmlviewer.qrc new file mode 100644 index 0000000..3a9e608 --- /dev/null +++ b/tools/qmlviewer/qmlviewer.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/" > + <file>content/Browser.qml</file> + <file>content/images/up.png</file> + <file>content/images/folder.png</file> + <file>content/images/titlebar.sci</file> + <file>content/images/titlebar.png</file> + </qresource> +</RCC> diff --git a/tools/qmlviewer/recopts.ui b/tools/qmlviewer/recopts.ui new file mode 100644 index 0000000..ce2da30 --- /dev/null +++ b/tools/qmlviewer/recopts.ui @@ -0,0 +1,513 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>RecordingOptions</class> + <widget class="QDialog" name="RecordingOptions"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>316</width> + <height>436</height> + </rect> + </property> + <property name="windowTitle"> + <string>Video options</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>File:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="file"/> + </item> + <item> + <widget class="QToolButton" name="pickfile"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Size</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QRadioButton" name="sizeOriginal"> + <property name="text"> + <string/> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QRadioButton" name="sizeVGA"> + <property name="text"> + <string>VGA</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="size720p"> + <property name="text"> + <string>720p</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QRadioButton" name="sizeQVGA"> + <property name="text"> + <string>QVGA</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="3"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QRadioButton" name="sizeCustom"> + <property name="text"> + <string>Width:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sizeWidth"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>9999</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Height:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sizeHeight"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>9999</number> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="2"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="rateOptions"> + <property name="title"> + <string>Rate</string> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QRadioButton" name="hz60"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>60Hz</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="hz50"> + <property name="text"> + <string>50Hz</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QRadioButton" name="hz25"> + <property name="text"> + <string>25Hz</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="4"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QRadioButton" name="hzCustom"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="hz"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>60</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Hz</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="2"> + <widget class="QRadioButton" name="hz24"> + <property name="text"> + <string>24Hz</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1"> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="ffmpegOptions"> + <property name="title"> + <string>Profile</string> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0" colspan="3"> + <widget class="QComboBox" name="profile"/> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QLineEdit" name="args"/> + </item> + <item row="1" column="2"> + <widget class="QToolButton" name="ffmpegHelp"> + <property name="text"> + <string>Help</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QLabel" name="warning"> + <property name="text"> + <string/> + </property> + </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> + <tabstops> + <tabstop>file</tabstop> + <tabstop>pickfile</tabstop> + <tabstop>sizeOriginal</tabstop> + <tabstop>sizeVGA</tabstop> + <tabstop>size720p</tabstop> + <tabstop>sizeQVGA</tabstop> + <tabstop>sizeCustom</tabstop> + <tabstop>sizeWidth</tabstop> + <tabstop>sizeHeight</tabstop> + <tabstop>hz60</tabstop> + <tabstop>hz25</tabstop> + <tabstop>hz50</tabstop> + <tabstop>hz24</tabstop> + <tabstop>hzCustom</tabstop> + <tabstop>hz</tabstop> + <tabstop>profile</tabstop> + <tabstop>args</tabstop> + <tabstop>ffmpegHelp</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>hzCustom</sender> + <signal>clicked()</signal> + <receiver>hz</receiver> + <slot>setFocus()</slot> + <hints> + <hint type="sourcelabel"> + <x>43</x> + <y>257</y> + </hint> + <hint type="destinationlabel"> + <x>129</x> + <y>262</y> + </hint> + </hints> + </connection> + <connection> + <sender>hz</sender> + <signal>textChanged(QString)</signal> + <receiver>hzCustom</receiver> + <slot>toggle()</slot> + <hints> + <hint type="sourcelabel"> + <x>143</x> + <y>262</y> + </hint> + <hint type="destinationlabel"> + <x>43</x> + <y>257</y> + </hint> + </hints> + </connection> + <connection> + <sender>hz</sender> + <signal>selectionChanged()</signal> + <receiver>hzCustom</receiver> + <slot>toggle()</slot> + <hints> + <hint type="sourcelabel"> + <x>143</x> + <y>262</y> + </hint> + <hint type="destinationlabel"> + <x>43</x> + <y>257</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>RecordingOptions</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>258</x> + <y>424</y> + </hint> + <hint type="destinationlabel"> + <x>60</x> + <y>219</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>RecordingOptions</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>258</x> + <y>424</y> + </hint> + <hint type="destinationlabel"> + <x>92</x> + <y>219</y> + </hint> + </hints> + </connection> + <connection> + <sender>profile</sender> + <signal>activated(int)</signal> + <receiver>RecordingOptions</receiver> + <slot>pickProfile(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>92</x> + <y>329</y> + </hint> + <hint type="destinationlabel"> + <x>48</x> + <y>194</y> + </hint> + </hints> + </connection> + <connection> + <sender>args</sender> + <signal>textEdited(QString)</signal> + <receiver>RecordingOptions</receiver> + <slot>storeCustomArgs(QString)</slot> + <hints> + <hint type="sourcelabel"> + <x>128</x> + <y>357</y> + </hint> + <hint type="destinationlabel"> + <x>102</x> + <y>189</y> + </hint> + </hints> + </connection> + <connection> + <sender>sizeWidth</sender> + <signal>valueChanged(int)</signal> + <receiver>sizeCustom</receiver> + <slot>toggle()</slot> + <hints> + <hint type="sourcelabel"> + <x>108</x> + <y>133</y> + </hint> + <hint type="destinationlabel"> + <x>48</x> + <y>133</y> + </hint> + </hints> + </connection> + <connection> + <sender>sizeHeight</sender> + <signal>valueChanged(int)</signal> + <receiver>sizeCustom</receiver> + <slot>toggle()</slot> + <hints> + <hint type="sourcelabel"> + <x>212</x> + <y>133</y> + </hint> + <hint type="destinationlabel"> + <x>64</x> + <y>129</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <signal>filePicked(QString)</signal> + <signal>argumentsPicked(QString)</signal> + <slot>pickFile()</slot> + <slot>pickProfile(int)</slot> + <slot>storeCustomArgs(QString)</slot> + </slots> +</ui> diff --git a/tools/qtconfig/translations/translations.pro b/tools/qtconfig/translations/translations.pro index bf8a1da..5d35b6a 100644 --- a/tools/qtconfig/translations/translations.pro +++ b/tools/qtconfig/translations/translations.pro @@ -9,6 +9,7 @@ FORMS = ../mainwindowbase.ui ../paletteeditoradvancedbase.ui ../previewwi TR_DIR = $$PWD/../../../translations TRANSLATIONS = \ + $$TR_DIR/qtconfig_hu.ts \ $$TR_DIR/qtconfig_pl.ts \ $$TR_DIR/qtconfig_ru.ts \ $$TR_DIR/qtconfig_zh_CN.ts \ diff --git a/tools/qvfb/translations/translations.pro b/tools/qvfb/translations/translations.pro index ef42063..b0b1af4 100644 --- a/tools/qvfb/translations/translations.pro +++ b/tools/qvfb/translations/translations.pro @@ -28,6 +28,7 @@ SOURCES = ../qvfb.cpp \ TR_DIR = $$PWD/../../../translations TRANSLATIONS = \ + $$TR_DIR/qvfb_hu.ts \ $$TR_DIR/qvfb_pl.ts \ $$TR_DIR/qvfb_ru.ts \ $$TR_DIR/qvfb_zh_CN.ts \ diff --git a/tools/shared/fontpanel/fontpanel.cpp b/tools/shared/fontpanel/fontpanel.cpp index ad297df..fe221fd 100644 --- a/tools/shared/fontpanel/fontpanel.cpp +++ b/tools/shared/fontpanel/fontpanel.cpp @@ -96,8 +96,12 @@ QFont FontPanel::selectedFont() const const QString family = rc.family(); rc.setPointSize(pointSize()); const QString styleDescription = styleString(); - rc.setItalic(m_fontDatabase.italic(family, styleDescription)); - + if (styleDescription.contains(QLatin1String("Italic"))) + rc.setStyle(QFont::StyleItalic); + else if (styleDescription.contains(QLatin1String("Oblique"))) + rc.setStyle(QFont::StyleOblique); + else + rc.setStyle(QFont::StyleNormal); rc.setBold(m_fontDatabase.bold(family, styleDescription)); // Weight < 0 asserts... |