diff --git a/README b/README index 610cd8eed08..d96918acb17 100644 --- a/README +++ b/README @@ -20,9 +20,10 @@ Prerequisites: * Qt 5.3.1 or later (with restrictions also Qt 4.8.x) * On Windows: - ActiveState Active Perl - - MinGW or Visual Studio 2010 or later + - MinGW with g++ 4.5 or Visual Studio 2010 or later - jom * On Mac OS X: latest Xcode + * On Linux: g++ 4.5 or later The installed toolchains have to match the one Qt was compiled with. diff --git a/dist/changes-3.2.0 b/dist/changes-3.2.0 index 4f78fe3a9a3..31d9cae0094 100644 --- a/dist/changes-3.2.0 +++ b/dist/changes-3.2.0 @@ -80,6 +80,7 @@ Qbs Projects Generic Projects Debugging + * Fixed tooltip expansion behavior (QTCREATORBUG-11404) * Changed default of "Load system GDB pretty printer" option back to "off" * Added option to disable automatic centering on currently debugged line in editor @@ -135,13 +136,27 @@ C++ Support * Fixed indentation of concatenated strings * Fixed pointer typedef resolving (QTCREATORBUG-10021) * Fixed scroll wheel behavior in editor's symbols dropdown - * Fixed encoding issues (QTCREATORBUG-7356) * Fixed that some wizards were ignoring configured file extensions (QTCREATORBUG-12309) * Fixed parsing of trailing type-specifier * Fixed parsing of expressions like vector{1} * Fixed generating getters and setters for variables with 'm' and 'm_' prefixes + * Fixed that "using namespace" did not highlight class in including files (QTCREATORBUG-12357) + * Fixed include paths handling (QTCREATORBUG-11599) + * Fixed corner cases for "Create Getter and Setter Member Functions" refactoring action + (QTCREATORBUG-12244) + * Fixed parsing of expressions like vector{1} + * Fixed completion for template with default argument + (QTCREATORBUG-12606, QTCREATORBUG-12605) + * Improved lambda support + * Fixed local uses, completion and find usages for parameters + * Fixed "duplicate data type in declaration" warning (QTCREATORBUG-12521) + * Improved infrastructure for Clang integration + * Reworked indexing data structure + * Started to clean up C++ editor + * Added support for UTF-8 in the lexer (QTCREATORBUG-7356) + * Added support for C99 designated initializers QML Support * Fixed handling of properties that start with underscore (QTCREATORBUG-12214) diff --git a/doc/src/editors/creator-coding-edit-mode.qdoc b/doc/src/editors/creator-coding-edit-mode.qdoc index d9d0615220d..53924284c5f 100644 --- a/doc/src/editors/creator-coding-edit-mode.qdoc +++ b/doc/src/editors/creator-coding-edit-mode.qdoc @@ -132,7 +132,7 @@ \image qtcreator-togglebookmark.png To add a note to a bookmark, right-click the bookmark and select - \gui{Edit Bookmark Note}. To view the note, move the mouse pointer over the + \gui{Edit Bookmark}. To view the note, move the mouse pointer over the bookmark. To go to previous bookmark in the current session, press \key{Ctrl+,}. diff --git a/qtcreator.pro b/qtcreator.pro index 9f1591526d1..ad7b7d763c5 100644 --- a/qtcreator.pro +++ b/qtcreator.pro @@ -28,44 +28,47 @@ OTHER_FILES += dist/copyright_template.txt \ $$files(scripts/*.sh) \ $$files(scripts/*.pl) -qmake_cache = $$targetPath($$IDE_BUILD_TREE/.qmake.cache) -!equals(QMAKE_HOST.os, Windows) { - maybe_quote = "\"" - maybe_backslash = "\\" -} -system("echo $${maybe_quote}$${LITERAL_HASH} config for qmake$${maybe_quote} > $$qmake_cache") -# Make sure the qbs dll ends up alongside the Creator executable. -exists(src/shared/qbs/qbs.pro) { - system("echo QBS_DLLDESTDIR = $${IDE_BUILD_TREE}/bin >> $$qmake_cache") - system("echo QBS_DESTDIR = $${maybe_backslash}\"$${IDE_LIBRARY_PATH}$${maybe_backslash}\" >> $$qmake_cache") - system("echo QBSLIBDIR = $${maybe_backslash}\"$${IDE_LIBRARY_PATH}$${maybe_backslash}\" >> $$qmake_cache") - system("echo QBS_INSTALL_PREFIX = $${QTC_PREFIX} >> $$qmake_cache") - system("echo QBS_LIB_INSTALL_DIR = $${QTC_PREFIX}/$${IDE_LIBRARY_BASENAME}/qtcreator >> $$qmake_cache") +minQtVersion(5, 0, 0):exists(src/shared/qbs/qbs.pro) { + # Make sure the qbs dll ends up alongside the Creator executable. + QBS_DLLDESTDIR = $${IDE_BUILD_TREE}/bin + cache(QBS_DLLDESTDIR) + QBS_DESTDIR = $${IDE_LIBRARY_PATH} + cache(QBS_DESTDIR) + QBSLIBDIR = $${IDE_LIBRARY_PATH} + cache(QBSLIBDIR) + QBS_INSTALL_PREFIX = $${QTC_PREFIX} + cache(QBS_INSTALL_PREFIX) + QBS_LIB_INSTALL_DIR = $${QTC_PREFIX}/$${IDE_LIBRARY_BASENAME}/qtcreator + cache(QBS_LIB_INSTALL_DIR) QBS_RESOURCES_BUILD_DIR = $${IDE_DATA_PATH}/qbs - system("echo QBS_RESOURCES_BUILD_DIR = $${maybe_backslash}\"$${QBS_RESOURCES_BUILD_DIR}$${maybe_backslash}\" >> $$qmake_cache") - system("echo QBS_RESOURCES_INSTALL_DIR = $${QTC_PREFIX}/share/qtcreator/qbs >> $$qmake_cache") + cache(QBS_RESOURCES_BUILD_DIR) + QBS_RESOURCES_INSTALL_DIR = $${QTC_PREFIX}/share/qtcreator/qbs + cache(QBS_RESOURCES_INSTALL_DIR) macx { QBS_PLUGINS_BUILD_DIR = $${IDE_LIBRARY_PATH} - system("echo QBS_APPS_RPATH_DIR = @loader_path/../PlugIns >> $$qmake_cache") + QBS_APPS_RPATH_DIR = @loader_path/../PlugIns } else { QBS_PLUGINS_BUILD_DIR = $${IDE_BUILD_TREE}/$${IDE_LIBRARY_BASENAME}/qtcreator - system("echo QBS_APPS_RPATH_DIR = '\\\$\\\$ORIGIN/../'/lib/qtcreator >> $$qmake_cache") + QBS_APPS_RPATH_DIR = \\\$\\\$ORIGIN/../$$IDE_LIBRARY_BASENAME/qtcreator } - system("echo QBS_PLUGINS_BUILD_DIR = $${maybe_backslash}\"$${QBS_PLUGINS_BUILD_DIR}$${maybe_backslash}\" >> $$qmake_cache") - system("echo QBS_PLUGINS_INSTALL_DIR = $${QTC_PREFIX}/$${IDE_LIBRARY_BASENAME}/qtcreator >> $$qmake_cache") - system("echo QBS_LIBRARY_DIRNAME = $${IDE_LIBRARY_BASENAME} >> $$qmake_cache") + cache(QBS_PLUGINS_BUILD_DIR) + cache(QBS_APPS_RPATH_DIR) + QBS_PLUGINS_INSTALL_DIR = $${QTC_PREFIX}/$${IDE_LIBRARY_BASENAME}/qtcreator + cache(QBS_PLUGINS_INSTALL_DIR) + QBS_LIBRARY_DIRNAME = $${IDE_LIBRARY_BASENAME} + cache(QBS_LIBRARY_DIRNAME) QBS_APPS_DESTDIR = $${IDE_BIN_PATH} - system("echo QBS_APPS_DESTDIR = $${maybe_backslash}\"$${QBS_APPS_DESTDIR}$${maybe_backslash}\">> $$qmake_cache") - system("echo QBS_APPS_INSTALL_DIR = $${QTC_PREFIX}/bin >> $$qmake_cache") + cache(QBS_APPS_DESTDIR) + QBS_APPS_INSTALL_DIR = $${QTC_PREFIX}/bin + cache(QBS_APPS_INSTALL_DIR) QBS_RELATIVE_PLUGINS_PATH = $$relative_path($$QBS_PLUGINS_BUILD_DIR, $$QBS_APPS_DESTDIR$$) - system("echo QBS_RELATIVE_PLUGINS_PATH = $${QBS_RELATIVE_PLUGINS_PATH}" >> $$qmake_cache) + cache(QBS_RELATIVE_PLUGINS_PATH) QBS_RELATIVE_SEARCH_PATH = $$relative_path($$QBS_RESOURCES_BUILD_DIR, $$QBS_APPS_DESTDIR) - system("echo QBS_RELATIVE_SEARCH_PATH = $${QBS_RELATIVE_SEARCH_PATH}" >> $$qmake_cache) - system("echo CONFIG += qbs_no_dev_install >> $$qmake_cache") + cache(QBS_RELATIVE_SEARCH_PATH) + QBS_CONFIG_ADDITION = qbs_no_dev_install + cache(CONFIG, add, QBS_CONFIG_ADDITION) } -_QMAKE_CACHE_ = $$qmake_cache # Qt 4 support prevents us from using cache(), so tell Qt 5 about the cache - contains(QT_ARCH, i386): ARCHITECTURE = x86 else: ARCHITECTURE = $$QT_ARCH diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index b110e50cfb8..24641131242 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -2218,6 +2218,26 @@ def qdump__QXmlAttributes(d, value): qdump__QList(d, value["attList"]) +def qdump__QXmlStreamStringRef(d, value): + s = value["m_string"] + data, size, alloc = d.stringData(s) + data += 2 * int(value["m_position"]) + size = int(value["m_size"]) + s = d.readMemory(data, 2 * size) + d.putValue(s, Hex4EncodedLittleEndian) + d.putPlainChildren(value) + + +def qdump__QXmlStreamAttribute(d, value): + s = value["m_name"]["m_string"] + data, size, alloc = d.stringData(s) + data += 2 * int(value["m_name"]["m_position"]) + size = int(value["m_name"]["m_size"]) + s = d.readMemory(data, 2 * size) + d.putValue(s, Hex4EncodedLittleEndian) + d.putPlainChildren(value) + + ####################################################################### # # V4 diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp index b3b96890085..b5ca681a9fe 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp @@ -94,6 +94,8 @@ static bool isPropertyBlackListed(const QmlDesigner::PropertyName &propertyName) namespace QmlDesigner { namespace Internal { +QHash ObjectNodeInstance::m_enumationValueHash; + ObjectNodeInstance::ObjectNodeInstance(QObject *object) : m_object(object), m_metaObject(0), @@ -477,7 +479,7 @@ void ObjectNodeInstance::setPropertyVariant(const PropertyName &name, const QVar QVariant fixedValue = fixResourcePaths(value); if (value.canConvert()) - fixedValue = QVariant::fromValue(value.value().nameToString()); + fixedValue = enumationValue(value.value()); QVariant oldValue = property.read(); if (oldValue.type() == QVariant::Url) { @@ -1325,6 +1327,39 @@ void ObjectNodeInstance::doComponentCompleteRecursive(QObject *object, NodeInsta } } +static QHash enumationValuesFromMetaEnum(const QMetaEnum &metaEnum) +{ + QHash enumationValues; + for (int index = 0; index < metaEnum.keyCount(); index++) { + EnumerationName enumerationName = EnumerationName(metaEnum.scope()) + "." + metaEnum.key(index); + enumationValues.insert(enumerationName, metaEnum.value(index)); + } + + return enumationValues; +} + +static QHash collectEnumationValues(const Enumeration &enumeration) +{ + QHash enumationValues; + EnumerationName enumerationScope = enumeration.scope(); + const QMetaObject *metaObject = QMetaType::metaObjectForType(QMetaType::type(enumerationScope.data())); + if (metaObject) { + int enumeratorCount = metaObject->enumeratorOffset() + metaObject->enumeratorCount(); + for (int index = metaObject->enumeratorOffset(); index < enumeratorCount; index++) + enumationValues.unite(enumationValuesFromMetaEnum(metaObject->enumerator(index))); + } + return enumationValues; +} + +QVariant ObjectNodeInstance::enumationValue(const Enumeration &enumeration) +{ + EnumerationName enumerationName = enumeration.toEnumerationName(); + if (!m_enumationValueHash.contains(enumerationName)) + m_enumationValueHash.unite(collectEnumationValues(enumeration)); + + return QVariant::fromValue(m_enumationValueHash.value(enumerationName)); +} + ObjectNodeInstance::Pointer ObjectNodeInstance::parentInstance() const { QObject *parentHolder = parent(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h index 1f178f51c19..2d4635b372f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h @@ -38,6 +38,8 @@ #include #include +#include "enumeration.h" + QT_BEGIN_NAMESPACE class QGraphicsItem; class QQmlContext; @@ -200,6 +202,7 @@ protected: QVariant convertSpecialCharacter(const QVariant& value) const; static QObject *parentObject(QObject *object); static void doComponentCompleteRecursive(QObject *object, NodeInstanceServer *nodeInstanceServer); + static QVariant enumationValue(const Enumeration &enumeration); private: QHash m_resetValueHash; @@ -217,6 +220,7 @@ private: qint32 m_instanceId; bool m_deleteHeldInstance; bool m_isInLayoutable; + static QHash m_enumationValueHash; }; } // namespace Internal diff --git a/share/qtcreator/qml/qmlpuppet/types/enumeration.cpp b/share/qtcreator/qml/qmlpuppet/types/enumeration.cpp index effe379a81d..1d4e80cfde0 100644 --- a/share/qtcreator/qml/qmlpuppet/types/enumeration.cpp +++ b/share/qtcreator/qml/qmlpuppet/types/enumeration.cpp @@ -76,7 +76,7 @@ QString Enumeration::toString() const return QString::fromUtf8(m_enumerationName); } -QString Enumeration::nameToString() +QString Enumeration::nameToString() const { return QString::fromUtf8(name()); } diff --git a/share/qtcreator/qml/qmlpuppet/types/enumeration.h b/share/qtcreator/qml/qmlpuppet/types/enumeration.h index 252fd548121..b17805315ca 100644 --- a/share/qtcreator/qml/qmlpuppet/types/enumeration.h +++ b/share/qtcreator/qml/qmlpuppet/types/enumeration.h @@ -55,7 +55,7 @@ public: EnumerationName name() const; EnumerationName toEnumerationName() const; QString toString() const; - QString nameToString(); + QString nameToString() const; private: EnumerationName m_enumerationName; diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index e6245eb0365..4f7be860df5 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -1095,20 +1095,24 @@ Function *Bind::lambdaDeclarator(LambdaDeclaratorAST *ast) Function *fun = control()->newFunction(0, 0); fun->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin()); fun->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd()); + + FullySpecifiedType type; if (ast->trailing_return_type) - _type = this->trailingReturnType(ast->trailing_return_type, _type); - fun->setReturnType(_type); + type = this->trailingReturnType(ast->trailing_return_type, type); ast->symbol = fun; // unsigned lparen_token = ast->lparen_token; - FullySpecifiedType type; this->parameterDeclarationClause(ast->parameter_declaration_clause, ast->lparen_token, fun); // unsigned rparen_token = ast->rparen_token; for (SpecifierListAST *it = ast->attributes; it; it = it->next) { type = this->specifier(it->value, type); } // unsigned mutable_token = ast->mutable_token; - _type = this->exceptionSpecification(ast->exception_specification, type); + type = this->exceptionSpecification(ast->exception_specification, type); + + if (!type.isValid()) + type.setType(control()->voidType()); + fun->setReturnType(type); return fun; } diff --git a/src/libs/extensionsystem/plugindetailsview.cpp b/src/libs/extensionsystem/plugindetailsview.cpp index 2cbcb0a7f44..ce0508cb986 100644 --- a/src/libs/extensionsystem/plugindetailsview.cpp +++ b/src/libs/extensionsystem/plugindetailsview.cpp @@ -29,6 +29,8 @@ #include "plugindetailsview.h" #include "ui_plugindetailsview.h" + +#include "pluginmanager.h" #include "pluginspec.h" #include @@ -86,7 +88,10 @@ void PluginDetailsView::update(PluginSpec *spec) m_ui->copyright->setText(spec->copyright()); m_ui->license->setText(spec->license()); const QRegExp platforms = spec->platformSpecification(); - m_ui->platforms->setText(platforms.isEmpty() ? tr("All") : platforms.pattern()); + const QString pluginPlatformString = platforms.isEmpty() ? tr("All") : platforms.pattern(); + const QString platformString = tr("%1 (current: \"%2\")").arg(pluginPlatformString, + PluginManager::platformName()); + m_ui->platforms->setText(platformString); QStringList depStrings; foreach (const PluginDependency &dep, spec->dependencies()) { QString depString = dep.name; diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index a9550ffa63f..ffe5e2b3f70 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -1377,11 +1377,20 @@ void PluginManagerPrivate::profilingSummary() const static inline QString getPlatformName() { #if defined(Q_OS_MAC) - QString result = QLatin1String("Mac OS"); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_0) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_0) { + QString result = QLatin1String("OS X"); result += QLatin1String(" 10.") + QString::number(QSysInfo::MacintoshVersion - QSysInfo::MV_10_0); - return result; + return result; + } else { + return QLatin1String("Mac OS"); + } #elif defined(Q_OS_UNIX) + QString base; +# ifdef Q_OS_LINUX + base = QLatin1String("Linux"); +# else + base = QLatin1String("Unix"); +# endif // Q_OS_LINUX QFile osReleaseFile(QLatin1String("/etc/os-release")); // Newer Linuxes if (osReleaseFile.open(QIODevice::ReadOnly)) { QString name; @@ -1398,22 +1407,10 @@ static inline QString getPlatformName() if (!name.isEmpty()) { if (!version.isEmpty()) name += QLatin1Char(' ') + version; - return name; + return base + QLatin1String(" (") + name + QLatin1Char(')'); } } - QFile issueFile(QLatin1String("/etc/issue")); // Older Linuxes - if (issueFile.open(QIODevice::ReadOnly)) { - QByteArray issue = issueFile.readAll(); - const int end = issue.lastIndexOf(" \\n"); - if (end >= 0) - issue.truncate(end); - return QString::fromLatin1(issue).trimmed(); - } -# ifdef Q_OS_LINUX - return QLatin1String("Linux"); -# else - return QLatin1String("Unix"); -# endif // Q_OS_LINUX + return base; #elif defined(Q_OS_WIN) QString result = QLatin1String("Windows"); switch (QSysInfo::WindowsVersion) { diff --git a/src/libs/libs.pro b/src/libs/libs.pro index 94b57dc3268..6dc44a10fbb 100644 --- a/src/libs/libs.pro +++ b/src/libs/libs.pro @@ -25,23 +25,6 @@ for(l, SUBDIRS) { SUBDIRS += \ utils/process_stub.pro -minQtVersion(5, 0, 0) { - QBS_DIRS = \ - corelib \ - qtprofilesetup \ - apps \ - ../shared/qbs/src/plugins \ - ../shared/qbs/static.pro - corelib.subdir = ../shared/qbs/src/lib/corelib - qtprofilesetup.subdir = ../shared/qbs/src/lib/qtprofilesetup - qtprofilesetup.depends = corelib - apps.subdir = ../shared/qbs/src/app - apps.depends = qtprofilesetup - - exists(../shared/qbs/qbs.pro): SUBDIRS += $$QBS_DIRS - TR_EXCLUDE = $$QBS_DIRS -} - win32:SUBDIRS += utils/process_ctrlc_stub.pro # Windows: Compile Qt Creator CDB extension if Debugging tools can be detected. diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index 52aafce6dc6..4993f99a48d 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -36,7 +36,12 @@ #include #include #include +#include +#include #include +#include +#include +#include #ifdef Q_OS_WIN #include @@ -679,6 +684,72 @@ FileName &FileName::appendString(QChar str) return *this; } +static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0) +{ + if (files) + files->clear(); + // Extract dropped files from Mime data. + if (!d->hasUrls()) + return false; + const QList urls = d->urls(); + if (urls.empty()) + return false; + // Try to find local files + bool hasFiles = false; + const QList::const_iterator cend = urls.constEnd(); + for (QList::const_iterator it = urls.constBegin(); it != cend; ++it) { + const QString fileName = it->toLocalFile(); + if (!fileName.isEmpty()) { + hasFiles = true; + if (files) + files->push_back(fileName); + else + break; // No result list, sufficient for checking + } + } + return hasFiles; +} + +FileDropSupport::FileDropSupport(QWidget *parentWidget) + : QObject(parentWidget) +{ + QTC_ASSERT(parentWidget, return); + parentWidget->setAcceptDrops(true); + parentWidget->installEventFilter(this); +} + +bool FileDropSupport::eventFilter(QObject *obj, QEvent *event) +{ + Q_UNUSED(obj) + if (event->type() == QEvent::DragEnter) { + auto dee = static_cast(event); + if (isDesktopFileManagerDrop(dee->mimeData())) + event->accept(); + else + event->ignore(); + } else if (event->type() == QEvent::Drop) { + auto de = static_cast(event); + QStringList tempFiles; + if (isDesktopFileManagerDrop(de->mimeData(), &tempFiles)) { + event->accept(); + bool needToScheduleEmit = m_files.isEmpty(); + m_files.append(tempFiles); + if (needToScheduleEmit) // otherwise we already have a timer pending + QTimer::singleShot(0, this, SLOT(emitFilesDropped())); + } else { + event->ignore(); + } + } + return false; +} + +void FileDropSupport::emitFilesDropped() +{ + QTC_ASSERT(!m_files.isEmpty(), return); + emit filesDropped(m_files); + m_files.clear(); +} + } // namespace Utils QT_BEGIN_NAMESPACE diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index 414e72095d2..b2dbd66ac10 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -35,6 +35,7 @@ #include #include // Mac. #include +#include namespace Utils {class FileName; } @@ -192,6 +193,26 @@ private: bool m_autoRemove; }; +class QTCREATOR_UTILS_EXPORT FileDropSupport : public QObject +{ + Q_OBJECT +public: + FileDropSupport(QWidget *parentWidget); + +signals: + void filesDropped(const QStringList &files); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +private slots: + void emitFilesDropped(); + +private: + QStringList m_files; + +}; + } // namespace Utils QT_BEGIN_NAMESPACE diff --git a/src/libs/utils/proxycredentialsdialog.cpp b/src/libs/utils/proxycredentialsdialog.cpp new file mode 100644 index 00000000000..848dc68defb --- /dev/null +++ b/src/libs/utils/proxycredentialsdialog.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "proxycredentialsdialog.h" +#include "ui_proxycredentialsdialog.h" + +#include +#include + +using namespace Utils; + +/*! + \class Utils::ProxyCredentialsDialog + + Dialog for asking the user about proxy credentials (username, password). +*/ + +ProxyCredentialsDialog::ProxyCredentialsDialog(const QNetworkProxy &proxy, QWidget *parent) : + QDialog(parent), + ui(new Ui::ProxyCredentialsDialog) +{ + ui->setupUi(this); + + setUserName(proxy.user()); + setPassword(proxy.password()); + + const QString proxyString = QString::fromLatin1("%1:%2").arg(proxy.hostName()).arg(proxy.port()); + ui->infotext->setText(ui->infotext->text().arg(proxyString)); +} + +ProxyCredentialsDialog::~ProxyCredentialsDialog() +{ + delete ui; +} + +QString ProxyCredentialsDialog::userName() const +{ + return ui->usernameLineEdit->text(); +} + +void ProxyCredentialsDialog::setUserName(const QString &username) +{ + ui->usernameLineEdit->setText(username); +} + +QString ProxyCredentialsDialog::password() const +{ + return ui->passwordLineEdit->text(); +} + +void ProxyCredentialsDialog::setPassword(const QString &passwd) +{ + ui->passwordLineEdit->setText(passwd); +} + diff --git a/src/plugins/coreplugin/macfullscreen.h b/src/libs/utils/proxycredentialsdialog.h similarity index 68% rename from src/plugins/coreplugin/macfullscreen.h rename to src/libs/utils/proxycredentialsdialog.h index 2482750cbdd..cea025888df 100644 --- a/src/plugins/coreplugin/macfullscreen.h +++ b/src/libs/utils/proxycredentialsdialog.h @@ -27,22 +27,37 @@ ** ****************************************************************************/ -#ifndef MACFULLSCREEN_H -#define MACFULLSCREEN_H +#ifndef PROXYCREDENTIALSDIALOG_H +#define PROXYCREDENTIALSDIALOG_H -#include "mainwindow.h" +#include "utils_global.h" +#include -namespace Core { -namespace Internal { -namespace MacFullScreen { +QT_FORWARD_DECLARE_CLASS(QNetworkProxy) -bool supportsFullScreen(); -// adds fullscreen button to window for lion -void addFullScreen(Core::Internal::MainWindow *window); -void toggleFullScreen(Core::Internal::MainWindow *window); +namespace Utils { -} // MacFullScreen -} // Internal -} // Core +namespace Ui { +class ProxyCredentialsDialog; +} -#endif // MACFULLSCREEN_H +class QTCREATOR_UTILS_EXPORT ProxyCredentialsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ProxyCredentialsDialog(const QNetworkProxy &proxy, QWidget *parent = 0); + ~ProxyCredentialsDialog(); + + QString userName() const; + void setUserName(const QString &username); + QString password() const; + void setPassword(const QString &passwd); + +private: + Ui::ProxyCredentialsDialog *ui; +}; + +} // namespace Utils + +#endif // PROXYCREDENTIALSDIALOG_H diff --git a/src/libs/utils/proxycredentialsdialog.ui b/src/libs/utils/proxycredentialsdialog.ui new file mode 100644 index 00000000000..4bf6a17c33c --- /dev/null +++ b/src/libs/utils/proxycredentialsdialog.ui @@ -0,0 +1,106 @@ + + + Utils::ProxyCredentialsDialog + + + + 0 + 0 + 279 + 114 + + + + Proxy Credentials + + + + + + The proxy %1 requires a username and password. + + + + + + + + + Username: + + + + + + + Username + + + + + + + Password: + + + + + + + QLineEdit::Password + + + Password + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + Utils::ProxyCredentialsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Utils::ProxyCredentialsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index be12d23f981..0532576a594 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -89,7 +89,8 @@ SOURCES += $$PWD/environment.cpp \ $$PWD/completinglineedit.cpp \ $$PWD/winutils.cpp \ $$PWD/itemviews.cpp \ - $$PWD/treeviewcombobox.cpp + $$PWD/treeviewcombobox.cpp \ + $$PWD/proxycredentialsdialog.cpp win32:SOURCES += $$PWD/consoleprocess_win.cpp else:SOURCES += $$PWD/consoleprocess_unix.cpp @@ -185,10 +186,12 @@ HEADERS += \ $$PWD/treeviewcombobox.h \ $$PWD/scopedswap.h \ $$PWD/algorithm.h \ - $$PWD/QtConcurrentTools + $$PWD/QtConcurrentTools \ + $$PWD/proxycredentialsdialog.h FORMS += $$PWD/filewizardpage.ui \ $$PWD/projectintropage.ui \ - $$PWD/newclasswidget.ui + $$PWD/newclasswidget.ui \ + $$PWD/proxycredentialsdialog.ui RESOURCES += $$PWD/utils.qrc diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index 6a17f6bcc93..be6094d1d75 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -136,6 +136,9 @@ QtcLibrary { "projectnamevalidatinglineedit.h", "proxyaction.cpp", "proxyaction.h", + "proxycredentialsdialog.cpp", + "proxycredentialsdialog.h", + "proxycredentialsdialog.ui", "qtcassert.cpp", "qtcassert.h", "qtcolorbutton.cpp", diff --git a/src/plugins/android/androiddeployqtstep.h b/src/plugins/android/androiddeployqtstep.h index 0760429f463..01745ccb5cf 100644 --- a/src/plugins/android/androiddeployqtstep.h +++ b/src/plugins/android/androiddeployqtstep.h @@ -52,8 +52,7 @@ public: QList availableCreationIds(ProjectExplorer::BuildStepList *parent) const; QString displayNameForId(Core::Id id) const; - bool canCreate(ProjectExplorer::BuildStepList *parent, - const Core::Id id) const; + bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const; ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id); bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const; diff --git a/src/plugins/android/androiddeploystepfactory.h b/src/plugins/android/androiddeploystepfactory.h index f8a25fb8fc2..8d27b85d514 100644 --- a/src/plugins/android/androiddeploystepfactory.h +++ b/src/plugins/android/androiddeploystepfactory.h @@ -44,8 +44,7 @@ public: QList availableCreationIds(ProjectExplorer::BuildStepList *parent) const; QString displayNameForId(Core::Id id) const; - bool canCreate(ProjectExplorer::BuildStepList *parent, - const Core::Id id) const; + bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const; ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id); bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const; diff --git a/src/plugins/android/androidpackagecreationfactory.h b/src/plugins/android/androidpackagecreationfactory.h index 6b3f47c7707..a987ed643b0 100644 --- a/src/plugins/android/androidpackagecreationfactory.h +++ b/src/plugins/android/androidpackagecreationfactory.h @@ -44,8 +44,7 @@ public: QList availableCreationIds(ProjectExplorer::BuildStepList *parent) const; QString displayNameForId(Core::Id id) const; - bool canCreate(ProjectExplorer::BuildStepList *parent, - const Core::Id id) const; + bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const; ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id); bool canRestore(ProjectExplorer::BuildStepList *parent, diff --git a/src/plugins/android/androidpackageinstallationfactory.h b/src/plugins/android/androidpackageinstallationfactory.h index 22918421b78..b2ea80f89fc 100644 --- a/src/plugins/android/androidpackageinstallationfactory.h +++ b/src/plugins/android/androidpackageinstallationfactory.h @@ -44,8 +44,7 @@ public: QList availableCreationIds(ProjectExplorer::BuildStepList *parent) const; QString displayNameForId(Core::Id id) const; - bool canCreate(ProjectExplorer::BuildStepList *parent, - const Core::Id id) const; + bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const; ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id); bool canRestore(ProjectExplorer::BuildStepList *parent, diff --git a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp index 7aed71f2885..bed8e72d410 100644 --- a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp +++ b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -148,6 +149,7 @@ void ArtisticStyle::formatFile() if (m_settings->version() > ArtisticStyleSettings::Version_2_03) { command.setProcessing(Command::PipeProcessing); command.setPipeAddsNewline(true); + command.setReturnsCRLF(Utils::HostOsInfo::isWindowsHost()); } else { command.addOption(QLatin1String("%file")); } diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index 5aae5577855..f0a21aa89ad 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -198,9 +198,14 @@ QString BeautifierPlugin::format(const QString &text, const Command &command, return QString(); } - if (command.pipeAddsNewline()) { + const bool addsNewline = command.pipeAddsNewline(); + const bool returnsCRLF = command.returnsCRLF(); + if (addsNewline || returnsCRLF) { QString formatted = QString::fromUtf8(process.readAllStandardOutput()); - formatted.remove(QRegExp(QLatin1String("(\\r\\n|\\n)$"))); + if (addsNewline) + formatted.remove(QRegExp(QLatin1String("(\\r\\n|\\n)$"))); + if (returnsCRLF) + formatted.replace(QLatin1String("\r\n"), QLatin1String("\n")); return formatted; } return QString::fromUtf8(process.readAllStandardOutput()); diff --git a/src/plugins/beautifier/beautifierplugin.h b/src/plugins/beautifier/beautifierplugin.h index c495dcb009a..fb241ebd684 100644 --- a/src/plugins/beautifier/beautifierplugin.h +++ b/src/plugins/beautifier/beautifierplugin.h @@ -37,6 +37,7 @@ #include #include +#include #include namespace Core { class IEditor; } diff --git a/src/plugins/beautifier/command.cpp b/src/plugins/beautifier/command.cpp index 834f469a58c..55206c3b0f8 100644 --- a/src/plugins/beautifier/command.cpp +++ b/src/plugins/beautifier/command.cpp @@ -35,6 +35,7 @@ namespace Internal { Command::Command() : m_processing(FileProcessing) , m_pipeAddsNewline(false) + , m_returnsCRLF(false) { } @@ -78,5 +79,16 @@ void Command::setPipeAddsNewline(bool pipeAddsNewline) m_pipeAddsNewline = pipeAddsNewline; } +bool Command::returnsCRLF() const +{ + return m_returnsCRLF; +} + +void Command::setReturnsCRLF(bool returnsCRLF) +{ + m_returnsCRLF = returnsCRLF; +} + + } // namespace Internal } // namespace Beautifier diff --git a/src/plugins/beautifier/command.h b/src/plugins/beautifier/command.h index e6774f38fae..102e9f91c3f 100644 --- a/src/plugins/beautifier/command.h +++ b/src/plugins/beautifier/command.h @@ -58,11 +58,15 @@ public: bool pipeAddsNewline() const; void setPipeAddsNewline(bool pipeAddsNewline); + bool returnsCRLF() const; + void setReturnsCRLF(bool returnsCRLF); + private: QString m_executable; QStringList m_options; Processing m_processing; bool m_pipeAddsNewline; + bool m_returnsCRLF; }; } // namespace Internal diff --git a/src/plugins/bookmarks/bookmark.cpp b/src/plugins/bookmarks/bookmark.cpp index 666b146d733..16e6d217805 100644 --- a/src/plugins/bookmarks/bookmark.cpp +++ b/src/plugins/bookmarks/bookmark.cpp @@ -57,6 +57,14 @@ void Bookmark::updateLineNumber(int line) } } +void Bookmark::move(int line) +{ + if (line != lineNumber()) { + BaseTextMark::move(line); + m_manager->updateBookmark(this); + } +} + void Bookmark::updateBlock(const QTextBlock &block) { if (m_lineText != block.text()) { diff --git a/src/plugins/bookmarks/bookmark.h b/src/plugins/bookmarks/bookmark.h index 89e5ea0d54d..5ac9db50d51 100644 --- a/src/plugins/bookmarks/bookmark.h +++ b/src/plugins/bookmarks/bookmark.h @@ -44,6 +44,7 @@ public: Bookmark(const QString &fileName, int lineNumber, BookmarkManager *manager); void updateLineNumber(int lineNumber); + void move(int line); void updateBlock(const QTextBlock &block); void updateFileName(const QString &fileName); void setNote(const QString ¬e); diff --git a/src/plugins/bookmarks/bookmarkmanager.cpp b/src/plugins/bookmarks/bookmarkmanager.cpp index a51c11ee258..c398a537024 100644 --- a/src/plugins/bookmarks/bookmarkmanager.cpp +++ b/src/plugins/bookmarks/bookmarkmanager.cpp @@ -45,15 +45,18 @@ #include #include -#include -#include -#include - #include #include +#include +#include +#include +#include +#include +#include +#include #include #include -#include +#include Q_DECLARE_METATYPE(Bookmarks::Internal::Bookmark*) @@ -243,7 +246,7 @@ void BookmarkView::contextMenuEvent(QContextMenuEvent *event) QMenu menu; QAction *moveUp = menu.addAction(tr("Move Up")); QAction *moveDown = menu.addAction(tr("Move Down")); - QAction *editNote = menu.addAction(tr("Edit Note")); + QAction *edit = menu.addAction(tr("&Edit")); menu.addSeparator(); QAction *remove = menu.addAction(tr("&Remove")); menu.addSeparator(); @@ -254,7 +257,7 @@ void BookmarkView::contextMenuEvent(QContextMenuEvent *event) moveUp->setEnabled(false); moveDown->setEnabled(false); remove->setEnabled(false); - editNote->setEnabled(false); + edit->setEnabled(false); } if (model()->rowCount() == 0) @@ -268,8 +271,8 @@ void BookmarkView::contextMenuEvent(QContextMenuEvent *event) this, SLOT(removeFromContextMenu())); connect(removeAll, SIGNAL(triggered()), this, SLOT(removeAll())); - connect(editNote, SIGNAL(triggered()), - m_manager, SLOT(editNote())); + connect(edit, SIGNAL(triggered()), + m_manager, SLOT(edit())); menu.exec(mapToGlobal(event->pos())); } @@ -673,27 +676,39 @@ void BookmarkManager::moveDown() saveBookmarks(); } -void BookmarkManager::editNote(const QString &fileName, int lineNumber) +void BookmarkManager::edit(const QString &fileName, int lineNumber) { Bookmark *b = findBookmark(fileName, lineNumber); QModelIndex current = selectionModel()->currentIndex(); selectionModel()->setCurrentIndex(current.sibling(m_bookmarksList.indexOf(b), 0), QItemSelectionModel::Select | QItemSelectionModel::Clear); - editNote(); + edit(); } -void BookmarkManager::editNote() +void BookmarkManager::edit() { QModelIndex current = selectionModel()->currentIndex(); Bookmark *b = m_bookmarksList.at(current.row()); - bool inputOk = false; - QString noteText = QInputDialog::getText(0, tr("Edit Note"), - tr("Note text:"), QLineEdit::Normal, - b->note(), &inputOk); - if (inputOk) { - b->updateNote(noteText.replace(QLatin1Char('\t'), QLatin1Char(' '))); + QDialog dlg; + dlg.setWindowTitle(tr("Edit Bookmark")); + auto layout = new QFormLayout(&dlg); + auto noteEdit = new QLineEdit(b->note()); + noteEdit->setMinimumWidth(300); + auto lineNumberSpinbox = new QSpinBox; + lineNumberSpinbox->setRange(1, INT_MAX); + lineNumberSpinbox->setValue(b->lineNumber()); + lineNumberSpinbox->setMaximumWidth(100); + auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttonBox, SIGNAL(accepted()), &dlg, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), &dlg, SLOT(reject())); + layout->addRow(tr("Note text:"), noteEdit); + layout->addRow(tr("Line number:"), lineNumberSpinbox); + layout->addWidget(buttonBox); + if (dlg.exec() == QDialog::Accepted) { + b->move(lineNumberSpinbox->value()); + b->updateNote(noteEdit->text().replace(QLatin1Char('\t'), QLatin1Char(' '))); emit dataChanged(current, current); saveBookmarks(); } diff --git a/src/plugins/bookmarks/bookmarkmanager.h b/src/plugins/bookmarks/bookmarkmanager.h index a1a2d4a038b..71f964c8158 100644 --- a/src/plugins/bookmarks/bookmarkmanager.h +++ b/src/plugins/bookmarks/bookmarkmanager.h @@ -97,8 +97,8 @@ public slots: void prev(); void moveUp(); void moveDown(); - void editNote(); - void editNote(const QString &fileName, int lineNumber); + void edit(); + void edit(const QString &fileName, int lineNumber); bool gotoBookmark(Bookmark *bookmark); signals: diff --git a/src/plugins/bookmarks/bookmarksplugin.cpp b/src/plugins/bookmarks/bookmarksplugin.cpp index caa3c25642b..c4fc525bdb0 100644 --- a/src/plugins/bookmarks/bookmarksplugin.cpp +++ b/src/plugins/bookmarks/bookmarksplugin.cpp @@ -105,7 +105,7 @@ bool BookmarksPlugin::initialize(const QStringList & /*arguments*/, QString *) cmd = Core::ActionManager::registerAction(m_docNextAction, BOOKMARKS_NEXTDOC_ACTION, globalcontext); mbm->addAction(cmd); - m_editNoteAction = new QAction(tr("Edit Bookmark Note"), this); + m_editBookmarkAction = new QAction(tr("Edit Bookmark"), this); m_bookmarkManager = new BookmarkManager; @@ -114,7 +114,7 @@ bool BookmarksPlugin::initialize(const QStringList & /*arguments*/, QString *) connect(m_nextAction, SIGNAL(triggered()), m_bookmarkManager, SLOT(next())); connect(m_docPrevAction, SIGNAL(triggered()), m_bookmarkManager, SLOT(prevInDocument())); connect(m_docNextAction, SIGNAL(triggered()), m_bookmarkManager, SLOT(nextInDocument())); - connect(m_editNoteAction, SIGNAL(triggered()), this, SLOT(bookmarkEditNoteActionTriggered())); + connect(m_editBookmarkAction, SIGNAL(triggered()), this, SLOT(editBookmarkActionTriggered())); connect(m_bookmarkManager, SIGNAL(updateActions(int)), this, SLOT(updateActions(int))); updateActions(m_bookmarkManager->state()); addAutoReleasedObject(new BookmarkViewFactory(m_bookmarkManager)); @@ -189,7 +189,7 @@ void BookmarksPlugin::requestContextMenu(TextEditor::ITextEditor *editor, menu->addAction(m_bookmarkMarginAction); if (m_bookmarkManager->hasBookmarkInPosition(m_bookmarkMarginActionFileName, m_bookmarkMarginActionLineNumber)) - menu->addAction(m_editNoteAction); + menu->addAction(m_editBookmarkAction); } void BookmarksPlugin::bookmarkMarginActionTriggered() @@ -198,9 +198,9 @@ void BookmarksPlugin::bookmarkMarginActionTriggered() m_bookmarkMarginActionLineNumber); } -void BookmarksPlugin::bookmarkEditNoteActionTriggered() +void BookmarksPlugin::editBookmarkActionTriggered() { - m_bookmarkManager->editNote(m_bookmarkMarginActionFileName, m_bookmarkMarginActionLineNumber); + m_bookmarkManager->edit(m_bookmarkMarginActionFileName, m_bookmarkMarginActionLineNumber); } Q_EXPORT_PLUGIN(BookmarksPlugin) diff --git a/src/plugins/bookmarks/bookmarksplugin.h b/src/plugins/bookmarks/bookmarksplugin.h index d417dda3bdf..63045c42cc7 100644 --- a/src/plugins/bookmarks/bookmarksplugin.h +++ b/src/plugins/bookmarks/bookmarksplugin.h @@ -70,7 +70,7 @@ private slots: void requestContextMenu(TextEditor::ITextEditor *editor, int lineNumber, QMenu *menu); void bookmarkMarginActionTriggered(); - void bookmarkEditNoteActionTriggered(); + void editBookmarkActionTriggered(); private: static BookmarksPlugin *m_instance; @@ -81,7 +81,7 @@ private: QAction *m_nextAction; QAction *m_docPrevAction; QAction *m_docNextAction; - QAction *m_editNoteAction; + QAction *m_editBookmarkAction; QAction *m_bookmarkMarginAction; int m_bookmarkMarginActionLineNumber; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs index 2fd4f5719b4..cd00db1f96f 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs @@ -20,7 +20,6 @@ QtcPlugin { ] files: [ - "CMakeProjectManager.mimetypes.xml", "cmakebuildconfiguration.cpp", "cmakebuildconfiguration.h", "cmakebuildinfo.h", diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro index 840787e5635..aa5cda39049 100644 --- a/src/plugins/coreplugin/coreplugin.pro +++ b/src/plugins/coreplugin/coreplugin.pro @@ -224,10 +224,8 @@ win32 { LIBS += -lole32 -luser32 } else:macx { - HEADERS += macfullscreen.h OBJECTIVE_SOURCES += \ - progressmanager/progressmanager_mac.mm \ - macfullscreen.mm + progressmanager/progressmanager_mac.mm LIBS += -framework AppKit } else:unix { diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp index cfe715b7e24..2ca9f1613ca 100644 --- a/src/plugins/coreplugin/editormanager/editorview.cpp +++ b/src/plugins/coreplugin/editormanager/editorview.cpp @@ -37,8 +37,8 @@ #include #include #include - #include +#include #include #include @@ -118,6 +118,10 @@ EditorView::EditorView(SplitterOrView *parentSplitterOrView, QWidget *parent) : m_container->addWidget(empty); m_widgetEditorMap.insert(empty, 0); + auto dropSupport = new Utils::FileDropSupport(this); + connect(dropSupport, SIGNAL(filesDropped(QStringList)), + this, SLOT(openDroppedFiles(QStringList))); + updateNavigatorActions(); } @@ -330,6 +334,17 @@ void EditorView::closeSplit() EditorManager::updateActions(); } +void EditorView::openDroppedFiles(const QStringList &files) +{ + const int count = files.size(); + for (int i = 0; i < count; ++i) { + EditorManager::openEditor(this, files.at(i), Id(), + i < count - 1 ? EditorManager::DoNotChangeCurrentEditor + | EditorManager::DoNotMakeVisible + : EditorManager::NoFlags); + } +} + void EditorView::setParentSplitterOrView(SplitterOrView *splitterOrView) { m_parentSplitterOrView = splitterOrView; diff --git a/src/plugins/coreplugin/editormanager/editorview.h b/src/plugins/coreplugin/editormanager/editorview.h index 68aec837c7a..592f3e14262 100644 --- a/src/plugins/coreplugin/editormanager/editorview.h +++ b/src/plugins/coreplugin/editormanager/editorview.h @@ -115,6 +115,7 @@ private slots: void splitVertically(); void splitNewWindow(); void closeSplit(); + void openDroppedFiles(const QStringList &files); private: friend class SplitterOrView; // for setParentSplitterOrView diff --git a/src/plugins/coreplugin/macfullscreen.mm b/src/plugins/coreplugin/macfullscreen.mm deleted file mode 100644 index bd693cba95c..00000000000 --- a/src/plugins/coreplugin/macfullscreen.mm +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "macfullscreen.h" - -#include -#include -#include - -#include -#include - -enum { - Qtc_NSWindowCollectionBehaviorFullScreenPrimary = (1 << 7) -}; - -static NSString *Qtc_NSWindowDidEnterFullScreenNotification = @"NSWindowDidEnterFullScreenNotification"; -static NSString *Qtc_NSWindowDidExitFullScreenNotification = @"NSWindowDidExitFullScreenNotification"; - -@interface WindowObserver : NSObject { - Core::Internal::MainWindow *window; -} - -- (id)initWithMainWindow:(Core::Internal::MainWindow *)w; - -- (void)notifyDidEnterFullScreen:(NSNotification *)notification; -- (void)notifyDidExitFullScreen:(NSNotification *)notification; - -@end - -@implementation WindowObserver - -- (id)initWithMainWindow:(Core::Internal::MainWindow *)w -{ - if ((self = [self init])) { - window = w; - } - return self; -} - -- (void)notifyDidEnterFullScreen:(NSNotification *)notification -{ - Q_UNUSED(notification) - window->setIsFullScreen(true); -} - -- (void)notifyDidExitFullScreen:(NSNotification* )notification -{ - Q_UNUSED(notification) - window->setIsFullScreen(false); -} - -@end - -static WindowObserver *observer = nil; - -using namespace Core::Internal; - -bool MacFullScreen::supportsFullScreen() -{ - return QSysInfo::MacintoshVersion >= QSysInfo::MV_LION; -} - -void MacFullScreen::addFullScreen(MainWindow *window) -{ - if (supportsFullScreen()) { - NSView *nsview = (NSView *) window->winId(); - NSWindow *nswindow = [nsview window]; - [nswindow setCollectionBehavior:Qtc_NSWindowCollectionBehaviorFullScreenPrimary]; - - if (observer == nil) - observer = [[WindowObserver alloc] initWithMainWindow:window]; - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:observer selector:@selector(notifyDidEnterFullScreen:) - name:Qtc_NSWindowDidEnterFullScreenNotification object:nswindow]; - [nc addObserver:observer selector:@selector(notifyDidExitFullScreen:) - name:Qtc_NSWindowDidExitFullScreenNotification object:nswindow]; - } -} - -void MacFullScreen::toggleFullScreen(MainWindow *window) -{ - if (supportsFullScreen()) { - NSView *nsview = (NSView *) window->winId(); - NSWindow *nswindow = [nsview window]; - [nswindow performSelector:@selector(toggleFullScreen:) withObject: nil]; - } -} diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 8b8049093a5..d2a469b5a7a 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -55,10 +55,6 @@ #include "externaltoolmanager.h" #include "editormanager/systemeditor.h" -#if defined(Q_OS_MAC) -#include "macfullscreen.h" -#endif - #include #include #include @@ -74,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -87,7 +84,6 @@ #include #include #include -#include #include #include @@ -211,11 +207,10 @@ MainWindow::MainWindow() : //signal(SIGINT, handleSigInt); statusBar()->setProperty("p_styled", true); - setAcceptDrops(true); -#if defined(Q_OS_MAC) - MacFullScreen::addFullScreen(this); -#endif + auto dropSupport = new Utils::FileDropSupport(this); + connect(dropSupport, SIGNAL(filesDropped(QStringList)), + this, SLOT(openDroppedFiles(QStringList))); } void MainWindow::setSidebarVisible(bool visible) @@ -241,12 +236,19 @@ void MainWindow::setOverrideColor(const QColor &color) m_overrideColor = color; } -void MainWindow::setIsFullScreen(bool fullScreen) +void MainWindow::updateFullScreenAction() { - if (fullScreen) - m_toggleFullScreenAction->setText(tr("Exit Full Screen")); - else - m_toggleFullScreenAction->setText(tr("Enter Full Screen")); + if (isFullScreen()) { + if (Utils::HostOsInfo::isMacHost()) + m_toggleFullScreenAction->setText(tr("Exit Full Screen")); + else + m_toggleFullScreenAction->setChecked(true); + } else { + if (Utils::HostOsInfo::isMacHost()) + m_toggleFullScreenAction->setText(tr("Enter Full Screen")); + else + m_toggleFullScreenAction->setChecked(false); + } } bool MainWindow::isNewItemDialogRunning() const @@ -386,61 +388,10 @@ void MainWindow::closeEvent(QCloseEvent *event) event->accept(); } -// Check for desktop file manager file drop events - -static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0) +void MainWindow::openDroppedFiles(const QStringList &files) { - if (files) - files->clear(); - // Extract dropped files from Mime data. - if (!d->hasUrls()) - return false; - const QList urls = d->urls(); - if (urls.empty()) - return false; - // Try to find local files - bool hasFiles = false; - const QList::const_iterator cend = urls.constEnd(); - for (QList::const_iterator it = urls.constBegin(); it != cend; ++it) { - const QString fileName = it->toLocalFile(); - if (!fileName.isEmpty()) { - hasFiles = true; - if (files) - files->push_back(fileName); - else - break; // No result list, sufficient for checking - } - } - return hasFiles; -} - -void MainWindow::dragEnterEvent(QDragEnterEvent *event) -{ - if (isDesktopFileManagerDrop(event->mimeData()) && m_filesToOpenDelayed.isEmpty()) - event->accept(); - else - event->ignore(); -} - -void MainWindow::dropEvent(QDropEvent *event) -{ - QStringList files; - if (isDesktopFileManagerDrop(event->mimeData(), &files)) { - event->accept(); - m_filesToOpenDelayed.append(files); - QTimer::singleShot(50, this, SLOT(openDelayedFiles())); - } else { - event->ignore(); - } -} - -void MainWindow::openDelayedFiles() -{ - if (m_filesToOpenDelayed.isEmpty()) - return; raiseWindow(); - openFiles(m_filesToOpenDelayed, ICore::SwitchMode); - m_filesToOpenDelayed.clear(); + openFiles(files, ICore::SwitchMode); } IContext *MainWindow::currentContextObject() const @@ -700,11 +651,23 @@ void MainWindow::registerDefaultActions() cmd = ActionManager::registerAction(m_zoomAction, Constants::ZOOM_WINDOW, globalContext); mwindow->addAction(cmd, Constants::G_WINDOW_SIZE); connect(m_zoomAction, SIGNAL(triggered()), this, SLOT(showMaximized())); - - // Window separator - mwindow->addSeparator(globalContext, Constants::G_WINDOW_SIZE); } + // Full Screen Action + m_toggleFullScreenAction = new QAction(this); + m_toggleFullScreenAction->setMenuRole(QAction::NoRole); + m_toggleFullScreenAction->setCheckable(!Utils::HostOsInfo::isMacHost()); + updateFullScreenAction(); + cmd = ActionManager::registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, globalContext); + cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Meta+F") : tr("Ctrl+Shift+F11"))); + if (Utils::HostOsInfo::isMacHost()) + cmd->setAttribute(Command::CA_UpdateText); + mwindow->addAction(cmd, Constants::G_WINDOW_SIZE); + connect(m_toggleFullScreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen())); + + if (UseMacShortcuts) + mwindow->addSeparator(globalContext, Constants::G_WINDOW_SIZE); + // Show Sidebar Action m_toggleSideBarAction = new QAction(QIcon(QLatin1String(Constants::ICON_TOGGLE_SIDEBAR)), tr("Show Sidebar"), this); @@ -724,25 +687,6 @@ void MainWindow::registerDefaultActions() connect(m_toggleModeSelectorAction, SIGNAL(triggered(bool)), ModeManager::instance(), SLOT(setModeSelectorVisible(bool))); mwindow->addAction(cmd, Constants::G_WINDOW_VIEWS); -#if defined(Q_OS_MAC) - const QString fullScreenActionText(tr("Enter Full Screen")); - bool supportsFullScreen = MacFullScreen::supportsFullScreen(); -#else - const QString fullScreenActionText(tr("Full Screen")); - bool supportsFullScreen = true; -#endif - if (supportsFullScreen) { - // Full Screen Action - m_toggleFullScreenAction = new QAction(fullScreenActionText, this); - m_toggleFullScreenAction->setMenuRole(QAction::NoRole); - m_toggleFullScreenAction->setCheckable(!Utils::HostOsInfo::isMacHost()); - cmd = ActionManager::registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, globalContext); - cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Meta+F") : tr("Ctrl+Shift+F11"))); - cmd->setAttribute(Command::CA_UpdateText); /* for Mac */ - mwindow->addAction(cmd, Constants::G_WINDOW_SIZE); - connect(m_toggleFullScreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool))); - } - // Window->Views ActionContainer *mviews = ActionManager::createMenu(Constants::M_WINDOW_VIEWS); mwindow->addMenu(mviews, Constants::G_WINDOW_VIEWS); @@ -969,10 +913,8 @@ void MainWindow::changeEvent(QEvent *e) qDebug() << "main window state changed to minimized=" << minimized; m_minimizeAction->setEnabled(!minimized); m_zoomAction->setEnabled(!minimized); - } else { - bool isFullScreen = (windowState() & Qt::WindowFullScreen) != 0; - m_toggleFullScreenAction->setChecked(isFullScreen); } + updateFullScreenAction(); } } @@ -1179,25 +1121,13 @@ QPrinter *MainWindow::printer() const return m_printer; } -void MainWindow::setFullScreen(bool on) +void MainWindow::toggleFullScreen() { -#if defined(Q_OS_MAC) - Q_UNUSED(on) - MacFullScreen::toggleFullScreen(this); -#else - if (bool(windowState() & Qt::WindowFullScreen) == on) - return; - - if (on) { - setWindowState(windowState() | Qt::WindowFullScreen); - //statusBar()->hide(); - //menuBar()->hide(); - } else { + if (isFullScreen()) { setWindowState(windowState() & ~Qt::WindowFullScreen); - //menuBar()->show(); - //statusBar()->show(); + } else { + setWindowState(windowState() | Qt::WindowFullScreen); } -#endif } // Display a warning with an additional button to open diff --git a/src/plugins/coreplugin/mainwindow.h b/src/plugins/coreplugin/mainwindow.h index 1540d082476..5d89286969f 100644 --- a/src/plugins/coreplugin/mainwindow.h +++ b/src/plugins/coreplugin/mainwindow.h @@ -107,7 +107,7 @@ public: void setOverrideColor(const QColor &color); - void setIsFullScreen(bool fullScreen); + void updateFullScreenAction(); bool isNewItemDialogRunning() const; @@ -119,7 +119,7 @@ public slots: void newFile(); void openFileWith(); void exit(); - void setFullScreen(bool on); + void toggleFullScreen(); void showNewItemDialog(const QString &title, const QList &factories, @@ -137,8 +137,6 @@ public slots: protected: virtual void changeEvent(QEvent *e); virtual void closeEvent(QCloseEvent *event); - virtual void dragEnterEvent(QDragEnterEvent *event); - virtual void dropEvent(QDropEvent *event); private slots: void openFile(); @@ -151,7 +149,7 @@ private slots: void updateFocusWidget(QWidget *old, QWidget *now); void setSidebarVisible(bool visible); void destroyVersionDialog(); - void openDelayedFiles(); + void openDroppedFiles(const QStringList &files); void restoreWindowState(); void newItemDialogFinished(); @@ -213,8 +211,6 @@ private: QToolButton *m_toggleSideBarButton; QColor m_overrideColor; - - QStringList m_filesToOpenDelayed; }; } // namespace Internal diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index ce9853714b0..a1f08a02f14 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -1194,6 +1194,39 @@ void CppEditorPlugin::test_quickfix_data() << CppQuickFixFactoryPtr(new OptimizeForLoop) << _("void foo() {fo@r (int i = 0; i < -3; ++i) {}}\n") << _(); + + QTest::newRow("InsertQtPropertyMembers") + << CppQuickFixFactoryPtr(new InsertQtPropertyMembers) + << _("struct XmarksTheSpot {\n" + " @Q_PROPERTY(int it READ getIt WRITE setIt NOTIFY itChanged)\n" + "};\n" + ) + << _("struct XmarksTheSpot {\n" + " Q_PROPERTY(int it READ getIt WRITE setIt NOTIFY itChanged)\n" + "\n" + "public:\n" + " int getIt() const\n" + " {\n" + " return m_it;\n" + " }\n" + "\n" + "public slots:\n" + " void setIt(int arg)\n" + " {\n" + " if (m_it == arg)\n" + " return;\n" + "\n" + " m_it = arg;\n" + " emit itChanged(arg);\n" + " }\n" + "\n" + "signals:\n" + " void itChanged(int arg);\n" + "\n" + "private:\n" + " int m_it;\n" + "};\n" + ); } void CppEditorPlugin::test_quickfix() diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 5b7e48a0074..6eb8a847d27 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -3953,8 +3953,8 @@ public: if (m_signalName.isEmpty()) { setter << m_storageName << " = arg;\n}\n"; } else { - setter << "if (" << m_storageName << " != arg) {\n" << m_storageName - << " = arg;\nemit " << m_signalName << "(arg);\n}\n}\n"; + setter << "if (" << m_storageName << " == arg)\nreturn;\n\n" + << m_storageName << " = arg;\nemit " << m_signalName << "(arg);\n}\n"; } InsertionLocation setterLoc = locator.methodDeclarationInClass(file->fileName(), m_class, InsertionPointLocator::PublicSlot); QTC_ASSERT(setterLoc.isValid(), return); diff --git a/src/plugins/cppeditor/fileandtokenactions_test.cpp b/src/plugins/cppeditor/fileandtokenactions_test.cpp index 6944ec6c4ff..f98eebbc497 100644 --- a/src/plugins/cppeditor/fileandtokenactions_test.cpp +++ b/src/plugins/cppeditor/fileandtokenactions_test.cpp @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -54,6 +55,7 @@ #if QT_VERSION >= 0x050000 #define MSKIP_SINGLE(x) QSKIP(x) #else +#include #define MSKIP_SINGLE(x) QSKIP(x, SkipSingle) #endif diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index f2d418dbc01..9fcc912688c 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -447,8 +447,7 @@ void CdbEngine::syncVerboseLog(bool verboseLog) postCommand(m_verboseLog ? QByteArray("!sym noisy") : QByteArray("!sym quiet"), 0); } -bool CdbEngine::setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, +bool CdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, const DebuggerToolTipContext &contextIn) { if (debug) @@ -469,10 +468,7 @@ bool CdbEngine::setToolTipExpression(const QPoint &mousePos, if (!localVariable) return false; context.iname = localVariable->iname; - DebuggerToolTipWidget *tw = new DebuggerToolTipWidget; - tw->setContext(context); - tw->acquireEngine(this); - DebuggerToolTipManager::showToolTip(mousePos, tw); + DebuggerToolTipManager::showToolTip(context, this); return true; } @@ -1972,8 +1968,10 @@ void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply) foreach (const WatchData &wd, watchData) nsp << wd.toString() <<'\n'; } - if (flags & LocalsUpdateForNewFrame) + if (flags & LocalsUpdateForNewFrame) { emit stackFrameCompleted(); + DebuggerToolTipManager::updateEngine(this); + } } else { showMessage(QString::fromLatin1(reply->errorMessage), LogWarning); } diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h index e37265ed496..8aad2eec960 100644 --- a/src/plugins/debugger/cdb/cdbengine.h +++ b/src/plugins/debugger/cdb/cdbengine.h @@ -76,7 +76,7 @@ public: // Factory function that returns 0 if the debug engine library cannot be found. - virtual bool setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, + virtual bool setToolTipExpression(TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx); virtual void setupEngine(); virtual void setupInferior(); diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp index e0ccf4685f3..7c5a18fb733 100644 --- a/src/plugins/debugger/commonoptionspage.cpp +++ b/src/plugins/debugger/commonoptionspage.cpp @@ -76,8 +76,6 @@ private: QCheckBox *checkBoxKeepEditorStationaryWhileStepping; QLabel *labelMaximalStackDepth; QSpinBox *spinBoxMaximalStackDepth; - QSpinBox *spinBoxMaximalStringLength; - QSpinBox *spinBoxDisplayStringLimit; DebuggerSourcePathMappingWidget *sourcesMappingWidget; const QSharedPointer m_group; diff --git a/src/plugins/debugger/debuggercore.h b/src/plugins/debugger/debuggercore.h index b53c8189495..81c2408ddf2 100644 --- a/src/plugins/debugger/debuggercore.h +++ b/src/plugins/debugger/debuggercore.h @@ -60,7 +60,6 @@ class BreakHandler; class SnapshotHandler; class Symbol; class Section; -class DebuggerToolTipManager; class GlobalDebuggerOptions; enum TestCases @@ -120,7 +119,6 @@ public: virtual QStringList stringListSetting(int code) const = 0; virtual void setThreads(const QStringList &list, int index) = 0; - virtual DebuggerToolTipManager *toolTipManager() const = 0; virtual QSharedPointer globalDebuggerOptions() const = 0; static QTreeView *inspectorView(); diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 6afb7704a09..9ccd0f0b0b8 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -35,6 +35,7 @@ #include "debuggerrunner.h" #include "debuggerstringutils.h" #include "debuggerstartparameters.h" +#include "debuggertooltipmanager.h" #include "breakhandler.h" #include "disassembleragent.h" @@ -1176,11 +1177,16 @@ void DebuggerEngine::setState(DebuggerState state, bool forced) if (!forced && !isAllowedTransition(oldState, state)) qDebug() << "*** UNEXPECTED STATE TRANSITION: " << this << msg; + if (state == EngineRunRequested) { + DebuggerToolTipManager::registerEngine(this); + } + if (state == DebuggerFinished) { // Give up ownership on claimed breakpoints. BreakHandler *handler = breakHandler(); foreach (BreakpointModelId id, handler->engineBreakpointIds(this)) handler->notifyBreakpointReleased(id); + DebuggerToolTipManager::deregisterEngine(this); } showMessage(msg, LogDebug); @@ -1355,8 +1361,8 @@ DebuggerRunControl *DebuggerEngine::runControl() const return d->runControl(); } -bool DebuggerEngine::setToolTipExpression - (const QPoint &, TextEditor::ITextEditor *, const DebuggerToolTipContext &) +bool DebuggerEngine::setToolTipExpression(TextEditor::ITextEditor *, + const DebuggerToolTipContext &) { return false; } diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 453c755f4b5..718df1f1980 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -143,8 +143,8 @@ public: const DebuggerStartParameters &startParameters() const; DebuggerStartParameters &startParameters(); - virtual bool setToolTipExpression(const QPoint & mousePos, - TextEditor::ITextEditor *editor, const Internal::DebuggerToolTipContext &); + virtual bool setToolTipExpression(TextEditor::ITextEditor *editor, + const Internal::DebuggerToolTipContext &); virtual void updateWatchData(const Internal::WatchData &data, const Internal::WatchUpdateFlags & flags = Internal::WatchUpdateFlags()); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index ac39ec1cadd..5a3dbd662be 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -1202,7 +1202,6 @@ public slots: bool parseArguments(const QStringList &args, QString *errorMessage); void parseCommandLineArguments(); - DebuggerToolTipManager *toolTipManager() const { return m_toolTipManager; } QSharedPointer globalDebuggerOptions() const { return m_globalDebuggerOptions; } void updateQmlActions() { @@ -2526,7 +2525,7 @@ void DebuggerPluginPrivate::sessionLoaded() { m_breakHandler->loadSessionData(); dummyEngine()->watchHandler()->loadSessionData(); - m_toolTipManager->loadSessionData(); + DebuggerToolTipManager::loadSessionData(); } void DebuggerPluginPrivate::aboutToUnloadSession() @@ -2537,8 +2536,8 @@ void DebuggerPluginPrivate::aboutToUnloadSession() void DebuggerPluginPrivate::aboutToSaveSession() { dummyEngine()->watchHandler()->saveSessionData(); - m_toolTipManager->saveSessionData(); m_breakHandler->saveSessionData(); + DebuggerToolTipManager::saveSessionData(); } void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout) diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 1b30a6aba50..fcee2fedc2f 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -38,7 +38,6 @@ #include "debuggerrunconfigurationaspect.h" #include "debuggerstartparameters.h" #include "debuggerstringutils.h" -#include "debuggertooltipmanager.h" #include "breakhandler.h" #include "shared/peutils.h" @@ -136,9 +135,7 @@ DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration, QString errorMessage; d->m_engine = DebuggerRunControlFactory::createEngine(sp.masterEngineType, sp, &errorMessage); - if (d->m_engine) { - DebuggerToolTipManager::registerEngine(d->m_engine); - } else { + if (!d->m_engine) { debuggingFinished(); Core::ICore::showWarningWithOptions(DebuggerRunControl::tr("Debugger"), errorMessage); } diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp index 9f526a8b2b9..b4034c522f9 100644 --- a/src/plugins/debugger/debuggertooltipmanager.cpp +++ b/src/plugins/debugger/debuggertooltipmanager.cpp @@ -33,6 +33,9 @@ #include "debuggeractions.h" #include "stackhandler.h" #include "debuggercore.h" +#include "watchhandler.h" +#include "watchwindow.h" +#include "sourceutils.h" #include #include @@ -43,26 +46,24 @@ #include #include -#include -#include -#include #include +#include +#include #include +#include #include #include -#include -#include -#include - #include -#include +#include +#include +#include +#include +#include +#include using namespace Core; using namespace TextEditor; -enum { debugToolTips = 0 }; -enum { debugToolTipPositioning = 0 }; - // Expire tooltips after n days on (no longer load them) in order // to avoid them piling up. enum { toolTipsExpiryDays = 6 }; @@ -93,9 +94,6 @@ static const char modelItemElementC[] = "item"; // next start element of a desired type. static bool readStartElement(QXmlStreamReader &r, const char *name) { - if (debugToolTips > 1) - qDebug("readStartElement: looking for '%s', currently at: %s/%s", - name, qPrintable(r.tokenString()), qPrintable(r.name().toString())); while (r.tokenType() != QXmlStreamReader::StartElement || r.name() != QLatin1String(name)) switch (r.readNext()) { @@ -126,38 +124,29 @@ static void debugMode(const QAbstractItemModel *model) namespace Debugger { namespace Internal { -/* A Label that emits a signal when the user drags for moving the parent - * widget around. */ +// A label that can be dragged to drag something else. + class DraggableLabel : public QLabel { - Q_OBJECT public: - explicit DraggableLabel(QWidget *parent = 0); + explicit DraggableLabel(QWidget *target) + : m_target(target), m_moveStartPos(-1, -1), active(false) + {} - bool isActive() const { return m_active; } - void setActive(bool v) { m_active = v; } + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); -signals: - void dragged(const QPoint &d); - -protected: - virtual void mousePressEvent(QMouseEvent * event); - virtual void mouseReleaseEvent(QMouseEvent * event); - virtual void mouseMoveEvent(QMouseEvent * event); - -private: +public: + QWidget *m_target; QPoint m_moveStartPos; - bool m_active; + QPoint m_offset; + bool active; }; -DraggableLabel::DraggableLabel(QWidget *parent) : - QLabel(parent), m_moveStartPos(-1, -1), m_active(false) -{ -} - void DraggableLabel::mousePressEvent(QMouseEvent * event) { - if (m_active && event->button() == Qt::LeftButton) { + if (active && event->button() == Qt::LeftButton) { m_moveStartPos = event->globalPos(); event->accept(); } @@ -166,17 +155,21 @@ void DraggableLabel::mousePressEvent(QMouseEvent * event) void DraggableLabel::mouseReleaseEvent(QMouseEvent * event) { - if (m_active && event->button() == Qt::LeftButton) + if (active && event->button() == Qt::LeftButton) m_moveStartPos = QPoint(-1, -1); QLabel::mouseReleaseEvent(event); } void DraggableLabel::mouseMoveEvent(QMouseEvent * event) { - if (m_active && (event->buttons() & Qt::LeftButton)) { + if (active && (event->buttons() & Qt::LeftButton)) { if (m_moveStartPos != QPoint(-1, -1)) { const QPoint newPos = event->globalPos(); - emit dragged(event->globalPos() - m_moveStartPos); + const QPoint offset = newPos - m_moveStartPos; + + m_target->move(m_target->pos() + offset); + m_offset += offset; + m_moveStartPos = newPos; } event->accept(); @@ -190,7 +183,7 @@ void DraggableLabel::mouseMoveEvent(QMouseEvent * event) class DebuggerToolTipEditor { public: - explicit DebuggerToolTipEditor(IEditor *ie = 0); + explicit DebuggerToolTipEditor(IEditor *ie); bool isValid() const { return editor; } QString fileName() const { return editor->document() ? editor->document()->filePath() : QString(); } @@ -273,8 +266,8 @@ void StandardItemTreeModelBuilder::endRow() m_rowParents.pop(); } -/* Helper visitor base class for recursing over a tree model - * (see StandardItemTreeModelBuilder for the scheme). */ +// Helper visitor base class for recursing over a tree model +// (see StandardItemTreeModelBuilder for the scheme). class TreeModelVisitor { public: @@ -430,9 +423,6 @@ void DumpTreeModelVisitor::rowEnded() m_level--; } -} // namespace Internal -} // namespace Debugger - /* static QDebug operator<<(QDebug d, const QAbstractItemModel &model) { @@ -445,10 +435,51 @@ static QDebug operator<<(QDebug d, const QAbstractItemModel &model) } */ -namespace Debugger { -namespace Internal { +/*! + \class Debugger::Internal::TooltipFilterModel + + \brief The TooltipFilterModel class is a model for tooltips filtering an + item on the watchhandler matching its tree on the iname. + + In addition, suppress the model's tooltip data to avoid a tooltip on a tooltip. +*/ + +class TooltipFilterModel : public QSortFilterProxyModel +{ +public: + TooltipFilterModel() {} + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + { + return role == Qt::ToolTipRole + ? QVariant() : QSortFilterProxyModel::data(index, role); + } + + static bool isSubIname(const QByteArray &haystack, const QByteArray &needle) + { + return haystack.size() > needle.size() + && haystack.startsWith(needle) + && haystack.at(needle.size()) == '.'; + } + + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const + { + const QModelIndex nameIndex = sourceModel()->index(sourceRow, 0, sourceParent); + const QByteArray iname = nameIndex.data(LocalsINameRole).toByteArray(); +// qDebug() << "ACCEPTING FILTER" << iname +// << (iname == m_iname || isSubIname(iname, m_iname) || isSubIname(m_iname, iname)); + return iname == m_iname || isSubIname(iname, m_iname) || isSubIname(m_iname, iname); + } + + QByteArray m_iname; +}; + +///////////////////////////////////////////////////////////////////////// +// +// TreeModelCopyVisitor builds a QStandardItem from a tree model (copy). +// +///////////////////////////////////////////////////////////////////////// -// Visitor building a QStandardItem from a tree model (copy). class TreeModelCopyVisitor : public TreeModelVisitor { public: @@ -465,6 +496,82 @@ private: StandardItemTreeModelBuilder m_builder; }; +class DebuggerToolTipWidget; +class DebuggerToolTipManagerData +{ +public: + DebuggerToolTipManagerData() + : m_debugModeActive(false), m_lastToolTipPoint(-1, -1), m_lastToolTipEditor(0) + {} + + void purgeClosedToolTips() + { + for (int i = m_tooltips.size(); --i >= 0; ) + if (!m_tooltips.at(i)) + m_tooltips.removeAt(i); + } + + QList > m_tooltips; + bool m_debugModeActive; + QPoint m_lastToolTipPoint; + Core::IEditor *m_lastToolTipEditor; +}; + +static DebuggerToolTipManagerData *d = 0; + + +///////////////////////////////////////////////////////////////////////// +// +// DebuggerToolTipWidget +// +///////////////////////////////////////////////////////////////////////// + +class DebuggerToolTipWidget : public QWidget +{ + Q_OBJECT + +public: + DebuggerToolTipWidget(const DebuggerToolTipContext &context); + + bool isPinned() const { return m_isPinned; } + QString fileName() const { return m_context.fileName; } + QString function() const { return m_context.function; } + int position() const { return m_context.position; } + + const DebuggerToolTipContext &context() const { return m_context; } + + void acquireEngine(); + void releaseEngine(); + + void saveSessionData(QXmlStreamWriter &w) const; + void setWatchModel(QAbstractItemModel *watchModel); + void handleStackFrameCompleted(const QString &frameFile, const QString &frameFunction); + +public slots: + void handleItemIsExpanded(const QModelIndex &sourceIdx) + { + QTC_ASSERT(m_filterModel.sourceModel() == sourceIdx.model(), return); + QModelIndex mappedIdx = m_filterModel.mapFromSource(sourceIdx); + if (!m_treeView->isExpanded(mappedIdx)) + m_treeView->expand(mappedIdx); + } + + void copy(); + void positionShow(const DebuggerToolTipEditor &pe); + void pin(); + void toolButtonClicked(); + +private: +public: + bool m_isPinned; + QToolButton *m_toolButton; + DraggableLabel *m_titleLabel; + QDate m_creationDate; + DebuggerToolTipTreeView *m_treeView; //!< Pointing to either m_defaultModel oder m_filterModel + DebuggerToolTipContext m_context; + TooltipFilterModel m_filterModel; //!< Pointing to a valid watchModel + QStandardItemModel m_defaultModel; +}; void DebuggerToolTipWidget::pin() { @@ -481,7 +588,7 @@ void DebuggerToolTipWidget::pin() // We have just be restored from session data. setWindowFlags(Qt::ToolTip); } - m_titleLabel->setActive(true); // User can now drag + m_titleLabel->active = true; // User can now drag } void DebuggerToolTipWidget::toolButtonClicked() @@ -503,27 +610,28 @@ void DebuggerToolTipWidget::toolButtonClicked() on restoring. */ -DebuggerToolTipContext::DebuggerToolTipContext() : position(0), line(0), column(0) +DebuggerToolTipContext::DebuggerToolTipContext() + : position(0), line(0), column(0) { } -DebuggerToolTipContext DebuggerToolTipContext::fromEditor(IEditor *ie, int pos) +bool DebuggerToolTipContext::matchesFrame(const QString &frameFile, const QString &frameFunction) const { - DebuggerToolTipContext rc; - if (const IDocument *document = ie->document()) { - if (const ITextEditor *te = qobject_cast(ie)) { - rc.fileName = document->filePath(); - rc.position = pos; - te->convertPosition(pos, &rc.line, &rc.column); - } - } - return rc; + return (fileName.isEmpty() || frameFile.isEmpty() || fileName == frameFile) + && (function.isEmpty() || frameFunction.isEmpty() || function == frameFunction); +} + +bool DebuggerToolTipContext::isSame(const DebuggerToolTipContext &other) const +{ + return fileName == other.fileName + && function == other.function + && iname == other.iname; } QDebug operator<<(QDebug d, const DebuggerToolTipContext &c) { QDebug nsp = d.nospace(); - nsp << c.fileName << '@' << c.line << ',' << c.column << " (" << c.position << ')'; + nsp << c.fileName << '@' << c.line << ',' << c.column << " (" << c.position << ')' << "INAME: " << c.iname << " EXP: " << c.expression; if (!c.function.isEmpty()) nsp << ' ' << c.function << "()"; return d; @@ -570,141 +678,189 @@ QDebug operator<<(QDebug d, const DebuggerToolTipContext &c) static QString msgReleasedText() { return DebuggerToolTipWidget::tr("Previous"); } -DebuggerToolTipWidget::DebuggerToolTipWidget(QWidget *parent) : - QWidget(parent), - m_isPinned(false), - m_toolButton(new QToolButton), - m_titleLabel(new DraggableLabel), - m_engineAcquired(false), - m_creationDate(QDate::currentDate()), - m_treeView(new DebuggerToolTipTreeView(this)), - m_defaultModel(new QStandardItemModel(this)) +DebuggerToolTipWidget::DebuggerToolTipWidget(const DebuggerToolTipContext &context) { + setFocusPolicy(Qt::NoFocus); + + m_isPinned = false; + m_context = context; + m_filterModel.m_iname = context.iname; + const QIcon pinIcon(QLatin1String(":/debugger/images/pin.xpm")); - const QList pinIconSizes = pinIcon.availableSizes(); + m_toolButton = new QToolButton; m_toolButton->setIcon(pinIcon); - connect(m_toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked())); - QToolButton *copyButton = new QToolButton; + auto copyButton = new QToolButton; copyButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_COPY))); - connect(copyButton, SIGNAL(clicked()), this, SLOT(copy())); + m_titleLabel = new DraggableLabel(this); m_titleLabel->setText(msgReleasedText()); m_titleLabel->setMinimumWidth(40); // Ensure a draggable area even if text is empty. - connect(m_titleLabel, SIGNAL(dragged(QPoint)), this, SLOT(slotDragged(QPoint))); - QToolBar *toolBar = new QToolBar(this); + auto toolBar = new QToolBar(this); toolBar->setProperty("_q_custom_style_disabled", QVariant(true)); + const QList pinIconSizes = pinIcon.availableSizes(); if (!pinIconSizes.isEmpty()) toolBar->setIconSize(pinIconSizes.front()); toolBar->addWidget(m_toolButton); toolBar->addWidget(m_titleLabel); toolBar->addWidget(copyButton); + m_treeView = new DebuggerToolTipTreeView(this); m_treeView->setFocusPolicy(Qt::NoFocus); - QVBoxLayout *mainLayout = new QVBoxLayout(this); + auto mainLayout = new QVBoxLayout(this); mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->addWidget(toolBar); mainLayout->addWidget(m_treeView); + + connect(m_toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked())); + connect(copyButton, SIGNAL(clicked()), this, SLOT(copy())); } -bool DebuggerToolTipWidget::matches(const QString &fileName, - const QString &engineType, - const QString &function) const +void DebuggerToolTipWidget::setWatchModel(QAbstractItemModel *watchModel) { - if (fileName.isEmpty() || m_context.fileName != fileName) - return false; - // Optional. - if (!engineType.isEmpty() && engineType != m_engineType) - return false; - if (function.isEmpty() || m_context.function.isEmpty()) - return true; - return function == m_context.function; + QTC_ASSERT(watchModel, return); + m_filterModel.setSourceModel(watchModel); + connect(watchModel, SIGNAL(itemIsExpanded(QModelIndex)), + this, SLOT(handleItemIsExpanded(QModelIndex)), Qt::UniqueConnection); + connect(watchModel, SIGNAL(columnAdjustmentRequested()), + m_treeView, SLOT(computeSize()), Qt::UniqueConnection); } -void DebuggerToolTipWidget::acquireEngine(DebuggerEngine *engine) +void DebuggerToolTipWidget::handleStackFrameCompleted(const QString &frameFile, const QString &frameFunction) { - QTC_ASSERT(engine, return); + const bool sameFrame = m_context.matchesFrame(frameFile, frameFunction); + const bool isAcquired = m_treeView->model() == &m_filterModel; + if (isAcquired && !sameFrame) + releaseEngine(); + else if (!isAcquired && sameFrame) + acquireEngine(); - if (debugToolTips) - qDebug() << this << " acquiring" << engine << m_engineAcquired; - if (m_engineAcquired) - return; - doAcquireEngine(engine); - m_engineType = engine->objectName(); - m_engineAcquired = true; - m_titleLabel->setText(QString()); + if (isAcquired) { + m_treeView->expand(m_filterModel.index(0, 0)); + WatchTreeView::reexpand(m_treeView, m_filterModel.index(0, 0)); + } +} + +void DebuggerToolTipWidget::acquireEngine() +{ + m_titleLabel->setText(m_context.expression); + m_treeView->setModel(&m_filterModel); + m_treeView->setRootIndex(m_filterModel.index(0, 0)); + m_treeView->expand(m_filterModel.index(0, 0)); + WatchTreeView::reexpand(m_treeView, m_filterModel.index(0, 0)); } void DebuggerToolTipWidget::releaseEngine() { - // Release engine of same type - if (!m_engineAcquired) - return; - if (debugToolTips) - qDebug() << "releaseEngine" << this; - doReleaseEngine(); + // Save data to stream and restore to the backup m_defaultModel. + m_defaultModel.removeRows(0, m_defaultModel.rowCount()); + TreeModelCopyVisitor v(&m_filterModel, &m_defaultModel); + v.run(); + m_titleLabel->setText(msgReleasedText()); - m_engineAcquired = false; + m_treeView->setModel(&m_defaultModel); + m_treeView->setRootIndex(m_defaultModel.index(0, 0)); + m_treeView->expandAll(); } void DebuggerToolTipWidget::copy() { - const QString clipboardText = clipboardContents(); + QString clipboardText = DebuggerToolTipManager::treeModelClipboardContents(m_treeView->model()); QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(clipboardText, QClipboard::Selection); clipboard->setText(clipboardText, QClipboard::Clipboard); } -void DebuggerToolTipWidget::slotDragged(const QPoint &p) -{ - move(pos() + p); - m_offset += p; -} - -bool DebuggerToolTipWidget::positionShow(const DebuggerToolTipEditor &te) +void DebuggerToolTipWidget::positionShow(const DebuggerToolTipEditor &te) { // Figure out new position of tooltip using the text edit. // If the line changed too much, close this tip. - QTC_ASSERT(te.isValid(), return false); + QTC_ASSERT(te.isValid(), return); QTextCursor cursor(te.widget->document()); cursor.setPosition(m_context.position); const int line = cursor.blockNumber(); if (qAbs(m_context.line - line) > 2) { - if (debugToolTips) - qDebug() << "Closing " << this << " in positionShow() lines " - << line << m_context.line; close(); - return false; + return ; } - if (debugToolTipPositioning) - qDebug() << "positionShow" << this << line << cursor.columnNumber(); - const QPoint screenPos = te.widget->toolTipPosition(cursor) + m_offset; + const QPoint screenPos = te.widget->toolTipPosition(cursor) + m_titleLabel->m_offset; const QRect toolTipArea = QRect(screenPos, QSize(sizeHint())); const QRect plainTextArea = QRect(te.widget->mapToGlobal(QPoint(0, 0)), te.widget->size()); - const bool visible = plainTextArea.contains(toolTipArea); - if (debugToolTips) - qDebug() << "DebuggerToolTipWidget::positionShow() " << this << m_context - << " line: " << line << " plainTextPos " << toolTipArea - << " offset: " << m_offset - << " Area: " << plainTextArea << " Screen pos: " - << screenPos << te.widget << " visible=" << visible; + const bool visible = plainTextArea.intersects(toolTipArea); + // qDebug() << "DebuggerToolTipWidget::positionShow() " << this << m_context + // << " line: " << line << " plainTextPos " << toolTipArea + // << " offset: " << m_titleLabel->m_offset + // << " Area: " << plainTextArea << " Screen pos: " + // << screenPos << te.widget << " visible=" << visible; if (!visible) { hide(); - return false; + return; } move(screenPos); show(); - return true; } - // Parse a 'yyyyMMdd' date +static DebuggerToolTipWidget *findOrCreateWidget(const DebuggerToolTipContext &context) +{ + foreach (const QPointer &tw, d->m_tooltips) + if (tw && tw->m_context.isSame(context)) + return tw; + + auto tw = new DebuggerToolTipWidget(context); + tw->setAttribute(Qt::WA_DeleteOnClose); + tw->setObjectName(QLatin1String("DebuggerTreeViewToolTipWidget: ") + QLatin1String(context.iname)); + tw->m_context.creationDate = QDate::currentDate(); + + d->m_tooltips.push_back(tw); + + return tw; +} + +static void restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m) +{ + StandardItemTreeModelBuilder builder(m); + int columnCount = 1; + bool withinModel = true; + while (withinModel && !r.atEnd()) { + const QXmlStreamReader::TokenType token = r.readNext(); + switch (token) { + case QXmlStreamReader::StartElement: { + const QStringRef element = r.name(); + // Root model element with column count. + if (element == QLatin1String(modelElementC)) { + if (const int cc = r.attributes().value(QLatin1String(modelColumnCountAttributeC)).toString().toInt()) + columnCount = cc; + m->setColumnCount(columnCount); + } else if (element == QLatin1String(modelRowElementC)) { + builder.startRow(); + } else if (element == QLatin1String(modelItemElementC)) { + builder.addItem(r.readElementText()); + } + } + break; // StartElement + case QXmlStreamReader::EndElement: { + const QStringRef element = r.name(); + // Row closing: pop off parent. + if (element == QLatin1String(modelRowElementC)) + builder.endRow(); + else if (element == QLatin1String(modelElementC)) + withinModel = false; + } + break; // EndElement + default: + break; + } // switch + } // while +} + +// Parse a 'yyyyMMdd' date static QDate dateFromString(const QString &date) { return date.size() == 8 ? @@ -712,20 +868,10 @@ static QDate dateFromString(const QString &date) QDate(); } -DebuggerToolTipWidget *DebuggerToolTipWidget::loadSessionData(QXmlStreamReader &r) -{ - if (debugToolTips) - qDebug() << ">DebuggerToolTipWidget::loadSessionData" << r.tokenString() << r.name(); - DebuggerToolTipWidget *rc = DebuggerToolTipWidget::loadSessionDataI(r); - if (debugToolTips) - qDebug() << " toolTipsExpiryDays) { - if (debugToolTips) - qDebug() << "Expiring tooltip " << context.fileName << '@' << context.position << " from " << creationDate; - r.readElementText(QXmlStreamReader::SkipChildElements); // Skip - return 0; - } - if (debugToolTips) - qDebug() << "Creating tooltip " << context << " from " << creationDate << offset; - DebuggerToolTipWidget *rc = 0; - if (className == QLatin1String("Debugger::Internal::DebuggerToolTipWidget")) - rc = new DebuggerToolTipWidget; - if (rc) { - rc->setContext(context); - rc->setAttribute(Qt::WA_DeleteOnClose); - rc->setEngineType(engineType); - rc->doLoadSessionData(r); - rc->setCreationDate(creationDate); - rc->pin(); - } else { + context.engineType = attributes.value(QLatin1String(engineTypeAttributeC)).toString(); + context.creationDate = dateFromString(attributes.value(QLatin1String(dateAttributeC)).toString()); + bool readTree = context.isValid(); + if (!context.creationDate.isValid() || context.creationDate.daysTo(QDate::currentDate()) > toolTipsExpiryDays) { + // qDebug() << "Expiring tooltip " << context.fileName << '@' << context.position << " from " << creationDate; + //readTree = false; + } else if (className != QLatin1String("Debugger::Internal::DebuggerToolTipWidget")) { qWarning("Unable to create debugger tool tip widget of class %s", qPrintable(className.toString())); + readTree = false; + } + + if (readTree) { + DebuggerToolTipWidget *tw = findOrCreateWidget(context); + restoreTreeModel(r, &tw->m_defaultModel); + tw->pin(); + tw->acquireEngine(); + tw->m_titleLabel->setText(DebuggerToolTipManager::tr("Restored")); + tw->m_treeView->setModel(&tw->m_defaultModel); + tw->m_treeView->setRootIndex(tw->m_defaultModel.index(0, 0)); + tw->m_treeView->expandAll(); + } else { r.readElementText(QXmlStreamReader::SkipChildElements); // Skip } - return rc; + + r.readNext(); // Skip } void DebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const @@ -782,61 +931,23 @@ void DebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const attributes.append(QLatin1String(textLineAttributeC), QString::number(m_context.line)); attributes.append(QLatin1String(textColumnAttributeC), QString::number(m_context.column)); attributes.append(QLatin1String(dateAttributeC), m_creationDate.toString(QLatin1String("yyyyMMdd"))); - if (m_offset.x()) - attributes.append(QLatin1String(offsetXAttributeC), QString::number(m_offset.x())); - if (m_offset.y()) - attributes.append(QLatin1String(offsetYAttributeC), QString::number(m_offset.y())); - if (!m_engineType.isEmpty()) - attributes.append(QLatin1String(engineTypeAttributeC), m_engineType); + if (m_titleLabel->m_offset.x()) + attributes.append(QLatin1String(offsetXAttributeC), QString::number(m_titleLabel->m_offset.x())); + if (m_titleLabel->m_offset.y()) + attributes.append(QLatin1String(offsetYAttributeC), QString::number(m_titleLabel->m_offset.y())); + attributes.append(QLatin1String(engineTypeAttributeC), m_context.engineType); + attributes.append(QLatin1String(treeExpressionAttributeC), m_context.expression); + attributes.append(QLatin1String(treeInameAttributeC), QLatin1String(m_context.iname)); w.writeAttributes(attributes); - doSaveSessionData(w); + + w.writeStartElement(QLatin1String(treeElementC)); + XmlWriterTreeModelVisitor v(&m_filterModel, w); + v.run(); + w.writeEndElement(); + w.writeEndElement(); } -/*! - \class Debugger::Internal::TooltipFilterModel - - \brief The TooltipFilterModel class is a model for tooltips filtering an - item on the watchhandler matching its tree on the iname. - - In addition, suppress the model's tooltip data to avoid a tooltip on a tooltip. -*/ - -class TooltipFilterModel : public QSortFilterProxyModel -{ -public: - TooltipFilterModel(QAbstractItemModel *model, const QByteArray &iname) - : m_iname(iname) - { - setSourceModel(model); - } - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const - { - return role == Qt::ToolTipRole - ? QVariant() : QSortFilterProxyModel::data(index, role); - } - - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; - -private: - const QByteArray m_iname; -}; - -static bool isSubIname(const QByteArray &haystack, const QByteArray &needle) -{ - return haystack.size() > needle.size() - && haystack.startsWith(needle) - && haystack.at(needle.size()) == '.'; -} - -bool TooltipFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const -{ - const QModelIndex nameIndex = sourceModel()->index(sourceRow, 0, sourceParent); - const QByteArray iname = nameIndex.data(LocalsINameRole).toByteArray(); - return iname == m_iname || isSubIname(iname, m_iname) || isSubIname(m_iname, iname); -} - /*! \class Debugger::Internal::DebuggerToolTipTreeView @@ -877,31 +988,6 @@ void DebuggerToolTipTreeView::collapseNode(const QModelIndex &idx) model()->setData(idx, false, LocalsExpandedRole); } -void DebuggerToolTipTreeView::handleItemIsExpanded(const QModelIndex &sourceIdx) -{ - QSortFilterProxyModel *filterModel = qobject_cast(model()); - QModelIndex mappedIdx = filterModel ? filterModel->mapFromSource(sourceIdx) : sourceIdx; - if (!isExpanded(mappedIdx)) - expand(mappedIdx); -} - -QAbstractItemModel *DebuggerToolTipTreeView::swapModel(QAbstractItemModel *newModel) -{ - QAbstractItemModel *previousModel = model(); - if (previousModel != newModel) { - if (previousModel) - previousModel->disconnect(SIGNAL(rowsInserted(QModelIndex,int,int)), this); - setModel(newModel); - connect(newModel, SIGNAL(rowsInserted(QModelIndex,int,int)), - SLOT(computeSize()), Qt::QueuedConnection); - if (QSortFilterProxyModel *filterModel = qobject_cast(newModel)) { - connect(filterModel->sourceModel(), SIGNAL(itemIsExpanded(QModelIndex)), - SLOT(handleItemIsExpanded(QModelIndex))); - } - } - return previousModel; -} - int DebuggerToolTipTreeView::computeHeight(const QModelIndex &index) const { int s = rowHeight(index); @@ -913,6 +999,7 @@ int DebuggerToolTipTreeView::computeHeight(const QModelIndex &index) const void DebuggerToolTipTreeView::computeSize() { + WatchTreeView::reexpand(this, model()->index(0, 0)); int columns = 30; // Decoration int rows = 0; bool rootDecorated = false; @@ -960,131 +1047,18 @@ void DebuggerToolTipTreeView::computeSize() setMinimumSize(m_size); setMaximumSize(m_size); setRootIsDecorated(rootDecorated); - - // This pretty much feels like a hack. - // But it "solves" QTCREATORBUG-9852 - QApplication::processEvents(); - viewport()->update(); } -void DebuggerToolTipWidget::doAcquireEngine(DebuggerEngine *engine) -{ - // Create a filter model on the debugger's model and switch to it. - QAbstractItemModel *model = engine->watchModel(); - TooltipFilterModel *filterModel = - new TooltipFilterModel(model, m_context.iname); - swapModel(filterModel); -} - -QAbstractItemModel *DebuggerToolTipWidget::swapModel(QAbstractItemModel *newModel) -{ - QAbstractItemModel *oldModel = m_treeView->swapModel(newModel); - // When looking at some 'this.m_foo.x', expand all items - if (newModel) { - if (const int level = m_context.iname.count('.')) { - QModelIndex index = newModel->index(0, 0); - for (int i = 0; i < level && index.isValid(); i++, index = index.child(0, 0)) - m_treeView->setExpanded(index, true); - } - } - return oldModel; -} - -void DebuggerToolTipWidget::doReleaseEngine() -{ - // Save data to stream and restore to the m_defaultModel (QStandardItemModel) - m_defaultModel->removeRows(0, m_defaultModel->rowCount()); - if (const QAbstractItemModel *model = m_treeView->model()) { - TreeModelCopyVisitor v(model, m_defaultModel); - v.run(); - } - delete swapModel(m_defaultModel); -} - -void DebuggerToolTipWidget::restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m) -{ - StandardItemTreeModelBuilder builder(m); - int columnCount = 1; - bool withinModel = true; - while (withinModel && !r.atEnd()) { - const QXmlStreamReader::TokenType token = r.readNext(); - switch (token) { - case QXmlStreamReader::StartElement: { - const QStringRef element = r.name(); - // Root model element with column count. - if (element == QLatin1String(modelElementC)) { - if (const int cc = r.attributes().value(QLatin1String(modelColumnCountAttributeC)).toString().toInt()) - columnCount = cc; - m->setColumnCount(columnCount); - } else if (element == QLatin1String(modelRowElementC)) { - builder.startRow(); - } else if (element == QLatin1String(modelItemElementC)) { - builder.addItem(r.readElementText()); - } - } - break; // StartElement - case QXmlStreamReader::EndElement: { - const QStringRef element = r.name(); - // Row closing: pop off parent. - if (element == QLatin1String(modelRowElementC)) - builder.endRow(); - else if (element == QLatin1String(modelElementC)) - withinModel = false; - } - break; // EndElement - default: - break; - } // switch - } // while -} - -void DebuggerToolTipWidget::doSaveSessionData(QXmlStreamWriter &w) const -{ - w.writeStartElement(QLatin1String(treeElementC)); - QXmlStreamAttributes attributes; - if (!m_context.expression.isEmpty()) - attributes.append(QLatin1String(treeExpressionAttributeC), m_context.expression); - attributes.append(QLatin1String(treeInameAttributeC), QLatin1String(m_context.iname)); - w.writeAttributes(attributes); - if (QAbstractItemModel *model = m_treeView->model()) { - XmlWriterTreeModelVisitor v(model, w); - v.run(); - } - w.writeEndElement(); -} - -void DebuggerToolTipWidget::doLoadSessionData(QXmlStreamReader &r) -{ - if (!readStartElement(r, treeElementC)) - return; - // Restore data to default model and show that. - const QXmlStreamAttributes attributes = r.attributes(); - m_context.iname = attributes.value(QLatin1String(treeInameAttributeC)).toString().toLatin1(); - m_context.expression = attributes.value(QLatin1String(treeExpressionAttributeC)).toString(); - if (debugToolTips) - qDebug() << "DebuggerTreeViewToolTipWidget::doLoadSessionData() " << m_debuggerModel << m_context.iname; - setObjectName(QLatin1String("DebuggerTreeViewToolTipWidget: ") + QLatin1String(m_context.iname)); - restoreTreeModel(r, m_defaultModel); - r.readNext(); // Skip - m_treeView->swapModel(m_defaultModel); -} - -QString DebuggerToolTipWidget::treeModelClipboardContents(const QAbstractItemModel *m) +QString DebuggerToolTipManager::treeModelClipboardContents(const QAbstractItemModel *model) { QString rc; + QTC_ASSERT(model, return rc); QTextStream str(&rc); - DumpTreeModelVisitor v(m, DumpTreeModelVisitor::ClipboardMode, str); + DumpTreeModelVisitor v(model, DumpTreeModelVisitor::ClipboardMode, str); v.run(); return rc; } -QString DebuggerToolTipWidget::clipboardContents() const -{ - if (const QAbstractItemModel *model = m_treeView->model()) - return DebuggerToolTipWidget::treeModelClipboardContents(model); - return QString(); -} - /*! \class Debugger::Internal::DebuggerToolTipManager @@ -1100,27 +1074,6 @@ QString DebuggerToolTipWidget::clipboardContents() const (by file name and function) acquire the engine, others release. */ -typedef QList > DebuggerToolTipWidgetList; -class DebuggerToolTipManagerData -{ -public: - DebuggerToolTipManagerData() - : m_debugModeActive(false), m_lastToolTipPoint(-1, -1), m_lastToolTipEditor(0) - {} - - void registerToolTip(DebuggerToolTipWidget *toolTipWidget); - void moveToolTipsBy(const QPoint &distance); - // Purge out closed (null) tooltips and return list for convenience - void purgeClosedToolTips(); - - DebuggerToolTipWidgetList m_tooltips; - - bool m_debugModeActive; - QPoint m_lastToolTipPoint; - Core::IEditor *m_lastToolTipEditor; -}; - -static DebuggerToolTipManagerData *d = 0; static DebuggerToolTipManager *m_instance = 0; DebuggerToolTipManager::DebuggerToolTipManager(QObject *parent) : @@ -1136,12 +1089,42 @@ DebuggerToolTipManager::~DebuggerToolTipManager() m_instance = 0; } -void DebuggerToolTipManager::registerEngine(DebuggerEngine *engine) +void DebuggerToolTipManager::registerEngine(DebuggerEngine *) { - connect(engine, SIGNAL(stateChanged(Debugger::DebuggerState)), - m_instance, SLOT(slotDebuggerStateChanged(Debugger::DebuggerState))); - connect(engine, SIGNAL(stackFrameCompleted()), - m_instance, SLOT(slotStackFrameCompleted())); + loadSessionData(); +} + +void DebuggerToolTipManager::updateEngine(DebuggerEngine *engine) +{ + QTC_ASSERT(engine, return); + d->purgeClosedToolTips(); + if (d->m_tooltips.isEmpty()) + return; + + // Stack frame changed: All tooltips of that file acquire the engine, + // all others release (arguable, this could be more precise?) + QString fileName; + QString function; + const int index = engine->stackHandler()->currentIndex(); + if (index >= 0) { + const StackFrame frame = engine->stackHandler()->currentFrame(); + if (frame.usable) { + fileName = frame.file; + function = frame.function; + } + } + foreach (const QPointer &tw, d->m_tooltips) + tw->handleStackFrameCompleted(fileName, function); + slotUpdateVisibleToolTips(); // Move out when stepping in same file. +} + +void DebuggerToolTipManager::deregisterEngine(DebuggerEngine *engine) +{ + QTC_ASSERT(engine, return); + foreach (const QPointer &tw, d->m_tooltips) + if (tw && tw->m_context.engineType == engine->objectName()) + tw->releaseEngine(); + saveSessionData(); } bool DebuggerToolTipManager::hasToolTips() @@ -1149,37 +1132,18 @@ bool DebuggerToolTipManager::hasToolTips() return !d->m_tooltips.isEmpty(); } -void DebuggerToolTipManager::showToolTip(const QPoint &p, DebuggerToolTipWidget *toolTipWidget) +void DebuggerToolTipManager::showToolTip + (const DebuggerToolTipContext &context, DebuggerEngine *engine) { - if (debugToolTipPositioning) - qDebug() << "DebuggerToolTipManager::showToolTip" << p << " Mouse at " << QCursor::pos(); - const Utils::WidgetContent widgetContent(toolTipWidget, true); - Utils::ToolTip::show(p, widgetContent, debuggerCore()->mainWindow()); - d->registerToolTip(toolTipWidget); -} + QTC_ASSERT(engine, return); + QTC_ASSERT(!context.expression.isEmpty(), qDebug(" BUT EMPTY"); return); -void DebuggerToolTipManagerData::registerToolTip(DebuggerToolTipWidget *toolTipWidget) -{ - QTC_ASSERT(toolTipWidget->context().isValid(), return); - m_tooltips.push_back(toolTipWidget); -} + DebuggerToolTipWidget *tw = findOrCreateWidget(context); + tw->setWatchModel(engine->watchHandler()->model()); + tw->acquireEngine(); -void DebuggerToolTipManagerData::purgeClosedToolTips() -{ - for (DebuggerToolTipWidgetList::iterator it = m_tooltips.begin(); it != m_tooltips.end() ; ) { - if (it->isNull()) - it = m_tooltips.erase(it); - else - ++it; - } -} - -void DebuggerToolTipManagerData::moveToolTipsBy(const QPoint &distance) -{ - purgeClosedToolTips(); - foreach (const QPointer &tw, m_tooltips) - if (tw->isVisible()) - tw->move(tw->pos() + distance); + const Utils::WidgetContent widgetContent(tw, true); + Utils::ToolTip::show(context.mousePosition, widgetContent, debuggerCore()->mainWindow()); } bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e) @@ -1189,8 +1153,12 @@ bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e) switch (e->type()) { case QEvent::Move: { // Move along with parent (toplevel) const QMoveEvent *me = static_cast(e); - d->moveToolTipsBy(me->pos() - me->oldPos()); - } + const QPoint dist = me->pos() - me->oldPos(); + d->purgeClosedToolTips(); + foreach (const QPointer &tw, d->m_tooltips) + if (tw->isVisible()) + tw->move(tw->pos() + dist); + } break; case QEvent::WindowStateChange: { // Hide/Show along with parent (toplevel) const QWindowStateChangeEvent *se = static_cast(e); @@ -1217,46 +1185,32 @@ void DebuggerToolTipManager::sessionAboutToChange() void DebuggerToolTipManager::loadSessionData() { const QString data = DebuggerCore::sessionValue(sessionSettingsKeyC).toString(); - if (data.isEmpty()) - return; QXmlStreamReader r(data); r.readNextStartElement(); - if (r.tokenType() != QXmlStreamReader::StartElement || r.name() != QLatin1String(sessionDocumentC)) - return; - const double version = r.attributes().value(QLatin1String(sessionVersionAttributeC)).toString().toDouble(); - while (!r.atEnd()) - if (DebuggerToolTipWidget *tw = DebuggerToolTipWidget::loadSessionData(r)) - d->registerToolTip(tw); - - if (debugToolTips) - qDebug() << "DebuggerToolTipManager::loadSessionData version " << version << " restored " << d->m_tooltips.size(); - slotUpdateVisibleToolTips(); + if (r.tokenType() == QXmlStreamReader::StartElement && r.name() == QLatin1String(sessionDocumentC)) + while (!r.atEnd()) + loadSessionDataI(r); } void DebuggerToolTipManager::saveSessionData() { QString data; d->purgeClosedToolTips(); - if (!d->m_tooltips.isEmpty()) { - QXmlStreamWriter w(&data); - w.writeStartDocument(); - w.writeStartElement(QLatin1String(sessionDocumentC)); - w.writeAttribute(QLatin1String(sessionVersionAttributeC), QLatin1String("1.0")); - foreach (const QPointer &tw, d->m_tooltips) - if (tw->isPinned()) - tw->saveSessionData(w); - w.writeEndDocument(); - } - if (debugToolTips) - qDebug() << "DebuggerToolTipManager::saveSessionData" << d->m_tooltips.size() << data ; + + QXmlStreamWriter w(&data); + w.writeStartDocument(); + w.writeStartElement(QLatin1String(sessionDocumentC)); + w.writeAttribute(QLatin1String(sessionVersionAttributeC), QLatin1String("1.0")); + foreach (const QPointer &tw, d->m_tooltips) + if (tw->isPinned()) + tw->saveSessionData(w); + w.writeEndDocument(); + DebuggerCore::setSessionValue(sessionSettingsKeyC, QVariant(data)); } void DebuggerToolTipManager::closeAllToolTips() { - if (debugToolTips) - qDebug() << "DebuggerToolTipManager::closeAllToolTips"; - d->purgeClosedToolTips(); foreach (const QPointer &tw, d->m_tooltips) tw->close(); @@ -1280,9 +1234,6 @@ void DebuggerToolTipManager::slotUpdateVisibleToolTips() return; } - if (debugToolTips) - qDebug() << "DebuggerToolTipManager::slotUpdateVisibleToolTips() " << sender(); - DebuggerToolTipEditor toolTipEditor = DebuggerToolTipEditor(EditorManager::currentEditor()); if (!toolTipEditor.isValid() || toolTipEditor.fileName().isEmpty()) { hide(); @@ -1304,23 +1255,12 @@ void DebuggerToolTipManager::slotDebuggerStateChanged(DebuggerState state) const QObject *engine = sender(); QTC_ASSERT(engine, return); - const QString name = engine->objectName(); - if (debugToolTips) - qDebug() << "DebuggerToolTipWidget::debuggerStateChanged" - << engine << DebuggerEngine::stateName(state); - // Release at earliest possible convenience. switch (state) { - case InferiorRunRequested: - case DebuggerNotReady: case InferiorShutdownRequested: case EngineShutdownRequested: case DebuggerFinished: case EngineShutdownOk: { - d->purgeClosedToolTips(); - foreach (const QPointer &tw, d->m_tooltips) - if (tw->engineType() == name) - tw->releaseEngine(); break; } default: @@ -1328,54 +1268,6 @@ void DebuggerToolTipManager::slotDebuggerStateChanged(DebuggerState state) } } -void DebuggerToolTipManager::slotStackFrameCompleted() -{ - d->purgeClosedToolTips(); - if (d->m_tooltips.isEmpty()) - return; - DebuggerEngine *engine = qobject_cast(sender()); - QTC_ASSERT(engine, return); - - // Stack frame changed: All tooltips of that file acquire the engine, - // all others release (arguable, this could be more precise?) - QString fileName; - int lineNumber = 0; - // Get the current frame. - const QString engineName = engine->objectName(); - QString function; - const int index = engine->stackHandler()->currentIndex(); - if (index >= 0) { - const StackFrame frame = engine->stackHandler()->currentFrame(); - if (frame.usable) { - fileName = frame.file; - lineNumber = frame.line; - function = frame.function; - } - } - if (debugToolTips) - qDebug("DebuggerToolTipWidget::slotStackFrameCompleted(%s, %s@%d, %s())", - qPrintable(engineName), qPrintable(fileName), lineNumber, - qPrintable(function)); - unsigned acquiredCount = 0; - foreach (const QPointer &tw, d->m_tooltips) { - if (tw->matches(fileName, engineName, function)) { - tw->acquireEngine(engine); - acquiredCount++; - } else { - tw->releaseEngine(); - } - } - slotUpdateVisibleToolTips(); // Move out when stepping in same file. - if (debugToolTips) - qDebug() << "DebuggerToolTipWidget::slotStackFrameCompleted()" - << engineName << fileName << lineNumber << " acquired " << acquiredCount; -} - -bool DebuggerToolTipManager::debug() -{ - return debugToolTips; -} - void DebuggerToolTipManager::slotEditorOpened(IEditor *e) { // Move tooltip along when scrolled. @@ -1391,9 +1283,6 @@ void DebuggerToolTipManager::slotEditorOpened(IEditor *e) void DebuggerToolTipManager::debugModeEntered() { - if (debugToolTips) - qDebug("DebuggerToolTipManager::debugModeEntered"); - // Hook up all signals in debug mode. if (!d->m_debugModeActive) { d->m_debugModeActive = true; @@ -1414,9 +1303,6 @@ void DebuggerToolTipManager::debugModeEntered() void DebuggerToolTipManager::leavingDebugMode() { - if (debugToolTips) - qDebug("DebuggerToolTipManager::leavingDebugMode"); - // Remove all signals in debug mode. if (d->m_debugModeActive) { d->m_debugModeActive = false; @@ -1436,67 +1322,81 @@ void DebuggerToolTipManager::leavingDebugMode() } } -void DebuggerToolTipManager::slotTooltipOverrideRequested(ITextEditor *editor, - const QPoint &point, - int pos, bool *handled) +void DebuggerToolTipManager::slotTooltipOverrideRequested + (ITextEditor *editor, const QPoint &point, int pos, bool *handled) { QTC_ASSERT(handled, return); + QTC_ASSERT(editor, return); + QTC_ASSERT(editor->document(), return); const int movedDistance = (point - d->m_lastToolTipPoint).manhattanLength(); - const bool samePosition = d->m_lastToolTipEditor == editor && movedDistance < 25; - if (debugToolTipPositioning) - qDebug() << ">slotTooltipOverrideRequested() " << editor << point - << "from " << d->m_lastToolTipPoint << ") pos: " - << pos << *handled - << " Same position=" << samePosition << " d=" << movedDistance; + if (d->m_lastToolTipEditor == editor && movedDistance < 25) { + *handled = true; + return; + } - DebuggerEngine *currentEngine = 0; - do { - if (samePosition) - *handled = true; + *handled = tryHandleToolTipOverride(editor, point, pos); - if (*handled) - break; // Avoid flicker. - - DebuggerCore *core = debuggerCore(); - if (!core->boolSetting(UseToolTipsInMainEditor)) - break; - - currentEngine = core->currentEngine(); - if (!currentEngine || !currentEngine->canDisplayTooltip()) - break; - - const DebuggerToolTipContext context = DebuggerToolTipContext::fromEditor(editor, pos); - if (context.isValid() && currentEngine->setToolTipExpression(point, editor, context)) { - *handled = true; - d->m_lastToolTipEditor = editor; - d->m_lastToolTipPoint = point; - } - - } while (false); - - // Other tooltip, close all in case mouse never entered the tooltip - // and no leave was triggered. - if (!*handled) { + if (*handled) { + d->m_lastToolTipEditor = editor; + d->m_lastToolTipPoint = point; + } else { d->m_lastToolTipEditor = 0; d->m_lastToolTipPoint = QPoint(-1, -1); } - if (debugToolTipPositioning) - qDebug() << "boolSetting(UseToolTipsInMainEditor)) + return false; + + DebuggerEngine *currentEngine = core->currentEngine(); + if (!currentEngine || !currentEngine->canDisplayTooltip()) + return false; + + DebuggerToolTipContext context; + context.engineType = currentEngine->objectName(); + context.fileName = editor->document()->filePath(); + context.position = pos; + context.mousePosition = point; + editor->convertPosition(pos, &context.line, &context.column); + QString raw = cppExpressionAt(editor, context.position, &context.line, &context.column, &context.function); + context.expression = fixCppExpression(raw); + + if (context.expression.isEmpty()) + return false; + + // Prefer a filter on an existing local variable if it can be found. + if (const WatchData *localVariable = currentEngine->watchHandler()->findCppLocalVariable(context.expression)) { + context.expression = QLatin1String(localVariable->exp); + if (context.expression.isEmpty()) + context.expression = localVariable->name; + context.iname = localVariable->iname; + showToolTip(context, currentEngine); + return true; + } + + context.iname = "tooltip." + context.expression.toLatin1().toHex(); + + if (currentEngine->setToolTipExpression(editor, context)) + return true; + + // Other tooltip, close all in case mouse never entered the tooltip + // and no leave was triggered. + return false; } DebuggerToolTipContexts DebuggerToolTipManager::treeWidgetExpressions - (const QString &fileName, const QString &engineType, const QString &function) + (DebuggerEngine *, const QString &fileName, const QString &function) { DebuggerToolTipContexts rc; foreach (const QPointer &tw, d->m_tooltips) { - if (!tw.isNull() && tw->matches(fileName, engineType, function)) + if (tw && tw->context().matchesFrame(fileName, function)) rc.push_back(tw->context()); } - if (debugToolTips) - qDebug() << "DebuggerToolTipManager::treeWidgetExpressions" - << fileName << engineType << function << rc; return rc; } diff --git a/src/plugins/debugger/debuggertooltipmanager.h b/src/plugins/debugger/debuggertooltipmanager.h index 9f554830dee..2957c9e6333 100644 --- a/src/plugins/debugger/debuggertooltipmanager.h +++ b/src/plugins/debugger/debuggertooltipmanager.h @@ -32,47 +32,37 @@ #include "debuggerconstants.h" +#include +#include #include -#include -#include -#include -#include - QT_BEGIN_NAMESPACE -class QVBoxLayout; -class QToolButton; -class QStandardItemModel; -class QToolBar; class QDebug; QT_END_NAMESPACE -namespace Core { -class IEditor; -class IMode; -} - +namespace Core { class IEditor; } namespace TextEditor { class ITextEditor; } namespace Debugger { class DebuggerEngine; namespace Internal { -class DraggableLabel; -class DebuggerToolTipEditor; class DebuggerToolTipContext { public: DebuggerToolTipContext(); - static DebuggerToolTipContext fromEditor(Core::IEditor *ed, int pos); - bool isValid() const { return !fileName.isEmpty(); } + bool isValid() const { return !expression.isEmpty(); } + bool matchesFrame(const QString &frameFile, const QString &frameFunction) const; + bool isSame(const DebuggerToolTipContext &other) const; QString fileName; int position; int line; int column; QString function; //!< Optional function. This must be set by the engine as it is language-specific. + QString engineType; + QDate creationDate; QPoint mousePosition; QString expression; @@ -84,81 +74,6 @@ typedef QList DebuggerToolTipContexts; QDebug operator<<(QDebug, const DebuggerToolTipContext &); -class DebuggerToolTipTreeView; - -class DebuggerToolTipWidget : public QWidget -{ - Q_OBJECT - -public: - bool isPinned() const { return m_isPinned; } - - explicit DebuggerToolTipWidget(QWidget *parent = 0); - bool engineAcquired() const { return m_engineAcquired; } - - QString fileName() const { return m_context.fileName; } - QString function() const { return m_context.function; } - int position() const { return m_context.position; } - // Check for a match at position. - bool matches(const QString &fileName, - const QString &engineType = QString(), - const QString &function= QString()) const; - - const DebuggerToolTipContext &context() const { return m_context; } - void setContext(const DebuggerToolTipContext &c) { m_context = c; } - - QString engineType() const { return m_engineType; } - void setEngineType(const QString &e) { m_engineType = e; } - - QDate creationDate() const { return m_creationDate; } - void setCreationDate(const QDate &d) { m_creationDate = d; } - - static DebuggerToolTipWidget *loadSessionData(QXmlStreamReader &r); - - static QString treeModelClipboardContents(const QAbstractItemModel *m); - -public slots: - void saveSessionData(QXmlStreamWriter &w) const; - - void acquireEngine(Debugger::DebuggerEngine *engine); - void releaseEngine(); - void copy(); - bool positionShow(const DebuggerToolTipEditor &pe); - void pin(); - -private slots: - void slotDragged(const QPoint &p); - void toolButtonClicked(); - -private: - bool m_isPinned; - QToolButton *m_toolButton; - -private: - static DebuggerToolTipWidget *loadSessionDataI(QXmlStreamReader &r); - void doAcquireEngine(Debugger::DebuggerEngine *engine); - void doReleaseEngine(); - void doSaveSessionData(QXmlStreamWriter &w) const; - void doLoadSessionData(QXmlStreamReader &r); - QString clipboardContents() const; - - DraggableLabel *m_titleLabel; - bool m_engineAcquired; - QString m_engineType; - DebuggerToolTipContext m_context; - QDate m_creationDate; - QPoint m_offset; //!< Offset to text cursor position (user dragging). - -private: - QAbstractItemModel *swapModel(QAbstractItemModel *newModel); - static void restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m); - - int m_debuggerModel; - - DebuggerToolTipTreeView *m_treeView; - QStandardItemModel *m_defaultModel; -}; - class DebuggerToolTipTreeView : public QTreeView { Q_OBJECT @@ -168,16 +83,14 @@ public: QAbstractItemModel *swapModel(QAbstractItemModel *model); QSize sizeHint() const { return m_size; } - int computeHeight(const QModelIndex &index) const; -public slots: +private slots: void computeSize(); void expandNode(const QModelIndex &idx); void collapseNode(const QModelIndex &idx); - void handleItemIsExpanded(const QModelIndex &sourceIdx); private: - void init(QAbstractItemModel *model); + int computeHeight(const QModelIndex &index) const; QSize m_size; }; @@ -191,35 +104,40 @@ public: ~DebuggerToolTipManager(); static void registerEngine(DebuggerEngine *engine); + static void deregisterEngine(DebuggerEngine *engine); + static void updateEngine(DebuggerEngine *engine); static bool hasToolTips(); // Collect all expressions of DebuggerTreeViewToolTipWidget - static DebuggerToolTipContexts treeWidgetExpressions(const QString &fileName, - const QString &engineType = QString(), - const QString &function= QString()); + static DebuggerToolTipContexts treeWidgetExpressions(DebuggerEngine *engine, + const QString &fileName, const QString &function = QString()); - static void showToolTip(const QPoint &p, DebuggerToolTipWidget *); + static void showToolTip(const DebuggerToolTipContext &context, + DebuggerEngine *engine); virtual bool eventFilter(QObject *, QEvent *); - static bool debug(); + static QString treeModelClipboardContents(const QAbstractItemModel *model); public slots: void debugModeEntered(); void leavingDebugMode(); void sessionAboutToChange(); - void loadSessionData(); - void saveSessionData(); + static void loadSessionData(); + static void saveSessionData(); static void closeAllToolTips(); - void hide(); + static void hide(); private slots: - void slotUpdateVisibleToolTips(); + static void slotUpdateVisibleToolTips(); void slotDebuggerStateChanged(Debugger::DebuggerState); - void slotStackFrameCompleted(); void slotEditorOpened(Core::IEditor *); void slotTooltipOverrideRequested(TextEditor::ITextEditor *editor, const QPoint &point, int pos, bool *handled); + +private: + bool tryHandleToolTipOverride(TextEditor::ITextEditor *editor, + const QPoint &point, int pos); }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index b201a1ec663..e635cbbd457 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3629,42 +3629,30 @@ void GdbEngine::handleRegisterListValues(const GdbResponse &response) // ////////////////////////////////////////////////////////////////////// -void GdbEngine::showToolTip() -{ - if (m_toolTipContext.isNull()) - return; - const QString expression = m_toolTipContext->expression; - if (DebuggerToolTipManager::debug()) - qDebug() << "GdbEngine::showToolTip " << expression << m_toolTipContext->iname << (*m_toolTipContext); +//void GdbEngine::showToolTip() +//{ +// const QString expression = m_toolTipContext.expression; +// if (DebuggerToolTipManager::debug()) +// qDebug() << "GdbEngine::showToolTip " << expression << m_toolTipContext.iname << m_toolTipContext; - if (m_toolTipContext->iname.startsWith("tooltip") - && (!debuggerCore()->boolSetting(UseToolTipsInMainEditor) - || !watchHandler()->isValidToolTip(m_toolTipContext->iname))) { - watchHandler()->removeData(m_toolTipContext->iname); - return; - } +// if (m_toolTipContext.iname.startsWith("tooltip") +// && (!debuggerCore()->boolSetting(UseToolTipsInMainEditor) +// || !watchHandler()->isValidToolTip(m_toolTipContext.iname))) { +// watchHandler()->removeData(m_toolTipContext.iname); +// return; +// } - DebuggerToolTipWidget *tw = new DebuggerToolTipWidget; - tw->setContext(*m_toolTipContext); - tw->acquireEngine(this); - DebuggerToolTipManager::showToolTip(m_toolTipContext->mousePosition, tw); - // Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711). - m_toolTipContext.reset(); -} - -QString GdbEngine::tooltipExpression() const -{ - return m_toolTipContext.isNull() ? QString() : m_toolTipContext->expression; -} +// DebuggerToolTipManager::showToolTip(m_toolTipContext, this); +//} void GdbEngine::resetLocation() { - m_toolTipContext.reset(); + m_toolTipContext.expression.clear(); DebuggerEngine::resetLocation(); } -bool GdbEngine::setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &contextIn) +bool GdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, + const DebuggerToolTipContext &context) { if (state() != InferiorStopOk || !isCppEditor(editor)) { //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED " @@ -3672,46 +3660,13 @@ bool GdbEngine::setToolTipExpression(const QPoint &mousePos, return false; } - DebuggerToolTipContext context = contextIn; - int line, column; - QString exp = fixCppExpression(cppExpressionAt(editor, context.position, &line, &column, &context.function)); - if (exp.isEmpty()) - return false; - // Prefer a filter on an existing local variable if it can be found. - QByteArray iname; - if (const WatchData *localVariable = watchHandler()->findCppLocalVariable(exp)) { - exp = QLatin1String(localVariable->exp); - iname = localVariable->iname; - } else { - iname = tooltipIName(exp); - } - - if (DebuggerToolTipManager::debug()) - qDebug() << "GdbEngine::setToolTipExpression1 " << exp << iname << context; - - // Same expression: Display synchronously. - if (!m_toolTipContext.isNull() && m_toolTipContext->expression == exp) { - showToolTip(); - return true; - } - - m_toolTipContext.reset(new DebuggerToolTipContext(context)); - m_toolTipContext->mousePosition = mousePos; - m_toolTipContext->expression = exp; - m_toolTipContext->iname = iname; - // Local variable: Display synchronously. - if (iname.startsWith("local")) { - showToolTip(); - return true; - } - - if (DebuggerToolTipManager::debug()) - qDebug() << "GdbEngine::setToolTipExpression2 " << exp << (*m_toolTipContext); + m_toolTipContext = context; + // qDebug() << "GdbEngine::setToolTipExpression2 " << exp << m_toolTipContext; UpdateParameters params; params.tryPartial = true; params.tooltipOnly = true; - params.varList = iname; + params.varList = context.iname; updateLocalsPython(params); return true; } @@ -3777,7 +3732,12 @@ void GdbEngine::rebuildWatchModel() showMessage(LogWindow::logTimeStamp(), LogMiscInput); showMessage(_("").arg(count), LogMiscInput); showStatusMessage(tr("Finished retrieving data"), 400); - showToolTip(); + + if (m_toolTipContext.isValid()) { + DebuggerToolTipManager::showToolTip(m_toolTipContext, this); + m_toolTipContext = DebuggerToolTipContext(); + } + DebuggerToolTipManager::updateEngine(this); } void GdbEngine::handleVarAssign(const GdbResponse &) @@ -4879,9 +4839,9 @@ void GdbEngine::updateLocalsPython(const UpdateParameters ¶ms) // Re-create tooltip items that are not filters on existing local variables in // the tooltip model. DebuggerToolTipContexts toolTips = - DebuggerToolTipManager::treeWidgetExpressions(fileName, objectName(), function); + DebuggerToolTipManager::treeWidgetExpressions(this, fileName, function); - const QString currentExpression = tooltipExpression(); + const QString currentExpression = m_toolTipContext.expression; if (!currentExpression.isEmpty()) { int currentIndex = -1; for (int i = 0; i < toolTips.size(); ++i) { @@ -5019,8 +4979,10 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response) //PENDING_DEBUG("\n\n .... AND TRIGGERS MODEL UPDATE\n"); rebuildWatchModel(); //} - if (!partial) + if (!partial) { emit stackFrameCompleted(); + DebuggerToolTipManager::updateEngine(this); + } } else { showMessage(_("DUMPER FAILED: " + response.toString())); } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 215338b25d5..b30e40d5bf4 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -34,6 +34,7 @@ #include #include +#include #include @@ -406,8 +407,8 @@ protected: // // Watch specific stuff // - virtual bool setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &); + virtual bool setToolTipExpression(TextEditor::ITextEditor *editor, + const DebuggerToolTipContext &); virtual void assignValueInDebugger(const WatchData *data, const QString &expr, const QVariant &value); @@ -467,8 +468,7 @@ protected: void showExecutionError(const QString &message); static QByteArray tooltipIName(const QString &exp); - QString tooltipExpression() const; - QScopedPointer m_toolTipContext; + DebuggerToolTipContext m_toolTipContext; // For short-circuiting stack and thread list evaluation. bool m_stackNeeded; diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index e8d914d34aa..34965c77b06 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -36,6 +36,9 @@ #include #include +#include +#include + #include #include #include @@ -62,33 +65,6 @@ class GdbOptionsPageWidget : public QWidget { public: explicit GdbOptionsPageWidget(QWidget *parent = 0); - - QGroupBox *groupBoxGeneral; - QSpinBox *spinBoxGdbWatchdogTimeout; - QCheckBox *checkBoxSkipKnownFrames; - QCheckBox *checkBoxUseMessageBoxForSignals; - QCheckBox *checkBoxAdjustBreakpointLocations; - QCheckBox *checkBoxUseDynamicType; - QCheckBox *checkBoxLoadGdbInit; - QCheckBox *checkBoxLoadGdbDumpers; - QCheckBox *checkBoxIntelFlavor; - QCheckBox *checkBoxIdentifyDebugInfoPackages; - - QGroupBox *groupBoxStartupCommands; - QTextEdit *textEditStartupCommands; - QGroupBox *groupBoxPostAttachCommands; - QTextEdit *textEditPostAttachCommands; - QGroupBox *groupBoxCustomDumperCommands; - QTextEdit *textEditCustomDumperCommands; - QLineEdit *extraDumperFile; - - //QGroupBox *groupBoxPluginDebugging; - //QRadioButton *radioButtonAllPluginBreakpoints; - //QRadioButton *radioButtonSelectedPluginBreakpoints; - //QRadioButton *radioButtonNoPluginBreakpoints; - //QLabel *labelSelectedPluginBreakpoints; - //QLineEdit *lineEditSelectedPluginBreakpointsPattern; - Utils::SavedActionSet group; }; @@ -97,10 +73,10 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) { (void) new VariableChooser(this); - groupBoxGeneral = new QGroupBox(this); + auto groupBoxGeneral = new QGroupBox(this); groupBoxGeneral->setTitle(GdbOptionsPage::tr("General")); - QLabel *labelGdbWatchdogTimeout = new QLabel(groupBoxGeneral); + auto labelGdbWatchdogTimeout = new QLabel(groupBoxGeneral); labelGdbWatchdogTimeout->setText(GdbOptionsPage::tr("GDB timeout:")); labelGdbWatchdogTimeout->setToolTip(GdbOptionsPage::tr( "The number of seconds Qt Creator will wait before it terminates\n" @@ -109,7 +85,7 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) "loading big libraries or listing source files takes much longer than\n" "that on slow machines. In this case, the value should be increased.")); - spinBoxGdbWatchdogTimeout = new QSpinBox(groupBoxGeneral); + auto spinBoxGdbWatchdogTimeout = new QSpinBox(groupBoxGeneral); spinBoxGdbWatchdogTimeout->setToolTip(labelGdbWatchdogTimeout->toolTip()); spinBoxGdbWatchdogTimeout->setSuffix(GdbOptionsPage::tr("sec")); spinBoxGdbWatchdogTimeout->setLayoutDirection(Qt::LeftToRight); @@ -118,7 +94,7 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) spinBoxGdbWatchdogTimeout->setSingleStep(20); spinBoxGdbWatchdogTimeout->setValue(20); - checkBoxSkipKnownFrames = new QCheckBox(groupBoxGeneral); + auto checkBoxSkipKnownFrames = new QCheckBox(groupBoxGeneral); checkBoxSkipKnownFrames->setText(GdbOptionsPage::tr("Skip known frames when stepping")); checkBoxSkipKnownFrames->setToolTip(GdbOptionsPage::tr( "

" @@ -127,14 +103,14 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) "counting code is skipped, and a single Step Into for a signal\n" "emission ends up directly in the slot connected to it.")); - checkBoxUseMessageBoxForSignals = new QCheckBox(groupBoxGeneral); + auto checkBoxUseMessageBoxForSignals = new QCheckBox(groupBoxGeneral); checkBoxUseMessageBoxForSignals->setText(GdbOptionsPage::tr( "Show a message box when receiving a signal")); checkBoxUseMessageBoxForSignals->setToolTip(GdbOptionsPage::tr( "Displays a message box as soon as your application\n" "receives a signal like SIGSEGV during debugging.")); - checkBoxAdjustBreakpointLocations = new QCheckBox(groupBoxGeneral); + auto checkBoxAdjustBreakpointLocations = new QCheckBox(groupBoxGeneral); checkBoxAdjustBreakpointLocations->setText(GdbOptionsPage::tr( "Adjust breakpoint locations")); checkBoxAdjustBreakpointLocations->setToolTip(GdbOptionsPage::tr( @@ -144,32 +120,32 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) "This option reflects such temporary change by moving the breakpoint\n" "markers in the source code editor.")); - checkBoxUseDynamicType = new QCheckBox(groupBoxGeneral); + auto checkBoxUseDynamicType = new QCheckBox(groupBoxGeneral); checkBoxUseDynamicType->setText(GdbOptionsPage::tr( "Use dynamic object type for display")); checkBoxUseDynamicType->setToolTip(GdbOptionsPage::tr( "Specifies whether the dynamic or the static type of objects will be " "displayed. Choosing the dynamic type might be slower.")); - checkBoxLoadGdbInit = new QCheckBox(groupBoxGeneral); + auto checkBoxLoadGdbInit = new QCheckBox(groupBoxGeneral); checkBoxLoadGdbInit->setText(GdbOptionsPage::tr("Load .gdbinit file on startup")); checkBoxLoadGdbInit->setToolTip(GdbOptionsPage::tr( "Allows or inhibits reading the user's default\n" ".gdbinit file on debugger startup.")); - checkBoxLoadGdbDumpers = new QCheckBox(groupBoxGeneral); + auto checkBoxLoadGdbDumpers = new QCheckBox(groupBoxGeneral); checkBoxLoadGdbDumpers->setText(GdbOptionsPage::tr("Load system GDB pretty printers")); checkBoxLoadGdbDumpers->setToolTip(GdbOptionsPage::tr( "Uses the default GDB pretty printers installed in your " "system or linked to the libraries your application uses.")); - checkBoxIntelFlavor = new QCheckBox(groupBoxGeneral); + auto checkBoxIntelFlavor = new QCheckBox(groupBoxGeneral); checkBoxIntelFlavor->setText(GdbOptionsPage::tr("Use Intel style disassembly")); checkBoxIntelFlavor->setToolTip(GdbOptionsPage::tr( "GDB shows by default AT&&T style disassembly." "")); - checkBoxIdentifyDebugInfoPackages = new QCheckBox(groupBoxGeneral); + auto checkBoxIdentifyDebugInfoPackages = new QCheckBox(groupBoxGeneral); checkBoxIdentifyDebugInfoPackages->setText(GdbOptionsPage::tr("Create tasks from missing packages")); checkBoxIdentifyDebugInfoPackages->setToolTip(GdbOptionsPage::tr( "

Attempts to identify missing debug info packages " @@ -185,7 +161,7 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) "

To execute arbitrary Python scripts, " "use python execfile('/path/to/script.py').

"); - groupBoxStartupCommands = new QGroupBox(this); + auto groupBoxStartupCommands = new QGroupBox(this); groupBoxStartupCommands->setTitle(GdbOptionsPage::tr("Additional Startup Commands")); groupBoxStartupCommands->setToolTip(GdbOptionsPage::tr( "

GDB commands entered here will be executed after " @@ -193,11 +169,11 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) "attached, and before the debugging helpers are initialized.

%1" "").arg(howToUsePython)); - textEditStartupCommands = new QTextEdit(groupBoxStartupCommands); + auto textEditStartupCommands = new QTextEdit(groupBoxStartupCommands); textEditStartupCommands->setAcceptRichText(false); textEditStartupCommands->setToolTip(groupBoxStartupCommands->toolTip()); - groupBoxPostAttachCommands = new QGroupBox(this); + auto groupBoxPostAttachCommands = new QGroupBox(this); groupBoxPostAttachCommands->setTitle(GdbOptionsPage::tr("Additional Attach Commands")); groupBoxPostAttachCommands->setToolTip(GdbOptionsPage::tr( "

GDB commands entered here will be executed after " @@ -206,11 +182,11 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) "such as \"monitor reset\" or \"load\"." "")); - textEditPostAttachCommands = new QTextEdit(groupBoxPostAttachCommands); + auto textEditPostAttachCommands = new QTextEdit(groupBoxPostAttachCommands); textEditPostAttachCommands->setAcceptRichText(false); textEditPostAttachCommands->setToolTip(groupBoxPostAttachCommands->toolTip()); - groupBoxCustomDumperCommands = new QGroupBox(this); + auto groupBoxCustomDumperCommands = new QGroupBox(this); groupBoxCustomDumperCommands->setTitle(GdbOptionsPage::tr("Debugging Helper Customization")); groupBoxCustomDumperCommands->setToolTip(GdbOptionsPage::tr( "

GDB commands entered here will be executed after " @@ -218,14 +194,18 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) "You can load additional debugging helpers or modify existing ones here.

" "%1").arg(howToUsePython)); - textEditCustomDumperCommands = new QTextEdit(groupBoxCustomDumperCommands); + auto textEditCustomDumperCommands = new QTextEdit(groupBoxCustomDumperCommands); textEditCustomDumperCommands->setAcceptRichText(false); textEditCustomDumperCommands->setToolTip(groupBoxCustomDumperCommands->toolTip()); - extraDumperFile = new QLineEdit(groupBoxCustomDumperCommands); - extraDumperFile->setToolTip(GdbOptionsPage::tr( + auto groupBoxExtraDumperFile = new QGroupBox(this); + groupBoxExtraDumperFile->setTitle(GdbOptionsPage::tr("Extra Debugging Helpers")); + groupBoxExtraDumperFile->setToolTip(GdbOptionsPage::tr( "Path to a Python file containing additional data dumpers.")); + auto pathChooserExtraDumperFile = new Utils::PathChooser(groupBoxExtraDumperFile); + pathChooserExtraDumperFile->setExpectedKind(Utils::PathChooser::File); + /* groupBoxPluginDebugging = new QGroupBox(q); groupBoxPluginDebugging->setTitle(GdbOptionsPage::tr( @@ -255,9 +235,9 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) VariableChooser::addVariableSupport(textEditCustomDumperCommands); VariableChooser::addVariableSupport(textEditPostAttachCommands); VariableChooser::addVariableSupport(textEditStartupCommands); - VariableChooser::addVariableSupport(extraDumperFile); + VariableChooser::addVariableSupport(pathChooserExtraDumperFile->lineEdit()); - QFormLayout *formLayout = new QFormLayout(groupBoxGeneral); + auto formLayout = new QFormLayout(groupBoxGeneral); formLayout->addRow(labelGdbWatchdogTimeout, spinBoxGdbWatchdogTimeout); formLayout->addRow(checkBoxSkipKnownFrames); formLayout->addRow(checkBoxUseMessageBoxForSignals); @@ -268,38 +248,29 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) formLayout->addRow(checkBoxIntelFlavor); formLayout->addRow(checkBoxIdentifyDebugInfoPackages); - QGridLayout *startLayout = new QGridLayout(groupBoxStartupCommands); + auto startLayout = new QGridLayout(groupBoxStartupCommands); startLayout->addWidget(textEditStartupCommands, 0, 0, 1, 1); - QGridLayout *postAttachLayout = new QGridLayout(groupBoxPostAttachCommands); + auto postAttachLayout = new QGridLayout(groupBoxPostAttachCommands); postAttachLayout->addWidget(textEditPostAttachCommands, 0, 0, 1, 1); - QFormLayout *customDumperLayout = new QFormLayout(groupBoxCustomDumperCommands); - customDumperLayout->addRow(GdbOptionsPage::tr("Additional file:"), extraDumperFile); - customDumperLayout->addRow(textEditCustomDumperCommands); + auto customDumperLayout = new QGridLayout(groupBoxCustomDumperCommands); + customDumperLayout->addWidget(textEditCustomDumperCommands, 0, 0, 1, 1); - //QHBoxLayout *horizontalLayout = new QHBoxLayout(); - //horizontalLayout->addItem(new QSpacerItem(10, 10, QSizePolicy::Preferred, QSizePolicy::Minimum)); - //horizontalLayout->addWidget(labelSelectedPluginBreakpoints); - //horizontalLayout->addWidget(lineEditSelectedPluginBreakpointsPattern); + auto extraDumperLayout = new QGridLayout(groupBoxExtraDumperFile); + extraDumperLayout->addWidget(pathChooserExtraDumperFile, 0, 0, 1, 1); - QGridLayout *gridLayout = new QGridLayout(this); - gridLayout->addWidget(groupBoxGeneral, 0, 0, 2, 1); - gridLayout->addWidget(groupBoxStartupCommands, 0, 1, 1, 1); - gridLayout->addWidget(groupBoxPostAttachCommands, 1, 1, 1, 1); - gridLayout->addWidget(groupBoxCustomDumperCommands, 2, 1, 1, 1); + auto gridLayout = new QGridLayout(this); + gridLayout->addWidget(groupBoxGeneral, 0, 0, 5, 1); + gridLayout->addWidget(groupBoxExtraDumperFile, 5, 0, 1, 1); - //gridLayout->addWidget(groupBoxStartupCommands, 0, 1, 1, 1); - //gridLayout->addWidget(radioButtonAllPluginBreakpoints, 0, 0, 1, 1); - //gridLayout->addWidget(radioButtonSelectedPluginBreakpoints, 1, 0, 1, 1); - - //gridLayout->addLayout(horizontalLayout, 2, 0, 1, 1); - //gridLayout->addWidget(radioButtonNoPluginBreakpoints, 3, 0, 1, 1); - //gridLayout->addWidget(groupBoxPluginDebugging, 1, 0, 1, 2); + gridLayout->addWidget(groupBoxStartupCommands, 0, 1, 2, 1); + gridLayout->addWidget(groupBoxPostAttachCommands, 2, 1, 2, 1); + gridLayout->addWidget(groupBoxCustomDumperCommands, 4, 1, 2, 1); DebuggerCore *dc = debuggerCore(); group.insert(dc->action(GdbStartupCommands), textEditStartupCommands); - group.insert(dc->action(ExtraDumperFile), extraDumperFile); + group.insert(dc->action(ExtraDumperFile), pathChooserExtraDumperFile); group.insert(dc->action(ExtraDumperCommands), textEditCustomDumperCommands); group.insert(dc->action(GdbPostAttachCommands), textEditPostAttachCommands); group.insert(dc->action(LoadGdbInit), checkBoxLoadGdbInit); diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 90f18d631f3..a66db55f425 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -821,35 +821,23 @@ static QHash m_toolTipCache; void LldbEngine::showToolTip() { - if (m_toolTipContext.isNull()) + if (m_toolTipContext.expression.isEmpty()) return; - const QString expression = m_toolTipContext->expression; - if (DebuggerToolTipManager::debug()) - qDebug() << "LldbEngine::showToolTip " << expression << m_toolTipContext->iname << (*m_toolTipContext); + //const QString expression = m_toolTipContext->expression; + // qDebug() << "LldbEngine::showToolTip " << expression << m_toolTipContext->iname << (*m_toolTipContext); - if (m_toolTipContext->iname.startsWith("tooltip") - && (!debuggerCore()->boolSetting(UseToolTipsInMainEditor) - || !watchHandler()->isValidToolTip(m_toolTipContext->iname))) { - watchHandler()->removeData(m_toolTipContext->iname); - return; - } - - DebuggerToolTipWidget *tw = new DebuggerToolTipWidget; - tw->setContext(*m_toolTipContext); - tw->acquireEngine(this); - DebuggerToolTipManager::showToolTip(m_toolTipContext->mousePosition, tw); + DebuggerToolTipManager::showToolTip(m_toolTipContext, this); // Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711). - m_toolTipContext.reset(); + m_toolTipContext.expression.clear(); } void LldbEngine::resetLocation() { - m_toolTipContext.reset(); + m_toolTipContext.expression.clear(); DebuggerEngine::resetLocation(); } -bool LldbEngine::setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &contextIn) +bool LldbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, const DebuggerToolTipContext &context) { if (state() != InferiorStopOk || !isCppEditor(editor)) { //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED " @@ -857,46 +845,12 @@ bool LldbEngine::setToolTipExpression(const QPoint &mousePos, return false; } - DebuggerToolTipContext context = contextIn; - int line, column; - QString exp = fixCppExpression(cppExpressionAt(editor, context.position, &line, &column, &context.function)); - if (exp.isEmpty()) - return false; - // Prefer a filter on an existing local variable if it can be found. - QByteArray iname; - if (const WatchData *localVariable = watchHandler()->findCppLocalVariable(exp)) { - exp = QLatin1String(localVariable->exp); - iname = localVariable->iname; - } else { - iname = tooltipIName(exp); - } - - if (DebuggerToolTipManager::debug()) - qDebug() << "GdbEngine::setToolTipExpression1 " << exp << iname << context; - - // Same expression: Display synchronously. - if (!m_toolTipContext.isNull() && m_toolTipContext->expression == exp) { - showToolTip(); - return true; - } - - m_toolTipContext.reset(new DebuggerToolTipContext(context)); - m_toolTipContext->mousePosition = mousePos; - m_toolTipContext->expression = exp; - m_toolTipContext->iname = iname; - // Local variable: Display synchronously. - if (iname.startsWith("local")) { - showToolTip(); - return true; - } - - if (DebuggerToolTipManager::debug()) - qDebug() << "GdbEngine::setToolTipExpression2 " << exp << (*m_toolTipContext); + m_toolTipContext = context; UpdateParameters params; params.tryPartial = true; params.tooltipOnly = true; - params.varList = iname; + params.varList = context.iname; doUpdateLocals(params); return true; @@ -985,10 +939,9 @@ void LldbEngine::doUpdateLocals(UpdateParameters params) // Re-create tooltip items that are not filters on existing local variables in // the tooltip model. DebuggerToolTipContexts toolTips = - DebuggerToolTipManager::treeWidgetExpressions(frame.file, objectName(), frame.function); + DebuggerToolTipManager::treeWidgetExpressions(this, frame.file, frame.function); - const QString currentExpression = - m_toolTipContext.isNull() ? QString() : m_toolTipContext->expression; + const QString currentExpression = m_toolTipContext.expression; if (!currentExpression.isEmpty()) { int currentIndex = -1; for (int i = 0; i < toolTips.size(); ++i) { diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 65b2b89cbdf..38ff85ba822 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -107,8 +108,8 @@ private: void abortDebugger(); void resetLocation(); - bool setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &); + bool setToolTipExpression(TextEditor::ITextEditor *editor, + const DebuggerToolTipContext &); void continueInferior(); void interruptInferior(); @@ -217,7 +218,7 @@ private: QMap, int> m_disassemblerAgents; QMap, int> m_memoryAgents; QHash > m_memoryAgentTokens; - QScopedPointer m_toolTipContext; + DebuggerToolTipContext m_toolTipContext; void showToolTip(); diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index faaa25a9311..ea8e04e8ddc 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -452,10 +452,9 @@ static WatchData m_toolTip; static QPoint m_toolTipPos; static QHash m_toolTipCache; -bool PdbEngine::setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx) +bool PdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, + const DebuggerToolTipContext &ctx) { - Q_UNUSED(mousePos) Q_UNUSED(editor) if (state() != InferiorStopOk) { diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h index e10f3f73a72..bb91567fdf8 100644 --- a/src/plugins/debugger/pdb/pdbengine.h +++ b/src/plugins/debugger/pdb/pdbengine.h @@ -75,8 +75,8 @@ private: void shutdownInferior(); void shutdownEngine(); - bool setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &); + bool setToolTipExpression(TextEditor::ITextEditor *editor, + const DebuggerToolTipContext &); void continueInferior(); void interruptInferior(); diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index e09ff53f53f..8cea03a430e 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -89,15 +89,14 @@ bool QmlCppEngine::canDisplayTooltip() const return m_cppEngine->canDisplayTooltip() || m_qmlEngine->canDisplayTooltip(); } -bool QmlCppEngine::setToolTipExpression(const QPoint & mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx) +bool QmlCppEngine::setToolTipExpression(TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx) { QTC_ASSERT(editor, return false); bool success = false; if (editor->document()->id() == CppEditor::Constants::CPPEDITOR_ID) - success = m_cppEngine->setToolTipExpression(mousePos, editor, ctx); + success = m_cppEngine->setToolTipExpression(editor, ctx); else if (editor->document()->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) - success = m_qmlEngine->setToolTipExpression(mousePos, editor, ctx); + success = m_qmlEngine->setToolTipExpression(editor, ctx); return success; } diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index 2b3591fc61b..5320fe3ed73 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -46,8 +46,8 @@ public: ~QmlCppEngine(); bool canDisplayTooltip() const; - bool setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor * editor, const DebuggerToolTipContext &); + bool setToolTipExpression(TextEditor::ITextEditor *editor, + const DebuggerToolTipContext &); void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); void watchDataSelected(const QByteArray &iname); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 1f5f4cbf084..c36ec7cb4ac 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -983,12 +983,12 @@ void QmlEngine::requestModuleSymbols(const QString &moduleName) // ////////////////////////////////////////////////////////////////////// -bool QmlEngine::setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx) +bool QmlEngine::setToolTipExpression(TextEditor::ITextEditor *editor, + const DebuggerToolTipContext &ctx) { // This is processed by QML inspector, which has dependencies to // the qml js editor. Makes life easier. - emit tooltipRequested(mousePos, editor, ctx.position); + emit tooltipRequested(ctx.mousePosition, editor, ctx.position); return true; } diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 8a9e4bb98b5..cb0e9d6a856 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -128,8 +128,8 @@ private: void shutdownInferior(); void shutdownEngine(); - bool setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, const DebuggerToolTipContext &); + bool setToolTipExpression(TextEditor::ITextEditor *editor, + const DebuggerToolTipContext &); void continueInferior(); void interruptInferior(); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 8c45d960f26..ef16e42bd8f 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -500,7 +500,11 @@ WatchItem *WatchModel::findItem(const QByteArray &iname) const void WatchModel::checkIndex(const QModelIndex &index) const { - QTC_CHECK(index.isValid() ? index.model() == this : index.model() == 0); + if (index.isValid()) { + QTC_CHECK(index.model() == this); + } else { + QTC_CHECK(index.model() == 0); + } } WatchItem *WatchModel::createItem(const WatchData &data) diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 679ef2db5de..fbaffb12377 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -958,7 +958,7 @@ void WatchTreeView::contextMenuEvent(QContextMenuEvent *ev) } else if (act == &actRemoveWatchExpression) { handler->removeData(p.data(LocalsINameRole).toByteArray()); } else if (act == &actCopy) { - copyToClipboard(DebuggerToolTipWidget::treeModelClipboardContents(model())); + copyToClipboard(DebuggerToolTipManager::treeModelClipboardContents(model())); } else if (act == &actCopyValue) { copyToClipboard(mi1.data().toString()); } else if (act == &actShowInEditor) { @@ -1025,31 +1025,31 @@ void WatchTreeView::handleItemIsExpanded(const QModelIndex &idx) expand(idx); } -void WatchTreeView::resetHelper() -{ - QModelIndex idx = model()->index(m_type, 0); - resetHelper(idx); - expand(idx); -} - -void WatchTreeView::resetHelper(const QModelIndex &idx) +void WatchTreeView::reexpand(QTreeView *view, const QModelIndex &idx) { if (idx.data(LocalsExpandedRole).toBool()) { - //qDebug() << "EXPANDING " << model()->data(idx, LocalsINameRole); - if (!isExpanded(idx)) { - expand(idx); - for (int i = 0, n = model()->rowCount(idx); i != n; ++i) { - QModelIndex idx1 = model()->index(i, 0, idx); - resetHelper(idx1); + //qDebug() << "EXPANDING " << view->model()->data(idx, LocalsINameRole); + if (!view->isExpanded(idx)) { + view->expand(idx); + for (int i = 0, n = view->model()->rowCount(idx); i != n; ++i) { + QModelIndex idx1 = view->model()->index(i, 0, idx); + reexpand(view, idx1); } } } else { - //qDebug() << "COLLAPSING " << model()->data(idx, LocalsINameRole); - if (isExpanded(idx)) - collapse(idx); + //qDebug() << "COLLAPSING " << view->model()->data(idx, LocalsINameRole); + if (view->isExpanded(idx)) + view->collapse(idx); } } +void WatchTreeView::resetHelper() +{ + QModelIndex idx = model()->index(m_type, 0); + reexpand(this, idx); + expand(idx); +} + void WatchTreeView::reset() { BaseTreeView::reset(); diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index caeb68bef45..ff03e6aaf03 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -56,6 +56,7 @@ public: void reset(); void fillFormatMenu(QMenu *, const QModelIndex &mi); + static void reexpand(QTreeView *view, const QModelIndex &idx); public slots: void watchExpression(const QString &exp); @@ -91,7 +92,6 @@ private: void inputNewExpression(); void editItem(const QModelIndex &idx); - void resetHelper(const QModelIndex &idx); void setModelData(int role, const QVariant &value = QVariant(), const QModelIndex &index = QModelIndex()); diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 0d6ad83df02..699b4716c17 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -240,13 +240,26 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch_data() rows << RowData(TextLineData(QLatin1String("ABCD")), TextLineData(TextLineData::Separator)); rows << RowData(TextLineData(QLatin1String("EFGH"))); - rows << RowData(TextLineData(QLatin1String(""))); ChunkData chunk; chunk.rows = rows; QString patchText = header + QLatin1String("@@ -1,2 +1,1 @@\n" "-ABCD\n" " EFGH\n"); - QTest::newRow("Simple") << chunk + QTest::newRow("Simple not a last chunk") << chunk + << fileName + << fileName + << false + << patchText; + + /////////// + + // chunk the same here + patchText = header + QLatin1String("@@ -1,2 +1,1 @@\n" + "-ABCD\n" + " EFGH\n" + "\\ No newline at end of file\n"); + + QTest::newRow("Simple last chunk") << chunk << fileName << fileName << true @@ -255,8 +268,7 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch_data() /////////// rows.clear(); - rows << RowData(TextLineData(QLatin1String("ABCD")), - TextLineData(QLatin1String("ABCD"))); + rows << RowData(TextLineData(QLatin1String("ABCD"))); rows << RowData(TextLineData(QLatin1String("")), TextLineData(TextLineData::Separator)); chunk.rows = rows; @@ -265,7 +277,7 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch_data() "+ABCD\n" "\\ No newline at end of file\n"); - QTest::newRow("Last newline removed") << chunk + QTest::newRow("EOL in last line removed") << chunk << fileName << fileName << true @@ -275,11 +287,10 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch_data() // chunk the same here patchText = header + QLatin1String("@@ -1,2 +1,1 @@\n" - "-ABCD\n" - "-\n" - "+ABCD\n"); + " ABCD\n" + "-\n"); - QTest::newRow("Not a last newline removed") << chunk + QTest::newRow("Last empty line removed") << chunk << fileName << fileName << false @@ -288,8 +299,7 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch_data() /////////// rows.clear(); - rows << RowData(TextLineData(QLatin1String("ABCD")), - TextLineData(QLatin1String("ABCD"))); + rows << RowData(TextLineData(QLatin1String("ABCD"))); rows << RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String(""))); chunk.rows = rows; @@ -298,7 +308,7 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch_data() "\\ No newline at end of file\n" "+ABCD\n"); - QTest::newRow("Last newline added") << chunk + QTest::newRow("EOL to last line added") << chunk << fileName << fileName << true @@ -308,11 +318,26 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch_data() // chunk the same here patchText = header + QLatin1String("@@ -1,1 +1,2 @@\n" - "-ABCD\n" - "+ABCD\n" + " ABCD\n" "+\n"); - QTest::newRow("Not a last newline added") << chunk + QTest::newRow("Last empty line added") << chunk + << fileName + << fileName + << false + << patchText; + + /////////// + + rows.clear(); + rows << RowData(TextLineData(QLatin1String("ABCD")), + TextLineData(QLatin1String("EFGH"))); + chunk.rows = rows; + patchText = header + QLatin1String("@@ -1,1 +1,1 @@\n" + "-ABCD\n" + "+EFGH\n"); + + QTest::newRow("Last line with a newline modified") << chunk << fileName << fileName << false @@ -325,19 +350,6 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch_data() TextLineData(QLatin1String("EFGH"))); rows << RowData(TextLineData(QLatin1String(""))); chunk.rows = rows; - patchText = header + QLatin1String("@@ -1,1 +1,1 @@\n" - "-ABCD\n" - "+EFGH\n"); - - QTest::newRow("Last line with a newline modified") << chunk - << fileName - << fileName - << true - << patchText; - - /////////// - - // chunk the same here patchText = header + QLatin1String("@@ -1,2 +1,2 @@\n" "-ABCD\n" "+EFGH\n" @@ -424,7 +436,35 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch() QString result = DiffUtils::makePatch(sourceChunk, leftFileName, rightFileName, lastChunk); - QCOMPARE(patchText, result); + QCOMPARE(result, patchText); + + bool ok; + QList resultList = DiffUtils::readPatch(result, false, &ok); + + QVERIFY(ok); + QCOMPARE(resultList.count(), 1); + for (int i = 0; i < resultList.count(); i++) { + const FileData &resultFileData = resultList.at(i); + QCOMPARE(resultFileData.leftFileInfo.fileName, leftFileName); + QCOMPARE(resultFileData.rightFileInfo.fileName, rightFileName); + QCOMPARE(resultFileData.chunks.count(), 1); + for (int j = 0; j < resultFileData.chunks.count(); j++) { + const ChunkData &resultChunkData = resultFileData.chunks.at(j); + QCOMPARE(resultChunkData.leftStartingLineNumber, sourceChunk.leftStartingLineNumber); + QCOMPARE(resultChunkData.rightStartingLineNumber, sourceChunk.rightStartingLineNumber); + QCOMPARE(resultChunkData.contextChunk, sourceChunk.contextChunk); + QCOMPARE(resultChunkData.rows.count(), sourceChunk.rows.count()); + for (int k = 0; k < sourceChunk.rows.count(); k++) { + const RowData &sourceRowData = sourceChunk.rows.at(k); + const RowData &resultRowData = resultChunkData.rows.at(k); + QCOMPARE(resultRowData.equal, sourceRowData.equal); + QCOMPARE(resultRowData.leftLine.text, sourceRowData.leftLine.text); + QCOMPARE(resultRowData.leftLine.textLineType, sourceRowData.leftLine.textLineType); + QCOMPARE(resultRowData.rightLine.text, sourceRowData.rightLine.text); + QCOMPARE(resultRowData.rightLine.textLineType, sourceRowData.rightLine.textLineType); + } + } + } } void DiffEditor::Internal::DiffEditorPlugin::testReadPatch_data() @@ -614,11 +654,74 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch_data() fileData8.rightFileInfo = DiffFileInfo(QLatin1String("file b.txt")); fileData8.fileOperation = FileData::RenameFile; - QList fileDataList; - fileDataList << fileData1 << fileData2 << fileData3 << fileData4 << fileData5 << fileData6 << fileData7 << fileData8; + QList fileDataList1; + fileDataList1 << fileData1 << fileData2 << fileData3 << fileData4 << fileData5 << fileData6 << fileData7 << fileData8; QTest::newRow("Git patch") << patch - << fileDataList; + << fileDataList1; + + ////////////// + + patch = QLatin1String("diff --git a/file foo.txt b/file foo.txt\n" + "index 1234567..9876543 100644\n" + "--- a/file foo.txt\n" + "+++ b/file foo.txt\n" + "@@ -50,4 +50,5 @@ void DiffEditor::ctor()\n" + " A\n" + " B\n" + " C\n" + "+\n"); + + fileData1.leftFileInfo = DiffFileInfo(QLatin1String("file foo.txt"), QLatin1String("1234567")); + fileData1.rightFileInfo = DiffFileInfo(QLatin1String("file foo.txt"), QLatin1String("9876543")); + fileData1.fileOperation = FileData::ChangeFile; + chunkData1.leftStartingLineNumber = 49; + chunkData1.rightStartingLineNumber = 49; + rows1.clear(); + rows1.append(RowData(TextLineData(QLatin1String("A")))); + rows1.append(RowData(TextLineData(QLatin1String("B")))); + rows1.append(RowData(TextLineData(QLatin1String("C")))); + rows1.append(RowData(TextLineData(TextLineData::Separator), + TextLineData(QLatin1String("")))); + chunkData1.rows = rows1; + fileData1.chunks.clear(); + fileData1.chunks.append(chunkData1); + + QList fileDataList2; + fileDataList2 << fileData1; + + QTest::newRow("Added line") << patch + << fileDataList2; + + ////////////// + + patch = QLatin1String("diff --git a/file foo.txt b/file foo.txt\n" + "index 1234567..9876543 100644\n" + "--- a/file foo.txt\n" + "+++ b/file foo.txt\n" + "@@ -1,1 +1,1 @@\n" + "-ABCD\n" + "\\ No newline at end of file\n" + "+ABCD\n"); + + fileData1.leftFileInfo = DiffFileInfo(QLatin1String("file foo.txt"), QLatin1String("1234567")); + fileData1.rightFileInfo = DiffFileInfo(QLatin1String("file foo.txt"), QLatin1String("9876543")); + fileData1.fileOperation = FileData::ChangeFile; + chunkData1.leftStartingLineNumber = 0; + chunkData1.rightStartingLineNumber = 0; + rows1.clear(); + rows1.append(RowData(TextLineData(QLatin1String("ABCD")))); + rows1.append(RowData(TextLineData(TextLineData::Separator), + TextLineData(QLatin1String("")))); + chunkData1.rows = rows1; + fileData1.chunks.clear(); + fileData1.chunks.append(chunkData1); + + QList fileDataList3; + fileDataList3 << fileData1; + + QTest::newRow("Last newline added to a line without newline") << patch + << fileDataList3; } void DiffEditor::Internal::DiffEditorPlugin::testReadPatch() diff --git a/src/plugins/diffeditor/diffutils.cpp b/src/plugins/diffeditor/diffutils.cpp index 18725363fb3..f975462c47e 100644 --- a/src/plugins/diffeditor/diffutils.cpp +++ b/src/plugins/diffeditor/diffutils.cpp @@ -131,15 +131,23 @@ ChunkData DiffUtils::calculateOriginalData(const QList &leftDiffList, : Diff(Diff::Equal); if (leftDiff.command == Diff::Delete) { + if (j == rightDiffList.count() && lastLineEqual && leftDiff.text.startsWith(QLatin1Char('\n'))) + equalLines.insert(leftLineNumber, rightLineNumber); // process delete handleDifference(leftDiff.text, &leftLines, &leftLineNumber); lastLineEqual = lastLinesEqual(leftLines, rightLines); + if (j == rightDiffList.count()) + lastLineEqual = false; i++; } if (rightDiff.command == Diff::Insert) { + if (i == leftDiffList.count() && lastLineEqual && rightDiff.text.startsWith(QLatin1Char('\n'))) + equalLines.insert(leftLineNumber, rightLineNumber); // process insert handleDifference(rightDiff.text, &rightLines, &rightLineNumber); lastLineEqual = lastLinesEqual(leftLines, rightLines); + if (i == leftDiffList.count()) + lastLineEqual = false; j++; } if (leftDiff.command == Diff::Equal && rightDiff.command == Diff::Equal) { @@ -262,6 +270,7 @@ FileData DiffUtils::calculateContextData(const ChunkData &originalData, FileData fileData; fileData.contextChunksIncluded = true; + fileData.lastChunkAtTheEndOfFile = true; QMap hiddenRows; int i = 0; @@ -353,13 +362,24 @@ QString DiffUtils::makePatch(const ChunkData &chunkData, int rightLineCount = 0; QList leftBuffer, rightBuffer; + int lastEqualRow = -1; + if (lastChunk) { + for (int i = chunkData.rows.count(); i > 0; i--) { + if (chunkData.rows.at(i - 1).equal) { + if (i != chunkData.rows.count()) + lastEqualRow = i - 1; + break; + } + } + } + for (int i = 0; i <= chunkData.rows.count(); i++) { const RowData &rowData = i < chunkData.rows.count() ? chunkData.rows.at(i) : RowData(TextLineData(TextLineData::Separator)); // dummy, // ensure we process buffers to the end. // rowData will be equal - if (rowData.equal) { + if (rowData.equal && i != lastEqualRow) { if (leftBuffer.count()) { for (int j = 0; j < leftBuffer.count(); j++) { const QString line = makePatchLine(QLatin1Char('-'), @@ -554,11 +574,15 @@ static QList readLines(const QString &patch, } } - if (i < lines.count() + if (i < lines.count() // we broke before + // or we have noNewLine in some equal line and in either delete or insert line || (noNewLineInEqual >= 0 && (noNewLineInDelete >= 0 || noNewLineInInsert >= 0)) + // or we have noNewLine in not the last equal line || (noNewLineInEqual >= 0 && noNewLineInEqual != lastEqual) - || (noNewLineInDelete >= 0 && noNewLineInDelete != lastDelete) - || (noNewLineInInsert >= 0 && noNewLineInInsert != lastInsert)) { + // or we have noNewLine in not the last delete line or there is a equal line after the noNewLine for delete + || (noNewLineInDelete >= 0 && (noNewLineInDelete != lastDelete || lastEqual > lastDelete)) + // or we have noNewLine in not the last insert line or there is a equal line after the noNewLine for insert + || (noNewLineInInsert >= 0 && (noNewLineInInsert != lastInsert || lastEqual > lastInsert))) { if (ok) *ok = false; return QList(); @@ -577,26 +601,35 @@ static QList readLines(const QString &patch, removeNewLineFromLastDelete = true; if (noNewLineInInsert >= 0) removeNewLineFromLastInsert = true; - } else if (lastEqual > lastDelete && lastEqual > lastInsert) { - removeNewLineFromLastEqual = true; - } else if (lastDelete > lastEqual && lastDelete > lastInsert) { - if (lastInsert > lastEqual) { - removeNewLineFromLastDelete = true; - removeNewLineFromLastInsert = true; - } else if (lastEqual > lastInsert) { + } else { + if (noNewLineInEqual >= 0) { removeNewLineFromLastEqual = true; - prependNewLineAfterLastEqual = true; - } - } else if (lastInsert > lastEqual && lastInsert > lastDelete) { - if (lastDelete > lastEqual) { - removeNewLineFromLastDelete = true; - removeNewLineFromLastInsert = true; - } else if (lastEqual > lastDelete) { - removeNewLineFromLastEqual = true; - prependNewLineAfterLastEqual = true; + } else if (lastChunk) { + if (lastEqual > lastDelete && lastEqual > lastInsert) { + removeNewLineFromLastEqual = true; + } else if (lastDelete > lastEqual && lastDelete > lastInsert) { + if (lastInsert > lastEqual) { + removeNewLineFromLastDelete = true; + removeNewLineFromLastInsert = true; + } else if (lastEqual > lastInsert) { + removeNewLineFromLastEqual = true; + removeNewLineFromLastDelete = true; + prependNewLineAfterLastEqual = true; + } + } else if (lastInsert > lastEqual && lastInsert > lastDelete) { + if (lastDelete > lastEqual) { + removeNewLineFromLastDelete = true; + removeNewLineFromLastInsert = true; + } else if (lastEqual > lastDelete) { + removeNewLineFromLastEqual = true; + removeNewLineFromLastInsert = true; + prependNewLineAfterLastEqual = true; + } + } } } + if (removeNewLineFromLastEqual) { Diff &diff = diffList[lastEqual]; diff.text = diff.text.left(diff.text.count() - 1); diff --git a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp index 87001b3fe6f..5858fe91ff5 100644 --- a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp +++ b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp @@ -478,13 +478,24 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData, (*selections)[*blockNumber].append(DiffSelection(&m_chunkLineFormat)); + int lastEqualRow = -1; + if (lastChunk) { + for (int i = chunkData.rows.count(); i > 0; i--) { + if (chunkData.rows.at(i - 1).equal) { + if (i != chunkData.rows.count()) + lastEqualRow = i - 1; + break; + } + } + } + for (int i = 0; i <= chunkData.rows.count(); i++) { const RowData &rowData = i < chunkData.rows.count() ? chunkData.rows.at(i) : RowData(TextLineData(TextLineData::Separator)); // dummy, // ensure we process buffers to the end. // rowData will be equal - if (rowData.equal) { + if (rowData.equal && i != lastEqualRow) { if (leftBuffer.count()) { for (int j = 0; j < leftBuffer.count(); j++) { const TextLineData &lineData = leftBuffer.at(j); diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index 57f6519d7e7..fbbfe74eaa5 100644 --- a/src/plugins/help/helpplugin.cpp +++ b/src/plugins/help/helpplugin.cpp @@ -555,6 +555,7 @@ HelpViewer *HelpPlugin::externalHelpViewer() if (!m_externalWindowState.isNull()) m_externalWindow->setGeometry(m_externalWindowState); m_externalWindow->show(); + m_externalWindow->setFocus(); return m_externalWindow->currentViewer(); } diff --git a/src/plugins/ios/Ios.pluginspec.in b/src/plugins/ios/Ios.pluginspec.in index 80f1c6d798f..10af513c880 100644 --- a/src/plugins/ios/Ios.pluginspec.in +++ b/src/plugins/ios/Ios.pluginspec.in @@ -1,7 +1,7 @@ Digia Plc (C) 2014 Digia Plc - Mac OS.* + OS X.* Commercial Usage diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp index a67e7a54189..24c03a94ec2 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp @@ -243,24 +243,25 @@ void QbsBuildStep::buildingDone(bool success) item.codeLocation().fileName(), item.codeLocation().line()); QbsProject *pro = static_cast(project()); - connect(pro, SIGNAL(projectParsingDone(bool)), this, SLOT(reparsingDone())); // Building can uncover additional target artifacts. - // Wait for reparsing to finish, since before that our run configurations may not be valid. - pro->parseCurrentBuildConfiguration(true); + pro->updateAfterBuild(); + + // The reparsing, if it is necessary, has to be done before finished() is emitted, as + // otherwise a potential additional build step could conflict with the parsing step. + if (pro->parsingScheduled()) { + connect(pro, SIGNAL(projectParsingDone(bool)), this, SLOT(reparsingDone())); + pro->parseCurrentBuildConfiguration(true); + } else { + finish(); + } } void QbsBuildStep::reparsingDone() { disconnect(static_cast(project()), SIGNAL(projectParsingDone(bool)), this, SLOT(reparsingDone())); - QTC_ASSERT(m_fi, return); - m_fi->reportResult(m_lastWasSuccess); - m_fi = 0; // do not delete, it is not ours - m_job->deleteLater(); - m_job = 0; - - emit finished(); + finish(); } void QbsBuildStep::handleTaskStarted(const QString &desciption, int max) @@ -374,6 +375,17 @@ void QbsBuildStep::setMaxJobs(int jobcount) emit qbsBuildOptionsChanged(); } +void QbsBuildStep::finish() +{ + QTC_ASSERT(m_fi, return); + m_fi->reportResult(m_lastWasSuccess); + m_fi = 0; // do not delete, it is not ours + m_job->deleteLater(); + m_job = 0; + + emit finished(); +} + // -------------------------------------------------------------------- // QbsBuildStepConfigWidget: // -------------------------------------------------------------------- diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.h b/src/plugins/qbsprojectmanager/qbsbuildstep.h index 158eaf20410..dded12290a0 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildstep.h +++ b/src/plugins/qbsprojectmanager/qbsbuildstep.h @@ -98,6 +98,8 @@ private: void setCheckTimestamps(bool ts); void setMaxJobs(int jobcount); + void finish(); + QVariantMap m_qbsConfiguration; qbs::BuildOptions m_qbsBuildOptions; diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index 3dfc8d84bd1..8b011c642e9 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -35,14 +35,13 @@ #include #include +#include #include #include #include #include #include -#include - #include #include @@ -125,6 +124,7 @@ static bool addQbsFiles(QbsBaseProjectNode *node, const QStringList &filePaths, foreach (const QString &path, filePaths) { qbs::ErrorInfo err = prj.addFiles(productData, groupData, QStringList() << path); if (err.hasError()) { + Core::MessageManager::write(err.toString()); *notAdded += path; } else { allPaths += path; @@ -144,6 +144,7 @@ static bool removeQbsFiles(QbsBaseProjectNode *node, const QStringList &filePath foreach (const QString &path, filePaths) { qbs::ErrorInfo err = prj.removeFiles(productData, groupData, QStringList() << path); if (err.hasError()) { + Core::MessageManager::write(err.toString()); *notRemoved += path; } else { allPaths.removeOne(path); @@ -743,16 +744,8 @@ QbsGroupNode *QbsProductNode::findGroupNode(const QString &name) // QbsProjectNode: // -------------------------------------------------------------------- -QbsProjectNode::QbsProjectNode(QbsProject *project) : - QbsBaseProjectNode(project->projectFilePath().toString()), - m_project(project) -{ - ctor(); -} - QbsProjectNode::QbsProjectNode(const QString &path) : - QbsBaseProjectNode(path), - m_project(0) + QbsBaseProjectNode(path) { ctor(); } @@ -768,19 +761,6 @@ bool QbsProjectNode::addFiles(const QStringList &filePaths, QStringList *notAdde return prd ? prd->addFiles(filePaths, notAdded) : false; } -void QbsProjectNode::setProject(const qbs::Project &prj) -{ - m_qbsProject = prj; -} - -void QbsProjectNode::update() -{ - if (m_qbsProject.isValid()) - update(m_qbsProject.projectData()); - else - update(qbs::ProjectData()); -} - void QbsProjectNode::update(const qbs::ProjectData &prjData) { QList toAdd; @@ -811,7 +791,7 @@ void QbsProjectNode::update(const qbs::ProjectData &prjData) if (!prjData.name().isEmpty()) setDisplayName(prjData.name()); else - setDisplayName(m_project->displayName()); + setDisplayName(project()->displayName()); removeProjectNodes(toRemove); addProjectNodes(toAdd); @@ -819,25 +799,17 @@ void QbsProjectNode::update(const qbs::ProjectData &prjData) QbsProject *QbsProjectNode::project() const { - if (!m_project && projectNode()) - return static_cast(projectNode())->project(); - return m_project; + return static_cast(parentFolderNode())->project(); } const qbs::Project QbsProjectNode::qbsProject() const { - QbsProjectNode *parent = qobject_cast(projectNode()); - if (!m_qbsProject.isValid() && parent != this) - return parent->qbsProject(); - return m_qbsProject; + return project()->qbsProject(); } const qbs::ProjectData QbsProjectNode::qbsProjectData() const { - if (m_qbsProject.isValid()) - return m_qbsProject.projectData(); - else - return qbs::ProjectData(); + return project()->qbsProjectData(); } bool QbsProjectNode::showInSimpleTree() const @@ -875,5 +847,17 @@ QbsProjectNode *QbsProjectNode::findProjectNode(const QString &name) return 0; } + +QbsRootProjectNode::QbsRootProjectNode(QbsProject *project) : + QbsProjectNode(project->projectFilePath().toString()), + m_project(project) +{ +} + +void QbsRootProjectNode::update() +{ + update(m_project->qbsProjectData()); +} + } // namespace Internal } // namespace QbsProjectManager diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h index 1640a043100..f4d73e8d3d2 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.h +++ b/src/plugins/qbsprojectmanager/qbsnodes.h @@ -36,8 +36,6 @@ #include -namespace qbs { class Project; } - namespace QbsProjectManager { namespace Internal { @@ -165,34 +163,46 @@ class QbsProjectNode : public QbsBaseProjectNode Q_OBJECT public: - explicit QbsProjectNode(QbsProject *project); explicit QbsProjectNode(const QString &path); ~QbsProjectNode(); bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0); - void setProject(const qbs::Project &prj); // This does *not* update the node tree! - - void update(); - - QbsProject *project() const; + virtual QbsProject *project() const; const qbs::Project qbsProject() const; const qbs::ProjectData qbsProjectData() const; bool showInSimpleTree() const; + +protected: + void update(const qbs::ProjectData &prjData); + private: void ctor(); - void update(const qbs::ProjectData &prjData); - QbsProductNode *findProductNode(const QString &name); QbsProjectNode *findProjectNode(const QString &name); - QbsProject *m_project; - - qbs::Project m_qbsProject; static QIcon m_projectIcon; }; + +class QbsRootProjectNode : public QbsProjectNode +{ + Q_OBJECT + +public: + explicit QbsRootProjectNode(QbsProject *project); + + using QbsProjectNode::update; + void update(); + + QbsProject *project() const { return m_project; } + +private: + QbsProject * const m_project; +}; + + } // namespace Internal } // namespace QbsProjectManager diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index c0d69a8c1b3..eaafb89c818 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -101,6 +101,7 @@ QbsProject::QbsProject(QbsManager *manager, const QString &fileName) : m_qbsProjectParser(0), m_qbsUpdateFutureInterface(0), m_forceParsing(false), + m_parsingScheduled(false), m_currentBc(0) { m_parsingDelay.setInterval(1000); // delay parsing by 1s. @@ -120,7 +121,7 @@ QbsProject::QbsProject(QbsManager *manager, const QString &fileName) : updateDocuments(QSet() << fileName); // NOTE: QbsProjectNode does not use this as a parent! - m_rootProjectNode = new QbsProjectNode(this); // needs documents to be initialized! + m_rootProjectNode = new QbsRootProjectNode(this); // needs documents to be initialized! } QbsProject::~QbsProject() @@ -255,16 +256,14 @@ Utils::FileName QbsProject::defaultBuildDirectory(const QString &projectFilePath qbs::Project QbsProject::qbsProject() const { - if (!m_rootProjectNode) - return qbs::Project(); - return m_rootProjectNode->qbsProject(); + return m_qbsProject; } const qbs::ProjectData QbsProject::qbsProjectData() const { - if (!m_rootProjectNode) - return qbs::ProjectData(); - return m_rootProjectNode->qbsProjectData(); + if (m_qbsProject.isValid()) + return m_qbsProject.projectData(); + return qbs::ProjectData(); } bool QbsProject::needsSpecialDeployment() const @@ -276,12 +275,14 @@ void QbsProject::handleQbsParsingDone(bool success) { QTC_ASSERT(m_qbsProjectParser, return); - qbs::Project project; - if (success) - project = m_qbsProjectParser->qbsProject(); - generateErrors(m_qbsProjectParser->error()); + if (success) { + m_qbsProject = m_qbsProjectParser->qbsProject(); + QTC_CHECK(m_qbsProject.isValid()); + readQbsData(); + } + m_qbsProjectParser->deleteLater(); m_qbsProjectParser = 0; @@ -291,11 +292,6 @@ void QbsProject::handleQbsParsingDone(bool success) m_qbsUpdateFutureInterface = 0; } - if (project.isValid()) - m_rootProjectNode->setProject(project); - - readQbsData(); - emit projectParsingDone(success); } @@ -363,17 +359,14 @@ void QbsProject::readQbsData() qbs::ProjectData data = m_rootProjectNode->qbsProjectData(); updateCppCodeModel(data); updateQmlJsCodeModel(data); - updateApplicationTargets(data); - updateDeploymentInfo(project); - - foreach (Target *t, targets()) - t->updateDefaultRunConfigurations(); + updateBuildTargetData(); emit fileListChanged(); } void QbsProject::parseCurrentBuildConfiguration(bool force) { + m_parsingScheduled = false; if (!m_forceParsing) m_forceParsing = force; @@ -385,6 +378,11 @@ void QbsProject::parseCurrentBuildConfiguration(bool force) parse(bc->qbsConfiguration(), bc->environment(), bc->buildDirectory().toString()); } +void QbsProject::updateAfterBuild() +{ + updateBuildTargetData(); +} + void QbsProject::registerQbsProjectParser(QbsProjectParser *p) { m_parsingDelay.stop(); @@ -652,5 +650,13 @@ void QbsProject::updateDeploymentInfo(const qbs::Project &project) activeTarget()->setDeploymentData(deploymentData); } +void QbsProject::updateBuildTargetData() +{ + updateApplicationTargets(m_qbsProject.projectData()); + updateDeploymentInfo(m_qbsProject); + foreach (Target *t, targets()) + t->updateDefaultRunConfigurations(); +} + } // namespace Internal } // namespace QbsProjectManager diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h index e7d6e691463..97c01787bc1 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.h +++ b/src/plugins/qbsprojectmanager/qbsproject.h @@ -38,6 +38,8 @@ #include +#include + #include #include #include @@ -62,6 +64,7 @@ namespace QbsProjectManager { namespace Internal { class QbsProjectNode; +class QbsRootProjectNode; class QbsProjectParser; class QbsBuildConfiguration; @@ -91,6 +94,9 @@ public: bool isParsing() const; bool hasParseResult() const; void parseCurrentBuildConfiguration(bool force); + void scheduleParsing() { m_parsingScheduled = true; } + bool parsingScheduled() const { return m_parsingScheduled; } + void updateAfterBuild(); void registerQbsProjectParser(QbsProjectParser *p); @@ -133,17 +139,20 @@ private: void updateQmlJsCodeModel(const qbs::ProjectData &prj); void updateApplicationTargets(const qbs::ProjectData &projectData); void updateDeploymentInfo(const qbs::Project &project); + void updateBuildTargetData(); QbsManager *const m_manager; const QString m_projectName; const QString m_fileName; + qbs::Project m_qbsProject; QSet m_qbsDocuments; - QbsProjectNode *m_rootProjectNode; + QbsRootProjectNode *m_rootProjectNode; QbsProjectParser *m_qbsProjectParser; QFutureInterface *m_qbsUpdateFutureInterface; bool m_forceParsing; + bool m_parsingScheduled; QFuture m_codeModelFuture; diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp index 9fdd1c7080e..68bfec5291f 100644 --- a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp +++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp @@ -514,14 +514,15 @@ void QbsProjectManagerPlugin::reparseCurrentProject() void QbsProjectManagerPlugin::reparseProject(QbsProject *project) { - if (!project || BuildManager::isBuilding(project)) { - // Qbs does update the build graph during the build. So we cannot - // start to parse while a build is running or we will lose information. - // Just return since the qbsbuildstep will trigger a reparse after the build. + if (!project) return; - } - project->parseCurrentBuildConfiguration(true); + // Qbs does update the build graph during the build. So we cannot + // start to parse while a build is running or we will lose information. + if (BuildManager::isBuilding(project)) + project->scheduleParsing(); + else + project->parseCurrentBuildConfiguration(true); } } // namespace Internal diff --git a/src/plugins/qmakeprojectmanager/QmakeProjectManager.mimetypes.xml b/src/plugins/qmakeprojectmanager/QmakeProjectManager.mimetypes.xml index b9d06e6aeab..1967bc05804 100644 --- a/src/plugins/qmakeprojectmanager/QmakeProjectManager.mimetypes.xml +++ b/src/plugins/qmakeprojectmanager/QmakeProjectManager.mimetypes.xml @@ -15,4 +15,19 @@ Qt Project feature file + + + Qt Project configuration file + + + + + Qt Project cache file + + + + + Qt Project stash file + + diff --git a/src/plugins/qmakeprojectmanager/profileeditorfactory.cpp b/src/plugins/qmakeprojectmanager/profileeditorfactory.cpp index a5473d799cd..223d067957d 100644 --- a/src/plugins/qmakeprojectmanager/profileeditorfactory.cpp +++ b/src/plugins/qmakeprojectmanager/profileeditorfactory.cpp @@ -51,6 +51,9 @@ ProFileEditorFactory::ProFileEditorFactory(QmakeManager *manager) : addMimeType(QmakeProjectManager::Constants::PROFILE_MIMETYPE); addMimeType(QmakeProjectManager::Constants::PROINCLUDEFILE_MIMETYPE); addMimeType(QmakeProjectManager::Constants::PROFEATUREFILE_MIMETYPE); + addMimeType(QmakeProjectManager::Constants::PROCONFIGURATIONFILE_MIMETYPE); + addMimeType(QmakeProjectManager::Constants::PROCACHEFILE_MIMETYPE); + addMimeType(QmakeProjectManager::Constants::PROSTASHFILE_MIMETYPE); new TextEditor::TextEditorActionHandler(this, Constants::C_PROFILEEDITOR, TextEditor::TextEditorActionHandler::UnCommentSelection | TextEditor::TextEditorActionHandler::JumpToFileUnderCursor); diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs index dc98d61df25..564a0b75a7f 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs @@ -38,7 +38,6 @@ QtcPlugin { "profilehighlighter.cpp", "profilehighlighter.h", "profilehoverhandler.cpp", "profilehoverhandler.h", "qmakebuildinfo.h", - "qmakeparser.cpp", "qmakeparser.h", "qmakekitconfigwidget.cpp", "qmakekitconfigwidget.h", "qmakekitinformation.cpp", "qmakekitinformation.h", "qmakeparser.cpp", "qmakeparser.h", diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerconstants.h b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerconstants.h index a729868789e..a4c2b2cdead 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerconstants.h +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerconstants.h @@ -48,6 +48,9 @@ const char PROFILE_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors" const char PROFILE_MIMETYPE[] = "application/vnd.qt.qmakeprofile"; const char PROINCLUDEFILE_MIMETYPE [] = "application/vnd.qt.qmakeproincludefile"; const char PROFEATUREFILE_MIMETYPE [] = "application/vnd.qt.qmakeprofeaturefile"; +const char PROCONFIGURATIONFILE_MIMETYPE [] = "application/vnd.qt.qmakeproconfigurationfile"; +const char PROCACHEFILE_MIMETYPE [] = "application/vnd.qt.qmakeprocachefile"; +const char PROSTASHFILE_MIMETYPE [] = "application/vnd.qt.qmakeprostashfile"; // Actions const char RUNQMAKE[] = "Qt4Builder.RunQMake"; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp index c69d385b6c1..bc6bf236826 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp @@ -223,9 +223,6 @@ void ItemLibraryModel::updateVisibility() foreach (ItemLibrarySection *itemLibrarySection, m_sections) { QString sectionSearchText = m_searchText; - if (itemLibrarySection->sectionName().toLower().contains(m_searchText)) - sectionSearchText.clear(); - bool sectionChanged = false; bool sectionVisibility = itemLibrarySection->updateSectionVisibility(sectionSearchText, §ionChanged); diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp index 1d48c10a6d5..db38f86ad16 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreeview.cpp @@ -58,7 +58,11 @@ class TreeViewStyle : public QProxyStyle public: void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const { + static QRect mouseOverStateSavedFrameRectangle; if (element == QStyle::PE_PanelItemViewRow) { + if (option->state & QStyle::State_MouseOver) + mouseOverStateSavedFrameRectangle = option->rect; + if (option->state & QStyle::State_Selected) { NavigatorTreeView::drawSelectionBackground(painter, *option); } else { @@ -71,22 +75,26 @@ public: // painter->restore(); } } else if (element == PE_IndicatorItemViewItemDrop) { - painter->save(); - QRect rect = option->rect; - rect.setLeft(0); - rect.setWidth(widget->rect().width()); - QColor highlight = option->palette.text().color(); - highlight.setAlphaF(0.7); - painter->setPen(QPen(highlight.lighter(), 1)); - if (option->rect.height() == 0) { - if (option->rect.top()>0) - painter->drawLine(rect.topLeft(), rect.topRight()); - } else { - highlight.setAlphaF(0.2); - painter->setBrush(highlight); - painter->drawRect(rect.adjusted(0, 0, -1, -1)); + // between elements and on elements we have a width + if (option->rect.width() > 0) { + m_currentTextColor = option->palette.text().color(); + QRect frameRectangle = adjustedRectangleToWidgetWidth(option->rect, widget); + painter->save(); + + if (option->rect.height() == 0) { + bool isNotRootItem = option->rect.top() > 10 && mouseOverStateSavedFrameRectangle.top() > 10; + if (isNotRootItem) { + drawIndicatorLine(frameRectangle.topLeft(), frameRectangle.topRight(), painter); + // there is only a line in the styleoption object at this moment + // so we need to use the last saved rect from the mouse over state + frameRectangle = adjustedRectangleToWidgetWidth(mouseOverStateSavedFrameRectangle, widget); + drawBackgroundFrame(frameRectangle, painter); + } + } else { + drawHighlightFrame(frameRectangle, painter); + } + painter->restore(); } - painter->restore(); } else if (element == PE_FrameFocusRect) { // don't draw } else { @@ -100,6 +108,56 @@ public: else return QProxyStyle::styleHint(hint, option, widget, returnData); } + +private: // functions + QColor highlightBrushColor() const + { + QColor highlightBrushColor = m_currentTextColor; + highlightBrushColor.setAlphaF(0.7); + return highlightBrushColor; + } + QColor highlightLineColor() const + { + return highlightBrushColor().lighter(); + } + QColor backgroundBrushColor() const + { + QColor backgroundBrushColor = highlightBrushColor(); + backgroundBrushColor.setAlphaF(0.2); + return backgroundBrushColor; + } + QColor backgroundLineColor() const + { + return backgroundBrushColor().lighter(); + } + + void drawHighlightFrame(const QRect &frameRectangle, QPainter *painter) const + { + painter->setPen(QPen(highlightLineColor(), 2)); + painter->setBrush(highlightBrushColor()); + painter->drawRect(frameRectangle); + } + void drawBackgroundFrame(const QRect &frameRectangle, QPainter *painter) const + { + painter->setPen(QPen(backgroundLineColor(), 2)); + painter->setBrush(backgroundBrushColor()); + painter->drawRect(frameRectangle); + } + void drawIndicatorLine(const QPoint &leftPoint, const QPoint &rightPoint, QPainter *painter) const + { + painter->setPen(QPen(highlightLineColor(), 3)); + painter->drawLine(leftPoint, rightPoint); + } + + QRect adjustedRectangleToWidgetWidth(const QRect &originalRectangle, const QWidget *widget) const + { + QRect adjustesRectangle = originalRectangle; + adjustesRectangle.setLeft(0); + adjustesRectangle.setWidth(widget->rect().width()); + return adjustesRectangle.adjusted(0, 0, -1, -1); + } +private: // variables + mutable QColor m_currentTextColor; }; } diff --git a/src/plugins/qmldesigner/designercore/include/basetexteditmodifier.h b/src/plugins/qmldesigner/designercore/include/basetexteditmodifier.h index 4b8e95cb7f9..24aa6864bcd 100644 --- a/src/plugins/qmldesigner/designercore/include/basetexteditmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/basetexteditmodifier.h @@ -52,9 +52,6 @@ public: virtual int indentDepth() const; virtual bool renameId(const QString &oldId, const QString &newId); - - virtual QmlJS::Snapshot getSnapshot() const; - virtual QStringList importPaths() const; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/include/componenttextmodifier.h b/src/plugins/qmldesigner/designercore/include/componenttextmodifier.h index a17236f76fa..b31d6506a3b 100644 --- a/src/plugins/qmldesigner/designercore/include/componenttextmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/componenttextmodifier.h @@ -58,7 +58,6 @@ public: virtual void deactivateChangeSignals(); virtual void reactivateChangeSignals(); - virtual QmlJS::Snapshot getSnapshot() const; virtual QStringList importPaths() const; virtual bool renameId(const QString & /* oldId */, const QString & /* newId */) { return false; } diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 44cdc1aa87a..b5e3bb94b8d 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -101,6 +101,7 @@ public: void setUsedImports(const QList &usedImports); bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false); QString pathForImport(const Import &import); + QStringList importPaths() const; RewriterView *rewriterView() const; void setRewriterView(RewriterView *rewriterView); diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstance.h b/src/plugins/qmldesigner/designercore/include/nodeinstance.h index 55b8623f742..bd07c80f307 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstance.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstance.h @@ -78,6 +78,7 @@ public: QPixmap blurredRenderPixmap() const; QVariant property(const PropertyName &name) const; + bool hasProperty(const PropertyName &name) const; bool hasBindingForProperty(const PropertyName &name) const; QPair anchor(const PropertyName &name) const; bool hasAnchor(const PropertyName &name) const; diff --git a/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h b/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h index 0648dea9b67..730722ea1eb 100644 --- a/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h @@ -73,8 +73,7 @@ public: virtual void deactivateChangeSignals(); virtual void reactivateChangeSignals(); - virtual QmlJS::Snapshot getSnapshot() const = 0; - virtual QStringList importPaths() const = 0; + virtual QStringList importPaths() const; virtual bool renameId(const QString & /* oldId */, const QString & /* newId */) { return false; } @@ -108,10 +107,6 @@ public: virtual int indentDepth() const { return 0; } - - virtual QmlJS::Snapshot getSnapshot() const; - - virtual QStringList importPaths() const; }; } diff --git a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h index ffad71c30cf..8e071fee875 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h @@ -73,6 +73,7 @@ public: NodeProperty nodeProperty(const PropertyName &name) const; NodeListProperty nodeListProperty(const PropertyName &name) const; + bool instanceHasValue(const PropertyName &name) const; QVariant instanceValue(const PropertyName &name) const; TypeName instanceType(const PropertyName &name) const; diff --git a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h index 9ff93fd1283..7577622f074 100644 --- a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h +++ b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h @@ -69,6 +69,7 @@ private: // functions void unregisterQmlFile(const QFileInfo &fileInfo, const QString &qualifier); void registerQmlFile(const QFileInfo &fileInfo, const QString &qualifier, bool addToLibrary); Model *model() const; + QStringList importPaths() const; private: // variables QFileSystemWatcher m_watcher; diff --git a/src/plugins/qmldesigner/designercore/include/textmodifier.h b/src/plugins/qmldesigner/designercore/include/textmodifier.h index 62248e5eb42..d95405e0477 100644 --- a/src/plugins/qmldesigner/designercore/include/textmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/textmodifier.h @@ -83,7 +83,7 @@ public: virtual void deactivateChangeSignals() = 0; virtual void reactivateChangeSignals() = 0; - virtual QmlJS::Snapshot getSnapshot() const = 0; + static QmlJS::Snapshot qmljsSnapshot(); virtual QStringList importPaths() const = 0; virtual bool renameId(const QString &oldId, const QString &newId) = 0; diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp index 7ca96cc7b24..2d60729a611 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp @@ -315,6 +315,14 @@ QVariant NodeInstance::property(const PropertyName &name) const return QVariant(); } +bool NodeInstance::hasProperty(const PropertyName &name) const +{ + if (isValid()) + return d->propertyValues.contains(name); + + return false; +} + bool NodeInstance::hasBindingForProperty(const PropertyName &name) const { if (isValid()) diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp index 875671a04f3..8c265dd0e45 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp @@ -100,8 +100,8 @@ static bool hasQtQuick1(NodeInstanceView *nodeInstanceView) static void showCannotConnectToPuppetWarningAndSwitchToEditMode() { - QmlDesignerWarning::show(QCoreApplication::translate("NodeInstanceServerProxy", "Cannot Connect to Qml Emulation Layer (Qml Puppet)"), - QCoreApplication::translate("NodeInstanceServerProxy", "The executable of the emulation layer process is maybe hanging. " + QmlDesignerWarning::show(QCoreApplication::translate("NodeInstanceServerProxy", "Cannot Connect to QML Emulation Layer (QML Puppet)"), + QCoreApplication::translate("NodeInstanceServerProxy", "The executable of the QML emulation layer (QML Puppet) process is maybe hanging. " "Switching to an other kit maybe helps.")); QmlDesignerPlugin::instance()->switchToTextModeDeferred(); @@ -200,8 +200,8 @@ NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceV } } else { - QmlDesignerWarning::show(tr("Cannot Start QML Puppet Executable"), - tr("The executable of the QML Puppet process cannot be started or is hanging.")); + QmlDesignerWarning::show(tr("Cannot Start QML Emulation Layer (QML Puppet)"), + tr("The executable of the QML emulation layer (QML Puppet) process cannot be started or is hanging.")); QmlDesignerPlugin::instance()->switchToTextModeDeferred(); } @@ -384,8 +384,8 @@ void NodeInstanceServerProxy::processFinished(int exitCode, QProcess::ExitStatus if (m_captureFileForTest.isOpen()) { m_captureFileForTest.close(); m_captureFileForTest.remove(); - QMessageBox::warning(Core::ICore::dialogParent(), tr("QML Puppet Crashed"), - tr("You are recording a puppet stream and the puppet crashed. " + QMessageBox::warning(Core::ICore::dialogParent(), tr("QML Emulation Layer (QML Puppet) Crashed"), + tr("You are recording a puppet stream and the emulations layer crashed. " "It is recommended to reopen the Qt Quick Designer and start again.")); } diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp index 7e1c937b4eb..f7e69c674e0 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp @@ -184,16 +184,16 @@ bool PuppetCreator::build(const QString &qmlPuppetProjectFilePath) const } if (!buildSucceeded) - QmlDesignerWarning::show(QCoreApplication::translate("PuppetCreator", "Emulation layer building was unsuccessful"), + QmlDesignerWarning::show(QCoreApplication::translate("PuppetCreator", "QML Emulation Layer (QML Puppet) Building was Unsuccessful"), QCoreApplication::translate("PuppetCreator", - "The emulation layer (Qml Puppet) cannot be built. " + "The QML emulation layer (QML Puppet) cannot be built. " "The fallback emulation layer, which does not support all features, will be used." )); } } else { QmlDesignerWarning::show(QCoreApplication::translate("PuppetCreator", "Qt Version is not supported"), QCoreApplication::translate("PuppetCreator", - "The emulation layer (Qml Puppet) cannot be built because the Qt version is too old " + "The QML emulation layer (QML Puppet) cannot be built because the Qt version is too old " "or it cannot run natively on your computer. " "The fallback emulation layer, which does not support all features, will be used." )); @@ -206,7 +206,7 @@ static void warnAboutInvalidKit() { QmlDesignerWarning::show(QCoreApplication::translate("PuppetCreator", "Kit is invalid"), QCoreApplication::translate("PuppetCreator", - "The emulation layer (Qml Puppet) cannot be built because the kit is not configured correctly. " + "The QML emulation layer (QML Puppet) cannot be built because the kit is not configured correctly. " "For example the compiler can be misconfigured. " "Fix the kit configuration and restart Qt Creator. " "Otherwise, the fallback emulation layer, which does not support all features, will be used." diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index 1463d39984f..e50d18383da 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -959,7 +959,7 @@ QString NodeMetaInfoPrivate::importDirectoryPath() const return importInfo.path(); } else if (importInfo.type() == ImportType::Library) { if (modelManager) { - foreach (const QString &importPath, modelManager->importPaths()) { + foreach (const QString &importPath, model()->importPaths()) { const QString targetPath = QDir(importPath).filePath(importInfo.path()); if (QDir(targetPath).exists()) return targetPath; diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp index 1618f29079b..fc92f460d15 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp @@ -61,20 +61,6 @@ static bool operator<(const QFileInfo &file1, const QFileInfo &file2) QT_END_NAMESPACE -static inline QStringList importPaths() { - QStringList paths; - - // env import paths - QByteArray envImportPath = qgetenv("QML_IMPORT_PATH"); - if (!envImportPath.isEmpty()) { - paths = QString::fromUtf8(envImportPath) - .split(Utils::HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); - } - - paths.append(QmlJS::ModelManagerInterface::instance()->importPaths()); - - return paths; -} static inline bool checkIfDerivedFromItem(const QString &fileName) { @@ -413,6 +399,14 @@ Model *SubComponentManager::model() const return m_model.data(); } +QStringList SubComponentManager::importPaths() const +{ + if (model()) + return model()->importPaths(); + + return QStringList(); +} + /*! \class SubComponentManager diff --git a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp index 44a2d2692e8..e30e2fb6a14 100644 --- a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp @@ -105,26 +105,3 @@ bool BaseTextEditModifier::renameId(const QString &oldId, const QString &newId) } return false; } - -QmlJS::Snapshot BaseTextEditModifier::getSnapshot() const -{ - QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); - if (modelManager) - return modelManager->snapshot(); - else - return QmlJS::Snapshot(); -} - -QStringList BaseTextEditModifier::importPaths() const -{ - QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); - if (modelManager && textDocument()) { - QString documentFilePath = textDocument()->baseUrl().toLocalFile(); - if (!documentFilePath.isEmpty()) { - QmlJS::Document::Ptr qmljsDocument = modelManager->snapshot().document(documentFilePath); - return modelManager->defaultVContext(QmlJS::Language::Qml, qmljsDocument, true).paths; - } - } - - return QStringList(); -} diff --git a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp index 562f9821381..d78a03e6f29 100644 --- a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp @@ -129,8 +129,5 @@ void ComponentTextModifier::contentsChange(int /*position*/, int /*charsRemoved* { } -QmlJS::Snapshot ComponentTextModifier::getSnapshot() const -{ return m_originalModifier->getSnapshot(); } - QStringList ComponentTextModifier::importPaths() const { return m_originalModifier->importPaths(); } diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index f82cc837621..2fe40bd15e7 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -35,7 +35,7 @@ #include "invalidargumentexception.h" #include - +#include #include #include @@ -1818,7 +1818,23 @@ QString Model::pathForImport(const Import &import) if (!rewriterView()) return QString(); - return rewriterView()->pathForImport(import); + return rewriterView()->pathForImport(import); +} + +QStringList Model::importPaths() const +{ + QStringList importPathList; + + QString documentDirectoryPath = QFileInfo(fileUrl().toLocalFile()).absolutePath(); + + if (!documentDirectoryPath.isEmpty()) + importPathList.append(documentDirectoryPath); + + if (textModifier()) { + importPathList.append(textModifier()->importPaths()); + } + + return importPathList; } RewriterView *Model::rewriterView() const diff --git a/src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp index 2bee3d92cbb..71c22c9d3d5 100644 --- a/src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp @@ -197,21 +197,16 @@ void PlainTextEditModifier::reactivateChangeSignals() } } -QmlJS::Snapshot NotIndentingTextEditModifier::getSnapshot() const +QStringList PlainTextEditModifier::importPaths() const { QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); - if (modelManager) - return modelManager->snapshot(); - else - return QmlJS::Snapshot(); -} + if (modelManager && textDocument()) { + QString documentFilePath = textDocument()->baseUrl().toLocalFile(); + if (!documentFilePath.isEmpty()) { + QmlJS::Document::Ptr qmljsDocument = modelManager->snapshot().document(documentFilePath); + return modelManager->defaultVContext(QmlJS::Language::Qml, qmljsDocument, true).paths; + } + } - -QStringList NotIndentingTextEditModifier::importPaths() const -{ - QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); - if (modelManager) - return modelManager->importPaths(); - else - return QStringList(); + return QStringList(); } diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp index 40dff682ac5..7911967a2fb 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp @@ -147,6 +147,11 @@ NodeListProperty QmlObjectNode::nodeListProperty(const PropertyName &name) const return modelNode().nodeListProperty(name); } +bool QmlObjectNode::instanceHasValue(const PropertyName &name) const +{ + return nodeInstance().hasProperty(name); +} + bool QmlObjectNode::propertyAffectedByCurrentState(const PropertyName &name) const { if (!isValid()) diff --git a/src/plugins/qmldesigner/designercore/model/textmodifier.cpp b/src/plugins/qmldesigner/designercore/model/textmodifier.cpp index fdb14cf575b..a6f9d337e71 100644 --- a/src/plugins/qmldesigner/designercore/model/textmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/textmodifier.cpp @@ -29,8 +29,19 @@ #include "textmodifier.h" +#include + using namespace QmlDesigner; TextModifier::~TextModifier() { } + +QmlJS::Snapshot TextModifier::qmljsSnapshot() +{ + QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); + if (modelManager) + return modelManager->snapshot(); + else + return QmlJS::Snapshot(); +} diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index f16e70f3c63..8a1ba2e664d 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -803,7 +803,7 @@ void TextToModelMerger::setupUsedImports() QList usedImports; foreach (const QmlJS::Import &import, allImports) { - if (import.used) { + if (import.used && !import.info.name().isEmpty()) { if (import.info.type() == ImportType::Library) { usedImports.append(Import::createLibraryImport(import.info.name(), import.info.version().toString(), import.info.as())); } else if (import.info.type() == ImportType::Directory || import.info.type() == ImportType::File) { @@ -826,7 +826,7 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH try { - Snapshot snapshot = m_rewriterView->textModifier()->getSnapshot(); + Snapshot snapshot = m_rewriterView->textModifier()->qmljsSnapshot(); const QString fileName = url.toLocalFile(); Document::MutablePtr doc = Document::create(fileName.isEmpty() ? QStringLiteral("") : fileName, Language::Qml); doc->setSource(data); diff --git a/src/plugins/qmljstools/qmljstools.qbs b/src/plugins/qmljstools/qmljstools.qbs index c49721bae74..c47c5039998 100644 --- a/src/plugins/qmljstools/qmljstools.qbs +++ b/src/plugins/qmljstools/qmljstools.qbs @@ -19,7 +19,6 @@ QtcPlugin { Depends { name: "QtSupport" } files: [ - "QmlJSTools.mimetypes.xml", "qmljsbundleprovider.cpp", "qmljsbundleprovider.h", "qmljscodestylepreferencesfactory.cpp", @@ -34,8 +33,6 @@ QtcPlugin { "qmljslocatordata.cpp", "qmljslocatordata.h", "qmljsmodelmanager.cpp", - "qmljsmodelmanager.cpp", - "qmljsmodelmanager.h", "qmljsmodelmanager.h", "qmljsqtstylecodeformatter.cpp", "qmljsqtstylecodeformatter.h", diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index 2ab99e15c2d..d9c60d08396 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -273,7 +273,6 @@ Rectangle { onInteractiveChanged: interactive = stayInteractive onStayInteractiveChanged: interactive = stayInteractive - onContentXChanged: view.updateZoomControl() onWidthChanged: { var duration = Math.abs(zoomControl.endTime() - zoomControl.startTime()); if (duration > 0) @@ -312,19 +311,20 @@ Rectangle { onHeightChanged: requestPaint() property bool recursionGuard: false - function updateZoomControl() { + property int intX: x + property int intWidth: width + onIntXChanged: { // Don't updateZoomControl if we're just updating the flick range, _from_ // zoomControl. The other way round is OK. We _want_ the flick range to be updated // on external changes to zoomControl. if (recursionGuard) return; - var newStartTime = Math.round(flick.contentX * (endTime - startTime) / flick.width) + - zoomControl.windowStart(); - if (Math.abs(newStartTime - startTime) > 1) { - var newEndTime = Math.round((flick.contentX + flick.width) * - (endTime - startTime) / - flick.width) + zoomControl.windowStart(); + var newStartTime = intX * (endTime - startTime) / intWidth + + zoomControl.windowStart(); + if (Math.abs(newStartTime - startTime) >= 1) { + var newEndTime = (intX + intWidth) * (endTime - startTime) / intWidth + + zoomControl.windowStart(); zoomControl.setRange(newStartTime, newEndTime); } } @@ -339,12 +339,12 @@ Rectangle { if (!flick.movingHorizontally) { // This triggers an unwanted automatic change in contentX. We ignore that by // checking recursionGuard in this function and in updateZoomControl. - flick.contentWidth = zoomControl.windowLength() * flick.width / duration; + flick.contentWidth = zoomControl.windowLength() * intWidth / duration; - var newStartX = (startTime - zoomControl.windowStart()) * flick.width / + var newStartX = (startTime - zoomControl.windowStart()) * intWidth / duration; - if (isFinite(newStartX) && Math.abs(newStartX - flick.contentX) >= 1) + if (isFinite(newStartX) && Math.abs(newStartX - intX) >= 1) flick.contentX = newStartX; } recursionGuard = false; @@ -379,8 +379,8 @@ Rectangle { } // hack to pass mouse events to the other mousearea if enabled - startDragArea: selectionRange.ready ? selectionRange.getLeft() : -flick.contentX - endDragArea: selectionRange.ready ? selectionRange.getRight() : -flick.contentX-1 + startDragArea: selectionRange.ready ? selectionRange.getLeft() : -x + endDragArea: selectionRange.ready ? selectionRange.getRight() : -x - 1 } MouseArea { id: selectionRangeControl diff --git a/src/plugins/qmlprofiler/sortedtimelinemodel.cpp b/src/plugins/qmlprofiler/sortedtimelinemodel.cpp index 6a39b96d5b7..db23a35a974 100644 --- a/src/plugins/qmlprofiler/sortedtimelinemodel.cpp +++ b/src/plugins/qmlprofiler/sortedtimelinemodel.cpp @@ -29,7 +29,7 @@ /*! \class QmlProfiler::SortedTimelineModel - \brief Sorted model for timeline data + \brief The SortedTimelineModel class provides a sorted model for timeline data. The SortedTimelineModel lets you keep range data sorted by both start and end times, so that visible ranges can easily be computed. The only precondition for that to work is that the ranges @@ -83,7 +83,7 @@ /*! \fn int SortedTimelineModel::insertStart(qint64 startTime, const Data &item) Inserts the given data as range start at the given time position and - returns its index. The range end isn't set. + returns its index. The range end is not set. */ /*! @@ -94,14 +94,14 @@ /*! \fn int SortedTimelineModel::findFirstIndexNoParents(qint64 startTime) const Looks up the first range with an end time greater than the given time and - returns its index. If no such range is found it returns -1. + returns its index. If no such range is found, it returns -1. */ /*! \fn int SortedTimelineModel::findFirstIndex(qint64 startTime) const Looks up the first range with an end time greater than the given time and - returns its parent's index. If no such range is found it returns -1. If there - is no parent it returns the found range's index. The parent of a range is the + returns its parent's index. If no such range is found, it returns -1. If there + is no parent, it returns the found range's index. The parent of a range is the range with the lowest start time that completely covers the child range. "Completely covers" means: parent.startTime <= child.startTime && parent.endTime >= child.endTime @@ -110,7 +110,7 @@ /*! \fn int SortedTimelineModel::findLastIndex(qint64 endTime) const Looks up the last range with a start time smaller than the given time and - returns its index. If no such range is found it returns -1. + returns its index. If no such range is found, it returns -1. */ /*! diff --git a/src/plugins/qmlprofiler/timelinerenderer.cpp b/src/plugins/qmlprofiler/timelinerenderer.cpp index 24815f3aa65..e8e67838bb0 100644 --- a/src/plugins/qmlprofiler/timelinerenderer.cpp +++ b/src/plugins/qmlprofiler/timelinerenderer.cpp @@ -43,10 +43,10 @@ using namespace QmlProfiler::Internal; TimelineRenderer::TimelineRenderer(QQuickPaintedItem *parent) : QQuickPaintedItem(parent), m_startTime(0), m_endTime(0), m_spacing(0), m_spacedDuration(0), - m_lastStartTime(0), m_lastEndTime(0) - , m_profilerModelProxy(0) + m_lastStartTime(0), m_lastEndTime(0), m_profilerModelProxy(0), m_selectedItem(-1), + m_selectedModel(-1), m_selectionLocked(true), m_startDragArea(-1), m_endDragArea(-1) { - clearData(); + resetCurrentSelection(); setAcceptedMouseButtons(Qt::LeftButton); setAcceptHoverEvents(true); } @@ -93,11 +93,24 @@ inline void TimelineRenderer::getItemXExtent(int modelIndex, int i, int ¤t m_spacing, m_spacedDuration))); } else { currentX = -OutOfScreenMargin; - itemWidth = qMax(1.0, (qMin((m_profilerModelProxy->getDuration(modelIndex, i) + start) * - m_spacing + OutOfScreenMargin, m_spacedDuration))); + // Explicitly round the "start" part down, away from 0, to match the implicit rounding of + // currentX in the > 0 case. If we don't do that we get glitches where a pixel is added if + // the element starts outside the screen and subtracted if it starts inside the screen. + itemWidth = qMax(1.0, (qMin(m_profilerModelProxy->getDuration(modelIndex, i) * m_spacing + + floor(start * m_spacing) + OutOfScreenMargin, + m_spacedDuration))); } } +void TimelineRenderer::resetCurrentSelection() +{ + m_currentSelection.startTime = -1; + m_currentSelection.endTime = -1; + m_currentSelection.row = -1; + m_currentSelection.eventIndex = -1; + m_currentSelection.modelIndex = -1; +} + void TimelineRenderer::paint(QPainter *p) { qint64 windowDuration = m_endTime - m_startTime; @@ -314,7 +327,8 @@ void TimelineRenderer::mousePressEvent(QMouseEvent *event) void TimelineRenderer::mouseReleaseEvent(QMouseEvent *event) { Q_UNUSED(event); - manageClicked(); + if (!m_profilerModelProxy->isEmpty()) + manageClicked(); } void TimelineRenderer::mouseMoveEvent(QMouseEvent *event) @@ -411,18 +425,18 @@ void TimelineRenderer::manageHovered(int mouseX, int mouseY) void TimelineRenderer::clearData() { - m_startTime = 0; - m_endTime = 0; m_lastStartTime = 0; m_lastEndTime = 0; - m_currentSelection.startTime = -1; - m_currentSelection.endTime = -1; - m_currentSelection.row = -1; - m_currentSelection.eventIndex = -1; - m_currentSelection.modelIndex = -1; - m_selectedItem = -1; - m_selectedModel = -1; - m_selectionLocked = true; + m_spacing = 0; + m_spacedDuration = 0; + resetCurrentSelection(); + setStartTime(0); + setEndTime(0); + setSelectedItem(-1); + setSelectedModel(-1); + setSelectionLocked(true); + setStartDragArea(-1); + setEndDragArea(-1); } int TimelineRenderer::getYPosition(int modelIndex, int index) const diff --git a/src/plugins/qmlprofiler/timelinerenderer.h b/src/plugins/qmlprofiler/timelinerenderer.h index 587438f6044..a515228fdea 100644 --- a/src/plugins/qmlprofiler/timelinerenderer.h +++ b/src/plugins/qmlprofiler/timelinerenderer.h @@ -198,6 +198,7 @@ private: private: static const int OutOfScreenMargin = 3; // margin to make sure the rectangles stay invisible inline void getItemXExtent(int modelIndex, int i, int ¤tX, int &itemWidth); + void resetCurrentSelection(); qint64 m_startTime; qint64 m_endTime; diff --git a/src/plugins/qnx/blackberrydeployconfigurationfactory.h b/src/plugins/qnx/blackberrydeployconfigurationfactory.h index 58869902e87..3e37610246a 100644 --- a/src/plugins/qnx/blackberrydeployconfigurationfactory.h +++ b/src/plugins/qnx/blackberrydeployconfigurationfactory.h @@ -50,8 +50,7 @@ public: QString displayNameForId(Core::Id id) const; bool canCreate(ProjectExplorer::Target *parent, Core::Id id) const; - ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, - const Core::Id id); + ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, Core::Id id); bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const; ProjectExplorer::DeployConfiguration *restore(ProjectExplorer::Target *parent, diff --git a/src/plugins/qnx/blackberrydeploystepfactory.h b/src/plugins/qnx/blackberrydeploystepfactory.h index 962605a31d3..64b3fb8b438 100644 --- a/src/plugins/qnx/blackberrydeploystepfactory.h +++ b/src/plugins/qnx/blackberrydeploystepfactory.h @@ -47,8 +47,7 @@ public: QString displayNameForId(Core::Id id) const; bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const; - ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, - const Core::Id id); + ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id); bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const; ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, diff --git a/src/plugins/qnx/qnxdeployconfigurationfactory.h b/src/plugins/qnx/qnxdeployconfigurationfactory.h index 2972e7e1cd0..f502d34b68d 100644 --- a/src/plugins/qnx/qnxdeployconfigurationfactory.h +++ b/src/plugins/qnx/qnxdeployconfigurationfactory.h @@ -47,8 +47,7 @@ public: QString displayNameForId(Core::Id id) const; bool canCreate(ProjectExplorer::Target *parent, Core::Id id) const; - ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, - const Core::Id id); + ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, Core::Id id); bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const; ProjectExplorer::DeployConfiguration *restore(ProjectExplorer::Target *parent, diff --git a/src/plugins/qnx/qnxdeploystepfactory.h b/src/plugins/qnx/qnxdeploystepfactory.h index 46323553ff0..1f368df249b 100644 --- a/src/plugins/qnx/qnxdeploystepfactory.h +++ b/src/plugins/qnx/qnxdeploystepfactory.h @@ -47,8 +47,7 @@ public: QString displayNameForId(Core::Id id) const; bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const; - ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, - const Core::Id id); + ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id); bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const; ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, diff --git a/src/plugins/texteditor/basetextdocumentlayout.cpp b/src/plugins/texteditor/basetextdocumentlayout.cpp index 22291bb5849..619085e3d78 100644 --- a/src/plugins/texteditor/basetextdocumentlayout.cpp +++ b/src/plugins/texteditor/basetextdocumentlayout.cpp @@ -50,6 +50,7 @@ public: TextMarks marksAt(int line) const; void removeMark(ITextMark *mark); void updateMark(ITextMark *mark); + void moveMark(ITextMark *mark, int previousLine); void removeMarkFromMarksCache(TextEditor::ITextMark *mark); private: @@ -177,6 +178,18 @@ void DocumentMarker::updateMark(ITextMark *mark) documentLayout->requestUpdate(); } +void DocumentMarker::moveMark(ITextMark *mark, int previousLine) +{ + QTextBlock block = document->findBlockByNumber(previousLine - 1); + if (TextBlockUserData *data = BaseTextDocumentLayout::testUserData(block)) { + if (!data->removeMark(mark)) + qDebug() << "Could not find mark" << mark << "on line" << previousLine; + } + removeMarkFromMarksCache(mark); + mark->setMarkableInterface(0); + addMark(mark); +} + } // namespace Internal } // namespace TextEditor diff --git a/src/plugins/texteditor/basetexteditor_test.cpp b/src/plugins/texteditor/basetexteditor_test.cpp index 077a97d0952..4339e674e19 100644 --- a/src/plugins/texteditor/basetexteditor_test.cpp +++ b/src/plugins/texteditor/basetexteditor_test.cpp @@ -29,6 +29,7 @@ #ifdef WITH_TESTS +#include #include #include #include diff --git a/src/plugins/texteditor/itextmark.cpp b/src/plugins/texteditor/itextmark.cpp index 7102a9b5b30..d6c8b76edb3 100644 --- a/src/plugins/texteditor/itextmark.cpp +++ b/src/plugins/texteditor/itextmark.cpp @@ -53,6 +53,16 @@ void ITextMark::updateLineNumber(int lineNumber) m_lineNumber = lineNumber; } +void ITextMark::move(int line) +{ + if (line == m_lineNumber) + return; + const int previousLine = m_lineNumber; + m_lineNumber = line; + if (m_markableInterface) + m_markableInterface->moveMark(this, previousLine); +} + void ITextMark::updateBlock(const QTextBlock &) {} diff --git a/src/plugins/texteditor/itextmark.h b/src/plugins/texteditor/itextmark.h index f02c5813623..755696275f8 100644 --- a/src/plugins/texteditor/itextmark.h +++ b/src/plugins/texteditor/itextmark.h @@ -72,6 +72,7 @@ public: virtual void paint(QPainter *painter, const QRect &rect) const; virtual void updateLineNumber(int lineNumber); virtual void updateBlock(const QTextBlock &block); + virtual void move(int line); virtual void removedFromEditor(); virtual bool isClickable() const; virtual void clicked(); @@ -114,6 +115,7 @@ public: virtual TextMarks marksAt(int line) const = 0; virtual void removeMark(ITextMark *mark) = 0; virtual void updateMark(ITextMark *mark) = 0; + virtual void moveMark(ITextMark *mark, int previousLine) = 0; }; } // namespace TextEditor diff --git a/src/plugins/vcsbase/submiteditorwidget.cpp b/src/plugins/vcsbase/submiteditorwidget.cpp index 7f070a978e3..efbc5d40c04 100644 --- a/src/plugins/vcsbase/submiteditorwidget.cpp +++ b/src/plugins/vcsbase/submiteditorwidget.cpp @@ -657,9 +657,9 @@ void SubmitEditorWidget::fileListCustomContextMenuRequested(const QPoint & pos) // Execute menu offering to check/uncheck all QMenu menu; //: Check all for submit - QAction *checkAllAction = menu.addAction(tr("Check All")); + QAction *checkAllAction = menu.addAction(tr("Select All")); //: Uncheck all for submit - QAction *uncheckAllAction = menu.addAction(tr("Uncheck All")); + QAction *uncheckAllAction = menu.addAction(tr("Unselect All")); QAction *action = menu.exec(d->m_ui.fileView->mapToGlobal(pos)); if (action == checkAllAction) { checkAll(); diff --git a/src/plugins/vcsbase/submiteditorwidget.ui b/src/plugins/vcsbase/submiteditorwidget.ui index 0111080e1af..3bde1b3feb5 100644 --- a/src/plugins/vcsbase/submiteditorwidget.ui +++ b/src/plugins/vcsbase/submiteditorwidget.ui @@ -56,7 +56,7 @@ - Check a&ll + Select a&ll false diff --git a/src/src.pro b/src/src.pro index 2f986ab2e18..aacdc95e778 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,7 +1,29 @@ +include(../qtcreator.pri) + TEMPLATE = subdirs CONFIG += ordered -SUBDIRS = \ +minQtVersion(5, 0, 0) { + QBS_DIRS = \ + qbscorelib \ + qbsqtprofilesetup \ + qbsapps \ + qbsplugins \ + qbsstatic + + qbscorelib.subdir = shared/qbs/src/lib/corelib + qbsqtprofilesetup.subdir = shared/qbs/src/lib/qtprofilesetup + qbsqtprofilesetup.depends = qbscorelib + qbsapps.subdir = shared/qbs/src/app + qbsapps.depends = qbsqtprofilesetup + qbsplugins.subdir = shared/qbs/src/plugins + qbsstatic.file = shared/qbs/static.pro + + exists(shared/qbs/qbs.pro): SUBDIRS += $$QBS_DIRS + TR_EXCLUDE = $$QBS_DIRS +} + +SUBDIRS += \ libs \ app \ plugins \ diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp index 1bb998b2e39..83d16fa3fc3 100644 --- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp +++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ using namespace CPlusPlus; QCOMPARE(QString::fromLatin1(errors), QString::fromLatin1(expectedErrors)); \ } while (0) +inline QString _(const QByteArray &ba) { return QString::fromUtf8(ba, ba.size()); } class tst_cxx11: public QObject { @@ -98,6 +100,44 @@ class tst_cxx11: public QObject } }; + class FindLambdaFunction : public SymbolVisitor + { + public: + FindLambdaFunction() : m_function(0) {} + + Function *operator()(const CPlusPlus::Document::Ptr &document) + { + accept(document->globalNamespace()); + return m_function; + } + + private: + bool preVisit(Symbol *) { return !m_function; } + + bool visit(Function *function) + { + if (function->name()) + return true; + + m_function = function; + return false; + } + + private: + Function *m_function; + }; + + static void processDocument(const Document::Ptr doc, QByteArray source, + LanguageFeatures languageFeatures, QByteArray *errors) + { + Client client(errors); + doc->control()->setDiagnosticClient(&client); + doc->setUtf8Source(source); + doc->translationUnit()->setLanguageFeatures(languageFeatures); + doc->check(); + doc->control()->setDiagnosticClient(0); + } + Document::Ptr document(const QString &fileName, QByteArray *errors = 0, bool c99Enabled = false) { Document::Ptr doc = Document::create(fileName); @@ -106,12 +146,7 @@ class tst_cxx11: public QObject LanguageFeatures features; features.cxx11Enabled = true; features.c99Enabled = c99Enabled; - Client client(errors); - doc->control()->setDiagnosticClient(&client); - doc->setUtf8Source(QTextStream(&file).readAll().toUtf8()); - doc->translationUnit()->setLanguageFeatures(features); - doc->check(); - doc->control()->setDiagnosticClient(0); + processDocument(doc, QTextStream(&file).readAll().toUtf8(), features, errors); } else { qWarning() << "could not read file" << fileName; } @@ -132,6 +167,9 @@ private Q_SLOTS: // checks for the semantic // void inlineNamespaceLookup(); + + void lambdaType_data(); + void lambdaType(); }; @@ -213,5 +251,68 @@ void tst_cxx11::inlineNamespaceLookup() QCOMPARE(results.size(), 1); // the symbol is visible from the global scope } +void tst_cxx11::lambdaType_data() +{ + QTest::addColumn("source"); + QTest::addColumn("expectedType"); + + QTest::newRow("basic1") + << _("void f()\n" + "{\n" + " [](){};\n" + "}\n") + << _("void ()"); + + QTest::newRow("basic2") + << _("class C {\n" + " void f()\n" + " {\n" + " [](){};\n" + " }\n" + "};\n") + << _("void ()"); + + QTest::newRow("trailing return type") + << _("void f()\n" + "{\n" + " []() -> int { return 0; };\n" + "}\n") + << _("int ()"); + + QTest::newRow("return expression") + << _("void f()\n" + "{\n" + " []() { return true; };\n" + "}\n") + << _("bool ()"); +} + +void tst_cxx11::lambdaType() +{ + QFETCH(QString, source); + QFETCH(QString, expectedType); + + LanguageFeatures features; + features.cxx11Enabled = true; + + QByteArray errors; + Document::Ptr doc = Document::create(QLatin1String("testFile")); + processDocument(doc, source.toUtf8(), features, &errors); + + const bool hasErrors = !errors.isEmpty(); + if (hasErrors) + qDebug() << errors; + QVERIFY(!hasErrors); + + Function *function = FindLambdaFunction()(doc); + QVERIFY(function); + + Overview oo; + oo.showReturnTypes = true; + + QEXPECT_FAIL("return expression", "Not implemented", Abort); + QCOMPARE(oo.prettyType(function->type()), expectedType); +} + QTEST_APPLESS_MAIN(tst_cxx11) #include "tst_cxx11.moc" diff --git a/tests/system/objects.map b/tests/system/objects.map index c8e30b6187e..bed4b0b9413 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -77,7 +77,7 @@ :File has been removed.Close_QPushButton {text='Close' type='QPushButton' unnamed='1' visible='1' window=':File has been removed_QMessageBox'} :File has been removed.Save_QPushButton {text='Save' type='QPushButton' unnamed='1' visible='1' window=':File has been removed_QMessageBox'} :File has been removed_QMessageBox {text?='The file * removed*. Do you want to save it under a different name, or close the editor?' type='QMessageBox' unnamed='1' visible='1'} -:Files.Check all_QCheckBox {container=':splitter.Files_QGroupBox' name='checkAllCheckBox' text='Check all' type='QCheckBox' visible='1'} +:Files.Check all_QCheckBox {container=':splitter.Files_QGroupBox' name='checkAllCheckBox' text='Select all' type='QCheckBox' visible='1'} :Form.Startup_QGroupBox {container=':qt_tabwidget_stackedwidget.Form_QWidget' name='startupGroupBox' title='Startup' type='QGroupBox' visible='1'} :FormEditorStack.CheckBox_QCheckBox {container=':*Qt Creator.FormEditorStack_Designer::Internal::FormEditorStack' name='checkBox' text='CheckBox' type='QCheckBox' visible='1'} :FormEditorStack.PushButton_QPushButton {container=':*Qt Creator.FormEditorStack_Designer::Internal::FormEditorStack' name='pushButton' text='PushButton' type='QPushButton' visible='1'} diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py index 086aa9411e0..218c59049f9 100644 --- a/tests/system/shared/qtcreator.py +++ b/tests/system/shared/qtcreator.py @@ -121,6 +121,10 @@ def waitForCleanShutdown(timeOut=10): break def checkForStillRunningQmlExecutable(possibleNames): + if JIRA.isBugStillOpen(12644): + possibleNames.append('WerFault.exe') + else: + test.warning("Remove temporary workaround for QTCREATORBUG-12644!") for qmlHelper in possibleNames: tasks = subprocess.Popen("tasklist /FI \"IMAGENAME eq %s\"" % qmlHelper, shell=True, stdout=subprocess.PIPE) diff --git a/tests/system/suite_debugger/tst_qml_locals/test.py b/tests/system/suite_debugger/tst_qml_locals/test.py index f76b2d35f9c..ce74e4c8a7a 100644 --- a/tests/system/suite_debugger/tst_qml_locals/test.py +++ b/tests/system/suite_debugger/tst_qml_locals/test.py @@ -47,6 +47,7 @@ def main(): startApplication('qtcreator' + SettingsPath + ' "%s"' % qmlProjFile) if not startedWithoutPluginError(): return + waitFor('object.exists(":Qt Creator_Utils::NavigationTreeView")', 10000) fancyConfButton = findObject(":*Qt Creator_Core::Internal::FancyToolButton") fancyRunButton = findObject(":*Qt Creator.Run_Core::Internal::FancyToolButton") fancyDebugButton = findObject(":*Qt Creator.Start Debugging_Core::Internal::FancyToolButton")