diff options
Diffstat (limited to 'src')
285 files changed, 4059 insertions, 1673 deletions
diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index ee6d7f3a9d..84092fc93d 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -464,6 +464,57 @@ void Document::setGlobalNamespace(Namespace *globalNamespace) _globalNamespace = globalNamespace; } +/*! + * Extract the function name including scope at the given position. + * + * Note that a function (scope) starts at the name of that function, not at the return type. The + * implication is that this method will return an empty string when the line/column is on the + * return type. + * + * \param line the line number, starting with line 1 + * \param column the column number, starting with column 1 + */ +QString Document::functionAt(int line, int column) const +{ + if (line < 1 || column < 1) + return QString(); + + CPlusPlus::Symbol *symbol = lastVisibleSymbolAt(line, column); + if (!symbol) + return QString(); + + // Find the enclosing function scope (which might be several levels up, or we might be standing + // on it) + Scope *scope; + if (symbol->isScope()) + scope = symbol->asScope(); + else + scope = symbol->enclosingScope(); + + while (scope && !scope->isFunction() ) + scope = scope->enclosingScope(); + + if (!scope) + return QString(); + + // We found the function scope, extract its name. + const Overview o; + QString rc = o.prettyName(scope->name()); + + // Prepend namespace "Foo::Foo::foo()" up to empty root namespace + for (const Symbol *owner = scope->enclosingNamespace(); + owner; owner = owner->enclosingNamespace()) { + const QString name = o.prettyName(owner->name()); + if (name.isEmpty()) { + break; + } else { + rc.prepend(QLatin1String("::")); + rc.prepend(name); + } + } + return rc; +} + Scope *Document::scopeAt(unsigned line, unsigned column) { FindScopeAt findScopeAt(_translationUnit, line, column); diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index 589e2b9503..b9a58f547f 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -99,6 +99,7 @@ public: QList<Macro> definedMacros() const { return _definedMacros; } + QString functionAt(int line, int column) const; Symbol *lastVisibleSymbolAt(unsigned line, unsigned column = 0) const; Scope *scopeAt(unsigned line, unsigned column = 0); diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 91aa73efb9..3643601a85 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1332,19 +1332,6 @@ void Preprocessor::synchronizeOutputLines(const PPToken &tk, bool forceLine) adjustForCommentOrStringNewlines(&m_env->currentLine, tk); } -void Preprocessor::removeTrailingOutputLines() -{ - QByteArray &buffer = currentOutputBuffer(); - int i = buffer.size() - 1; - while (i >= 0 && buffer.at(i) == '\n') - --i; - const int mightChop = buffer.size() - i - 1; - if (mightChop > 1) { - // Keep one new line at end. - buffer.chop(mightChop - 1); - } -} - std::size_t Preprocessor::computeDistance(const Preprocessor::PPToken &tk, bool forceTillLine) { // Find previous non-space character or line begin. @@ -1450,8 +1437,6 @@ void Preprocessor::preprocess(const QString &fileName, const QByteArray &source, } while (tk.isNot(T_EOF_SYMBOL)); - removeTrailingOutputLines(); - if (includeGuardMacroName) { if (m_state.m_includeGuardState == State::IncludeGuardState_AfterDefine || m_state.m_includeGuardState == State::IncludeGuardState_AfterEndif) @@ -1915,8 +1900,6 @@ void Preprocessor::handleEndIfDirective(PPToken *tk, const PPToken £Token) void Preprocessor::handleIfDefDirective(bool checkUndefined, PPToken *tk) { - static const QByteArray qCreatorRun("Q_CREATOR_RUN"); - lex(tk); // consume "ifdef" token if (tk->is(T_IDENTIFIER)) { if (checkUndefined && m_state.m_ifLevel == 0) @@ -1937,8 +1920,6 @@ void Preprocessor::handleIfDefDirective(bool checkUndefined, PPToken *tk) } } else if (m_env->isBuiltinMacro(macroName)) { value = true; - } else if (macroName == qCreatorRun) { - value = true; } if (checkUndefined) diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index f118a00da4..2614c107b1 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -237,7 +237,6 @@ private: void maybeStartOutputLine(); void generateOutputLineMarker(unsigned lineno); void synchronizeOutputLines(const PPToken &tk, bool forceLine = false); - void removeTrailingOutputLines(); void enforceSpacing(const PPToken &tk, bool forceSpacing = false); static std::size_t computeDistance(const PPToken &tk, bool forceTillLine = false); diff --git a/src/libs/extensionsystem/plugindetailsview.cpp b/src/libs/extensionsystem/plugindetailsview.cpp index ca3c267cea..cb9e792443 100644 --- a/src/libs/extensionsystem/plugindetailsview.cpp +++ b/src/libs/extensionsystem/plugindetailsview.cpp @@ -46,7 +46,6 @@ using namespace ExtensionSystem; /*! - \fn PluginDetailsView::PluginDetailsView(QWidget *parent) Constructs a new view with given \a parent widget. */ PluginDetailsView::PluginDetailsView(QWidget *parent) @@ -57,7 +56,6 @@ PluginDetailsView::PluginDetailsView(QWidget *parent) } /*! - \fn PluginDetailsView::~PluginDetailsView() \internal */ PluginDetailsView::~PluginDetailsView() @@ -66,7 +64,6 @@ PluginDetailsView::~PluginDetailsView() } /*! - \fn void PluginDetailsView::update(PluginSpec *spec) Reads the given \a spec and displays its values in this PluginDetailsView. */ diff --git a/src/libs/extensionsystem/pluginerrorview.cpp b/src/libs/extensionsystem/pluginerrorview.cpp index 7d4c9e825a..81d3c63f1b 100644 --- a/src/libs/extensionsystem/pluginerrorview.cpp +++ b/src/libs/extensionsystem/pluginerrorview.cpp @@ -46,7 +46,6 @@ using namespace ExtensionSystem; /*! - \fn PluginErrorView::PluginErrorView(QWidget *parent) Constructs a new error view with given \a parent widget. */ PluginErrorView::PluginErrorView(QWidget *parent) @@ -57,7 +56,6 @@ PluginErrorView::PluginErrorView(QWidget *parent) } /*! - \fn PluginErrorView::~PluginErrorView() \internal */ PluginErrorView::~PluginErrorView() @@ -66,7 +64,6 @@ PluginErrorView::~PluginErrorView() } /*! - \fn void PluginErrorView::update(PluginSpec *spec) Reads the given \a spec and displays its state and error information in this PluginErrorView. */ diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index e2e8d124e8..373f96a923 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -454,6 +454,8 @@ QHash<QString, PluginCollection *> PluginManager::pluginCollections() return m_instance->d->pluginCategories; } +static const char argumentKeywordC[] = ":arguments"; + /*! Serialize plugin options and arguments for sending in a single string via QtSingleApplication: @@ -462,9 +464,6 @@ QHash<QString, PluginCollection *> PluginManager::pluginCollections() \sa setPluginPaths() */ - -static const char argumentKeywordC[] = ":arguments"; - QString PluginManager::serializedArguments() { const QChar separator = QLatin1Char('|'); @@ -639,7 +638,6 @@ void PluginManager::formatPluginOptions(QTextStream &str, int optionIndentation, /*! Format the version of the plugin specs for command line help. */ - void PluginManager::formatPluginVersions(QTextStream &str) { const PluginSpecSet::const_iterator cend = m_instance->d->pluginSpecs.constEnd(); diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index 87a70d09c2..c9ccce4ce2 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -145,7 +145,6 @@ using namespace ExtensionSystem; using namespace ExtensionSystem::Internal; /*! - \fn uint qHash(const ExtensionSystem::PluginDependency &value) \internal */ uint ExtensionSystem::qHash(const ExtensionSystem::PluginDependency &value) @@ -154,7 +153,6 @@ uint ExtensionSystem::qHash(const ExtensionSystem::PluginDependency &value) } /*! - \fn bool PluginDependency::operator==(const PluginDependency &other) const \internal */ bool PluginDependency::operator==(const PluginDependency &other) const @@ -163,7 +161,6 @@ bool PluginDependency::operator==(const PluginDependency &other) const } /*! - \fn PluginSpec::PluginSpec() \internal */ PluginSpec::PluginSpec() @@ -172,7 +169,6 @@ PluginSpec::PluginSpec() } /*! - \fn PluginSpec::~PluginSpec() \internal */ PluginSpec::~PluginSpec() @@ -182,7 +178,6 @@ PluginSpec::~PluginSpec() } /*! - \fn QString PluginSpec::name() const The plugin name. This is valid after the PluginSpec::Read state is reached. */ QString PluginSpec::name() const @@ -191,7 +186,6 @@ QString PluginSpec::name() const } /*! - \fn QString PluginSpec::version() const The plugin version. This is valid after the PluginSpec::Read state is reached. */ QString PluginSpec::version() const @@ -200,7 +194,6 @@ QString PluginSpec::version() const } /*! - \fn QString PluginSpec::compatVersion() const The plugin compatibility version. This is valid after the PluginSpec::Read state is reached. */ QString PluginSpec::compatVersion() const @@ -209,7 +202,6 @@ QString PluginSpec::compatVersion() const } /*! - \fn QString PluginSpec::vendor() const The plugin vendor. This is valid after the PluginSpec::Read state is reached. */ QString PluginSpec::vendor() const @@ -218,7 +210,6 @@ QString PluginSpec::vendor() const } /*! - \fn QString PluginSpec::copyright() const The plugin copyright. This is valid after the PluginSpec::Read state is reached. */ QString PluginSpec::copyright() const @@ -227,7 +218,6 @@ QString PluginSpec::copyright() const } /*! - \fn QString PluginSpec::license() const The plugin license. This is valid after the PluginSpec::Read state is reached. */ QString PluginSpec::license() const @@ -236,7 +226,6 @@ QString PluginSpec::license() const } /*! - \fn QString PluginSpec::description() const The plugin description. This is valid after the PluginSpec::Read state is reached. */ QString PluginSpec::description() const @@ -245,7 +234,6 @@ QString PluginSpec::description() const } /*! - \fn QString PluginSpec::url() const The plugin url where you can find more information about the plugin. This is valid after the PluginSpec::Read state is reached. */ QString PluginSpec::url() const @@ -254,7 +242,6 @@ QString PluginSpec::url() const } /*! - \fn QString PluginSpec::category() const The category that the plugin belongs to. Categories are groups of plugins which allow for keeping them together in the UI. Returns an empty string if the plugin does not belong to a category. */ @@ -264,7 +251,6 @@ QString PluginSpec::category() const } /*! - \fn bool PluginSpec::isExperimental() const Returns if the plugin has its experimental flag set. */ bool PluginSpec::isExperimental() const @@ -283,7 +269,6 @@ bool PluginSpec::isDisabledByDefault() const } /*! - \fn bool PluginSpec::isEnabledInSettings() const Returns if the plugin should be loaded at startup. True by default The user can change it from the Plugin settings. Note: That this function returns true even if a plugin is disabled because @@ -295,7 +280,6 @@ bool PluginSpec::isEnabledInSettings() const } /*! - \fn bool PluginSpec::isEffectivelyEnabled() const Returns if the plugin is loaded at startup. \see PluginSpec::isEnabled */ @@ -307,7 +291,6 @@ bool PluginSpec::isEffectivelyEnabled() const } /*! - \fn bool PluginSpec::isDisabledIndirectly() const Returns true if loading was not done due to user unselecting this plugin or its dependencies. */ bool PluginSpec::isDisabledIndirectly() const @@ -316,7 +299,6 @@ bool PluginSpec::isDisabledIndirectly() const } /*! - \fn bool PluginSpec::isForceEnabled() const Returns if the plugin is enabled via the -load option on the command line. */ bool PluginSpec::isForceEnabled() const @@ -325,7 +307,6 @@ bool PluginSpec::isForceEnabled() const } /*! - \fn bool PluginSpec::isForceDisabled() const Returns if the plugin is disabled via the -noload option on the command line. */ bool PluginSpec::isForceDisabled() const @@ -334,7 +315,6 @@ bool PluginSpec::isForceDisabled() const } /*! - \fn QList<PluginDependency> PluginSpec::dependencies() const The plugin dependencies. This is valid after the PluginSpec::Read state is reached. */ QList<PluginDependency> PluginSpec::dependencies() const @@ -343,7 +323,6 @@ QList<PluginDependency> PluginSpec::dependencies() const } /*! - \fn PluginSpec::PluginArgumentDescriptions PluginSpec::argumentDescriptions() const Returns a list of descriptions of command line arguments the plugin processes. */ @@ -353,7 +332,6 @@ PluginSpec::PluginArgumentDescriptions PluginSpec::argumentDescriptions() const } /*! - \fn QString PluginSpec::location() const The absolute path to the directory containing the plugin xml description file this PluginSpec corresponds to. */ @@ -363,7 +341,6 @@ QString PluginSpec::location() const } /*! - \fn QString PluginSpec::filePath() const The absolute path to the plugin xml description file (including the file name) this PluginSpec corresponds to. */ @@ -373,7 +350,6 @@ QString PluginSpec::filePath() const } /*! - \fn QStringList PluginSpec::arguments() const Command line arguments specific to that plugin. Set at startup */ @@ -383,7 +359,6 @@ QStringList PluginSpec::arguments() const } /*! - \fn void PluginSpec::setArguments(const QStringList &arguments) Set the command line arguments specific to that plugin to \a arguments. */ @@ -393,7 +368,6 @@ void PluginSpec::setArguments(const QStringList &arguments) } /*! - \fn PluginSpec::addArgument(const QString &argument) Adds \a argument to the command line arguments specific to that plugin. */ @@ -404,7 +378,6 @@ void PluginSpec::addArgument(const QString &argument) /*! - \fn PluginSpec::State PluginSpec::state() const The state in which the plugin currently is. See the description of the PluginSpec::State enum for details. */ @@ -414,7 +387,6 @@ PluginSpec::State PluginSpec::state() const } /*! - \fn bool PluginSpec::hasError() const Returns whether an error occurred while reading/starting the plugin. */ bool PluginSpec::hasError() const @@ -423,7 +395,6 @@ bool PluginSpec::hasError() const } /*! - \fn QString PluginSpec::errorString() const Detailed, possibly multi-line, error description in case of an error. */ QString PluginSpec::errorString() const @@ -432,7 +403,6 @@ QString PluginSpec::errorString() const } /*! - \fn bool PluginSpec::provides(const QString &pluginName, const QString &version) const Returns if this plugin can be used to fill in a dependency of the given \a pluginName and \a version. @@ -444,7 +414,6 @@ bool PluginSpec::provides(const QString &pluginName, const QString &version) con } /*! - \fn IPlugin *PluginSpec::plugin() const The corresponding IPlugin instance, if the plugin library has already been successfully loaded, i.e. the PluginSpec::Loaded state is reached. */ @@ -454,7 +423,6 @@ IPlugin *PluginSpec::plugin() const } /*! - \fn QList<PluginSpec *> PluginSpec::dependencySpecs() const Returns the list of dependencies, already resolved to existing plugin specs. Valid if PluginSpec::Resolved state is reached. @@ -493,7 +461,6 @@ namespace { const char ARGUMENT_PARAMETER[] = "parameter"; } /*! - \fn PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec) \internal */ PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec) @@ -512,7 +479,6 @@ PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec) } /*! - \fn bool PluginSpecPrivate::read(const QString &fileName) \internal */ bool PluginSpecPrivate::read(const QString &fileName) @@ -590,7 +556,6 @@ void PluginSpec::setForceDisabled(bool value) } /*! - \fn bool PluginSpecPrivate::reportError(const QString &err) \internal */ bool PluginSpecPrivate::reportError(const QString &err) @@ -626,7 +591,6 @@ static inline QString msgUnexpectedToken() } /*! - \fn void PluginSpecPrivate::readPluginSpec(QXmlStreamReader &reader) \internal */ void PluginSpecPrivate::readPluginSpec(QXmlStreamReader &reader) @@ -702,10 +666,8 @@ void PluginSpecPrivate::readPluginSpec(QXmlStreamReader &reader) } /*! - \fn void PluginSpecPrivate::readArgumentDescriptions(QXmlStreamReader &reader) \internal */ - void PluginSpecPrivate::readArgumentDescriptions(QXmlStreamReader &reader) { QString element; @@ -736,7 +698,6 @@ void PluginSpecPrivate::readArgumentDescriptions(QXmlStreamReader &reader) } /*! - \fn void PluginSpecPrivate::readArgumentDescription(QXmlStreamReader &reader) \internal */ void PluginSpecPrivate::readArgumentDescription(QXmlStreamReader &reader) @@ -766,7 +727,6 @@ bool PluginSpecPrivate::readBooleanValue(QXmlStreamReader &reader, const char *k } /*! - \fn void PluginSpecPrivate::readDependencies(QXmlStreamReader &reader) \internal */ void PluginSpecPrivate::readDependencies(QXmlStreamReader &reader) @@ -799,7 +759,6 @@ void PluginSpecPrivate::readDependencies(QXmlStreamReader &reader) } /*! - \fn void PluginSpecPrivate::readDependencyEntry(QXmlStreamReader &reader) \internal */ void PluginSpecPrivate::readDependencyEntry(QXmlStreamReader &reader) @@ -834,7 +793,6 @@ void PluginSpecPrivate::readDependencyEntry(QXmlStreamReader &reader) } /*! - \fn bool PluginSpecPrivate::provides(const QString &pluginName, const QString &pluginVersion) const \internal */ bool PluginSpecPrivate::provides(const QString &pluginName, const QString &pluginVersion) const @@ -845,7 +803,6 @@ bool PluginSpecPrivate::provides(const QString &pluginName, const QString &plugi } /*! - \fn QRegExp &PluginSpecPrivate::versionRegExp() \internal */ QRegExp &PluginSpecPrivate::versionRegExp() @@ -854,7 +811,6 @@ QRegExp &PluginSpecPrivate::versionRegExp() return reg; } /*! - \fn bool PluginSpecPrivate::isValidVersion(const QString &version) \internal */ bool PluginSpecPrivate::isValidVersion(const QString &version) @@ -863,7 +819,6 @@ bool PluginSpecPrivate::isValidVersion(const QString &version) } /*! - \fn int PluginSpecPrivate::versionCompare(const QString &version1, const QString &version2) \internal */ int PluginSpecPrivate::versionCompare(const QString &version1, const QString &version2) @@ -888,7 +843,6 @@ int PluginSpecPrivate::versionCompare(const QString &version1, const QString &ve } /*! - \fn bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs) \internal */ bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs) @@ -956,7 +910,6 @@ void PluginSpecPrivate::disableIndirectlyIfDependencyDisabled() } /*! - \fn bool PluginSpecPrivate::loadLibrary() \internal */ bool PluginSpecPrivate::loadLibrary() @@ -1013,7 +966,6 @@ bool PluginSpecPrivate::loadLibrary() } /*! - \fn bool PluginSpecPrivate::initializePlugin() \internal */ bool PluginSpecPrivate::initializePlugin() @@ -1043,7 +995,6 @@ bool PluginSpecPrivate::initializePlugin() } /*! - \fn bool PluginSpecPrivate::initializeExtensions() \internal */ bool PluginSpecPrivate::initializeExtensions() @@ -1068,7 +1019,6 @@ bool PluginSpecPrivate::initializeExtensions() } /*! - \fn bool PluginSpecPrivate::delayedInitialize() \internal */ bool PluginSpecPrivate::delayedInitialize() @@ -1086,7 +1036,6 @@ bool PluginSpecPrivate::delayedInitialize() } /*! - \fn bool PluginSpecPrivate::stop() \internal */ IPlugin::ShutdownFlag PluginSpecPrivate::stop() @@ -1098,7 +1047,6 @@ IPlugin::ShutdownFlag PluginSpecPrivate::stop() } /*! - \fn bool PluginSpecPrivate::kill() \internal */ void PluginSpecPrivate::kill() diff --git a/src/libs/qmldebug/qpacketprotocol.cpp b/src/libs/qmldebug/qpacketprotocol.cpp index d9aa7493a9..4bc56c2173 100644 --- a/src/libs/qmldebug/qpacketprotocol.cpp +++ b/src/libs/qmldebug/qpacketprotocol.cpp @@ -265,8 +265,6 @@ QPacketAutoSend QPacketProtocol::send() } /*! - \fn void QPacketProtocol::send(const QPacket & packet) - Transmit the \a packet. */ void QPacketProtocol::send(const QPacket & p) diff --git a/src/libs/qmljs/parser/qmlerror.cpp b/src/libs/qmljs/parser/qmlerror.cpp index cd81100d1e..b097eea812 100644 --- a/src/libs/qmljs/parser/qmlerror.cpp +++ b/src/libs/qmljs/parser/qmlerror.cpp @@ -237,7 +237,6 @@ QString QmlError::toString() const /*! \relates QmlError - \fn QDebug operator<<(QDebug debug, const QmlError &error) Outputs a human readable version of \a error to \a debug. */ diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri index f31879a6f0..12913de0a5 100644 --- a/src/libs/qmljs/qmljs-lib.pri +++ b/src/libs/qmljs/qmljs-lib.pri @@ -39,7 +39,8 @@ HEADERS += \ $$PWD/consoleitem.h \ $$PWD/iscriptevaluator.h \ $$PWD/qmljssimplereader.h \ - $$PWD/persistenttrie.h + $$PWD/persistenttrie.h \ + $$PWD/qmljsqrcparser.h SOURCES += \ $$PWD/qmljsbind.cpp \ @@ -69,7 +70,8 @@ SOURCES += \ $$PWD/consolemanagerinterface.cpp \ $$PWD/consoleitem.cpp \ $$PWD/qmljssimplereader.cpp \ - $$PWD/persistenttrie.cpp + $$PWD/persistenttrie.cpp \ + $$PWD/qmljsqrcparser.cpp RESOURCES += \ $$PWD/qmljs.qrc diff --git a/src/libs/qmljs/qmljs.pro b/src/libs/qmljs/qmljs.pro index c9c018de5c..5db252b290 100644 --- a/src/libs/qmljs/qmljs.pro +++ b/src/libs/qmljs/qmljs.pro @@ -1,5 +1,5 @@ DEFINES += QMLJS_BUILD_DIR -QT +=script +QT +=script xml include(../../qtcreatorlibrary.pri) include(qmljs-lib.pri) diff --git a/src/libs/qmljs/qmljs.qbs b/src/libs/qmljs/qmljs.qbs index 2bef9864c4..7029b1149f 100644 --- a/src/libs/qmljs/qmljs.qbs +++ b/src/libs/qmljs/qmljs.qbs @@ -12,7 +12,7 @@ QtcLibrary { Depends { name: "Utils" } Depends { name: "LanguageUtils" } - Depends { name: "Qt"; submodules: ["widgets", "script"] } + Depends { name: "Qt"; submodules: ["widgets", "script", "xml"] } files: [ "jsoncheck.cpp", @@ -52,6 +52,8 @@ QtcLibrary { "qmljsmodelmanagerinterface.h", "qmljspropertyreader.cpp", "qmljspropertyreader.h", + "qmljsqrcparser.cpp", + "qmljsqrcparser.h", "qmljsreformatter.cpp", "qmljsreformatter.h", "qmljsrewriter.cpp", diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp index 3e55ccc42a..a7eb00c354 100644 --- a/src/libs/qmljs/qmljsdocument.cpp +++ b/src/libs/qmljs/qmljsdocument.cpp @@ -115,6 +115,22 @@ bool Document::isFullySupportedLanguage(Document::Language language) return false; } +bool Document::isQmlLikeOrJsLanguage(Document::Language language) +{ + switch (language) { + case QmlLanguage: + case QmlQtQuick1Language: + case QmlQtQuick2Language: + case QmlQbsLanguage: + case QmlProjectLanguage: + case QmlTypeInfoLanguage: + case JavaScriptLanguage: + return true; + default: + return false; + } +} + Document::Document(const QString &fileName, Language language) : _engine(0) , _ast(0) diff --git a/src/libs/qmljs/qmljsdocument.h b/src/libs/qmljs/qmljsdocument.h index e18f95d475..56ebb7061e 100644 --- a/src/libs/qmljs/qmljsdocument.h +++ b/src/libs/qmljs/qmljsdocument.h @@ -65,6 +65,7 @@ public: static bool isQmlLikeLanguage(Language languge); static bool isFullySupportedLanguage(Language language); + static bool isQmlLikeOrJsLanguage(Language language); protected: Document(const QString &fileName, Language language); diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 24d68d4948..c9b1f4381a 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -35,6 +35,7 @@ #include "qmljstypedescriptionreader.h" #include "qmljsvalueowner.h" #include "qmljscontext.h" +#include "qmljsmodelmanagerinterface.h" #include "parser/qmljsast_p.h" #include <utils/qtcassert.h> @@ -2107,13 +2108,19 @@ ImportInfo ImportInfo::pathImport(const QString &docPath, const QString &path, importFileInfo = QFileInfo(docPath + QDir::separator() + path); info._path = importFileInfo.absoluteFilePath(); - if (importFileInfo.isFile()) + if (importFileInfo.isFile()) { info._type = FileImport; - else if (importFileInfo.isDir()) + } else if (importFileInfo.isDir()) { info._type = DirectoryImport; - else + } else if (path.startsWith(QLatin1String("qrc:"))) { + info._path = path; + if (ModelManagerInterface::instance()->filesAtQrcPath(info.path()).isEmpty()) + info._type = QrcDirectoryImport; + else + info._type = QrcFileImport; + } else { info._type = UnknownFileImport; - + } info._version = version; info._as = as; info._ast = ast; @@ -2192,7 +2199,7 @@ const Value *TypeScope::lookupMember(const QString &name, const Context *context const ImportInfo &info = i.info; // JS import has no types - if (info.type() == ImportInfo::FileImport) + if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport) continue; if (!info.as().isEmpty()) { @@ -2222,7 +2229,7 @@ void TypeScope::processMembers(MemberProcessor *processor) const const ImportInfo &info = i.info; // JS import has no types - if (info.type() == ImportInfo::FileImport) + if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport) continue; if (!info.as().isEmpty()) @@ -2249,7 +2256,7 @@ const Value *JSImportScope::lookupMember(const QString &name, const Context *, const ImportInfo &info = i.info; // JS imports are always: import "somefile.js" as Foo - if (info.type() != ImportInfo::FileImport) + if (info.type() != ImportInfo::FileImport && info.type() != ImportInfo::QrcFileImport) continue; if (info.as() == name) { @@ -2272,7 +2279,7 @@ void JSImportScope::processMembers(MemberProcessor *processor) const const ObjectValue *import = i.object; const ImportInfo &info = i.info; - if (info.type() == ImportInfo::FileImport) + if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport) processor->processProperty(info.as(), import); } } @@ -2329,7 +2336,7 @@ ImportInfo Imports::info(const QString &name, const Context *context) const continue; } - if (info.type() == ImportInfo::FileImport) { + if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport) { if (import->className() == firstId) return info; } else { @@ -2349,7 +2356,7 @@ QString Imports::nameForImportedObject(const ObjectValue *value, const Context * const ObjectValue *import = i.object; const ImportInfo &info = i.info; - if (info.type() == ImportInfo::FileImport) { + if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport) { if (import == value) return import->className(); } else { diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 56f914713f..356f52bb38 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -872,6 +872,8 @@ public: LibraryImport, FileImport, DirectoryImport, + QrcFileImport, + QrcDirectoryImport, UnknownFileImport // refers a file/directory that wasn't found }; diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index e90dd9a9ae..2d5672fa20 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -34,6 +34,7 @@ #include "qmljsbind.h" #include "qmljsutils.h" #include "qmljsmodelmanagerinterface.h" +#include <qmljs/qmljsqrcparser.h> #include <QDir> #include <QDebug> @@ -245,6 +246,8 @@ void LinkPrivate::populateImportedTypes(Imports *imports, Document::Ptr doc) switch (info.type()) { case ImportInfo::FileImport: case ImportInfo::DirectoryImport: + case ImportInfo::QrcFileImport: + case ImportInfo::QrcDirectoryImport: import = importFileOrDirectory(doc, info); break; case ImportInfo::LibraryImport: @@ -285,7 +288,7 @@ Import LinkPrivate::importFileOrDirectory(Document::Ptr doc, const ImportInfo &i import.object = 0; import.valid = true; - const QString &path = importInfo.path(); + QString path = importInfo.path(); if (importInfo.type() == ImportInfo::DirectoryImport || importInfo.type() == ImportInfo::ImplicitDirectoryImport) { @@ -304,8 +307,36 @@ Import LinkPrivate::importFileOrDirectory(Document::Ptr doc, const ImportInfo &i Document::Ptr importedDoc = snapshot.document(path); if (importedDoc) import.object = importedDoc->bind()->rootObjectValue(); - } + } else if (importInfo.type() == ImportInfo::QrcFileImport) { + QLocale locale; + QStringList filePaths = ModelManagerInterface::instance() + ->filesAtQrcPath(path, &locale, 0, ModelManagerInterface::ActiveQrcResources); + if (filePaths.isEmpty()) { + filePaths = ModelManagerInterface::instance()->filesAtQrcPath(path); + } + if (!filePaths.isEmpty()) { + Document::Ptr importedDoc = snapshot.document(filePaths.at(0)); + if (importedDoc) + import.object = importedDoc->bind()->rootObjectValue(); + } + } else if (importInfo.type() == ImportInfo::QrcDirectoryImport){ + import.object = new ObjectValue(valueOwner); + + importLibrary(doc, path, &import); + QMapIterator<QString,QStringList> iter(ModelManagerInterface::instance() + ->filesInQrcPath(path)); + while (iter.hasNext()) { + iter.next(); + if (Document::isQmlLikeLanguage(Document::guessLanguageFromSuffix(iter.key()))) { + Document::Ptr importedDoc = snapshot.document(iter.value().at(0)); + if (importedDoc && importedDoc->bind()->rootObjectValue()) { + const QString targetName = QFileInfo(iter.key()).baseName(); + import.object->setMember(targetName, importedDoc->bind()->rootObjectValue()); + } + } + } + } return import; } diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index b708c3ca41..cdcaef362d 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -53,6 +53,11 @@ class QMLJS_EXPORT ModelManagerInterface: public QObject Q_OBJECT public: + enum QrcResourceSelector { + ActiveQrcResources, + AllQrcResources + }; + class ProjectInfo { public: @@ -80,6 +85,8 @@ public: QPointer<ProjectExplorer::Project> project; QStringList sourceFiles; QStringList importPaths; + QStringList activeResourceFiles; + QStringList allResourceFiles; // whether trying to run qmldump makes sense bool tryQmlDump; @@ -142,6 +149,14 @@ public: bool emitDocumentOnDiskChanged) = 0; virtual void fileChangedOnDisk(const QString &path) = 0; virtual void removeFiles(const QStringList &files) = 0; + virtual QStringList filesAtQrcPath(const QString &path, const QLocale *locale = 0, + ProjectExplorer::Project *project = 0, + QrcResourceSelector resources = AllQrcResources) = 0; + virtual QMap<QString,QStringList> filesInQrcPath(const QString &path, + const QLocale *locale = 0, + ProjectExplorer::Project *project = 0, + bool addDirs = false, + QrcResourceSelector resources = AllQrcResources) = 0; virtual QList<ProjectInfo> projectInfos() const = 0; virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const = 0; diff --git a/src/libs/qmljs/qmljsqrcparser.cpp b/src/libs/qmljs/qmljsqrcparser.cpp new file mode 100644 index 0000000000..cdecbcd735 --- /dev/null +++ b/src/libs/qmljs/qmljsqrcparser.cpp @@ -0,0 +1,517 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qmljsqrcparser.h" +#include <QFile> +#include <QDir> +#include <QFileInfo> +#include <QStringList> +#include <QDomDocument> +#include <QLocale> +#include <QMutex> +#include <QSet> +#include <QMutexLocker> +#include <QMultiHash> +#include <QCoreApplication> +#include <utils/qtcassert.h> +#include <QDebug> + +namespace QmlJS { + +namespace Internal { +/*! + * \class QrcParser + * \brief Parses one or more qrc files, and keeps their content cached + * + * A Qrc resource contains files read from the filesystem but organized in a possibly different way. + * + * To easily describe that with a simple structure we use a map from qrc paths to the paths in the + * filesystem. + * By using a map we can easily find all qrc paths that start with a given prefix, and thus loop + * on a qrc directory. + * + * Qrc files also support languages, those are mapped to a prefix of the qrc path. + * For example the french /image/bla.png (lang=fr) will have the path "fr/image/bla.png". + * The empty language represent the default resource. + * Languages are looked up using the locale uiLanguages() property + * + * For a single qrc a given path maps to a single file, but when one has multiple + * (platform specific exclusive) qrc files, then multiple files match, so QStringList are used. + * + * Especially the collect* methods are thought as low level interface. + */ +class QrcParserPrivate +{ + Q_DECLARE_TR_FUNCTIONS(QmlJS::QrcParser) +public: + typedef QMap<QString,QStringList> SMap; + QrcParserPrivate(QrcParser *q); + bool parseFile(const QString &path); + QString firstFileAtPath(const QString &path, const QLocale &locale) const; + void collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale = 0) const; + bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const; + void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false, + const QLocale *locale = 0) const; + QStringList errorMessages() const; + QStringList languages() const; +private: + static QString fixPrefix(const QString &prefix); + QStringList allUiLanguages(const QLocale *locale) const; + + SMap m_resources; + QStringList m_languages; + QStringList m_errorMessages; +}; + +class QrcCachePrivate +{ + Q_DECLARE_TR_FUNCTIONS(QmlJS::QrcCachePrivate) +public: + QrcCachePrivate(QrcCache *q); + QrcParser::Ptr addPath(const QString &path); + void removePath(const QString &path); + QrcParser::Ptr updatePath(const QString &path); + QrcParser::Ptr parsedPath(const QString &path); + void clear(); +private: + QHash<QString, QPair<QrcParser::Ptr,int> > m_cache; + QMutex m_mutex; +}; +} // namespace Internal + +/*! \brief normalizes the path to a file in a qrc resource by dropping the "qrc:/" or ":" and + * any extra slashes at the beginning + */ +QString QrcParser::normalizedQrcFilePath(const QString &path) { + QString normPath = path; + int endPrefix = 0; + if (path.startsWith(QLatin1String("qrc:/"))) { + endPrefix = 4; + } else if (path.startsWith(QLatin1String(":/"))) { + endPrefix = 1; + } + if (endPrefix < path.size() && path.at(endPrefix) == QLatin1Char('/')) + while (endPrefix + 1 < path.size() && path.at(endPrefix+1) == QLatin1Char('/')) + ++endPrefix; + normPath = path.right(path.size()-endPrefix); + if (!normPath.startsWith(QLatin1String("/"))) + normPath.insert(0, QLatin1Char('/')); + return normPath; +} + +/*! \brief normalizes the path to a directory in a qrc resource by dropping the "qrc:/" or ":" and + * any extra slashes at the beginning, and ensuring it ends with a slash + */ +QString QrcParser::normalizedQrcDirectoryPath(const QString &path) { + QString normPath = normalizedQrcFilePath(path); + if (!normPath.endsWith(QLatin1Char('/'))) + normPath.append(QLatin1Char('/')); + return normPath; +} + +QrcParser::QrcParser() +{ + d = new Internal::QrcParserPrivate(this); +} + +QrcParser::~QrcParser() +{ + delete d; +} + +bool QrcParser::parseFile(const QString &path) +{ + return d->parseFile(path); +} + +/*! \brief returns fs path of the first (active) file at the given qrc path + */ +QString QrcParser::firstFileAtPath(const QString &path, const QLocale &locale) const +{ + return d->firstFileAtPath(path, locale); +} + +/*! \brief adds al the fs paths for the given qrc path to *res + * If locale is null all possible files are added, otherwise just the first match + * using that locale. + */ +void QrcParser::collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale) const +{ + d->collectFilesAtPath(path, res, locale); +} + +/*! \brief returns true if the given path is a non empty directory + */ +bool QrcParser::hasDirAtPath(const QString &path, const QLocale *locale) const +{ + return d->hasDirAtPath(path, locale); +} + +/*! \brief adds the directory contents of the given qrc path to res + * + * adds the qrcFileName => fs paths associations contained in the given qrc path + * to res. If addDirs is true directories are also added. + * If locale is null all possible files are added, otherwise just the first match + * using that locale. + */ +void QrcParser::collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs, + const QLocale *locale) const +{ + d->collectFilesInPath(path, res, addDirs, locale); +} + +/*! \brief returns the errors found while parsing + */ +QStringList QrcParser::errorMessages() const +{ + return d->errorMessages(); +} + +/*! \brief returns all languages used in this qrc resource + */ +QStringList QrcParser::languages() const +{ + return d->languages(); +} + +/*! \brief if the contents are valid + */ +bool QrcParser::isValid() const +{ + return errorMessages().isEmpty(); +} + +QrcParser::Ptr QrcParser::parseQrcFile(const QString &path) +{ + Ptr res(new QrcParser); + if (!path.isEmpty()) + res->parseFile(path); + return res; +} + +// ---------------- + +QrcCache::QrcCache() +{ + d = new Internal::QrcCachePrivate(this); +} + +QrcCache::~QrcCache() +{ + delete d; +} + +QrcParser::ConstPtr QrcCache::addPath(const QString &path) +{ + return d->addPath(path); +} + +void QrcCache::removePath(const QString &path) +{ + d->removePath(path); +} + +QrcParser::ConstPtr QrcCache::updatePath(const QString &path) +{ + return d->updatePath(path); +} + +QrcParser::ConstPtr QrcCache::parsedPath(const QString &path) +{ + return d->parsedPath(path); +} + +void QrcCache::clear() +{ + d->clear(); +} + +// -------------------- + +namespace Internal { + +QrcParserPrivate::QrcParserPrivate(QrcParser *) +{ } + +bool QrcParserPrivate::parseFile(const QString &path) +{ + QFile file(path); + if (!file.open(QIODevice::ReadOnly)) { + m_errorMessages.append(file.errorString()); + return false; + } + + QDomDocument doc; + + QString error_msg; + int error_line, error_col; + if (!doc.setContent(&file, &error_msg, &error_line, &error_col)) { + m_errorMessages.append(tr("XML error on line %1, col %2: %3") + .arg(error_line).arg(error_col).arg(error_msg)); + return false; + } + + QDomElement root = doc.firstChildElement(QLatin1String("RCC")); + if (root.isNull()) { + m_errorMessages.append(tr("The <RCC> root element is missing.")); + return false; + } + + QDomElement relt = root.firstChildElement(QLatin1String("qresource")); + for (; !relt.isNull(); relt = relt.nextSiblingElement(QLatin1String("qresource"))) { + + QString prefix = fixPrefix(relt.attribute(QLatin1String("prefix"))); + const QString language = relt.attribute(QLatin1String("lang")); + if (!m_languages.contains(language)) + m_languages.append(language); + + QDomElement felt = relt.firstChildElement(QLatin1String("file")); + for (; !felt.isNull(); felt = felt.nextSiblingElement(QLatin1String("file"))) { + const QString fileName = felt.text(); + QTC_CHECK(!QDir::isAbsolutePath(fileName)); + const QString alias = felt.attribute(QLatin1String("alias")); + QString filePath = QFileInfo(path).path() + QLatin1Char('/') + fileName; + QString accessPath; + if (!alias.isEmpty()) + accessPath = language + prefix + alias; + else + accessPath = language + prefix + fileName; + if (m_resources.contains(accessPath)) { + QStringList &val = m_resources[accessPath]; + if (!val.contains(filePath)) + val.append(filePath); + } else { + m_resources.insert(accessPath, QStringList(filePath)); + } + } + } + return true; +} + +// path is assumed to be a normalized absolute path +QString QrcParserPrivate::firstFileAtPath(const QString &path, const QLocale &locale) const +{ + QTC_CHECK(path.startsWith(QLatin1Char('/'))); + QStringList langs = allUiLanguages(&locale); + foreach (const QString &language, langs) { + if (m_languages.contains(language)) { + SMap::const_iterator res = m_resources.find(language + path); + if (res != m_resources.end()) + return res.value().at(0); + } + } + return QString(); +} + +void QrcParserPrivate::collectFilesAtPath(const QString &path, QStringList *files, + const QLocale *locale) const +{ + QTC_CHECK(path.startsWith(QLatin1Char('/'))); + QStringList langs = allUiLanguages(locale); + foreach (const QString &language, langs) { + if (m_languages.contains(language)) { + SMap::const_iterator res = m_resources.find(language + path); + if (res != m_resources.end()) + (*files) << res.value(); + } + } +} + +// path is expected to be normalized and start and end with a slash +bool QrcParserPrivate::hasDirAtPath(const QString &path, const QLocale *locale) const +{ + QTC_CHECK(path.startsWith(QLatin1Char('/'))); + QTC_CHECK(path.endsWith(QLatin1Char('/'))); + QStringList langs = allUiLanguages(locale); + foreach (const QString &language, langs) { + if (m_languages.contains(language)) { + QString key = language + path; + SMap::const_iterator res = m_resources.lowerBound(key); + if (res != m_resources.end() && res.key().startsWith(key)) + return true; + } + } + return false; +} + +void QrcParserPrivate::collectFilesInPath(const QString &path, QMap<QString,QStringList> *contents, + bool addDirs, const QLocale *locale) const +{ + QTC_CHECK(path.startsWith(QLatin1Char('/'))); + QTC_CHECK(path.endsWith(QLatin1Char('/'))); + SMap::const_iterator end = m_resources.end(); + QStringList langs = allUiLanguages(locale); + foreach (const QString &language, langs) { + QString key = language + path; + SMap::const_iterator res = m_resources.lowerBound(key); + while (res != end && res.key().startsWith(key)) { + const QString &actualKey = res.key(); + int endDir = actualKey.indexOf(QLatin1Char('/'), key.size()); + if (endDir == -1) { + QString fileName = res.key().right(res.key().size()-key.size()); + QStringList &els = (*contents)[fileName]; + foreach (const QString &val, res.value()) + if (!els.contains(val)){ + els << val; + } + ++res; + } else { + QString dirName = res.key().mid(key.size(), endDir - key.size() + 1); + if (addDirs) + contents->insert(dirName, QStringList()); + QString key2 = key + dirName; + do { + ++res; + } while (res != end && res.key().startsWith(key2)); + } + } + } +} + +QStringList QrcParserPrivate::errorMessages() const +{ + return m_errorMessages; +} + +QStringList QrcParserPrivate::languages() const +{ + return m_languages; +} + +QString QrcParserPrivate::fixPrefix(const QString &prefix) +{ + const QChar slash = QLatin1Char('/'); + QString result = QString(slash); + for (int i = 0; i < prefix.size(); ++i) { + const QChar c = prefix.at(i); + if (c == slash && result.at(result.size() - 1) == slash) + continue; + result.append(c); + } + + if (!result.endsWith(slash)) + result.append(slash); + + return result; +} + +QStringList QrcParserPrivate::allUiLanguages(const QLocale *locale) const +{ + if (!locale) + return languages(); + QStringList langs = locale->uiLanguages(); + foreach (const QString &language, langs) { // qt4 support + if (language.contains(QLatin1Char('_')) || language.contains(QLatin1Char('-'))) { + QStringList splits = QString(language).replace(QLatin1Char('_'), QLatin1Char('-')) + .split(QLatin1Char('-')); + if (splits.size() > 1 && !langs.contains(splits.at(0))) + langs.append(splits.at(0)); + } + } + if (!langs.contains(QString())) + langs.append(QString()); + return langs; +} + +// ---------------- + +QrcCachePrivate::QrcCachePrivate(QrcCache *) +{ } + +QrcParser::Ptr QrcCachePrivate::addPath(const QString &path) +{ + QPair<QrcParser::Ptr,int> currentValue; + { + QMutexLocker l(&m_mutex); + currentValue = m_cache.value(path, qMakePair(QrcParser::Ptr(0), 0)); + currentValue.second += 1; + if (currentValue.second > 1) { + m_cache.insert(path, currentValue); + return currentValue.first; + } + } + QrcParser::Ptr newParser = QrcParser::parseQrcFile(path); + if (!newParser->isValid()) + qDebug() << "adding invalid qrc " << path << " to the cache:" << newParser->errorMessages(); + { + QMutexLocker l(&m_mutex); + QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, qMakePair(QrcParser::Ptr(0), 0)); + if (currentValue.first.isNull()) + currentValue.first = newParser; + currentValue.second += 1; + m_cache.insert(path, currentValue); + return currentValue.first; + } +} + +void QrcCachePrivate::removePath(const QString &path) +{ + QPair<QrcParser::Ptr,int> currentValue; + { + QMutexLocker l(&m_mutex); + currentValue = m_cache.value(path, qMakePair(QrcParser::Ptr(0), 0)); + if (currentValue.second == 1) { + m_cache.remove(path); + } else if (currentValue.second > 1) { + currentValue.second -= 1; + m_cache.insert(path, currentValue); + } else { + QTC_CHECK(!m_cache.contains(path)); + } + } +} + +QrcParser::Ptr QrcCachePrivate::updatePath(const QString &path) +{ + QrcParser::Ptr newParser = QrcParser::parseQrcFile(path); + { + QMutexLocker l(&m_mutex); + QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, qMakePair(QrcParser::Ptr(0), 0)); + QTC_CHECK(currentValue.second > 0); + currentValue.first = newParser; + m_cache.insert(path, currentValue); + return currentValue.first; + } +} + +QrcParser::Ptr QrcCachePrivate::parsedPath(const QString &path) +{ + QMutexLocker l(&m_mutex); + QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, qMakePair(QrcParser::Ptr(0), 0)); + return currentValue.first; +} + +void QrcCachePrivate::clear() +{ + QMutexLocker l(&m_mutex); + m_cache.clear(); +} + +} // namespace Internal +} // namespace QmlJS diff --git a/src/libs/qmljs/qmljsqrcparser.h b/src/libs/qmljs/qmljsqrcparser.h new file mode 100644 index 0000000000..e25baa2c73 --- /dev/null +++ b/src/libs/qmljs/qmljsqrcparser.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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. +** +****************************************************************************/ + +#ifndef QMLJSQRCPARSER_H +#define QMLJSQRCPARSER_H +#include "qmljs_global.h" + +#include <QMap> +#include <QSharedPointer> +#include <QString> +#include <QStringList> + +QT_FORWARD_DECLARE_CLASS(QLocale) + +namespace QmlJS { + +namespace Internal { +class QrcParserPrivate; +class QrcCachePrivate; +} + +class QMLJS_EXPORT QrcParser +{ +public: + typedef QSharedPointer<QrcParser> Ptr; + typedef QSharedPointer<const QrcParser> ConstPtr; + ~QrcParser(); + bool parseFile(const QString &path); + QString firstFileAtPath(const QString &path, const QLocale &locale) const; + void collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale = 0) const; + bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const; + void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false, + const QLocale *locale = 0) const; + QStringList errorMessages() const; + QStringList languages() const; + bool isValid() const; + + static Ptr parseQrcFile(const QString &path); + static QString normalizedQrcFilePath(const QString &path); + static QString normalizedQrcDirectoryPath(const QString &path); +private: + QrcParser(); + QrcParser(const QrcParser &); + Internal::QrcParserPrivate *d; +}; + +class QMLJS_EXPORT QrcCache +{ +public: + QrcCache(); + ~QrcCache(); + QrcParser::ConstPtr addPath(const QString &path); + void removePath(const QString &path); + QrcParser::ConstPtr updatePath(const QString &path); + QrcParser::ConstPtr parsedPath(const QString &path); + void clear(); +private: + Internal::QrcCachePrivate *d; +}; +} +#endif // QMLJSQRCPARSER_H diff --git a/src/libs/qmljs/qmljsscopechain.cpp b/src/libs/qmljs/qmljsscopechain.cpp index 4c6ff96c93..a0a9bf0f91 100644 --- a/src/libs/qmljs/qmljsscopechain.cpp +++ b/src/libs/qmljs/qmljsscopechain.cpp @@ -30,6 +30,7 @@ #include "qmljsscopechain.h" #include "qmljsbind.h" #include "qmljsevaluate.h" +#include "qmljsmodelmanagerinterface.h" using namespace QmlJS; @@ -310,7 +311,10 @@ void ScopeChain::initializeRootScope() if (!m_document->bind()->isJsLibrary()) { foreach (Document::Ptr otherDoc, snapshot) { foreach (const ImportInfo &import, otherDoc->bind()->imports()) { - if (import.type() == ImportInfo::FileImport && m_document->fileName() == import.path()) { + if ((import.type() == ImportInfo::FileImport && m_document->fileName() == import.path()) + || (import.type() == ImportInfo::QrcFileImport + && ModelManagerInterface::instance()->filesAtQrcPath(import.path()) + .contains(m_document->fileName()))) { QmlComponentChain *component = new QmlComponentChain(otherDoc); componentScopes.insert(otherDoc.data(), component); chain->addInstantiatingComponent(component); diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index d5193bdad8..06b8936e82 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -373,10 +373,12 @@ bool FileSaver::finalize() return FileSaverBase::finalize(); SaveFile *sf = static_cast<SaveFile *>(m_file); - if (m_hasError) - sf->rollback(); - else + if (m_hasError) { + if (sf->isOpen()) + sf->rollback(); + } else { setResult(sf->commit()); + } delete sf; m_file = 0; return !m_hasError; diff --git a/src/libs/utils/savedaction.cpp b/src/libs/utils/savedaction.cpp index 953c161365..11a908280f 100644 --- a/src/libs/utils/savedaction.cpp +++ b/src/libs/utils/savedaction.cpp @@ -191,8 +191,6 @@ QString SavedAction::toString() const } /*! - \fn QAction *SavedAction::updatedAction(const QString &text) - Adjust the \c text() of the underlying action. This can be used to update the item shortly before e.g. a menu is shown. diff --git a/src/libs/utils/textfileformat.cpp b/src/libs/utils/textfileformat.cpp index c4c33cd652..62f22bb964 100644 --- a/src/libs/utils/textfileformat.cpp +++ b/src/libs/utils/textfileformat.cpp @@ -289,13 +289,11 @@ bool TextFileFormat::writeFile(const QString &fileName, QString plainText, QStri } Utils::FileSaver saver(fileName, fileMode); - if (saver.hasError()) { - *errorString = saver.errorString(); - return false; + if (!saver.hasError()) { + if (hasUtf8Bom && codec->name() == "UTF-8") + saver.write("\xef\xbb\xbf", 3); + saver.write(codec->fromUnicode(plainText)); } - if (hasUtf8Bom && codec->name() == "UTF-8") - saver.write("\xef\xbb\xbf", 3); - saver.write(codec->fromUnicode(plainText)); const bool ok = saver.finalize(errorString); if (debug) qDebug().nospace() << Q_FUNC_INFO << fileName << ' ' << *this << ' ' << plainText.size() diff --git a/src/libs/zeroconf/servicebrowser.cpp b/src/libs/zeroconf/servicebrowser.cpp index 0dd8accf4f..b1e8eebfb5 100644 --- a/src/libs/zeroconf/servicebrowser.cpp +++ b/src/libs/zeroconf/servicebrowser.cpp @@ -289,8 +289,6 @@ Service::~Service() } /*! - \fn QString Service::networkInterface() - Returns the interface on which the service is reachable. */ QNetworkInterface Service::networkInterface() const diff --git a/src/plugins/analyzerbase/analyzermanager.cpp b/src/plugins/analyzerbase/analyzermanager.cpp index 919b5b2a10..5101e20854 100644 --- a/src/plugins/analyzerbase/analyzermanager.cpp +++ b/src/plugins/analyzerbase/analyzermanager.cpp @@ -102,7 +102,6 @@ public: setIcon(QIcon(QLatin1String(":/images/analyzer_mode.png"))); setPriority(P_MODE_ANALYZE); setId(MODE_ANALYZE); - setType(MODE_EDIT_TYPE); } ~AnalyzerMode() diff --git a/src/plugins/analyzerbase/ianalyzerengine.h b/src/plugins/analyzerbase/ianalyzerengine.h index 233564120a..deea4638ce 100644 --- a/src/plugins/analyzerbase/ianalyzerengine.h +++ b/src/plugins/analyzerbase/ianalyzerengine.h @@ -84,6 +84,7 @@ public: StartMode mode() const { return m_sp.startMode; } virtual void notifyRemoteSetupDone(quint16) {} + virtual void notifyRemoteFinished(bool) {} public slots: virtual void logApplicationMessage(const QString &, Utils::OutputFormat) {} diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index ea41e543f6..800b43403d 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -206,6 +206,9 @@ void AndroidConfig::save(QSettings &settings) const settings.setValue(PartitionSizeKey, partitionSize); settings.setValue(AutomaticKitCreationKey, automaticKitCreation); settings.setValue(ToolchainHostKey, toolchainHost); + settings.setValue(MakeExtraSearchDirectory, + makeExtraSearchDirectories.isEmpty() ? QString() + : makeExtraSearchDirectories.at(0)); } void AndroidConfigurations::setConfig(const AndroidConfig &devConfigs) diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index b17e044b80..a47e6fccb0 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -572,19 +572,20 @@ void AndroidManager::updateTarget(ProjectExplorer::Target *target, const QString bool modified = false; bool comment = false; for (int i = 0; i < lines.size(); i++) { - if (lines[i].contains("@ANDROID-")) { - commentLines = targetSDKNumber < lines[i].mid(lines[i].lastIndexOf('-') + 1).toInt(); + QByteArray trimmed = lines[i].trimmed(); + if (trimmed.contains("@ANDROID-")) { + commentLines = targetSDKNumber < trimmed.mid(trimmed.lastIndexOf('-') + 1).toInt(); comment = !comment; continue; } if (!comment) continue; if (commentLines) { - if (!lines[i].trimmed().startsWith("//QtCreator")) { + if (!trimmed.startsWith("//QtCreator")) { lines[i] = "//QtCreator " + lines[i]; modified = true; } - } else { if (lines[i].trimmed().startsWith("//QtCreator")) { + } else { if (trimmed.startsWith("//QtCreator")) { lines[i] = lines[i].mid(12); modified = true; } diff --git a/src/plugins/bazaar/bazaarplugin.cpp b/src/plugins/bazaar/bazaarplugin.cpp index ebf104bc97..3614e74529 100644 --- a/src/plugins/bazaar/bazaarplugin.cpp +++ b/src/plugins/bazaar/bazaarplugin.cpp @@ -540,9 +540,7 @@ void BazaarPlugin::showCommitWidget(const QList<VcsBase::VcsBaseClient::StatusIt return; } - Core::IEditor *editor = Core::EditorManager::openEditor(saver.fileName(), - Constants::COMMIT_ID, - Core::EditorManager::ModeSwitch); + Core::IEditor *editor = Core::EditorManager::openEditor(saver.fileName(), Constants::COMMIT_ID); if (!editor) { outputWindow->appendError(tr("Unable to create an editor for the commit.")); return; diff --git a/src/plugins/bookmarks/bookmarkmanager.cpp b/src/plugins/bookmarks/bookmarkmanager.cpp index aee3b30f6c..c4a7d4ca64 100644 --- a/src/plugins/bookmarks/bookmarkmanager.cpp +++ b/src/plugins/bookmarks/bookmarkmanager.cpp @@ -39,7 +39,7 @@ #include <coreplugin/actionmanager/command.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> -#include <texteditor/basetexteditor.h> +#include <texteditor/itexteditor.h> #include <utils/tooltip/tooltip.h> #include <utils/tooltip/tipcontents.h> #include <utils/qtcassert.h> @@ -237,9 +237,11 @@ 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")); + menu.addSeparator(); QAction *remove = menu.addAction(tr("&Remove")); + menu.addSeparator(); QAction *removeAll = menu.addAction(tr("Remove All")); - QAction *editNote = menu.addAction(tr("Edit Note")); m_contextMenuIndex = indexAt(event->pos()); if (!m_contextMenuIndex.isValid()) { @@ -508,8 +510,8 @@ Bookmark *BookmarkManager::bookmarkForIndex(const QModelIndex &index) bool BookmarkManager::gotoBookmark(Bookmark *bookmark) { using namespace TextEditor; - if (ITextEditor *editor = qobject_cast<ITextEditor *>(BaseTextEditorWidget::openEditorAt(bookmark->filePath(), - bookmark->lineNumber()))) { + if (ITextEditor *editor = qobject_cast<ITextEditor *>(EditorManager::openEditorAt(bookmark->filePath(), + bookmark->lineNumber()))) { return (editor->currentLine() == bookmark->lineNumber()); } return false; diff --git a/src/plugins/classview/classviewmanager.cpp b/src/plugins/classview/classviewmanager.cpp index 7cd708f898..a09eb9bf02 100644 --- a/src/plugins/classview/classviewmanager.cpp +++ b/src/plugins/classview/classviewmanager.cpp @@ -36,7 +36,6 @@ #include <utils/qtcassert.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> -#include <texteditor/basetexteditor.h> #include <cpptools/cppmodelmanagerinterface.h> #include <cpptools/cpptoolsconstants.h> #include <coreplugin/icore.h> @@ -441,10 +440,7 @@ void Manager::onDocumentUpdated(CPlusPlus::Document::Ptr doc) void Manager::gotoLocation(const QString &fileName, int line, int column) { - bool newEditor = false; - TextEditor::BaseTextEditorWidget::openEditorAt(fileName, line, column, Core::Id(), - Core::EditorManager::IgnoreNavigationHistory, - &newEditor); + Core::EditorManager::openEditorAt(fileName, line, column); } /*! diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index d7614bf67e..ee881e3e4b 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -687,9 +687,7 @@ QString ClearCasePlugin::ccGetFileActivity(const QString &workingDir, const QStr ClearCaseSubmitEditor *ClearCasePlugin::openClearCaseSubmitEditor(const QString &fileName, bool isUcm) { Core::IEditor *editor = - Core::EditorManager::openEditor(fileName, - Constants::CLEARCASECHECKINEDITOR_ID, - Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(fileName, Constants::CLEARCASECHECKINEDITOR_ID); ClearCaseSubmitEditor *submitEditor = qobject_cast<ClearCaseSubmitEditor*>(editor); QTC_CHECK(submitEditor); submitEditor->registerActions(m_submitUndoAction, m_submitRedoAction, m_checkInSelectedAction, m_checkInDiffAction); @@ -932,7 +930,7 @@ void ClearCasePlugin::ccDiffWithPred(const QString &workingDir, const QStringLis // Show in the same editor if diff has been executed before if (Core::IEditor *existingEditor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) { existingEditor->createNew(result); - Core::EditorManager::activateEditor(existingEditor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(existingEditor); setDiffBaseDirectory(existingEditor, workingDir); return; } @@ -1192,7 +1190,7 @@ void ClearCasePlugin::history(const QString &workingDir, const QString tag = VcsBase::VcsBaseEditorWidget::editorTag(VcsBase::LogOutput, workingDir, files); if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); - Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(editor); } else { const QString title = QString::fromLatin1("cc history %1").arg(id); const QString source = VcsBase::VcsBaseEditorWidget::getSource(workingDir, files); @@ -1305,7 +1303,7 @@ void ClearCasePlugin::vcsAnnotate(const QString &workingDir, const QString &file if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(res); VcsBase::VcsBaseEditorWidget::gotoLineOfEditor(editor, lineNumber); - Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(editor); } else { const QString title = QString::fromLatin1("cc annotate %1").arg(id); Core::IEditor *newEditor = showOutputInEditor(title, res, VcsBase::AnnotateOutput, source, codec); @@ -1341,7 +1339,7 @@ void ClearCasePlugin::describe(const QString &source, const QString &changeNr) const QString tag = VcsBase::VcsBaseEditorWidget::editorTag(VcsBase::DiffOutput, source, QStringList(), changeNr); if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(description); - Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(editor); } else { const QString title = QString::fromLatin1("cc describe %1").arg(id); Core::IEditor *newEditor = showOutputInEditor(title, description, VcsBase::DiffOutput, source, codec); @@ -1413,7 +1411,7 @@ Core::IEditor *ClearCasePlugin::showOutputInEditor(const QString& title, const Q if (codec) e->setCodec(codec); Core::IEditor *ie = e->editor(); - Core::EditorManager::activateEditor(ie, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(ie); return ie; } diff --git a/src/plugins/coreplugin/basefilewizard.cpp b/src/plugins/coreplugin/basefilewizard.cpp index cb8f8bc4c9..9b4750fd1e 100644 --- a/src/plugins/coreplugin/basefilewizard.cpp +++ b/src/plugins/coreplugin/basefilewizard.cpp @@ -649,7 +649,7 @@ bool BaseFileWizard::postGenerateOpenEditors(const GeneratedFiles &l, QString *e { foreach (const Core::GeneratedFile &file, l) { if (file.attributes() & Core::GeneratedFile::OpenEditorAttribute) { - if (!Core::EditorManager::openEditor(file.path(), file.editorId(), Core::EditorManager::ModeSwitch )) { + if (!Core::EditorManager::openEditor(file.path(), file.editorId())) { if (errorMessage) *errorMessage = tr("Failed to open an editor for '%1'.").arg(QDir::toNativeSeparators(file.path())); return false; diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 1bdc864a07..db0b96591f 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -109,7 +109,7 @@ const char SPLIT_SIDE_BY_SIDE[] = "QtCreator.SplitSideBySide"; const char SPLIT_NEW_WINDOW[] = "QtCreator.SplitNewWindow"; const char REMOVE_CURRENT_SPLIT[] = "QtCreator.RemoveCurrentSplit"; const char REMOVE_ALL_SPLITS[] = "QtCreator.RemoveAllSplits"; -const char GOTO_OTHER_SPLIT[] = "QtCreator.GotoOtherSplit"; +const char GOTO_NEXT_SPLIT[] = "QtCreator.GotoOtherSplit"; const char CLOSE[] = "QtCreator.Close"; const char CLOSE_ALTERNATIVE[] = "QtCreator.Close_Alternative"; // temporary, see QTCREATORBUG-72 const char CLOSEALL[] = "QtCreator.CloseAll"; diff --git a/src/plugins/coreplugin/designmode.cpp b/src/plugins/coreplugin/designmode.cpp index 47f1734954..a591d995fc 100644 --- a/src/plugins/coreplugin/designmode.cpp +++ b/src/plugins/coreplugin/designmode.cpp @@ -120,7 +120,6 @@ DesignMode::DesignMode() setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Design.png"))); setPriority(Constants::P_MODE_DESIGN); setId(Constants::MODE_DESIGN); - setType(Constants::MODE_DESIGN_TYPE); ExtensionSystem::PluginManager::addObject(d->m_coreListener); diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp index 4d13e4cf49..8cc017240f 100644 --- a/src/plugins/coreplugin/documentmanager.cpp +++ b/src/plugins/coreplugin/documentmanager.cpp @@ -1352,7 +1352,7 @@ void DocumentManager::executeOpenWithMenuAction(QAction *action) return; } - EditorManager::openEditor(entry.fileName, entry.editorFactory->id(), EditorManager::ModeSwitch); + EditorManager::openEditor(entry.fileName, entry.editorFactory->id()); return; } if (entry.externalEditor) diff --git a/src/plugins/coreplugin/editmode.cpp b/src/plugins/coreplugin/editmode.cpp index 77ddd25ae7..1a6072e978 100644 --- a/src/plugins/coreplugin/editmode.cpp +++ b/src/plugins/coreplugin/editmode.cpp @@ -55,7 +55,6 @@ EditMode::EditMode() : setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Edit.png"))); setPriority(Constants::P_MODE_EDIT); setId(Constants::MODE_EDIT); - setType(Constants::MODE_EDIT_TYPE); m_rightSplitWidgetLayout->setSpacing(0); m_rightSplitWidgetLayout->setMargin(0); diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 88762f1f29..47f64a2d60 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -196,7 +196,7 @@ struct EditorManagerPrivate QAction *m_splitNewWindowAction; QAction *m_removeCurrentSplitAction; QAction *m_removeAllSplitsAction; - QAction *m_gotoOtherSplitAction; + QAction *m_gotoNextSplitAction; QAction *m_saveCurrentEditorContextAction; QAction *m_saveAsCurrentEditorContextAction; @@ -381,7 +381,7 @@ EditorManager::EditorManager(QWidget *parent) : mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); connect(d->m_splitSideBySideAction, SIGNAL(triggered()), this, SLOT(splitSideBySide())); - d->m_splitNewWindowAction = new QAction(tr("Split New Window"), this); + d->m_splitNewWindowAction = new QAction(tr("Open in New Window"), this); cmd = ActionManager::registerAction(d->m_splitNewWindowAction, Constants::SPLIT_NEW_WINDOW, editManagerContext); cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+E,4") : tr("Ctrl+E,4"))); mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); @@ -399,11 +399,11 @@ EditorManager::EditorManager(QWidget *parent) : mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); connect(d->m_removeAllSplitsAction, SIGNAL(triggered()), this, SLOT(removeAllSplits())); - d->m_gotoOtherSplitAction = new QAction(tr("Go to Next Split"), this); - cmd = ActionManager::registerAction(d->m_gotoOtherSplitAction, Constants::GOTO_OTHER_SPLIT, editManagerContext); + d->m_gotoNextSplitAction = new QAction(tr("Go to Next Split or Window"), this); + cmd = ActionManager::registerAction(d->m_gotoNextSplitAction, Constants::GOTO_NEXT_SPLIT, editManagerContext); cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+E,o") : tr("Ctrl+E,o"))); mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); - connect(d->m_gotoOtherSplitAction, SIGNAL(triggered()), this, SLOT(gotoOtherSplit())); + connect(d->m_gotoNextSplitAction, SIGNAL(triggered()), this, SLOT(gotoNextSplit())); ActionContainer *medit = ActionManager::actionContainer(Constants::M_EDIT); ActionContainer *advancedMenu = ActionManager::createMenu(Constants::M_EDIT_ADVANCED); @@ -604,13 +604,20 @@ EditorView *EditorManager::viewForEditor(IEditor *editor) return 0; } -SplitterOrView *EditorManager::findRoot(EditorView *view) +SplitterOrView *EditorManager::findRoot(const EditorView *view, int *rootIndex) { SplitterOrView *current = view->parentSplitterOrView(); - while (current && !m_instance->d->m_root.contains(current)) { + while (current) { + int index = m_instance->d->m_root.indexOf(current); + if (index >= 0) { + if (rootIndex) + *rootIndex = index; + return current; + } current = current->findParentSplitter(); } - return current; + QTC_CHECK(false); // we should never have views without a root + return 0; } QList<IEditor *> EditorManager::editorsForFileName(const QString &filename) const @@ -691,15 +698,15 @@ void EditorManager::splitNewWindow(Internal::EditorView *view) context->setContext(Context(Constants::C_EDITORMANAGER)); context->setWidget(splitter); ICore::addContextObject(context); + m_instance->d->m_root.append(splitter); + m_instance->d->m_rootContext.append(context); + connect(splitter, SIGNAL(destroyed(QObject*)), m_instance, SLOT(rootDestroyed(QObject*))); splitter->show(); ICore::raiseWindow(splitter); if (newEditor) m_instance->activateEditor(splitter->view(), newEditor, IgnoreNavigationHistory); else splitter->view()->setFocus(); - m_instance->d->m_root.append(splitter); - m_instance->d->m_rootContext.append(context); - connect(splitter, SIGNAL(destroyed(QObject*)), m_instance, SLOT(rootDestroyed(QObject*))); m_instance->updateActions(); } @@ -1042,15 +1049,15 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask if (!newCurrent) newCurrent = pickUnusedEditor(); if (newCurrent) { - activateEditor(view, newCurrent, NoActivate); + activateEditor(view, newCurrent, DoNotChangeCurrentEditor); } else { QModelIndex idx = d->m_editorModel->firstRestoredEditor(); if (idx.isValid()) { - activateEditorForIndex(view, idx, NoActivate); + activateEditorForIndex(view, idx, DoNotChangeCurrentEditor); } else { const QList<IEditor *> editors = d->m_editorModel->editors(); if (!editors.isEmpty()) - activateEditor(view, editors.last(), NoActivate); + activateEditor(view, editors.last(), DoNotChangeCurrentEditor); } } } @@ -1105,11 +1112,11 @@ void EditorManager::closeDuplicate(Core::IEditor *editor) if (!newCurrent) newCurrent = pickUnusedEditor(); if (newCurrent) { - activateEditor(view, newCurrent, NoActivate); + activateEditor(view, newCurrent, DoNotChangeCurrentEditor); } else { QModelIndex idx = d->m_editorModel->firstRestoredEditor(); if (idx.isValid()) - activateEditorForIndex(view, idx, NoActivate); + activateEditorForIndex(view, idx, DoNotChangeCurrentEditor); } } @@ -1151,6 +1158,18 @@ void EditorManager::activateEditorForIndex(Internal::EditorView *view, const QMo d->m_editorModel->removeEditor(index); } +void EditorManager::activateView(EditorView *view) +{ + QTC_ASSERT(view, return); + if (IEditor *editor = view->currentEditor()) { + setCurrentEditor(editor, true); + editor->widget()->setFocus(); + ICore::raiseWindow(editor->widget()); + } else { + setCurrentView(view); + } +} + Core::IEditor *EditorManager::placeEditor(Core::Internal::EditorView *view, Core::IEditor *editor) { Q_ASSERT(view && editor); @@ -1202,13 +1221,22 @@ Core::IEditor *EditorManager::activateEditor(Core::Internal::EditorView *view, C editor = placeEditor(view, editor); - if (!(flags & NoActivate)) { + if (!(flags & DoNotChangeCurrentEditor)) { setCurrentEditor(editor, (flags & IgnoreNavigationHistory)); - if (flags & ModeSwitch) - switchToPreferedMode(); - if (isVisible()) { - editor->widget()->setFocus(); - ICore::raiseWindow(editor->widget()); + if (!(flags & DoNotMakeVisible)) { + // switch to design mode? + if (editor->isDesignModePreferred()) { + ModeManager::activateMode(Core::Constants::MODE_DESIGN); + ModeManager::setFocusToCurrentMode(); + } else { + int rootIndex; + findRoot(view, &rootIndex); + if (rootIndex == 0) // main window --> we might need to switch mode + if (!editor->widget()->isVisible()) + ModeManager::activateMode(Core::Constants::MODE_EDIT); + editor->widget()->setFocus(); + ICore::raiseWindow(editor->widget()); + } } } return editor; @@ -1394,18 +1422,23 @@ Core::Id EditorManager::getOpenWithEditorId(const QString &fileName, IEditor *EditorManager::openEditor(const QString &fileName, const Id &editorId, OpenEditorFlags flags, bool *newEditor) { + if (flags & EditorManager::OpenInOtherSplit) + m_instance->gotoOtherSplit(); return m_instance->openEditor(m_instance->currentEditorView(), fileName, editorId, flags, newEditor); } -IEditor *EditorManager::openEditorInNextSplit(const QString &fileName, const Id &editorId, OpenEditorFlags flags, bool *newEditor) +IEditor *EditorManager::openEditorAt(const QString &fileName, int line, int column, + const Id &editorId, OpenEditorFlags flags, bool *newEditor) { - if (!m_instance->hasSplitter()) - m_instance->splitSideBySide(); - - m_instance->gotoOtherSplit(); - return m_instance->openEditor(m_instance->currentEditorView(), - fileName, editorId, flags, newEditor); + m_instance->cutForwardNavigationHistory(); + m_instance->addCurrentPositionToNavigationHistory(); + OpenEditorFlags tempFlags = flags | IgnoreNavigationHistory; + Core::IEditor *editor = Core::EditorManager::openEditor(fileName, editorId, + tempFlags, newEditor); + if (editor && line != -1) + editor->gotoLine(line, column); + return editor; } static int extractLineNumber(QString *fileName) @@ -1548,22 +1581,6 @@ QStringList EditorManager::getOpenFileNames() const } -/// Empty mode == figure out the correct mode from the editor -/// forcePrefered = true, switch to the mode even if the editor is visible in another mode -/// forcePrefered = false, only switch if it is not visible -void EditorManager::switchToPreferedMode() -{ - Id preferedMode; - // Figure out preferred mode for editor - if (d->m_currentEditor) - preferedMode = d->m_currentEditor->preferredModeType(); - - if (!preferedMode.isValid()) - preferedMode = Id(Constants::MODE_EDIT_TYPE); - - ModeManager::activateModeType(preferedMode); -} - IEditor *EditorManager::openEditorWithContents(const Id &editorId, QString *titlePattern, const QString &contents) @@ -1973,7 +1990,7 @@ void EditorManager::updateActions() bool hasSplitter = parentSplitter && parentSplitter->isSplitter(); d->m_removeCurrentSplitAction->setEnabled(hasSplitter); d->m_removeAllSplitsAction->setEnabled(hasSplitter); - d->m_gotoOtherSplitAction->setEnabled(hasSplitter); + d->m_gotoNextSplitAction->setEnabled(hasSplitter || d->m_root.size() > 1); } void EditorManager::setCloseSplitEnabled(SplitterOrView *splitterOrView, bool enable) @@ -2010,7 +2027,8 @@ QList<IEditor*> EditorManager::visibleEditors() const if (view->currentEditor()) editors.append(view->currentEditor()); view = view->findNextView(); - } while (view && view != firstView); + QTC_ASSERT(view != firstView, break); // we start with firstView and shouldn't have cycles + } while (view); } } else { if (root->editor()) @@ -2166,7 +2184,7 @@ bool EditorManager::restoreState(const QByteArray &state) continue; QFileInfo rfi(autoSaveName(fileName)); if (rfi.exists() && fi.lastModified() < rfi.lastModified()) - openEditor(fileName, id); + openEditor(fileName, id, DoNotMakeVisible); else d->m_editorModel->addRestoredEditor(fileName, displayName, id); } @@ -2375,26 +2393,77 @@ void EditorManager::removeAllSplits() root->unsplitAll(); } +/*! + * Moves focus to the next split, cycling through windows. + */ +void EditorManager::gotoNextSplit() +{ + EditorView *view = currentEditorView(); + if (!view) + return; + EditorView *nextView = view->findNextView(); + if (!nextView) { + // we are in the "last" view in this root + int rootIndex = -1; + SplitterOrView *root = findRoot(view, &rootIndex); + QTC_ASSERT(root, return); + QTC_ASSERT(rootIndex >= 0 && rootIndex < d->m_root.size(), return); + // find next root. this might be the same root if there's only one. + int nextRootIndex = rootIndex + 1; + if (nextRootIndex >= d->m_root.size()) + nextRootIndex = 0; + nextView = d->m_root.at(nextRootIndex)->findFirstView(); + QTC_CHECK(nextView); + } + + if (nextView) + activateView(nextView); +} + +/*! + * Moves focus to "other" split, possibly creating a split if necessary. + * If there's no split and no other window, a side-by-side split is created. + * If the current window is split, focus is moved to the next split within this window, cycling. + * If the current window is not split, focus is moved to the next window. + */ void EditorManager::gotoOtherSplit() { EditorView *view = currentEditorView(); if (!view) return; - SplitterOrView *root = findRoot(view); - QTC_ASSERT(root, return); - if (!root->isSplitter()) - splitSideBySide(); - - view = view->findNextView(); - if (view) { - if (IEditor *editor = view->currentEditor()) { - setCurrentEditor(editor, true); - editor->widget()->setFocus(); - ICore::raiseWindow(editor->widget()); + EditorView *nextView = view->findNextView(); + if (!nextView) { + // we are in the "last" view in this root + int rootIndex = -1; + SplitterOrView *root = findRoot(view, &rootIndex); + QTC_ASSERT(root, return); + QTC_ASSERT(rootIndex >= 0 && rootIndex < d->m_root.size(), return); + // stay in same window if it is split + if (root->isSplitter()) { + nextView = root->findFirstView(); + QTC_CHECK(nextView != view); } else { - setCurrentView(view); + // find next root. this might be the same root if there's only one. + int nextRootIndex = rootIndex + 1; + if (nextRootIndex >= d->m_root.size()) + nextRootIndex = 0; + nextView = d->m_root.at(nextRootIndex)->findFirstView(); + QTC_CHECK(nextView); + // if we had only one root with only one view, we end up at the startpoint + // in that case we need to split + if (nextView == view) { + QTC_CHECK(!root->isSplitter()); + splitSideBySide(); // that deletes 'view' + view = root->findFirstView(); + nextView = view->findNextView(); + QTC_CHECK(nextView != view); + QTC_CHECK(nextView); + } } } + + if (nextView) + activateView(nextView); } qint64 EditorManager::maxTextFileSize() diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h index 1dabf2f368..38cb29cf88 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.h +++ b/src/plugins/coreplugin/editormanager/editormanager.h @@ -107,18 +107,20 @@ public: static EditorToolBar *createToolBar(QWidget *parent = 0); enum OpenEditorFlag { - NoActivate = 1, + DoNotChangeCurrentEditor = 1, IgnoreNavigationHistory = 2, - ModeSwitch = 4, - CanContainLineNumber = 8 + DoNotMakeVisible = 4, + CanContainLineNumber = 8, + OpenInOtherSplit = 16 }; Q_DECLARE_FLAGS(OpenEditorFlags, OpenEditorFlag) static QString splitLineNumber(QString *fileName); static IEditor *openEditor(const QString &fileName, const Id &editorId = Id(), OpenEditorFlags flags = 0, bool *newEditor = 0); - static IEditor *openEditorInNextSplit(const QString &fileName, const Id &editorId = Id(), - OpenEditorFlags flags = 0, bool *newEditor = 0); + static IEditor *openEditorAt(const QString &fileName, int line, int column = 0, + const Id &editorId = Id(), OpenEditorFlags flags = 0, + bool *newEditor = 0); static IEditor *openEditorWithContents(const Id &editorId, QString *titlePattern = 0, const QString &contents = QString()); @@ -234,6 +236,8 @@ private slots: void rootDestroyed(QObject *root); void setCurrentEditorFromContextChange(); + void gotoNextSplit(); + public slots: void goBackInNavigationHistory(); void goForwardInNavigationHistory(); @@ -257,6 +261,7 @@ private: IEditor *duplicateEditor(IEditor *editor); IEditor *activateEditor(Internal::EditorView *view, IEditor *editor, OpenEditorFlags flags = 0); void activateEditorForIndex(Internal::EditorView *view, const QModelIndex &index, OpenEditorFlags = 0); + void activateView(Internal::EditorView *view); IEditor *openEditor(Internal::EditorView *view, const QString &fileName, const Id &id = Id(), OpenEditorFlags flags = 0, bool *newEditor = 0); @@ -264,7 +269,7 @@ private: void setCurrentView(Internal::EditorView *view); Internal::EditorView *currentEditorView() const; static Internal::EditorView *viewForEditor(IEditor *editor); - static Internal::SplitterOrView *findRoot(Internal::EditorView *view); + static Internal::SplitterOrView *findRoot(const Internal::EditorView *view, int *rootIndex = 0); void closeEditor(IEditor *editor); void closeDuplicate(IEditor *editor); @@ -273,7 +278,6 @@ private: static void splitNewWindow(Internal::EditorView *view); IEditor *pickUnusedEditor() const; void addDocumentToRecentFiles(IDocument *document); - void switchToPreferedMode(); void updateAutoSave(); void setCloseSplitEnabled(Internal::SplitterOrView *splitterOrView, bool enable); void updateMakeWritableWarning(); diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp index 87e4ecee5a..6bd6009b3d 100644 --- a/src/plugins/coreplugin/editormanager/editorview.cpp +++ b/src/plugins/coreplugin/editormanager/editorview.cpp @@ -144,8 +144,8 @@ EditorView *EditorView::findNextView() current = parent; parent = current->findParentSplitter(); } - // current has no parent, so just take the very first view - return current->findFirstView(); + // current has no parent, so we are at the top and there is no "next" view + return 0; } void EditorView::closeView() @@ -299,7 +299,7 @@ IEditor *EditorView::currentEditor() const void EditorView::listSelectionActivated(int index) { QAbstractItemModel *model = EditorManager::instance()->openedEditorsModel(); - EditorManager::instance()->activateEditorForIndex(this, model->index(index, 0), Core::EditorManager::ModeSwitch); + EditorManager::instance()->activateEditorForIndex(this, model->index(index, 0)); } void EditorView::splitHorizontally() @@ -465,11 +465,11 @@ void EditorView::goBackInNavigationHistory() IEditor *editor = 0; if (location.document) { editor = em->activateEditorForDocument(this, location.document, - EditorManager::IgnoreNavigationHistory | EditorManager::ModeSwitch); + EditorManager::IgnoreNavigationHistory); } if (!editor) { editor = em->openEditor(this, location.fileName, location.id, - EditorManager::IgnoreNavigationHistory | EditorManager::ModeSwitch); + EditorManager::IgnoreNavigationHistory); if (!editor) { m_navigationHistory.removeAt(m_currentNavigationHistoryPosition); continue; @@ -492,7 +492,7 @@ void EditorView::goForwardInNavigationHistory() IEditor *editor = 0; if (location.document) { editor = em->activateEditorForDocument(this, location.document, - EditorManager::IgnoreNavigationHistory | EditorManager::ModeSwitch); + EditorManager::IgnoreNavigationHistory); } if (!editor) { editor = em->openEditor(this, location.fileName, location.id, EditorManager::IgnoreNavigationHistory); @@ -784,13 +784,13 @@ void SplitterOrView::restoreState(const QByteArray &state) if (!QFile::exists(fileName)) return; IEditor *e = em->openEditor(view(), fileName, Id::fromString(id), Core::EditorManager::IgnoreNavigationHistory - | Core::EditorManager::NoActivate); + | Core::EditorManager::DoNotChangeCurrentEditor); if (!e) { QModelIndex idx = em->openedEditorsModel()->firstRestoredEditor(); if (idx.isValid()) em->activateEditorForIndex(view(), idx, Core::EditorManager::IgnoreNavigationHistory - | Core::EditorManager::NoActivate); + | Core::EditorManager::DoNotChangeCurrentEditor); } if (e) { diff --git a/src/plugins/coreplugin/editormanager/ieditor.h b/src/plugins/coreplugin/editormanager/ieditor.h index d420313136..f2c64f7a9b 100644 --- a/src/plugins/coreplugin/editormanager/ieditor.h +++ b/src/plugins/coreplugin/editormanager/ieditor.h @@ -68,7 +68,7 @@ public: virtual QWidget *toolBar() = 0; - virtual Id preferredModeType() const { return Id(); } + virtual bool isDesignModePreferred() const { return false; } signals: void changed(); diff --git a/src/plugins/coreplugin/editormanager/ieditorfactory.cpp b/src/plugins/coreplugin/editormanager/ieditorfactory.cpp index f501289f92..fdceef33b9 100644 --- a/src/plugins/coreplugin/editormanager/ieditorfactory.cpp +++ b/src/plugins/coreplugin/editormanager/ieditorfactory.cpp @@ -29,11 +29,12 @@ #include "ieditorfactory.h" -#include "ieditor.h" -#include "editormanager.h" +#include <utils/qtcassert.h> -Core::IDocument *Core::IEditorFactory::open(const QString &fileName) +Core::IDocument *Core::IEditorFactory::open(const QString &) { - Core::IEditor *iface = Core::EditorManager::openEditor(fileName, id()); - return iface ? iface->document() : 0; + qWarning("This should never be called, use IEditorFactor::createEditor, " + "or EditorManager::openEditor instead!"); + QTC_CHECK(false); + return 0; } diff --git a/src/plugins/coreplugin/editormanager/ieditorfactory.h b/src/plugins/coreplugin/editormanager/ieditorfactory.h index 5d59ab0e31..029554af0d 100644 --- a/src/plugins/coreplugin/editormanager/ieditorfactory.h +++ b/src/plugins/coreplugin/editormanager/ieditorfactory.h @@ -44,7 +44,7 @@ public: IEditorFactory(QObject *parent = 0) : IDocumentFactory(parent) {} virtual IEditor *createEditor(QWidget *parent) = 0; - virtual IDocument *open(const QString &fileName); + virtual IDocument *open(const QString &); }; } // namespace Core diff --git a/src/plugins/coreplugin/editormanager/openeditorsview.cpp b/src/plugins/coreplugin/editormanager/openeditorsview.cpp index 9a46246846..0b6dacba5b 100644 --- a/src/plugins/coreplugin/editormanager/openeditorsview.cpp +++ b/src/plugins/coreplugin/editormanager/openeditorsview.cpp @@ -189,7 +189,7 @@ void OpenEditorsWidget::handleClicked(const QModelIndex &index) void OpenEditorsWidget::activateEditor(const QModelIndex &index) { selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - EditorManager::instance()->activateEditorForIndex(index, EditorManager::ModeSwitch); + EditorManager::instance()->activateEditorForIndex(index); } void OpenEditorsWidget::closeEditor(const QModelIndex &index) diff --git a/src/plugins/coreplugin/editormanager/openeditorswindow.cpp b/src/plugins/coreplugin/editormanager/openeditorswindow.cpp index e7caecf711..1367c799a5 100644 --- a/src/plugins/coreplugin/editormanager/openeditorswindow.cpp +++ b/src/plugins/coreplugin/editormanager/openeditorswindow.cpp @@ -225,11 +225,10 @@ void OpenEditorsWindow::selectEditor(QTreeWidgetItem *item) return; if (IDocument *document = item->data(0, Qt::UserRole).value<IDocument*>()) { EditorView *view = item->data(0, Qt::UserRole+1).value<EditorView*>(); - EditorManager::instance()->activateEditorForDocument(view, document, EditorManager::ModeSwitch); + EditorManager::instance()->activateEditorForDocument(view, document); } else { if (!EditorManager::openEditor( - item->toolTip(0), item->data(0, Qt::UserRole+2).value<Core::Id>(), - Core::EditorManager::ModeSwitch)) { + item->toolTip(0), item->data(0, Qt::UserRole+2).value<Core::Id>())) { EditorManager::instance()->openedEditorsModel()->removeEditor(item->toolTip(0)); delete item; } diff --git a/src/plugins/coreplugin/editortoolbar.cpp b/src/plugins/coreplugin/editortoolbar.cpp index ffc9b69d12..9fd7e2ca82 100644 --- a/src/plugins/coreplugin/editortoolbar.cpp +++ b/src/plugins/coreplugin/editortoolbar.cpp @@ -87,7 +87,7 @@ EditorToolBarPrivate::EditorToolBarPrivate(QWidget *parent, EditorToolBar *q) : m_splitButton(new QToolButton), m_horizontalSplitAction(new QAction(QIcon(QLatin1String(Constants::ICON_SPLIT_HORIZONTAL)), EditorManager::tr("Split"), parent)), m_verticalSplitAction(new QAction(QIcon(QLatin1String(Constants::ICON_SPLIT_VERTICAL)), EditorManager::tr("Split Side by Side"), parent)), - m_splitNewWindowAction(new QAction(EditorManager::tr("Split New Window"), parent)), + m_splitNewWindowAction(new QAction(EditorManager::tr("Open in New Window"), parent)), m_closeSplitButton(new QToolButton), m_activeToolBar(0), m_toolBarPlaceholder(new QWidget), @@ -311,7 +311,7 @@ void EditorToolBar::changeActiveEditor(int row) { EditorManager *em = ICore::editorManager(); QAbstractItemModel *model = d->m_editorList->model(); - em->activateEditorForIndex(model->index(row, 0), EditorManager::ModeSwitch); + em->activateEditorForIndex(model->index(row, 0)); } void EditorToolBar::listContextMenu(QPoint pos) diff --git a/src/plugins/coreplugin/imode.h b/src/plugins/coreplugin/imode.h index 232b0bf51f..ea9de058a2 100644 --- a/src/plugins/coreplugin/imode.h +++ b/src/plugins/coreplugin/imode.h @@ -49,7 +49,6 @@ public: QIcon icon() const { return m_icon; } int priority() const { return m_priority; } Id id() const { return m_id; } - Id type() const { return m_type; } bool isEnabled() const; void setEnabled(bool enabled); @@ -57,7 +56,6 @@ public: void setIcon(const QIcon &icon) { m_icon = icon; } void setPriority(int priority) { m_priority = priority; } void setId(Id id) { m_id = id; } - void setType(Id type) { m_type = type; } signals: void enabledStateChanged(bool enabled); @@ -67,7 +65,6 @@ private: QIcon m_icon; int m_priority; Id m_id; - Id m_type; bool m_isEnabled; }; diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 64f90435a6..6ae0d92318 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -861,8 +861,6 @@ IDocument *MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesF } } else { QFlags<EditorManager::OpenEditorFlag> emFlags; - if (flags & ICore::SwitchMode) - emFlags = EditorManager::ModeSwitch; if (flags & ICore::CanContainLineNumbers) emFlags |= EditorManager::CanContainLineNumber; IEditor *editor = EditorManager::openEditor(absoluteFilePath, Id(), emFlags); @@ -1005,7 +1003,7 @@ void MainWindow::openFileWith() if (isExternal) EditorManager::openExternalEditor(fileName, editorId); else - EditorManager::openEditor(fileName, editorId, Core::EditorManager::ModeSwitch); + EditorManager::openEditor(fileName, editorId); } } @@ -1289,7 +1287,7 @@ void MainWindow::openRecentFile() { if (const QAction *action = qobject_cast<const QAction*>(sender())) { const DocumentManager::RecentFile file = action->data().value<DocumentManager::RecentFile>(); - EditorManager::openEditor(file.first, file.second, EditorManager::ModeSwitch); + EditorManager::openEditor(file.first, file.second); } } diff --git a/src/plugins/coreplugin/modemanager.cpp b/src/plugins/coreplugin/modemanager.cpp index f1f019be14..b278f08c48 100644 --- a/src/plugins/coreplugin/modemanager.cpp +++ b/src/plugins/coreplugin/modemanager.cpp @@ -73,6 +73,7 @@ struct ModeManagerPrivate Context m_addedContexts; int m_oldCurrent; bool m_saveSettingsOnModeChange; + bool m_modeSelectorVisible; }; static ModeManagerPrivate *d; @@ -100,6 +101,8 @@ ModeManager::ModeManager(Internal::MainWindow *mainWindow, d->m_actionBar = new Internal::FancyActionBar(modeStack); d->m_modeStack->addCornerWidget(d->m_actionBar); d->m_saveSettingsOnModeChange = false; + d->m_modeSelectorVisible = true; + d->m_modeStack->setSelectionWidgetVisible(d->m_modeSelectorVisible); connect(d->m_modeStack, SIGNAL(currentAboutToShow(int)), SLOT(currentTabAboutToChange(int))); connect(d->m_modeStack, SIGNAL(currentChanged(int)), SLOT(currentTabChanged(int))); @@ -147,21 +150,6 @@ IMode *ModeManager::mode(Id id) return 0; } -void ModeManager::activateModeType(Id type) -{ - if (currentMode() && currentMode()->type() == type) - return; - int index = -1; - for (int i = 0; i < d->m_modes.count(); ++i) { - if (d->m_modes.at(i)->type() == type) { - index = i; - break; - } - } - if (index != -1) - d->m_modeStack->setCurrentIndex(index); -} - void ModeManager::slotActivateMode(int id) { m_instance->activateMode(Id::fromUniqueIdentifier(id)); @@ -330,21 +318,22 @@ void ModeManager::setFocusToCurrentMode() QWidget *widget = mode->widget(); if (widget) { QWidget *focusWidget = widget->focusWidget(); - if (focusWidget) - focusWidget->setFocus(); - else - widget->setFocus(); + if (!focusWidget) + focusWidget = widget; + focusWidget->setFocus(); + ICore::raiseWindow(focusWidget); } } void ModeManager::setModeSelectorVisible(bool visible) { + d->m_modeSelectorVisible = visible; d->m_modeStack->setSelectionWidgetVisible(visible); } bool ModeManager::isModeSelectorVisible() { - return d->m_modeStack->isSelectionWidgetVisible(); + return d->m_modeSelectorVisible; } ModeManager *ModeManager::instance() diff --git a/src/plugins/coreplugin/modemanager.h b/src/plugins/coreplugin/modemanager.h index caf17cada0..f053f98d9f 100644 --- a/src/plugins/coreplugin/modemanager.h +++ b/src/plugins/coreplugin/modemanager.h @@ -65,7 +65,6 @@ public: static void addProjectSelector(QAction *action); static void addWidget(QWidget *widget); - static void activateModeType(Id type); static void activateMode(Id id); static void setFocusToCurrentMode(); static bool isModeSelectorVisible(); diff --git a/src/plugins/coreplugin/progressmanager/futureprogress.cpp b/src/plugins/coreplugin/progressmanager/futureprogress.cpp index 917c3b3ec5..da6a6a1dcd 100644 --- a/src/plugins/coreplugin/progressmanager/futureprogress.cpp +++ b/src/plugins/coreplugin/progressmanager/futureprogress.cpp @@ -145,7 +145,6 @@ FutureProgress::FutureProgress(QWidget *parent) : } /*! - \fn FutureProgress::~FutureProgress() \internal */ FutureProgress::~FutureProgress() @@ -155,7 +154,6 @@ FutureProgress::~FutureProgress() } /*! - \fn void FutureProgress::setWidget(QWidget *widget) Sets the \a widget to show below the progress bar. This will be destroyed when the progress indicator is destroyed. Default is to show no widget below the progress indicator. @@ -172,7 +170,6 @@ void FutureProgress::setWidget(QWidget *widget) } /*! - \fn void FutureProgress::setTitle(const QString &title) Changes the \a title of the progress indicator. */ void FutureProgress::setTitle(const QString &title) @@ -181,7 +178,6 @@ void FutureProgress::setTitle(const QString &title) } /*! - \fn QString FutureProgress::title() const Returns the title of the progress indicator. */ QString FutureProgress::title() const @@ -268,7 +264,6 @@ void FutureProgress::setProgressText(const QString &text) } /*! - \fn void FutureProgress::setFuture(const QFuture<void> &future) \internal */ void FutureProgress::setFuture(const QFuture<void> &future) @@ -277,7 +272,6 @@ void FutureProgress::setFuture(const QFuture<void> &future) } /*! - \fn QFuture<void> FutureProgress::future() const Returns a QFuture object that represents this running task. */ QFuture<void> FutureProgress::future() const @@ -286,7 +280,6 @@ QFuture<void> FutureProgress::future() const } /*! - \fn void FutureProgress::mousePressEvent(QMouseEvent *event) \internal */ void FutureProgress::mousePressEvent(QMouseEvent *event) @@ -304,7 +297,6 @@ void FutureProgress::paintEvent(QPaintEvent *) } /*! - \fn bool FutureProgress::hasError() const Returns the error state of this progress indicator. */ bool FutureProgress::hasError() const diff --git a/src/plugins/coreplugin/variablemanager.cpp b/src/plugins/coreplugin/variablemanager.cpp index 3af6ab709f..06146712ae 100644 --- a/src/plugins/coreplugin/variablemanager.cpp +++ b/src/plugins/coreplugin/variablemanager.cpp @@ -308,7 +308,7 @@ void VariableManager::registerFileVariables(const QByteArray &prefix, const QStr { registerVariable(prefix + kFilePathPostfix, tr("%1: Full path including file name.").arg(heading)); registerVariable(prefix + kPathPostfix, tr("%1: Full path excluding file name.").arg(heading)); - registerVariable(prefix + kFileNamePostfix, tr("%1: File name without including path.").arg(heading)); + registerVariable(prefix + kFileNamePostfix, tr("%1: File name without path.").arg(heading)); registerVariable(prefix + kFileBaseNamePostfix, tr("%1: File base name without path and suffix.").arg(heading)); } diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp index 461c1526a5..ce8cef68e5 100644 --- a/src/plugins/coreplugin/vcsmanager.cpp +++ b/src/plugins/coreplugin/vcsmanager.cpp @@ -106,6 +106,11 @@ public: return result; } + void clearCache() + { + m_cachedMatches.clear(); + } + void resetCache(const QString &dir) { QTC_ASSERT(QDir(dir).isAbsolute(), return); @@ -226,8 +231,10 @@ IVersionControl* VcsManager::findVersionControlForDirectory(const QString &input foreach (IVersionControl * versionControl, versionControls) { QString topLevel; - if (versionControl->managesDirectory(directory, &topLevel)) + if (versionControl->isConfigured() + && versionControl->managesDirectory(directory, &topLevel)) { allThatCanManage.push_back(StringVersionControlPair(topLevel, versionControl)); + } } // To properly find a nested repository (say, git checkout inside SVN), @@ -379,4 +386,12 @@ void VcsManager::promptToAdd(const QString &directory, const QStringList &fileNa } } +void VcsManager::clearVersionControlCache() +{ + QStringList repoList = d->m_cachedMatches.keys(); + d->clearCache(); + foreach (const QString &repo, repoList) + emit repositoryChanged(repo); +} + } // namespace Core diff --git a/src/plugins/coreplugin/vcsmanager.h b/src/plugins/coreplugin/vcsmanager.h index 103ecb8f09..e8f43623a5 100644 --- a/src/plugins/coreplugin/vcsmanager.h +++ b/src/plugins/coreplugin/vcsmanager.h @@ -95,6 +95,9 @@ public: signals: void repositoryChanged(const QString &repository); +public slots: + void clearVersionControlCache(); + private: VcsManagerPrivate *d; }; diff --git a/src/plugins/cpaster/cpasterplugin.cpp b/src/plugins/cpaster/cpasterplugin.cpp index 2d1409c5e9..12102111d1 100644 --- a/src/plugins/cpaster/cpasterplugin.cpp +++ b/src/plugins/cpaster/cpasterplugin.cpp @@ -380,7 +380,7 @@ void CodepasterPlugin::finishFetch(const QString &titleDescription, const QString fileName = saver.fileName(); m_fetchedSnippets.push_back(fileName); // Open editor with title. - Core::IEditor *editor = EditorManager::openEditor(fileName, Core::Id(), EditorManager::ModeSwitch); + Core::IEditor *editor = EditorManager::openEditor(fileName); QTC_ASSERT(editor, return); editor->setDisplayName(titleDescription); } diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index dd42d6cb7f..ae80aa425e 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -1992,22 +1992,14 @@ bool CPPEditorWidget::openCppEditorAt(const Link &link, bool inNextSplit) if (!link.hasValidTarget()) return false; - Core::EditorManager *editorManager = Core::EditorManager::instance(); - if (inNextSplit) { - if (!editorManager->hasSplitter()) - editorManager->splitSideBySide(); - editorManager->gotoOtherSplit(); - } else if (baseTextDocument()->fileName() == link.targetFileName) { - editorManager->addCurrentPositionToNavigationHistory(); - gotoLine(link.targetLine, link.targetColumn); - setFocus(); - return true; - } - - return TextEditor::BaseTextEditorWidget::openEditorAt(link.targetFileName, - link.targetLine, - link.targetColumn, - Constants::CPPEDITOR_ID); + Core::EditorManager::OpenEditorFlags flags; + if (inNextSplit) + flags |= Core::EditorManager::OpenInOtherSplit; + return Core::EditorManager::openEditorAt(link.targetFileName, + link.targetLine, + link.targetColumn, + Constants::CPPEDITOR_ID, + flags); } void CPPEditorWidget::semanticRehighlight(bool force) diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index 239e6dc844..64c19e3130 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -178,7 +178,8 @@ private slots: void test_quickfix_MoveFuncDefOutside_MemberFuncOutsideWithNs(); void test_quickfix_MoveFuncDefOutside_FreeFuncToCpp(); void test_quickfix_MoveFuncDefOutside_FreeFuncToCppNS(); - void test_quickfix_MoveFuncDefOutside_CtorWithInitialization(); + void test_quickfix_MoveFuncDefOutside_CtorWithInitialization1(); + void test_quickfix_MoveFuncDefOutside_CtorWithInitialization2(); void test_quickfix_MoveFuncDefToDecl_MemberFunc(); void test_quickfix_MoveFuncDefToDecl_MemberFuncOutside(); diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 17823ecade..66aa48fd47 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -842,17 +842,17 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_namespace2() // Source File original = - "#include \"file.h\"\n" - "using namespace N;\n" - "\n" - ; + "#include \"file.h\"\n" + "using namespace N;\n" + ; expected = original + - "\n" - "Foo::Foo()\n" - "{\n\n" - "}\n" - "\n" - ; + "\n" + "\n" + "Foo::Foo()\n" + "{\n\n" + "}\n" + "\n" + ; testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp")); InsertDefFromDecl factory; @@ -1310,7 +1310,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCpp() // Header File original = "class Foo {\n" - " inline int numbe@r() const {\n" + " inline int numbe@r() const\n" + " {\n" " return 5;\n" " }\n" "\n" @@ -1332,7 +1333,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCpp() "#include \"file.h\"\n" "\n" "\n" - "int Foo::number() const {\n" + "int Foo::number() const\n" + "{\n" " return 5;\n" "}\n" "\n"; @@ -1348,7 +1350,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside() { QByteArray original = "class Foo {\n" - " inline int numbe@r() const {\n" + " inline int numbe@r() const\n" + " {\n" " return 5;\n" " }\n" "};"; @@ -1357,7 +1360,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside() " inline int number() const;\n" "};\n" "\n" - "int Foo::number() const {\n" + "int Foo::number() const\n" + "{\n" " return 5;\n" "}" "\n\n"; @@ -1378,7 +1382,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNS() original = "namespace MyNs {\n" "class Foo {\n" - " inline int numbe@r() const {\n" + " inline int numbe@r() const\n" + " {\n" " return 5;\n" " }\n" "};\n" @@ -1399,7 +1404,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNS() "#include \"file.h\"\n" "\n" "\n" - "int MyNs::Foo::number() const {\n" + "int MyNs::Foo::number() const\n" + "{\n" " return 5;\n" "}\n" "\n"; @@ -1421,7 +1427,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNSUsing() original = "namespace MyNs {\n" "class Foo {\n" - " inline int numbe@r() const {\n" + " inline int numbe@r() const\n" + " {\n" " return 5;\n" " }\n" "};\n" @@ -1444,7 +1451,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNSUsing() "using namespace MyNs;\n" "\n" "\n" - "int Foo::number() const {\n" + "int Foo::number() const\n" + "{\n" " return 5;\n" "}\n" "\n"; @@ -1461,7 +1469,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutsideWithNs() QByteArray original = "namespace MyNs {\n" "class Foo {\n" - " inline int numbe@r() const {\n" + " inline int numbe@r() const\n" + " {\n" " return 5;\n" " }\n" "};}"; @@ -1471,7 +1480,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutsideWithNs() " inline int number() const;\n" "};\n" "\n" - "int Foo::number() const {\n" + "int Foo::number() const\n" + "{\n" " return 5;\n" "}" "\n}\n"; @@ -1490,7 +1500,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCpp() // Header File original = - "int numbe@r() const {\n" + "int numbe@r() const\n" + "{\n" " return 5;\n" "}\n"; expected = @@ -1506,7 +1517,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCpp() "#include \"file.h\"\n" "\n" "\n" - "int number() const {\n" + "int number() const\n" + "{\n" " return 5;\n" "}\n" "\n"; @@ -1527,7 +1539,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCppNS() // Header File original = "namespace MyNamespace {\n" - "int numbe@r() const {\n" + "int numbe@r() const\n" + "{\n" " return 5;\n" "}\n" "}\n"; @@ -1546,7 +1559,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCppNS() "#include \"file.h\"\n" "\n" "\n" - "int MyNamespace::number() const {\n" + "int MyNamespace::number() const\n" + "{\n" " return 5;\n" "}\n" "\n"; @@ -1558,7 +1572,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCppNS() } /// Check: Move Ctor with member initialization list (QTCREATORBUG-9157). -void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_CtorWithInitialization() +void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_CtorWithInitialization1() { QList<TestDocumentPtr> testFiles; QByteArray original; @@ -1597,6 +1611,51 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_CtorWithInitialization() data.run(&factory); } +/// Check: Move Ctor with member initialization list (QTCREATORBUG-9462). +void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_CtorWithInitialization2() +{ + QList<TestDocumentPtr> testFiles; + QByteArray original; + QByteArray expected; + + // Header File + original = + "class Foo\n" + "{\n" + "public:\n" + " Fo@o() : member(2)\n" + " {\n" + " }\n" + "\n" + " int member;\n" + "};"; + + expected = + "class Foo\n" + "{\n" + "public:\n" + " Foo();\n" + "\n" + " int member;\n" + "};\n"; + testFiles << TestDocument::create(original, expected, QLatin1String("file.h")); + + // Source File + original ="#include \"file.h\"\n"; + expected = + "#include \"file.h\"\n" + "\n" + "Foo::Foo() : member(2)\n" + "{\n" + "}\n" + "\n"; + testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp")); + + MoveFuncDefOutside factory; + TestCase data(testFiles); + data.run(&factory); +} + /// Check: revert test_quickfix_MoveFuncDefOutside_MemberFuncToCpp() void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFunc() { @@ -1605,8 +1664,14 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFunc() QByteArray expected; // Header File - original = "class Foo {inline int number() const;};\n"; - expected = "class Foo {inline int number() const {return 5;}};\n\n"; + original = + "class Foo {\n" + " inline int number() const;\n" + "};\n"; + expected = + "class Foo {\n" + " inline int number() const {return 5;}\n" + "};\n\n"; testFiles << TestDocument::create(original, expected, QLatin1String("file.h")); // Source File @@ -1632,13 +1697,15 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncOutside() " inline int number() const;\n" "};\n" "\n" - "int Foo::num@ber() const {\n" + "int Foo::num@ber() const\n" + "{\n" " return 5;\n" "}\n"; QByteArray expected = "class Foo {\n" - " inline int number() const {\n" + " inline int number() const\n" + " {\n" " return 5;\n" " }\n" "};\n" @@ -1666,7 +1733,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncToCppNS() expected = "namespace MyNs {\n" "class Foo {\n" - " inline int number() const {\n" + " inline int number() const\n" + " {\n" " return 5;\n" " }\n" "};\n" @@ -1677,7 +1745,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncToCppNS() original = "#include \"file.h\"\n" "\n" - "int MyNs::Foo::num@ber() const {\n" + "int MyNs::Foo::num@ber() const\n" + "{\n" " return 5;\n" "}\n"; expected = "#include \"file.h\"\n\n\n\n"; @@ -1705,7 +1774,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncToCppNSUsing() expected = "namespace MyNs {\n" "class Foo {\n" - " inline int number() const {\n" + " inline int number() const\n" + " {\n" " return 5;\n" " }\n" "};\n" @@ -1717,7 +1787,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncToCppNSUsing() "#include \"file.h\"\n" "using namespace MyNs;\n" "\n" - "int Foo::num@ber() const {\n" + "int Foo::num@ber() const\n" + "{\n" " return 5;\n" "}\n"; expected = @@ -1740,14 +1811,16 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncOutsideWithNs() " inline int number() const;\n" "};\n" "\n" - "int Foo::numb@er() const {\n" + "int Foo::numb@er() const\n" + "{\n" " return 5;\n" "}" "\n}\n"; QByteArray expected = "namespace MyNs {\n" "class Foo {\n" - " inline int number() const {\n" + " inline int number() const\n" + " {\n" " return 5;\n" " }\n" "};\n\n\n}\n\n"; @@ -1767,7 +1840,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_FreeFuncToCpp() // Header File original = "int number() const;\n"; expected = - "int number() const {\n" + "int number() const\n" + "{\n" " return 5;\n" "}\n\n"; testFiles << TestDocument::create(original, expected, QLatin1String("file.h")); @@ -1777,7 +1851,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_FreeFuncToCpp() "#include \"file.h\"\n" "\n" "\n" - "int numb@er() const {\n" + "int numb@er() const\n" + "{\n" " return 5;\n" "}\n"; expected = "#include \"file.h\"\n\n\n\n\n"; @@ -1802,7 +1877,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_FreeFuncToCppNS() "}\n"; expected = "namespace MyNamespace {\n" - "int number() const {\n" + "int number() const\n" + "{\n" " return 5;\n" "}\n" "}\n\n"; @@ -1812,7 +1888,8 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_FreeFuncToCppNS() original = "#include \"file.h\"\n" "\n" - "int MyNamespace::nu@mber() const {\n" + "int MyNamespace::nu@mber() const\n" + "{\n" " return 5;\n" "}\n"; expected = diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index a75d987170..095e596ad3 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -2334,8 +2334,8 @@ class InsertDeclOperation: public CppQuickFixOperation public: InsertDeclOperation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, const QString &targetFileName, const Class *targetSymbol, - InsertionPointLocator::AccessSpec xsSpec, const QString &decl) - : CppQuickFixOperation(interface, 0) + InsertionPointLocator::AccessSpec xsSpec, const QString &decl, int priority) + : CppQuickFixOperation(interface, priority) , m_targetFileName(targetFileName) , m_targetSymbol(targetSymbol) , m_xsSpec(xsSpec) @@ -2397,10 +2397,11 @@ public: , m_decl(decl) {} TextEditor::QuickFixOperation::Ptr - operator()(InsertionPointLocator::AccessSpec xsSpec) + operator()(InsertionPointLocator::AccessSpec xsSpec, int priority) { return TextEditor::QuickFixOperation::Ptr( - new InsertDeclOperation(m_interface, m_fileName, m_matchingClass, xsSpec, m_decl)); + new InsertDeclOperation(m_interface, m_fileName, m_matchingClass, xsSpec, m_decl, + priority)); } private: @@ -2462,12 +2463,12 @@ void InsertDeclFromDef::match(const CppQuickFixInterface &interface, QuickFixOpe // Add several possible insertion locations for declaration DeclOperationFactory operation(interface, fileName, matchingClass, decl); - result.append(operation(InsertionPointLocator::Public)); - result.append(operation(InsertionPointLocator::PublicSlot)); - result.append(operation(InsertionPointLocator::Protected)); - result.append(operation(InsertionPointLocator::ProtectedSlot)); - result.append(operation(InsertionPointLocator::Private)); - result.append(operation(InsertionPointLocator::PrivateSlot)); + result.append(operation(InsertionPointLocator::Public, 5)); + result.append(operation(InsertionPointLocator::PublicSlot, 4)); + result.append(operation(InsertionPointLocator::Protected, 3)); + result.append(operation(InsertionPointLocator::ProtectedSlot, 2)); + result.append(operation(InsertionPointLocator::Private, 1)); + result.append(operation(InsertionPointLocator::PrivateSlot, 0)); } } @@ -3696,7 +3697,7 @@ class ApplyDeclDefLinkOperation : public CppQuickFixOperation public: explicit ApplyDeclDefLinkOperation(const CppQuickFixInterface &interface, const QSharedPointer<FunctionDeclDefLink> &link) - : CppQuickFixOperation(interface, 10) + : CppQuickFixOperation(interface, 100) , m_link(link) {} @@ -3815,13 +3816,10 @@ public: // construct definition const QString funcDec = getDefinitionSignature(assistInterface(), m_func, toFile, scopeAtInsertPos); - QString textFuncBody; - if (m_funcDef->ctor_initializer) - textFuncBody = fromFile->textOf(m_funcDef->ctor_initializer) + QLatin1Char(' '); - textFuncBody += fromFile->textOf(m_funcDef->function_body); - QString funcDef = QString::fromLatin1("\n%1 %2\n") - .arg(funcDec) - .arg(textFuncBody); + QString funcDef = QLatin1String("\n") + funcDec; + const int startPosition = fromFile->endOf(m_funcDef->declarator); + const int endPosition = fromFile->endOf(m_funcDef->function_body); + funcDef += fromFile->textOf(startPosition, endPosition) + QLatin1String("\n"); if (m_cppFileName.isEmpty() || !m_insideHeader) funcDef = QLatin1String("\n") + funcDef; @@ -3839,7 +3837,7 @@ public: headerTarget.remove(fromFile->range(m_funcDef)); } else { QString textFuncDecl = fromFile->textOf(m_funcDef); - textFuncDecl.remove(-textFuncBody.length(), textFuncBody.length()); + textFuncDecl.truncate(startPosition - fromFile->startOf(m_funcDef)); textFuncDecl = textFuncDecl.trimmed() + QLatin1String(";"); headerTarget.replace(fromFile->range(m_funcDef), textFuncDecl); } @@ -3944,12 +3942,10 @@ public: CppRefactoringFilePtr fromFile = refactoring.file(m_fromFileName); CppRefactoringFilePtr toFile = refactoring.file(m_toFileName); ChangeSet::Range fromRange = fromFile->range(m_funcAST); - const QString definitionText = fromFile->textOf(m_funcAST->function_body); - QString wholeFunctionText = m_declarationText; - if (m_funcAST->ctor_initializer) - wholeFunctionText += QLatin1Char(' ') + fromFile->textOf(m_funcAST->ctor_initializer); - wholeFunctionText += QLatin1Char(' ') + definitionText; + const QString wholeFunctionText = m_declarationText + + fromFile->textOf(fromFile->endOf(m_funcAST->declarator), + fromFile->endOf(m_funcAST->function_body)); // Replace declaration with function and delete old definition Utils::ChangeSet toTarget; diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp index 11d75cc4ae..2883a6f8f2 100644 --- a/src/plugins/cppeditor/cpptypehierarchy.cpp +++ b/src/plugins/cppeditor/cpptypehierarchy.cpp @@ -105,10 +105,10 @@ private: if (!m_link.hasValidTarget()) return; - TextEditor::BaseTextEditorWidget::openEditorAt(m_link.targetFileName, - m_link.targetLine, - m_link.targetColumn, - Constants::CPPEDITOR_ID); + Core::EditorManager::openEditorAt(m_link.targetFileName, + m_link.targetLine, + m_link.targetColumn, + Constants::CPPEDITOR_ID); } CPPEditorWidget::Link m_link; @@ -205,10 +205,10 @@ void CppTypeHierarchyWidget::onItemClicked(const QModelIndex &index) const TextEditor::BaseTextEditorWidget::Link link = index.data(LinkRole).value<TextEditor::BaseTextEditorWidget::Link>(); if (link.hasValidTarget()) - TextEditor::BaseTextEditorWidget::openEditorAt(link.targetFileName, - link.targetLine, - link.targetColumn, - Constants::CPPEDITOR_ID); + Core::EditorManager::openEditorAt(link.targetFileName, + link.targetLine, + link.targetColumn, + Constants::CPPEDITOR_ID); } // CppTypeHierarchyStackedWidget diff --git a/src/plugins/cpptools/abstracteditorsupport.cpp b/src/plugins/cpptools/abstracteditorsupport.cpp index 6410473e34..cdbd86f342 100644 --- a/src/plugins/cpptools/abstracteditorsupport.cpp +++ b/src/plugins/cpptools/abstracteditorsupport.cpp @@ -55,29 +55,13 @@ QString AbstractEditorSupport::functionAt(const CppModelManagerInterface *modelM const QString &fileName, int line, int column) { - const CPlusPlus::Snapshot snapshot = modelManager->snapshot(); - const CPlusPlus::Document::Ptr document = snapshot.document(fileName); - if (!document) + if (!modelManager) return QString(); - if (const CPlusPlus::Symbol *symbol = document->lastVisibleSymbolAt(line, column)) - if (const CPlusPlus::Scope *scope = symbol->enclosingScope()) - if (const CPlusPlus::Scope *functionScope = scope->enclosingFunction()) - if (const CPlusPlus::Symbol *function = functionScope) { - const CPlusPlus::Overview o; - QString rc = o.prettyName(function->name()); - // Prepend namespace "Foo::Foo::foo()" up to empty root namespace - for (const CPlusPlus::Symbol *owner = function->enclosingNamespace(); - owner; owner = owner->enclosingNamespace()) { - const QString name = o.prettyName(owner->name()); - if (name.isEmpty()) { - break; - } else { - rc.prepend(QLatin1String("::")); - rc.prepend(name); - } - } - return rc; - } + + const CPlusPlus::Snapshot snapshot = modelManager->snapshot(); + if (const CPlusPlus::Document::Ptr document = snapshot.document(fileName)) + return document->functionAt(line, column); + return QString(); } diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp index 1ad33ca026..967bc9321c 100644 --- a/src/plugins/cpptools/cppcodeformatter.cpp +++ b/src/plugins/cpptools/cppcodeformatter.cpp @@ -207,6 +207,8 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block) // oops, the expression was a function declaration argument list, hand lbrace/colon to declaration_start leave(); continue; + } else { + turnInto(substatement_open); } break; default: tryExpression(); break; diff --git a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp index eaf3aa358d..e7aa07ac90 100644 --- a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp +++ b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp @@ -110,8 +110,7 @@ QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(QFutureInterfac void CppCurrentDocumentFilter::accept(Locator::FilterEntry selection) const { ModelItemInfo info = qvariant_cast<CppTools::ModelItemInfo>(selection.internalData); - TextEditor::BaseTextEditorWidget::openEditorAt(info.fileName, info.line, info.column, - Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditorAt(info.fileName, info.line, info.column); } void CppCurrentDocumentFilter::refresh(QFutureInterface<void> &future) diff --git a/src/plugins/cpptools/cppfilesettingspage.cpp b/src/plugins/cpptools/cppfilesettingspage.cpp index c0ebe30a33..1c0c49904d 100644 --- a/src/plugins/cpptools/cppfilesettingspage.cpp +++ b/src/plugins/cpptools/cppfilesettingspage.cpp @@ -305,8 +305,7 @@ void CppFileSettingsWidget::slotEdit() setLicenseTemplatePath(path); } // Edit (now) existing file with C++ - Core::EditorManager::openEditor(path, CppEditor::Constants::CPPEDITOR_ID, - Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(path, CppEditor::Constants::CPPEDITOR_ID); } // --------------- CppFileSettingsPage diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 4d8283c145..bcf590c0d9 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -32,11 +32,11 @@ #include "cpptoolsconstants.h" #include "cppmodelmanagerinterface.h" +#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/icore.h> #include <coreplugin/progressmanager/futureprogress.h> #include <coreplugin/progressmanager/progressmanager.h> #include <texteditor/basefilefind.h> -#include <texteditor/basetexteditor.h> #include <utils/qtcassert.h> #include <utils/runextensions.h> @@ -509,13 +509,10 @@ void CppFindReferences::setPaused(bool paused) void CppFindReferences::openEditor(const Find::SearchResultItem &item) { if (item.path.size() > 0) { - TextEditor::BaseTextEditorWidget::openEditorAt(QDir::fromNativeSeparators(item.path.first()), - item.lineNumber, item.textMarkPos, - Core::Id(), - Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()), + item.lineNumber, item.textMarkPos); } else { - Core::EditorManager::openEditor(QDir::fromNativeSeparators(item.text), - Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(QDir::fromNativeSeparators(item.text)); } } diff --git a/src/plugins/cpptools/cpplocatorfilter.cpp b/src/plugins/cpptools/cpplocatorfilter.cpp index 6bb5c8ef51..0117a7d981 100644 --- a/src/plugins/cpptools/cpplocatorfilter.cpp +++ b/src/plugins/cpptools/cpplocatorfilter.cpp @@ -177,8 +177,7 @@ QList<Locator::FilterEntry> CppLocatorFilter::matchesFor(QFutureInterface<Locato void CppLocatorFilter::accept(Locator::FilterEntry selection) const { ModelItemInfo info = qvariant_cast<CppTools::ModelItemInfo>(selection.internalData); - TextEditor::BaseTextEditorWidget::openEditorAt(info.fileName, info.line, info.column, - Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditorAt(info.fileName, info.line, info.column); } void CppLocatorFilter::reset() diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index f168e6bfa8..7fa7fc3a38 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -143,6 +143,7 @@ protected: static const char pp_configuration[] = "# 1 \"<configuration>\"\n" + "#define Q_CREATOR_RUN 1\n" "#define __cplusplus 1\n" "#define __extension__\n" "#define __context__\n" diff --git a/src/plugins/cpptools/cpppreprocessor.cpp b/src/plugins/cpptools/cpppreprocessor.cpp index 5c5d1bd803..d12b56b207 100644 --- a/src/plugins/cpptools/cpppreprocessor.cpp +++ b/src/plugins/cpptools/cpppreprocessor.cpp @@ -5,6 +5,18 @@ #include <QCoreApplication> +/*! + * \class CppTools::Internal::CppPreprocessor + * \brief The CppPreprocessor class updates set of indexed C++ files. + * + * Indexed file is truncated version of fully parsed document: copy of source + * code and full AST will be dropped when indexing is done. Working copy ensures + * that documents with most recent copy placed in memory will be parsed correctly. + * + * \sa CPlusPlus::Document + * \sa CppTools::CppModelManagerInterface::WorkingCopy + */ + using namespace CPlusPlus; using namespace CppTools; using namespace CppTools::Internal; diff --git a/src/plugins/cpptools/cpppreprocessor.h b/src/plugins/cpptools/cpppreprocessor.h index d931a880c4..c54bbefb30 100644 --- a/src/plugins/cpptools/cpppreprocessor.h +++ b/src/plugins/cpptools/cpppreprocessor.h @@ -14,11 +14,14 @@ namespace Internal { class CppModelManager; +// Documentation inside. class CPPTOOLS_EXPORT CppPreprocessor: public CPlusPlus::Client { Q_DISABLE_COPY(CppPreprocessor) public: + static QString cleanPath(const QString &path); + CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing = false); virtual ~CppPreprocessor(); @@ -26,15 +29,11 @@ public: void setWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy); void setIncludePaths(const QStringList &includePaths); void setFrameworkPaths(const QStringList &frameworkPaths); - void addFrameworkPath(const QString &frameworkPath); - void setProjectFiles(const QStringList &files); void setTodo(const QStringList &files); void run(const QString &fileName); void removeFromCache(const QString &fileName); - void resetEnvironment(); - static QString cleanPath(const QString &path); const QSet<QString> &todo() const { return m_todo; } @@ -69,6 +68,8 @@ protected: virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType type); private: + void addFrameworkPath(const QString &frameworkPath); + CPlusPlus::Snapshot m_snapshot; QPointer<CppModelManager> m_modelManager; bool m_dumpFileNameWhileParsing; diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index 7f70a37640..93b2a80482 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -164,7 +164,7 @@ void CppToolsPlugin::switchHeaderSourceInNextSplit() QString otherFile = correspondingHeaderOrSource( Core::EditorManager::currentEditor()->document()->fileName()); if (!otherFile.isEmpty()) - Core::EditorManager::openEditorInNextSplit(otherFile); + Core::EditorManager::openEditor(otherFile, Core::Id(), Core::EditorManager::OpenInOtherSplit); } static QStringList findFilesInProject(const QString &name, diff --git a/src/plugins/cpptools/insertionpointlocator.cpp b/src/plugins/cpptools/insertionpointlocator.cpp index 08d9722086..f7118a2cfe 100644 --- a/src/plugins/cpptools/insertionpointlocator.cpp +++ b/src/plugins/cpptools/insertionpointlocator.cpp @@ -363,7 +363,7 @@ public: : ASTVisitor(translationUnit) {} - void operator()(Declaration *decl, unsigned *line, unsigned *column) + void operator()(Symbol *decl, unsigned *line, unsigned *column) { // default to end of file _bestToken.maybeSet(-1, translationUnit()->ast()->lastToken()); @@ -470,7 +470,7 @@ static Declaration *isNonVirtualFunctionDeclaration(Symbol *s) return declaration; } -static InsertionLocation nextToSurroundingDefinitions(Declaration *declaration, const CppRefactoringChanges &changes) +static InsertionLocation nextToSurroundingDefinitions(Symbol *declaration, const CppRefactoringChanges &changes) { InsertionLocation noResult; Class *klass = declaration->enclosingClass(); @@ -545,15 +545,18 @@ static InsertionLocation nextToSurroundingDefinitions(Declaration *declaration, return InsertionLocation(QString::fromUtf8(definitionFunction->fileName()), prefix, suffix, line, column); } -QList<InsertionLocation> InsertionPointLocator::methodDefinition(Declaration *declaration) const +QList<InsertionLocation> InsertionPointLocator::methodDefinition(Symbol *declaration, + bool useSymbolFinder) const { QList<InsertionLocation> result; if (!declaration) return result; - CppTools::SymbolFinder symbolFinder; - if (symbolFinder.findMatchingDefinition(declaration, m_refactoringChanges.snapshot(), true)) - return result; + if (useSymbolFinder) { + CppTools::SymbolFinder symbolFinder; + if (symbolFinder.findMatchingDefinition(declaration, m_refactoringChanges.snapshot(), true)) + return result; + } const InsertionLocation location = nextToSurroundingDefinitions(declaration, m_refactoringChanges); if (location.isValid()) { diff --git a/src/plugins/cpptools/insertionpointlocator.h b/src/plugins/cpptools/insertionpointlocator.h index da9799744b..f5ea46d26d 100644 --- a/src/plugins/cpptools/insertionpointlocator.h +++ b/src/plugins/cpptools/insertionpointlocator.h @@ -98,7 +98,8 @@ public: const CPlusPlus::Class *clazz, AccessSpec xsSpec) const; - QList<InsertionLocation> methodDefinition(CPlusPlus::Declaration *declaration) const; + QList<InsertionLocation> methodDefinition(CPlusPlus::Symbol *declaration, + bool useSymbolFinder = true) const; private: CppRefactoringChanges m_refactoringChanges; diff --git a/src/plugins/cpptools/symbolsfindfilter.cpp b/src/plugins/cpptools/symbolsfindfilter.cpp index 78c636674d..290b5bd5fd 100644 --- a/src/plugins/cpptools/symbolsfindfilter.cpp +++ b/src/plugins/cpptools/symbolsfindfilter.cpp @@ -187,9 +187,9 @@ void SymbolsFindFilter::openEditor(const Find::SearchResultItem &item) if (!item.userData.canConvert<ModelItemInfo>()) return; ModelItemInfo info = item.userData.value<ModelItemInfo>(); - TextEditor::BaseTextEditorWidget::openEditorAt(info.fileName, - info.line, - info.column); + Core::EditorManager::openEditorAt(info.fileName, + info.line, + info.column); } QWidget *SymbolsFindFilter::createConfigWidget() diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index b3cadb5e17..85ffd0a65c 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -592,7 +592,7 @@ void CvsPlugin::cvsDiff(const CvsDiffParameters &p) const QString tag = VcsBaseEditorWidget::editorTag(DiffOutput, p.workingDir, p.files); if (IEditor *existingEditor = VcsBaseEditorWidget::locateEditorByTag(tag)) { existingEditor->createNew(output); - EditorManager::activateEditor(existingEditor, EditorManager::ModeSwitch); + EditorManager::activateEditor(existingEditor); setDiffBaseDirectory(existingEditor, p.workingDir); return; } @@ -615,8 +615,7 @@ void CvsPlugin::cvsDiff(const CvsDiffParameters &p) CvsSubmitEditor *CvsPlugin::openCVSSubmitEditor(const QString &fileName) { - IEditor *editor = EditorManager::openEditor(fileName, Constants::CVSCOMMITEDITOR_ID, - EditorManager::ModeSwitch); + IEditor *editor = EditorManager::openEditor(fileName, Constants::CVSCOMMITEDITOR_ID); CvsSubmitEditor *submitEditor = qobject_cast<CvsSubmitEditor*>(editor); QTC_CHECK(submitEditor); submitEditor->registerActions(m_submitUndoAction, m_submitRedoAction, m_submitCurrentLogAction, m_submitDiffAction); @@ -861,7 +860,7 @@ void CvsPlugin::filelog(const QString &workingDir, const QString tag = VcsBaseEditorWidget::editorTag(LogOutput, workingDir, files); if (Core::IEditor *editor = VcsBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); - Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(editor); } else { const QString title = QString::fromLatin1("cvs log %1").arg(id); Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, LogOutput, source, codec); @@ -1004,7 +1003,7 @@ void CvsPlugin::annotate(const QString &workingDir, const QString &file, if (IEditor *editor = VcsBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); VcsBaseEditorWidget::gotoLineOfEditor(editor, lineNumber); - EditorManager::activateEditor(editor, EditorManager::ModeSwitch); + EditorManager::activateEditor(editor); } else { const QString title = QString::fromLatin1("cvs annotate %1").arg(id); IEditor *newEditor = showOutputInEditor(title, response.stdOut, AnnotateOutput, source, codec); @@ -1199,7 +1198,7 @@ bool CvsPlugin::describe(const QString &repositoryPath, const QString commitId = entries.front().revisions.front().commitId; if (IEditor *editor = VcsBaseEditorWidget::locateEditorByTag(commitId)) { editor->createNew(output); - EditorManager::activateEditor(editor, EditorManager::ModeSwitch); + EditorManager::activateEditor(editor); setDiffBaseDirectory(editor, repositoryPath); } else { const QString title = QString::fromLatin1("cvs describe %1").arg(commitId); @@ -1285,7 +1284,7 @@ IEditor *CvsPlugin::showOutputInEditor(const QString& title, const QString &outp if (codec) e->setCodec(codec); IEditor *ie = e->editor(); - EditorManager::activateEditor(ie, EditorManager::ModeSwitch); + EditorManager::activateEditor(ie); return ie; } diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp index 0082bdce25..e096037c55 100644 --- a/src/plugins/debugger/commonoptionspage.cpp +++ b/src/plugins/debugger/commonoptionspage.cpp @@ -69,7 +69,11 @@ CommonOptionsPageWidget::CommonOptionsPageWidget checkBoxListSourceFiles->setText(tr("Populate source file view automatically")); checkBoxCloseBuffersOnExit = new QCheckBox(behaviorBox); - checkBoxCloseBuffersOnExit->setText(tr("Close temporary buffers on debugger exit")); + checkBoxCloseBuffersOnExit->setText(tr("Close temporary views on debugger exit")); + checkBoxCloseBuffersOnExit->setText(tr("Stopping and stepping in the debugger " + "will automatically open source or disassembler views associated with the " + "current location. Select this option to automatically close them when " + "the debugger exits.")); checkBoxSwitchModeOnExit = new QCheckBox(behaviorBox); checkBoxSwitchModeOnExit->setText(tr("Switch to previous mode on debugger exit")); diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index c84ca969a6..c042217885 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -447,6 +447,11 @@ DebuggerSettings::DebuggerSettings(QSettings *settings) insertItem(GdbStartupCommands, item); item = new SavedAction(this); + item->setSettingsKey(debugModeGroup, QLatin1String("GdbCustomDumperCommands")); + item->setDefaultValue(QString()); + insertItem(GdbCustomDumperCommands, item); + item = new SavedAction(this); + item->setSettingsKey(debugModeGroup, QLatin1String("GdbPostAttachCommands")); item->setDefaultValue(QString()); insertItem(GdbPostAttachCommands, item); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index d98423a76c..2abc5dddf4 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -130,6 +130,7 @@ enum DebuggerActionCode LoadGdbDumpers, AttemptQuickStart, GdbStartupCommands, + GdbCustomDumperCommands, GdbPostAttachCommands, GdbWatchdogTimeout, AutoEnrichParameters, diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index f90354e2b7..aada6367c9 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -508,7 +508,6 @@ public: setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Debug.png"))); setPriority(85); setId(MODE_DEBUG); - setType(CC::MODE_EDIT_TYPE); } ~DebugMode() @@ -3582,11 +3581,10 @@ void DebuggerPlugin::testPythonDumpers() void DebuggerPluginPrivate::testPythonDumpers1() { m_testSuccess = true; - QString proFile = ICore::resourcePath() -#ifndef Q_OS_MAC - + QLatin1String("/../..") -#endif - + QLatin1String("/tests/manual/debugger/simple/simple.pro"); + QString proFile = ICore::resourcePath(); + if (Utils::HostOsInfo::isMacHost()) + proFile += QLatin1String("/../.."); + proFile += QLatin1String("/../../tests/manual/debugger/simple/simple.pro"); testLoadProject(proFile, TestCallBack(this, "testPythonDumpers2")); QVERIFY(m_testSuccess); QTestEventLoop::instance().enterLoop(20); @@ -3617,8 +3615,10 @@ void DebuggerPlugin::testStateMachine() void DebuggerPluginPrivate::testStateMachine1() { m_testSuccess = true; - QString proFile = ICore::resourcePath() - + QLatin1String("/../../tests/manual/debugger/simple/simple.pro"); + QString proFile = ICore::resourcePath(); + if (Utils::HostOsInfo::isMacHost()) + proFile += QLatin1String("/../.."); + proFile += QLatin1String("/../../tests/manual/debugger/simple/simple.pro"); testLoadProject(proFile, TestCallBack(this, "testStateMachine2")); QVERIFY(m_testSuccess); QTestEventLoop::instance().enterLoop(20); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 705fab28b4..e8f80920f3 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1827,14 +1827,7 @@ void GdbEngine::handleShowVersion(const GdbResponse &response) postCommand("set detach-on-fork off", ConsoleCommand); //postCommand("set build-id-verbose 2", ConsoleCommand); - - if (m_gdbVersion > 70100) { - // Quick check whether we have python. - showMessage(_("NOTE: CHECK FOR PYTHON SUPPRESSED, VERSION TOO LOW")); - postCommand("python print 43", ConsoleCommand, CB(handleHasPython)); - } else { - pythonDumpersFailed(); - } + postCommand("python print 43", ConsoleCommand, CB(handleHasPython)); } } @@ -1854,6 +1847,12 @@ void GdbEngine::handleHasPython(const GdbResponse &response) void GdbEngine::handlePythonSetup(const GdbResponse &response) { if (response.resultClass == GdbResultDone) { + const QString commands = debuggerCore()->stringSetting(GdbCustomDumperCommands); + if (!commands.isEmpty()) { + postCommand(commands.toLocal8Bit()); + postCommand("bbsetup"); + } + postCommand("python qqStringCutOff = " + debuggerCore()->action(MaximalStringLength)->value().toByteArray(), ConsoleCommand|NonCriticalResponse); @@ -2413,7 +2412,6 @@ void GdbEngine::handleExecuteReturn(const GdbResponse &response) } /*! - \fn void Debugger::Internal::GdbEngine::setTokenBarrier() \brief Discard the results of all pending watch-updating commands. This method is called at the beginning of all step/next/finish etc. @@ -2421,7 +2419,6 @@ void GdbEngine::handleExecuteReturn(const GdbResponse &response) If non-watch-updating commands with call-backs are still in the pipe, it will complain. */ - void GdbEngine::setTokenBarrier() { //QTC_ASSERT(m_nonDiscardableCount == 0, /**/); @@ -4972,6 +4969,7 @@ void GdbEngine::tryLoadPythonDumpers() postCommand("python execfile('" + dumperSourcePath + "gbridge.py')", ConsoleCommand, CB(handlePythonSetup)); + } void GdbEngine::reloadDebuggingHelpers() diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index e65711ab1e..578b402739 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -72,6 +72,8 @@ public: QTextEdit *textEditStartupCommands; QGroupBox *groupBoxPostAttachCommands; QTextEdit *textEditPostAttachCommands; + QGroupBox *groupBoxCustomDumperCommands; + QTextEdit *textEditCustomDumperCommands; //QGroupBox *groupBoxPluginDebugging; //QRadioButton *radioButtonAllPluginBreakpoints; @@ -167,20 +169,21 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) "<b>Note:</b>This feature needs special support from the Linux " "distribution and GDB build and is not everywhere available.</p></body></html>")); - groupBoxStartupCommands = new QGroupBox(this); - groupBoxStartupCommands->setTitle(GdbOptionsPage::tr("Additional Startup Commands")); - groupBoxStartupCommands->setToolTip(GdbOptionsPage::tr( - "<html><head/><body><p>GDB commands entered here will be executed after " - "GDB has been started and the debugging helpers have been initialized.</p>" - "<p>You can add commands to load further debugging helpers here, or " - "modify existing ones.</p>" + QString howToUsePython = GdbOptionsPage::tr( "<p>To execute simple Python commands, prefix them with \"python\".</p>" "<p>To execute sequences of Python commands spanning multiple lines " "prepend the block with \"python\" on a separate line, and append " "\"end\" on a separate line.</p>" "<p>To execute arbitrary Python scripts, " - "use <i>python execfile('/path/to/script.py')</i>.</p>" - "</body></html>")); + "use <i>python execfile('/path/to/script.py')</i>.</p>"); + + groupBoxStartupCommands = new QGroupBox(this); + groupBoxStartupCommands->setTitle(GdbOptionsPage::tr("Additional Startup Commands")); + groupBoxStartupCommands->setToolTip(GdbOptionsPage::tr( + "<html><head/><body><p>GDB commands entered here will be executed after " + "GDB has been started, but before the debugged program is started or " + "attached, and before the debugging helpers are initialized.</p>%1" + "</body></html>").arg(howToUsePython)); textEditStartupCommands = new QTextEdit(groupBoxStartupCommands); textEditStartupCommands->setAcceptRichText(false); @@ -199,6 +202,18 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) textEditPostAttachCommands->setAcceptRichText(false); textEditPostAttachCommands->setToolTip(groupBoxPostAttachCommands->toolTip()); + groupBoxCustomDumperCommands = new QGroupBox(this); + groupBoxCustomDumperCommands->setTitle(GdbOptionsPage::tr("Debugging Helper Customization")); + groupBoxCustomDumperCommands->setToolTip(GdbOptionsPage::tr( + "<html><head/><body><p>GDB commands entered here will be executed after " + "Qt Creator's debugging helpers have been loaded and fully initialized. " + "You can load additional debugging helpers or modify existing ones here.</p>" + "%1</body></html>").arg(howToUsePython)); + + textEditCustomDumperCommands = new QTextEdit(groupBoxStartupCommands); + textEditCustomDumperCommands->setAcceptRichText(false); + textEditCustomDumperCommands->setToolTip(groupBoxStartupCommands->toolTip()); + /* groupBoxPluginDebugging = new QGroupBox(q); groupBoxPluginDebugging->setTitle(GdbOptionsPage::tr( @@ -242,6 +257,9 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) QGridLayout *postAttachLayout = new QGridLayout(groupBoxPostAttachCommands); postAttachLayout->addWidget(textEditPostAttachCommands, 0, 0, 1, 1); + QGridLayout *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); @@ -251,6 +269,7 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) 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); //gridLayout->addWidget(groupBoxStartupCommands, 0, 1, 1, 1); //gridLayout->addWidget(radioButtonAllPluginBreakpoints, 0, 0, 1, 1); @@ -262,6 +281,7 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent) DebuggerCore *dc = debuggerCore(); group.insert(dc->action(GdbStartupCommands), textEditStartupCommands); + group.insert(dc->action(GdbCustomDumperCommands), textEditCustomDumperCommands); group.insert(dc->action(GdbPostAttachCommands), textEditPostAttachCommands); group.insert(dc->action(LoadGdbInit), checkBoxLoadGdbInit); group.insert(dc->action(LoadGdbDumpers), checkBoxLoadGdbDumpers); diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 2b3af11a48..1e0d7bbd58 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -164,6 +164,8 @@ void LldbEngine::setupInferior() { QString executable = QFileInfo(startParameters().executable).absoluteFilePath(); runCommand(Command("setupInferior").arg("executable", executable)); + + requestUpdateWatchers(); } void LldbEngine::runEngine() @@ -676,18 +678,16 @@ void LldbEngine::updateAll() // ////////////////////////////////////////////////////////////////////// -void LldbEngine::assignValueInDebugger(const Internal::WatchData *, const QString &expression, const QVariant &value) +void LldbEngine::assignValueInDebugger(const Internal::WatchData *data, + const QString &expression, const QVariant &value) { - Q_UNUSED(expression); - Q_UNUSED(value); - //SDEBUG("ASSIGNING: " << (expression + QLatin1Char('=') + value.toString())); -#if 0 - m_scriptEngine->evaluate(expression + QLatin1Char('=') + value.toString()); - updateLocals(); -#endif + Q_UNUSED(data); + Command cmd("assignValue"); + cmd.arg("exp", expression.toLatin1().toHex()); + cmd.arg("value", value.toString().toLatin1().toHex()); + runCommand(cmd); } - void LldbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags) { Q_UNUSED(data); @@ -699,12 +699,13 @@ void LldbEngine::updateLocals() { WatchHandler *handler = watchHandler(); + //requestUpdateWatchers(); + Command cmd("updateData"); cmd.arg("expanded", handler->expansionRequests()); cmd.arg("typeformats", handler->typeFormatRequests()); cmd.arg("formats", handler->individualFormatRequests()); - QList<QByteArray> watcherData; // const QString fileName = stackHandler()->currentFrame().file; // if (!fileName.isEmpty()) { // const QString function = stackHandler()->currentFrame().function; @@ -739,18 +740,8 @@ void LldbEngine::updateLocals() // } // } - QHashIterator<QByteArray, int> it(handler->watcherNames()); - while (it.hasNext()) { - it.next(); - QHash<QByteArray, QByteArray> hash; - hash["exp"] = '\'' + it.key() + '\''; - hash["id"] = "'watch." + QByteArray::number(it.value()) + '\''; - watcherData.append(Command::toData(hash)); - } - cmd.args.append("'watchers':" + Command::toData(watcherData) + ','); - const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty(); - cmd.arg("passexeptions", alwaysVerbose); + cmd.arg("passexceptions", alwaysVerbose); cmd.arg("fancy", debuggerCore()->boolSetting(UseDebuggingHelpers)); cmd.arg("autoderef", debuggerCore()->boolSetting(AutoDerefPointers)); cmd.arg("dyntype", debuggerCore()->boolSetting(UseDynamicType)); @@ -839,58 +830,21 @@ void LldbEngine::readLldbStandardOutput() } } -QByteArray LldbEngine::currentOptions() const +void LldbEngine::requestUpdateWatchers() { - QByteArray localsOptions; - QByteArray stackOptions; - QByteArray threadsOptions; - - { - QByteArray watchers; - //if (!m_toolTipExpression.isEmpty()) - // watchers += m_toolTipExpression.toLatin1() - // + '#' + tooltipINameForExpression(m_toolTipExpression.toLatin1()); - - WatchHandler *handler = watchHandler(); - QHash<QByteArray, int> watcherNames = handler->watcherNames(); - QHashIterator<QByteArray, int> it(watcherNames); - while (it.hasNext()) { - it.next(); - if (!watchers.isEmpty()) - watchers += "##"; - watchers += it.key() + "#watch." + QByteArray::number(it.value()); - } - - QByteArray options; - if (debuggerCore()->boolSetting(UseDebuggingHelpers)) - options += "fancy,"; - if (debuggerCore()->boolSetting(AutoDerefPointers)) - options += "autoderef,"; - if (options.isEmpty()) - options += "defaults,"; - options.chop(1); - - localsOptions = "options:" + options + " " - + "vars: " - + "expanded:" + handler->expansionRequests() + " " - + "typeformats:" + handler->typeFormatRequests() + " " - + "formats:" + handler->individualFormatRequests() + " " - + "watcher:" + watchers.toHex(); - } - - { - int maxdepth = debuggerCore()->action(MaximalStackDepth)->value().toInt(); - ThreadId curthread = threadsHandler()->currentThread(); - stackOptions += "maxdepth:" + QByteArray::number(maxdepth); - stackOptions += ",curthread:" + QByteArray::number(curthread.raw()); + WatchHandler *handler = watchHandler(); + QHashIterator<QByteArray, int> it(handler->watcherNames()); + QList<QByteArray> watcherData; + while (it.hasNext()) { + it.next(); + QHash<QByteArray, QByteArray> hash; + hash["iname"] = "'watch." + QByteArray::number(it.value()) + '\''; + hash["exp"] = '\'' + it.key().toHex() + '\''; + watcherData.append(Command::toData(hash)); } - - QByteArray result; - result += "\"locals\":\"" + localsOptions + '"'; - result += ",\"stack\":\"" + stackOptions + '"'; - result += ",\"threads\":\"" + threadsOptions + '"'; - - return result; + Command cmd("setWatchers"); + cmd.args.append("'watchers':" + Command::toData(watcherData) + ','); + runCommand(cmd); } void LldbEngine::refreshLocals(const GdbMi &vars) @@ -911,10 +865,9 @@ void LldbEngine::refreshLocals(const GdbMi &vars) dummy.iname = child["iname"].data(); GdbMi wname = child["wname"]; if (wname.isValid()) { - // Happens (only) for watched expressions. They are encoded as - // base64 encoded 8 bit data, without quotes - dummy.name = decodeData(wname.data(), Base64Encoded8Bit); - dummy.exp = dummy.name.toUtf8(); + // Happens (only) for watched expressions. + dummy.exp = QByteArray::fromHex(wname.data()); + dummy.name = QString::fromUtf8(dummy.exp); } else { dummy.name = child["name"].toUtf8(); } diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index fe44c1940a..ff239aeee3 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -134,6 +134,7 @@ private: bool supportsThreads() const { return true; } bool isSynchronous() const { return true; } void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); + void requestUpdateWatchers(); void setRegisterValue(int regnr, const QString &value); void fetchMemory(Internal::MemoryAgent *, QObject *, quint64 addr, quint64 length); @@ -171,7 +172,6 @@ private: typedef void (LldbEngine::*LldbCommandContinuation)(); - QByteArray currentOptions() const; void handleStop(const QByteArray &response); void handleListLocals(const QByteArray &response); void handleListModules(const QByteArray &response); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index d3384f6472..323f196ad9 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -632,7 +632,7 @@ void QmlEngine::notifyEngineRemoteServerRunning(const QByteArray &serverChannel, if (ok) startParameters().qmlServerPort = qmlPort; else - qWarning() << tr("QML debugging port not set! Unable to convert %1 to unsigned int.").arg(QString::fromLatin1(serverChannel)); + qWarning() << tr("QML debugging port not set: Unable to convert %1 to unsigned int.").arg(QString::fromLatin1(serverChannel)); DebuggerEngine::notifyEngineRemoteServerRunning(serverChannel, pid); notifyEngineSetupOk(); diff --git a/src/plugins/debugger/qml/qmlinspectoradapter.cpp b/src/plugins/debugger/qml/qmlinspectoradapter.cpp index c2cd81e0d5..20d9219b6a 100644 --- a/src/plugins/debugger/qml/qmlinspectoradapter.cpp +++ b/src/plugins/debugger/qml/qmlinspectoradapter.cpp @@ -472,17 +472,7 @@ void QmlInspectorAdapter::jumpToObjectDefinitionInEditor( { const QString fileName = m_engine->toFileInProject(objSource.url()); - Core::EditorManager *editorManager = Core::EditorManager::instance(); - Core::IEditor *editor = editorManager->openEditor(fileName); - TextEditor::ITextEditor *textEditor - = qobject_cast<TextEditor::ITextEditor*>(editor); - - if (textEditor) { - editorManager->addCurrentPositionToNavigationHistory(); - textEditor->gotoLine(objSource.lineNumber()); - textEditor->widget()->setFocus(); - } - + Core::EditorManager::openEditorAt(fileName, objSource.lineNumber()); if (debugId != -1 && debugId != m_currentSelectedDebugId) { m_currentSelectedDebugId = debugId; m_currentSelectedDebugName = agent()->displayName(debugId); diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index a250660763..43106b36aa 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -232,9 +232,9 @@ static int memberVariableRecursion(const QAbstractItemModel *model, return childCount; } -/*! - \fn variableMemoryMarkup() +typedef QList<MemoryMarkup> MemoryMarkupList; +/*! \brief Creates markup for a variable in the memory view. Marks the visible children with alternating colors in the parent, that is, for @@ -272,9 +272,6 @@ static int memberVariableRecursion(const QAbstractItemModel *model, \sa Debugger::Internal::MemoryViewWidget */ - -typedef QList<MemoryMarkup> MemoryMarkupList; - static MemoryMarkupList variableMemoryMarkup(const QAbstractItemModel *model, const QModelIndex &modelIndex, diff --git a/src/plugins/designer/formeditorfactory.cpp b/src/plugins/designer/formeditorfactory.cpp index 736a033d47..3da34f486a 100644 --- a/src/plugins/designer/formeditorfactory.cpp +++ b/src/plugins/designer/formeditorfactory.cpp @@ -66,23 +66,15 @@ QString FormEditorFactory::displayName() const return qApp->translate("Designer", C_DESIGNER_XML_DISPLAY_NAME); } -Core::IDocument *FormEditorFactory::open(const QString &fileName) +Core::IEditor *FormEditorFactory::createEditor(QWidget *parent) { - Core::IEditor *iface = Core::EditorManager::openEditor(fileName, id()); - if (!iface) - return 0; - if (qobject_cast<FormWindowEditor *>(iface)) { + const EditorData data = FormEditorW::instance()->createEditor(parent); + if (data.formWindowEditor) { Core::InfoBarEntry info(Core::Id(Constants::INFO_READ_ONLY), tr("This file can only be edited in <b>Design</b> mode.")); info.setCustomButtonInfo(tr("Switch mode"), this, SLOT(designerModeClicked())); - iface->document()->infoBar()->addInfo(info); + data.formWindowEditor->document()->infoBar()->addInfo(info); } - return iface->document(); -} - -Core::IEditor *FormEditorFactory::createEditor(QWidget *parent) -{ - const EditorData data = FormEditorW::instance()->createEditor(parent); return data.formWindowEditor; } diff --git a/src/plugins/designer/formeditorfactory.h b/src/plugins/designer/formeditorfactory.h index 602d663025..d1183fbfc5 100644 --- a/src/plugins/designer/formeditorfactory.h +++ b/src/plugins/designer/formeditorfactory.h @@ -48,7 +48,6 @@ public: QStringList mimeTypes() const; Core::Id id() const; QString displayName() const; - Core::IDocument *open(const QString &fileName); Core::IEditor *createEditor(QWidget *parent); private slots: diff --git a/src/plugins/designer/formeditorw.cpp b/src/plugins/designer/formeditorw.cpp index 5bedf6a41c..e435c95cdb 100644 --- a/src/plugins/designer/formeditorw.cpp +++ b/src/plugins/designer/formeditorw.cpp @@ -912,7 +912,7 @@ void FormEditorW::switchSourceForm() { const QString fileToOpen = otherFile(); if (!fileToOpen.isEmpty()) - Core::EditorManager::openEditor(fileToOpen, Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(fileToOpen); } } // namespace Internal diff --git a/src/plugins/designer/formwindoweditor.cpp b/src/plugins/designer/formwindoweditor.cpp index 6ed794e19c..d6234089ee 100644 --- a/src/plugins/designer/formwindoweditor.cpp +++ b/src/plugins/designer/formwindoweditor.cpp @@ -259,9 +259,9 @@ TextEditor::PlainTextEditor *FormWindowEditor::textEditor() return &d->m_textEditor; } -Core::Id FormWindowEditor::preferredModeType() const +bool FormWindowEditor::isDesignModePreferred() const { - return Core::Id(Core::Constants::MODE_DESIGN_TYPE); + return true; } } // namespace Designer diff --git a/src/plugins/designer/formwindoweditor.h b/src/plugins/designer/formwindoweditor.h index 05f8f786fa..a04f417d16 100644 --- a/src/plugins/designer/formwindoweditor.h +++ b/src/plugins/designer/formwindoweditor.h @@ -81,7 +81,7 @@ public: virtual QWidget *toolBar(); - virtual Core::Id preferredModeType() const; + virtual bool isDesignModePreferred() const; // For uic code model support QString contents() const; diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp index 3b1395159f..956c1bc51d 100644 --- a/src/plugins/designer/qtcreatorintegration.cpp +++ b/src/plugins/designer/qtcreatorintegration.cpp @@ -270,7 +270,9 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line) static inline ITextEditor *editableAt(const QString &fileName, int line, int column) { - return qobject_cast<ITextEditor *>(TextEditor::BaseTextEditorWidget::openEditorAt(fileName, line, column)); + return qobject_cast<ITextEditor *>(Core::EditorManager::openEditorAt(fileName, line, column, + Core::Id(), + Core::EditorManager::DoNotMakeVisible)); } static void addDeclaration(const Snapshot &snapshot, @@ -626,7 +628,7 @@ bool QtCreatorIntegration::navigateToSlot(const QString &objectName, } // jump to function definition, position within code - TextEditor::BaseTextEditorWidget::openEditorAt(sourceDoc->fileName(), line + 2, indentation); + Core::EditorManager::openEditorAt(sourceDoc->fileName(), line + 2, indentation); return true; } diff --git a/src/plugins/diffeditor/diffeditoreditable.cpp b/src/plugins/diffeditor/diffeditor.cpp index 50f1f0f2e7..381339e2f3 100644 --- a/src/plugins/diffeditor/diffeditoreditable.cpp +++ b/src/plugins/diffeditor/diffeditor.cpp @@ -27,12 +27,14 @@ ** ****************************************************************************/ -#include "diffeditoreditable.h" +#include "diffeditor.h" #include "diffeditorfile.h" #include "diffeditorwidget.h" #include "diffeditorconstants.h" #include <coreplugin/icore.h> +#include <coreplugin/coreconstants.h> + #include <QCoreApplication> #include <QToolButton> #include <QSpinBox> @@ -45,9 +47,9 @@ namespace DiffEditor { -///////////////////////////////// DiffEditorEditable ////////////////////////////////// +///////////////////////////////// DiffEditor ////////////////////////////////// -DiffEditorEditable::DiffEditorEditable(DiffEditorWidget *editorWidget) +DiffEditor::DiffEditor(DiffEditorWidget *editorWidget) : IEditor(0), m_file(new Internal::DiffEditorFile(QLatin1String(Constants::DIFF_EDITOR_MIMETYPE), this)), m_editorWidget(editorWidget), @@ -59,20 +61,20 @@ DiffEditorEditable::DiffEditorEditable(DiffEditorWidget *editorWidget) this, SLOT(activateEntry(int))); } -DiffEditorEditable::~DiffEditorEditable() +DiffEditor::~DiffEditor() { delete m_toolWidget; if (m_widget) delete m_widget; } -bool DiffEditorEditable::createNew(const QString &contents) +bool DiffEditor::createNew(const QString &contents) { Q_UNUSED(contents) return true; } -bool DiffEditorEditable::open(QString *errorString, const QString &fileName, const QString &realFileName) +bool DiffEditor::open(QString *errorString, const QString &fileName, const QString &realFileName) { Q_UNUSED(errorString) Q_UNUSED(fileName) @@ -80,25 +82,25 @@ bool DiffEditorEditable::open(QString *errorString, const QString &fileName, con return true; } -Core::IDocument *DiffEditorEditable::document() +Core::IDocument *DiffEditor::document() { return m_file; } -QString DiffEditorEditable::displayName() const +QString DiffEditor::displayName() const { if (m_displayName.isEmpty()) m_displayName = QCoreApplication::translate("DiffEditor", Constants::DIFF_EDITOR_DISPLAY_NAME); return m_displayName; } -void DiffEditorEditable::setDisplayName(const QString &title) +void DiffEditor::setDisplayName(const QString &title) { m_displayName = title; emit changed(); } -Core::Id DiffEditorEditable::id() const +Core::Id DiffEditor::id() const { return Constants::DIFF_EDITOR_ID; } @@ -114,7 +116,7 @@ static QToolBar *createToolBar(const QWidget *someWidget) return toolBar; } -QWidget *DiffEditorEditable::toolBar() +QWidget *DiffEditor::toolBar() { if (m_toolWidget) return m_toolWidget; @@ -140,20 +142,33 @@ QWidget *DiffEditorEditable::toolBar() m_editorWidget, SLOT(setIgnoreWhitespaces(bool))); m_toolWidget->addWidget(whitespaceButton); - QLabel *contextLabel = new QLabel(tr("Context lines:"), m_toolWidget); + QLabel *contextLabel = new QLabel(m_toolWidget); + contextLabel->setText(tr("Context Lines:")); + contextLabel->setContentsMargins(6, 0, 6, 0); m_toolWidget->addWidget(contextLabel); QSpinBox *contextSpinBox = new QSpinBox(m_toolWidget); contextSpinBox->setRange(-1, 100); contextSpinBox->setValue(3); + contextSpinBox->setFrame(false); + contextSpinBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); // Mac Qt5 connect(contextSpinBox, SIGNAL(valueChanged(int)), m_editorWidget, SLOT(setContextLinesNumber(int))); m_toolWidget->addWidget(contextSpinBox); + QToolButton *toggleSync = new QToolButton(m_toolWidget); + toggleSync->setIcon(QIcon(QLatin1String(Core::Constants::ICON_LINK))); + toggleSync->setCheckable(true); + toggleSync->setChecked(true); + toggleSync->setToolTip(tr("Synchronize Horizontal Scroll Bars")); + connect(toggleSync, SIGNAL(clicked(bool)), + m_editorWidget, SLOT(setHorizontalScrollBarSynchronization(bool))); + m_toolWidget->addWidget(toggleSync); + return m_toolWidget; } -void DiffEditorEditable::setDiff(const QList<DiffEditorWidget::DiffFilesContents> &diffFileList, +void DiffEditor::setDiff(const QList<DiffEditorWidget::DiffFilesContents> &diffFileList, const QString &workingDirectory) { m_entriesComboBox->clear(); @@ -197,27 +212,27 @@ void DiffEditorEditable::setDiff(const QList<DiffEditorWidget::DiffFilesContents m_editorWidget->setDiff(diffFileList, workingDirectory); } -void DiffEditorEditable::clear(const QString &message) +void DiffEditor::clear(const QString &message) { m_entriesComboBox->clear(); updateEntryToolTip(); m_editorWidget->clear(message); } -void DiffEditorEditable::updateEntryToolTip() +void DiffEditor::updateEntryToolTip() { const QString &toolTip = m_entriesComboBox->itemData( m_entriesComboBox->currentIndex(), Qt::ToolTipRole).toString(); m_entriesComboBox->setToolTip(toolTip); } -void DiffEditorEditable::entryActivated(int index) +void DiffEditor::entryActivated(int index) { updateEntryToolTip(); m_editorWidget->navigateToDiffFile(index); } -void DiffEditorEditable::activateEntry(int index) +void DiffEditor::activateEntry(int index) { m_entriesComboBox->blockSignals(true); m_entriesComboBox->setCurrentIndex(index); diff --git a/src/plugins/diffeditor/diffeditoreditable.h b/src/plugins/diffeditor/diffeditor.h index 8a0aff264e..498a909065 100644 --- a/src/plugins/diffeditor/diffeditoreditable.h +++ b/src/plugins/diffeditor/diffeditor.h @@ -47,12 +47,12 @@ namespace Internal { class DiffEditorFile; } -class DIFFEDITOR_EXPORT DiffEditorEditable : public Core::IEditor +class DIFFEDITOR_EXPORT DiffEditor : public Core::IEditor { Q_OBJECT public: - explicit DiffEditorEditable(DiffEditorWidget *editorWidget); - virtual ~DiffEditorEditable(); + explicit DiffEditor(DiffEditorWidget *editorWidget); + virtual ~DiffEditor(); public: void setDiff(const QList<DiffEditorWidget::DiffFilesContents> &diffFileList, diff --git a/src/plugins/diffeditor/diffeditor.pro b/src/plugins/diffeditor/diffeditor.pro index 2d6b13fc23..0976171af7 100644 --- a/src/plugins/diffeditor/diffeditor.pro +++ b/src/plugins/diffeditor/diffeditor.pro @@ -3,13 +3,13 @@ include(../../qtcreatorplugin.pri) HEADERS += diffeditor_global.h \ diffeditorconstants.h \ - diffeditoreditable.h \ + diffeditor.h \ diffeditorfile.h \ diffeditorplugin.h \ diffeditorwidget.h \ differ.h -SOURCES += diffeditoreditable.cpp \ +SOURCES += diffeditor.cpp \ diffeditorfile.cpp \ diffeditorplugin.cpp \ diffeditorwidget.cpp \ diff --git a/src/plugins/diffeditor/diffeditor.qbs b/src/plugins/diffeditor/diffeditor.qbs index 1b1d5fd974..e4afa534f4 100644 --- a/src/plugins/diffeditor/diffeditor.qbs +++ b/src/plugins/diffeditor/diffeditor.qbs @@ -14,8 +14,8 @@ QtcPlugin { files: [ "diffeditor_global.h", "diffeditorconstants.h", - "diffeditoreditable.cpp", - "diffeditoreditable.h", + "diffeditor.cpp", + "diffeditor.h", "diffeditorfile.cpp", "diffeditorfile.h", "diffeditorplugin.cpp", diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 2fe3618574..6ca9090f03 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -28,7 +28,7 @@ ****************************************************************************/ #include "diffeditorplugin.h" -#include "diffeditoreditable.h" +#include "diffeditor.h" #include "diffeditorwidget.h" #include "diffeditorconstants.h" @@ -67,7 +67,7 @@ QString DiffEditorFactory::displayName() const Core::IEditor *DiffEditorFactory::createEditor(QWidget *parent) { DiffEditorWidget *editorWidget = new DiffEditorWidget(parent); - DiffEditorEditable *editor = new DiffEditorEditable(editorWidget); + DiffEditor *editor = new DiffEditor(editorWidget); return editor; } @@ -136,15 +136,15 @@ void DiffEditorPlugin::diff() const Core::Id editorId = Constants::DIFF_EDITOR_ID; //: Editor title QString title = tr("Diff \"%1\", \"%2\"").arg(fileName1).arg(fileName2); - DiffEditorEditable *editorEditable = qobject_cast<DiffEditorEditable *> + DiffEditor *editor = qobject_cast<DiffEditor *> (Core::EditorManager::openEditorWithContents(editorId, &title, QString())); - if (!editorEditable) + if (!editor) return; - Core::EditorManager::activateEditor(editorEditable, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(editor); - DiffEditorWidget *editorWidget = editorEditable->editorWidget(); + DiffEditorWidget *editorWidget = editor->editorWidget(); const QString text1 = getFileContents(fileName1, editorWidget->codec()); const QString text2 = getFileContents(fileName2, editorWidget->codec()); @@ -157,7 +157,7 @@ void DiffEditorPlugin::diff() QList<DiffEditorWidget::DiffFilesContents> list; list.append(dfc); - editorEditable->setDiff(list); + editor->setDiff(list); } QString DiffEditorPlugin::getFileContents(const QString &fileName, QTextCodec *codec) const diff --git a/src/plugins/diffeditor/diffeditorwidget.cpp b/src/plugins/diffeditor/diffeditorwidget.cpp index c2579fdec8..4bce0b3466 100644 --- a/src/plugins/diffeditor/diffeditorwidget.cpp +++ b/src/plugins/diffeditor/diffeditorwidget.cpp @@ -43,6 +43,7 @@ #include <texteditor/syntaxhighlighter.h> #include <texteditor/basetextdocument.h> #include <texteditor/texteditorsettings.h> +#include <texteditor/displaysettings.h> #include <coreplugin/minisplitter.h> @@ -138,6 +139,9 @@ public: void clearAllData(); QTextBlock firstVisibleBlock() const { return SnippetEditorWidget::firstVisibleBlock(); } +public slots: + void setDisplaySettings(const DisplaySettings &ds); + protected: virtual int extraAreaWidth(int *markWidthPtr = 0) const { return BaseTextEditorWidget::extraAreaWidth(markWidthPtr); } BaseTextEditor *createEditor() { return new DiffViewEditorEditable(this); } @@ -174,11 +178,26 @@ private: DiffViewEditorWidget::DiffViewEditorWidget(QWidget *parent) : SnippetEditorWidget(parent), m_lineNumberDigits(1), m_inPaintEvent(false) { - setLineNumbersVisible(true); + DisplaySettings settings = displaySettings(); + settings.m_textWrapping = false; + settings.m_displayLineNumbers = true; + settings.m_highlightCurrentLine = false; + settings.m_displayFoldingMarkers = true; + settings.m_markTextChanges = false; + settings.m_highlightBlocks = false; + SnippetEditorWidget::setDisplaySettings(settings); + setCodeFoldingSupported(true); setFrameStyle(QFrame::NoFrame); } +void DiffViewEditorWidget::setDisplaySettings(const DisplaySettings &ds) +{ + DisplaySettings settings = displaySettings(); + settings.m_visualizeWhitespace = ds.m_visualizeWhitespace; + SnippetEditorWidget::setDisplaySettings(settings); +} + QString DiffViewEditorWidget::lineNumber(int blockNumber) const { if (m_lineNumbers.contains(blockNumber)) @@ -355,7 +374,7 @@ void DiffViewEditorWidget::jumpToOriginalFile(const QTextCursor &cursor) const QDir dir(m_workingDirectory); const QString fileName = dir.absoluteFilePath(it.value().fileName); - Core::IEditor *ed = Core::EditorManager::openEditor(fileName, Core::Id(), Core::EditorManager::ModeSwitch); + Core::IEditor *ed = Core::EditorManager::openEditor(fileName); if (TextEditor::ITextEditor *editor = qobject_cast<TextEditor::ITextEditor *>(ed)) editor->gotoLine(lineNr, position); } @@ -514,33 +533,25 @@ DiffEditorWidget::DiffEditorWidget(QWidget *parent) { TextEditor::TextEditorSettings *settings = TextEditorSettings::instance(); - QToolButton *toggleSync = new QToolButton(); - toggleSync = new QToolButton; - toggleSync->setText(QLatin1String("S")); - toggleSync->setCheckable(true); - toggleSync->setChecked(m_syncScrollBars); - toggleSync->setToolTip(tr("Synchronize Horizontal Scroll Bars")); - toggleSync->setAutoRaise(true); - connect(toggleSync, SIGNAL(clicked(bool)), this, SLOT(toggleScrollBarSynchronization(bool))); - m_leftEditor = new DiffViewEditorWidget(this); m_leftEditor->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_leftEditor->setReadOnly(true); - m_leftEditor->setHighlightCurrentLine(false); - m_leftEditor->setWordWrapMode(QTextOption::NoWrap); connect(settings, SIGNAL(fontSettingsChanged(TextEditor::FontSettings)), m_leftEditor, SLOT(setFontSettings(TextEditor::FontSettings))); m_leftEditor->setFontSettings(settings->fontSettings()); + connect(settings, SIGNAL(displaySettingsChanged(TextEditor::DisplaySettings)), + m_leftEditor, SLOT(setDisplaySettings(TextEditor::DisplaySettings))); + m_leftEditor->setDisplaySettings(settings->displaySettings()); m_leftEditor->setCodeStyle(settings->codeStyle()); m_rightEditor = new DiffViewEditorWidget(this); - m_rightEditor->setCornerWidget(toggleSync); m_rightEditor->setReadOnly(true); - m_rightEditor->setHighlightCurrentLine(false); - m_rightEditor->setWordWrapMode(QTextOption::NoWrap); connect(settings, SIGNAL(fontSettingsChanged(TextEditor::FontSettings)), m_rightEditor, SLOT(setFontSettings(TextEditor::FontSettings))); m_rightEditor->setFontSettings(settings->fontSettings()); + connect(settings, SIGNAL(displaySettingsChanged(TextEditor::DisplaySettings)), + m_rightEditor, SLOT(setDisplaySettings(TextEditor::DisplaySettings))); + m_rightEditor->setDisplaySettings(settings->displaySettings()); m_rightEditor->setCodeStyle(settings->codeStyle()); connect(m_leftEditor->verticalScrollBar(), SIGNAL(valueChanged(int)), @@ -1402,7 +1413,7 @@ void DiffEditorWidget::rightDocumentSizeChanged() synchronizeFoldings(m_rightEditor, m_leftEditor); } -void DiffEditorWidget::toggleScrollBarSynchronization(bool on) +void DiffEditorWidget::setHorizontalScrollBarSynchronization(bool on) { m_syncScrollBars = on; } diff --git a/src/plugins/diffeditor/diffeditorwidget.h b/src/plugins/diffeditor/diffeditorwidget.h index a5057deab6..8e4973c7f6 100644 --- a/src/plugins/diffeditor/diffeditorwidget.h +++ b/src/plugins/diffeditor/diffeditorwidget.h @@ -86,6 +86,7 @@ public: public slots: void setContextLinesNumber(int lines); void setIgnoreWhitespaces(bool ignore); + void setHorizontalScrollBarSynchronization(bool on); void navigateToDiffFile(int diffFileIndex); signals: @@ -104,7 +105,6 @@ private slots: void rightCursorPositionChanged(); void leftDocumentSizeChanged(); void rightDocumentSizeChanged(); - void toggleScrollBarSynchronization(bool on); private: struct DiffList { diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp index ae2a7a31c3..e946ae20da 100644 --- a/src/plugins/fakevim/fakevim_test.cpp +++ b/src/plugins/fakevim/fakevim_test.cpp @@ -786,6 +786,29 @@ void FakeVimPlugin::test_vim_delete() KEYS("\"xd$", X "" N "def"); KEYS("\"xp", "ab" X "c" N "def"); KEYS("2\"xp", "abcabcab" X "c" N "def"); + + /* QTCREATORBUG-9289 */ + data.setText("abc" N "def"); + KEYS("$" "dw", "a" X "b" N "def"); + KEYS("dw", X "a" N "def"); + KEYS("dw", X "" N "def"); + KEYS("dw", X "def"); + + data.setText("abc" N "def ghi"); + KEYS("2dw", X "ghi"); + + data.setText("abc" N X "" N "def"); + KEYS("dw", "abc" N X "def"); + KEYS("k$" "dw", "a" X "b" N "def"); + KEYS("j$h" "dw", "ab" N X "d"); + + data.setText("abc" N "def"); + KEYS("2lvx", "a" X "b" N "def"); + KEYS("vlx", "a" X "def"); + + data.setText("abc" N "def"); + KEYS("2lvox", "a" X "b" N "def"); + KEYS("vlox", "a" X "def"); } void FakeVimPlugin::test_vim_delete_inner_word() diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 6de785baca..695578a9f1 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1502,11 +1502,11 @@ public: int count() const { return mvCount() * opCount(); } QTextBlock block() const { return m_cursor.block(); } int leftDist() const { return position() - block().position(); } - int rightDist() const { return block().length() - leftDist() - 1; } + int rightDist() const { return block().length() - leftDist() - (isVisualCharMode() ? 0 : 1); } bool atBlockStart() const { return m_cursor.atBlockStart(); } bool atBlockEnd() const { return m_cursor.atBlockEnd(); } bool atEndOfLine() const { return atBlockEnd() && block().length() > 1; } - bool atDocumentEnd() const { return position() >= lastPositionInDocument(); } + bool atDocumentEnd() const { return position() >= lastPositionInDocument(true); } bool atDocumentStart() const { return m_cursor.atStart(); } bool atEmptyLine(const QTextCursor &tc = QTextCursor()) const; @@ -1605,7 +1605,14 @@ public: } void moveRight(int n = 1) { //dump("RIGHT 1"); - m_cursor.movePosition(Right, KeepAnchor, n); + if (isVisualCharMode()) { + const QTextBlock currentBlock = block(); + const int max = currentBlock.position() + currentBlock.length() - 1; + const int pos = position() + n; + setPosition(qMin(pos, max)); + } else { + m_cursor.movePosition(Right, KeepAnchor, n); + } if (atEndOfLine()) emit q->fold(1, false); //dump("RIGHT 2"); @@ -2060,7 +2067,8 @@ void FakeVimHandler::Private::leaveFakeVim() // The command might have destroyed the editor. if (m_textedit || m_plaintextedit) { // We fake vi-style end-of-line behaviour - m_fakeEnd = atEndOfLine() && g.mode == CommandMode && !isVisualBlockMode(); + m_fakeEnd = atEndOfLine() && g.m_mode == CommandMode && !isVisualBlockMode() + && !isVisualCharMode(); //QTC_ASSERT(g.mode == InsertMode || g.mode == ReplaceMode // || !atBlockEnd() || block().length() <= 1, @@ -2247,7 +2255,7 @@ void FakeVimHandler::Private::exportSelection() if (visualBlockInverted) setAnchorAndPosition(anc + 1, pos); else - setAnchorAndPosition(anc, pos + 1); + setAnchorAndPosition(anc, pos); if (g.visualMode == VisualBlockMode) { commitCursor(); @@ -2824,6 +2832,23 @@ void FakeVimHandler::Private::fixSelection() if (g.rangemode == RangeBlockMode) return; + if (g.movetype == MoveInclusive) { + // If position or anchor is after end of non-empty line, include line break in selection. + if (document()->characterAt(position()) == ParagraphSeparator) { + if (!atEmptyLine()) { + setPosition(position() + 1); + return; + } + } else if (document()->characterAt(anchor()) == ParagraphSeparator) { + QTextCursor tc = m_cursor; + tc.setPosition(anchor()); + if (!atEmptyLine(tc)) { + setAnchorAndPosition(anchor() + 1, position()); + return; + } + } + } + if (g.movetype == MoveExclusive) { if (anchor() < position() && atBlockStart()) { // Exlusive motion ending at the beginning of line @@ -3529,6 +3554,11 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) g.movetype = MoveInclusive; } else { moveToNextWordStart(count, simple, true); + // Command 'dw' deletes to the next word on the same line or to end of line. + if (m_submode == DeleteSubMode && count == 1) { + const QTextBlock currentBlock = document()->findBlock(anchor()); + setPosition(qMin(position(), currentBlock.position() + currentBlock.length())); + } g.movetype = MoveExclusive; } setTargetColumn(); @@ -7270,10 +7300,9 @@ void FakeVimHandler::Private::redo() void FakeVimHandler::Private::updateCursorShape() { bool thinCursor = g.mode == ExMode - || g.subsubmode == SearchSubSubMode + || g.ubsubmode == SearchSubSubMode || g.mode == InsertMode - || isVisualMode() - || m_cursor.hasSelection(); + || (isVisualMode() && !isVisualCharMode()); EDITOR(setOverwriteMode(!thinCursor)); } @@ -7349,7 +7378,7 @@ void FakeVimHandler::Private::initVisualInsertMode(QChar command) void FakeVimHandler::Private::enterCommandMode(Mode returnToMode) { - if (atEndOfLine()) + if (isNoVisualMode() && atEndOfLine()) moveLeft(); g.mode = CommandMode; clearCommandMode(); diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 235696eda6..3d9c30356a 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -1324,7 +1324,7 @@ void FakeVimPluginPrivate::windowCommand(const QString &map, int count) else if (key == _("S") || key == _("<C-S>")) triggerAction(Core::Constants::SPLIT); else if (key == _("W") || key == _("<C-W>")) - triggerAction(Core::Constants::GOTO_OTHER_SPLIT); + triggerAction(Core::Constants::GOTO_NEXT_SPLIT); else if (key.contains(_("RIGHT")) || key == _("L") || key == _("<S-L>")) moveSomewhere(&moveRightWeight, key == _("<S-L>") ? -1 : count); else if (key.contains(_("LEFT")) || key == _("H") || key == _("<S-H>")) diff --git a/src/plugins/git/Git.mimetypes.xml b/src/plugins/git/Git.mimetypes.xml index c40c30181a..ae51ec2e9b 100644 --- a/src/plugins/git/Git.mimetypes.xml +++ b/src/plugins/git/Git.mimetypes.xml @@ -6,4 +6,9 @@ <glob pattern="COMMIT_MSG"/> <glob pattern="COMMIT_EDITMSG"/> </mime-type> + <mime-type type="text/vnd.qtcreator.git.rebase"> + <sub-class-of type="text/plain"/> + <comment>Git Commit File</comment> + <glob pattern="git-rebase-todo"/> + </mime-type> </mime-info> diff --git a/src/plugins/git/changeselectiondialog.cpp b/src/plugins/git/changeselectiondialog.cpp index 4f0e483750..cc5dc40b22 100644 --- a/src/plugins/git/changeselectiondialog.cpp +++ b/src/plugins/git/changeselectiondialog.cpp @@ -157,7 +157,7 @@ void ChangeSelectionDialog::chooseWorkingDirectory() QString ChangeSelectionDialog::workingDirectory() const { - if (!QDir(m_workingDirEdit->text()).exists()) + if (m_workingDirEdit->text().isEmpty() || !QDir(m_workingDirEdit->text()).exists()) return QString(); return GitPlugin::instance()->gitClient()-> @@ -230,7 +230,6 @@ void ChangeSelectionDialog::recalculateDetails() QString workingDir = workingDirectory(); QPalette palette = m_workingDirEdit->palette(); if (workingDir.isEmpty()) { - m_workingDirEdit->palette(); m_detailsText->setPlainText(tr("Error: Bad working directory.")); palette.setColor(QPalette::Text, Qt::red); m_workingDirEdit->setPalette(palette); diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp index c1687fb797..7522604336 100644 --- a/src/plugins/git/gerrit/gerritplugin.cpp +++ b/src/plugins/git/gerrit/gerritplugin.cpp @@ -106,28 +106,23 @@ private slots: void processReadyReadStandardOutput(); private: - // State enumeration. It starts in 'FetchState' and then - // branches to 'WritePatchFileState', 'CherryPickState' - // or 'CheckoutState' depending on FetchMode. enum State { - FetchState, // Fetch patch - WritePatchFileState, // Write patch to a file + FetchState, DoneState, ErrorState }; void handleError(const QString &message); - void startWritePatchFile(); + void show(); void cherryPick(); + void checkout(); const QSharedPointer<GerritChange> m_change; const QString m_repository; const FetchMode m_fetchMode; const QString m_git; const QSharedPointer<GerritParameters> m_parameters; - QScopedPointer<QTemporaryFile> m_patchFile; - QString m_patchFileName; State m_state; QProcess m_process; QFutureInterface<void> m_progress; @@ -183,7 +178,6 @@ void FetchContext::start() void FetchContext::processFinished(int exitCode, QProcess::ExitStatus es) { - Git::Internal::GitClient *client = Git::Internal::GitPlugin::instance()->gitClient(); if (es != QProcess::NormalExit) { handleError(tr("%1 crashed.").arg(m_git)); return; @@ -192,60 +186,18 @@ void FetchContext::processFinished(int exitCode, QProcess::ExitStatus es) handleError(tr("%1 returned %2.").arg(m_git).arg(exitCode)); return; } - switch (m_state) { - case DoneState: - case ErrorState: - break; - case FetchState: + if (m_state == FetchState) { m_progress.setProgressValue(m_progress.progressValue() + 1); - switch (m_fetchMode) { - case FetchDisplay: - if (client->settings()->boolValue(Git::Internal::GitSettings::useDiffEditorKey)) { - client->show(m_repository, QLatin1String("FETCH_HEAD")); - m_progress.reportFinished(); - m_state = DoneState; - deleteLater(); - } else { - m_state = WritePatchFileState; - startWritePatchFile(); - } - break; - case FetchCherryPick: - case FetchCheckout: - if (m_fetchMode == FetchCherryPick) { - cherryPick(); - } else { - client->synchronousCheckout(m_repository, QLatin1String("FETCH_HEAD")); - } - m_progress.reportFinished(); - m_state = DoneState; - deleteLater(); - break; - } // switch (m_fetchMode) - break; - case WritePatchFileState: - switch (m_fetchMode) { - case FetchDisplay: { - m_patchFileName = m_patchFile->fileName(); - m_patchFile->close(); - m_patchFile.reset(); - m_state = DoneState; - m_progress.reportFinished(); - QString title = QString(QLatin1String("Gerrit patch %1/%2")) - .arg(m_change->number).arg(m_change->currentPatchSet.patchSetNumber); - Core::IEditor *editor = Core::EditorManager::openEditor( - m_patchFileName, Git::Constants::GIT_DIFF_EDITOR_ID); - VcsBase::VcsBaseEditorWidget *vcsEditor = VcsBase::VcsBaseEditorWidget::getVcsBaseEditor(editor); - vcsEditor->setDiffBaseDirectory(m_repository); - vcsEditor->setForceReadOnly(true); - vcsEditor->setDisplayName(title); - deleteLater(); - break; - } - default: - break; - } - break; + if (m_fetchMode == FetchDisplay) + show(); + else if (m_fetchMode == FetchCherryPick) + cherryPick(); + else if (m_fetchMode == FetchCheckout) + checkout(); + + m_progress.reportFinished(); + m_state = DoneState; + deleteLater(); } } @@ -262,10 +214,7 @@ void FetchContext::processReadyReadStandardError() void FetchContext::processReadyReadStandardOutput() { const QByteArray output = m_process.readAllStandardOutput(); - if (m_state == WritePatchFileState) - m_patchFile->write(output); - else - VcsBase::VcsBaseOutputWindow::instance()->append(QString::fromLocal8Bit(output)); + VcsBase::VcsBaseOutputWindow::instance()->append(QString::fromLocal8Bit(output)); } void FetchContext::handleError(const QString &e) @@ -286,42 +235,30 @@ void FetchContext::processError(QProcess::ProcessError e) VcsBase::VcsBaseOutputWindow::instance()->appendError(msg); } -void FetchContext::startWritePatchFile() +void FetchContext::show() { - // Fetch to file in temporary folder. - QString tempPattern = QDir::tempPath(); - if (!tempPattern.endsWith(QLatin1Char('/'))) - tempPattern += QLatin1Char('/'); - tempPattern += QLatin1String("gerrit_") + QString::number(m_change->number) - + QLatin1Char('_') - + QString::number(m_change->currentPatchSet.patchSetNumber) - + QLatin1String("XXXXXX.patch"); - m_patchFile.reset(new QTemporaryFile(tempPattern)); - m_patchFile->setAutoRemove(false); - if (!m_patchFile->open()) { - handleError(tr("Error writing to temporary file.")); - return; - } - VcsBase::VcsBaseOutputWindow::instance()->append(tr("Writing %1...").arg(m_patchFile->fileName())); - QStringList args; - args << QLatin1String("format-patch") << QLatin1String("-1") - << QLatin1String("--stdout") << QLatin1String("FETCH_HEAD"); - VcsBase::VcsBaseOutputWindow::instance()->appendCommand(m_repository, m_git, args); - if (debug) - qDebug() << m_git << args; - m_process.start(m_git, args); - m_process.closeWriteChannel(); + const QString title = QString::number(m_change->number) + QLatin1Char('/') + + QString::number(m_change->currentPatchSet.patchSetNumber); + Git::Internal::GitPlugin::instance()->gitClient()->show( + m_repository, QLatin1String("FETCH_HEAD"), QStringList(), title); } void FetchContext::cherryPick() { // Point user to errors. - VcsBase::VcsBaseOutputWindow::instance()->popup(Core::IOutputPane::ModeSwitch | Core::IOutputPane::WithFocus); - VcsBase::VcsBaseOutputWindow::instance()->append(tr("Cherry-picking %1...").arg(m_patchFileName)); + VcsBase::VcsBaseOutputWindow::instance()->popup(Core::IOutputPane::ModeSwitch + | Core::IOutputPane::WithFocus); Git::Internal::GitPlugin::instance()->gitClient()->synchronousCherryPick( m_repository, QLatin1String("FETCH_HEAD")); } +void FetchContext::checkout() +{ + Git::Internal::GitPlugin::instance()->gitClient()->synchronousCheckout( + m_repository, QLatin1String("FETCH_HEAD")); +} + + GerritPlugin::GerritPlugin(QObject *parent) : QObject(parent) , m_parameters(new GerritParameters) @@ -375,11 +312,8 @@ void GerritPlugin::push() // QScopedPointer is required to delete the dialog when leaving the function GerritPushDialog dialog(topLevel, m_reviewers, Core::ICore::mainWindow()); - if (!dialog.localChangesFound()) { - QMessageBox::warning(Core::ICore::mainWindow(), tr("No Local Changes"), - tr("Change from HEAD appears to be in remote branch already. Aborting.")); + if (!dialog.localChangesFound()) return; - } if (!dialog.valid()) { QMessageBox::warning(Core::ICore::mainWindow(), tr("Initialization Failed"), @@ -416,7 +350,7 @@ void GerritPlugin::push() target += QLatin1Char('/') + topic; args << target; - Git::Internal::GitPlugin::instance()->gitClient()->synchronousPush(topLevel, args); + Git::Internal::GitPlugin::instance()->gitClient()->push(topLevel, args); } // Open or raise the Gerrit dialog window. diff --git a/src/plugins/git/gerrit/gerritpushdialog.cpp b/src/plugins/git/gerrit/gerritpushdialog.cpp index c5c52b602f..9dc42192db 100644 --- a/src/plugins/git/gerrit/gerritpushdialog.cpp +++ b/src/plugins/git/gerrit/gerritpushdialog.cpp @@ -50,28 +50,21 @@ GerritPushDialog::GerritPushDialog(const QString &workingDir, const QString &rev m_ui->repositoryLabel->setText(tr("<b>Local repository:</b> %1").arg( QDir::toNativeSeparators(workingDir))); - m_ui->commitView->init(workingDir, QString(), false); - Git::Internal::GitClient *gitClient = Git::Internal::GitPlugin::instance()->gitClient(); - QString output; - QString error; - QStringList args; - - args << QLatin1String("--no-color") << QLatin1String("--format=%P") - << QLatin1String("HEAD") << QLatin1String("--not")<< QLatin1String("--remotes"); - - if (!gitClient->synchronousLog(m_workingDir, args, &output) || output.isEmpty()) + if (!m_ui->commitView->init(workingDir, QString(), false)) return; - output.chop(1); - if (output.isEmpty()) { + QString earliestCommit = m_ui->commitView->earliestCommit(); + if (earliestCommit.isEmpty()) return; - } else { - output = output.mid(output.lastIndexOf(QLatin1Char('\n')) + 1); - m_localChangesFound = true; - } - args.clear(); - args << QLatin1String("--remotes") << QLatin1String("--contains") << output; + m_localChangesFound = true; + + Git::Internal::GitClient *gitClient = Git::Internal::GitPlugin::instance()->gitClient(); + QString output; + QString error; + QStringList args; + args << QLatin1String("--remotes") << QLatin1String("--contains") + << earliestCommit + QLatin1Char('^'); if (!gitClient->synchronousBranchCmd(m_workingDir, args, &output, &error)) return; diff --git a/src/plugins/git/git.pro b/src/plugins/git/git.pro index 0366c953e1..2a669e6777 100644 --- a/src/plugins/git/git.pro +++ b/src/plugins/git/git.pro @@ -22,7 +22,8 @@ HEADERS += gitplugin.h \ branchadddialog.h \ logchangedialog.h \ mergetool.h \ - branchcheckoutdialog.h + branchcheckoutdialog.h \ + githighlighters.h SOURCES += gitplugin.cpp \ gitclient.cpp \ @@ -46,7 +47,8 @@ SOURCES += gitplugin.cpp \ branchadddialog.cpp \ logchangedialog.cpp \ mergetool.cpp \ - branchcheckoutdialog.cpp + branchcheckoutdialog.cpp \ + githighlighters.cpp FORMS += settingspage.ui \ gitsubmitpanel.ui \ diff --git a/src/plugins/git/git.qbs b/src/plugins/git/git.qbs index 2f8110f8f2..2fdd1b6b96 100644 --- a/src/plugins/git/git.qbs +++ b/src/plugins/git/git.qbs @@ -42,6 +42,8 @@ QtcPlugin { "gitconstants.h", "giteditor.cpp", "giteditor.h", + "githighlighters.cpp", + "githighlighters.h", "gitplugin.cpp", "gitplugin.h", "gitsettings.cpp", diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index ed2172c605..3201097c6b 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -56,8 +56,7 @@ #include <vcsbase/vcsbaseoutputwindow.h> #include <vcsbase/vcsbaseplugin.h> -#include <diffeditor/diffeditorwidget.h> -#include <diffeditor/diffeditoreditable.h> +#include <diffeditor/diffeditor.h> #include <diffeditor/diffeditorconstants.h> #include <QCoreApplication> @@ -108,7 +107,7 @@ public: } }; - GitDiffHandler(DiffEditor::DiffEditorEditable *editor, + GitDiffHandler(DiffEditor::DiffEditor *editor, const QString &gitPath, const QString &workingDirectory, const QProcessEnvironment &environment, @@ -139,7 +138,7 @@ private: void feedEditor(); QString workingTreeContents(const QString &fileName) const; - QPointer<DiffEditor::DiffEditorEditable> m_editor; + QPointer<DiffEditor::DiffEditor> m_editor; const QString m_gitPath; const QString m_workingDirectory; const QProcessEnvironment m_processEnvironment; @@ -170,7 +169,7 @@ inline bool operator<(const GitDiffHandler::Revision &rev1, const GitDiffHandler return rev1.id < rev2.id; } -GitDiffHandler::GitDiffHandler(DiffEditor::DiffEditorEditable *editor, +GitDiffHandler::GitDiffHandler(DiffEditor::DiffEditor *editor, const QString &gitPath, const QString &workingDirectory, const QProcessEnvironment &environment, @@ -649,12 +648,13 @@ public: ~ConflictHandler() { + GitClient *client = GitPlugin::instance()->gitClient(); if (m_commit.isEmpty()) { GitPlugin::instance()->gitVersionControl()->emitRepositoryChanged(m_workingDirectory); - GitPlugin::instance()->gitClient()->endStashScope(m_workingDirectory); + if (client->checkCommandInProgress(m_workingDirectory) == GitClient::NoCommand) + client->endStashScope(m_workingDirectory); } else { - GitPlugin::instance()->gitClient()->handleMergeConflicts( - m_workingDirectory, m_commit, m_command); + client->handleMergeConflicts(m_workingDirectory, m_commit, m_command); } } @@ -794,6 +794,19 @@ QString GitClient::findGitDirForRepository(const QString &repositoryDir) const return res; } +QString GitClient::findRepositoryForGitDir(const QString &gitDir) const +{ + static QHash<QString, QString> gitDirCache; + QString &res = gitDirCache[gitDir]; + if (!res.isEmpty()) + return res; + QByteArray outputText; + QStringList arguments; + arguments << QLatin1String("rev-parse") << QLatin1String("--show-toplevel"); + fullySynchronousGit(gitDir, arguments, &outputText, 0, false); + return QString::fromLocal8Bit(outputText.trimmed()); +} + VcsBase::VcsBaseEditorWidget *GitClient::findExistingVCSEditor(const char *registerDynamicProperty, const QString &dynamicPropertyValue) const { @@ -803,27 +816,36 @@ VcsBase::VcsBaseEditorWidget *GitClient::findExistingVCSEditor(const char *regis return 0; // Exists already - Core::EditorManager::activateEditor(outputEditor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(outputEditor); outputEditor->createNew(m_msgWait); rc = VcsBase::VcsBaseEditorWidget::getVcsBaseEditor(outputEditor); return rc; } -DiffEditor::DiffEditorEditable *GitClient::findExistingDiffEditor(const char *registerDynamicProperty, - const QString &dynamicPropertyValue) const +DiffEditor::DiffEditor *GitClient::findExistingOrOpenNewDiffEditor(const char *registerDynamicProperty, + const QString &dynamicPropertyValue, const QString &titlePattern) const { Core::IEditor *outputEditor = locateEditor(registerDynamicProperty, dynamicPropertyValue); - if (!outputEditor) - return 0; - - // Exists already - Core::EditorManager::activateEditor(outputEditor, Core::EditorManager::ModeSwitch); - outputEditor->createNew(m_msgWait); + if (outputEditor) { + // Exists already + Core::EditorManager::activateEditor(outputEditor); + outputEditor->createNew(m_msgWait); + } - return qobject_cast<DiffEditor::DiffEditorEditable *>(outputEditor); + DiffEditor::DiffEditor *editor = qobject_cast<DiffEditor::DiffEditor *>(outputEditor); + if (!editor) { + const Core::Id editorId = DiffEditor::Constants::DIFF_EDITOR_ID; + QString title = titlePattern; + editor = qobject_cast<DiffEditor::DiffEditor *>( + Core::EditorManager::openEditorWithContents(editorId, &title, m_msgWait)); + editor->document()->setProperty(registerDynamicProperty, dynamicPropertyValue); + Core::EditorManager::activateEditor(editor); // should probably go outside this block + } + return editor; } + /* Create an editor associated to VCS output of a source file/directory * (using the file's codec). Makes use of a dynamic property to find an * existing instance and to reuse it (in case, say, 'git diff foo' is @@ -859,7 +881,7 @@ VcsBase::VcsBaseEditorWidget *GitClient::createVcsEditor(const Core::Id &id, } rc->setForceReadOnly(true); - Core::EditorManager::activateEditor(outputEditor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(outputEditor); if (configWidget) rc->setConfigurationWidget(configWidget); @@ -872,21 +894,13 @@ void GitClient::diff(const QString &workingDirectory, const QStringList &unstagedFileNames, const QStringList &stagedFileNames) { - if (settings()->boolValue(GitSettings::useDiffEditorKey)) { - const Core::Id editorId = DiffEditor::Constants::DIFF_EDITOR_ID; - QString title = tr("Git Diff"); + const QString title = tr("Git Diff"); + const int timeout = settings()->intValue(GitSettings::timeoutKey); - DiffEditor::DiffEditorEditable *editorEditable = findExistingDiffEditor("originalFileName", workingDirectory); - - if (!editorEditable) { - editorEditable = qobject_cast<DiffEditor::DiffEditorEditable *>( - Core::EditorManager::openEditorWithContents(editorId, &title, m_msgWait)); - editorEditable->document()->setProperty("originalFileName", workingDirectory); - Core::EditorManager::activateEditor(editorEditable, Core::EditorManager::ModeSwitch); // should probably go outside this block - } + if (settings()->boolValue(GitSettings::useDiffEditorKey)) { + DiffEditor::DiffEditor *editor = findExistingOrOpenNewDiffEditor("originalFileName", workingDirectory, title); - int timeout = settings()->intValue(GitSettings::timeoutKey); - GitDiffHandler *handler = new GitDiffHandler(editorEditable, gitBinaryPath(), workingDirectory, processEnvironment(), timeout); + GitDiffHandler *handler = new GitDiffHandler(editor, gitBinaryPath(), workingDirectory, processEnvironment(), timeout); if (unstagedFileNames.empty() && stagedFileNames.empty()) { // local repository diff @@ -901,7 +915,6 @@ void GitClient::diff(const QString &workingDirectory, } else { const QString binary = settings()->stringValue(GitSettings::binaryPathKey); const Core::Id editorId = Git::Constants::GIT_DIFF_EDITOR_ID; - const QString title = tr("Git Diff"); VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("originalFileName", workingDirectory); if (!editor) { @@ -927,8 +940,6 @@ void GitClient::diff(const QString &workingDirectory, QStringList cmdArgs; cmdArgs << QLatin1String("diff") << QLatin1String(noColorOption); - int timeout = settings()->intValue(GitSettings::timeoutKey); - if (unstagedFileNames.empty() && stagedFileNames.empty()) { QStringList arguments(cmdArgs); arguments << userDiffArgs; @@ -959,27 +970,18 @@ void GitClient::diff(const QString &workingDirectory, const QStringList &diffArgs, const QString &fileName) { + const QString title = tr("Git Diff \"%1\"").arg(fileName); if (settings()->boolValue(GitSettings::useDiffEditorKey)) { - const Core::Id editorId = DiffEditor::Constants::DIFF_EDITOR_ID; - QString title = tr("Git Diff \"%1\"").arg(fileName); const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, fileName); - - DiffEditor::DiffEditorEditable *editorEditable = findExistingDiffEditor("originalFileName", sourceFile); - if (!editorEditable) { - editorEditable = qobject_cast<DiffEditor::DiffEditorEditable *>( - Core::EditorManager::openEditorWithContents(editorId, &title, m_msgWait)); - editorEditable->document()->setProperty("originalFileName", sourceFile); - Core::EditorManager::activateEditor(editorEditable, Core::EditorManager::ModeSwitch); - } + DiffEditor::DiffEditor *editor = findExistingOrOpenNewDiffEditor("originalFileName", sourceFile, title); if (!fileName.isEmpty()) { int timeout = settings()->intValue(GitSettings::timeoutKey); - GitDiffHandler *handler = new GitDiffHandler(editorEditable, gitBinaryPath(), workingDirectory, processEnvironment(), timeout); + GitDiffHandler *handler = new GitDiffHandler(editor, gitBinaryPath(), workingDirectory, processEnvironment(), timeout); handler->diffFile(fileName); } } else { const Core::Id editorId = Git::Constants::GIT_DIFF_EDITOR_ID; - const QString title = tr("Git Diff \"%1\"").arg(fileName); const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, fileName); VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("originalFileName", sourceFile); @@ -1009,24 +1011,16 @@ void GitClient::diffBranch(const QString &workingDirectory, const QStringList &diffArgs, const QString &branchName) { + const QString title = tr("Git Diff Branch \"%1\"").arg(branchName); if (settings()->boolValue(GitSettings::useDiffEditorKey)) { - const Core::Id editorId = DiffEditor::Constants::DIFF_EDITOR_ID; - QString title = tr("Git Diff Branch \"%1\"").arg(branchName); - - DiffEditor::DiffEditorEditable *editorEditable = findExistingDiffEditor("BranchName", branchName); - if (!editorEditable) { - editorEditable = qobject_cast<DiffEditor::DiffEditorEditable *>( - Core::EditorManager::openEditorWithContents(editorId, &title, m_msgWait)); - editorEditable->document()->setProperty("BranchName", branchName); - Core::EditorManager::activateEditor(editorEditable, Core::EditorManager::ModeSwitch); - } + DiffEditor::DiffEditor *editor = + findExistingOrOpenNewDiffEditor("BranchName", branchName, title); int timeout = settings()->intValue(GitSettings::timeoutKey); - GitDiffHandler *handler = new GitDiffHandler(editorEditable, gitBinaryPath(), workingDirectory, processEnvironment(), timeout); + GitDiffHandler *handler = new GitDiffHandler(editor, gitBinaryPath(), workingDirectory, processEnvironment(), timeout); handler->diffBranch(branchName); } else { const Core::Id editorId = Git::Constants::GIT_DIFF_EDITOR_ID; - const QString title = tr("Git Diff Branch \"%1\"").arg(branchName); const QString sourceFile = VcsBase::VcsBaseEditorWidget::getSource(workingDirectory, QStringList()); VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("BranchName", branchName); @@ -1116,31 +1110,26 @@ static inline QString msgCannotShow(const QString &sha) return GitClient::tr("Cannot describe \"%1\".").arg(sha); } -void GitClient::show(const QString &source, const QString &id, const QStringList &args) +void GitClient::show(const QString &source, const QString &id, + const QStringList &args, const QString &name) { if (!canShow(id)) { outputWindow()->append(msgCannotShow(id)); return; } + const QString title = tr("Git Show \"%1\"").arg(name.isEmpty() ? id : name); + const QFileInfo sourceFi(source); + const QString workDir = sourceFi.isDir() ? sourceFi.absoluteFilePath() : sourceFi.absolutePath(); if (settings()->boolValue(GitSettings::useDiffEditorKey)) { - QString title = tr("Git Show \"%1\"").arg(id); - const Core::Id editorId = DiffEditor::Constants::DIFF_EDITOR_ID; - - DiffEditor::DiffEditorEditable *editorEditable = findExistingDiffEditor("show", id); - - if (!editorEditable) { - editorEditable = qobject_cast<DiffEditor::DiffEditorEditable *>( - Core::EditorManager::openEditorWithContents(editorId, &title, m_msgWait)); - editorEditable->document()->setProperty("show", id); - Core::EditorManager::activateEditor(editorEditable, Core::EditorManager::ModeSwitch); // should probably go outside this block - } + DiffEditor::DiffEditor *editor = findExistingOrOpenNewDiffEditor("show", id, title); int timeout = settings()->intValue(GitSettings::timeoutKey); - GitDiffHandler *handler = new GitDiffHandler(editorEditable, gitBinaryPath(), source, processEnvironment(), timeout); + GitDiffHandler *handler = new GitDiffHandler(editor, gitBinaryPath(), + findRepositoryForDirectory(workDir), + processEnvironment(), timeout); handler->show(id); } else { - const QString title = tr("Git Show \"%1\"").arg(id); const Core::Id editorId = Git::Constants::GIT_DIFF_EDITOR_ID; VcsBase::VcsBaseEditorWidget *editor = findExistingVCSEditor("show", id); if (!editor) @@ -1156,8 +1145,6 @@ void GitClient::show(const QString &source, const QString &id, const QStringList arguments.append(userArgs); arguments << id; - const QFileInfo sourceFi(source); - const QString workDir = sourceFi.isDir() ? sourceFi.absoluteFilePath() : sourceFi.absolutePath(); editor->setDiffBaseDirectory(workDir); executeGit(workDir, arguments, editor); } @@ -1230,7 +1217,7 @@ void GitClient::blame(const QString &workingDirectory, arguments << QLatin1String("--") << fileName; if (!revision.isEmpty()) arguments << revision; - executeGit(workingDirectory, arguments, editor, false, VcsBase::Command::NoReport, lineNumber); + executeGit(workingDirectory, arguments, editor, false, lineNumber); } bool GitClient::synchronousCheckout(const QString &workingDirectory, @@ -2042,7 +2029,6 @@ bool GitClient::synchronousShow(const QString &workingDirectory, const QString & // Retrieve list of files to be cleaned bool GitClient::cleanList(const QString &workingDirectory, const QString &flag, QStringList *files, QString *errorMessage) { - files->clear(); QStringList args; args << QLatin1String("clean") << QLatin1String("--dry-run") << flag; QByteArray outputText; @@ -2065,6 +2051,15 @@ bool GitClient::synchronousCleanList(const QString &workingDirectory, QStringLis { bool res = cleanList(workingDirectory, QLatin1String("-df"), files, errorMessage); res &= cleanList(workingDirectory, QLatin1String("-dXf"), ignoredFiles, errorMessage); + + SubmoduleDataMap submodules = submoduleList(workingDirectory); + foreach (const SubmoduleData &submodule, submodules) { + if (submodule.ignore != QLatin1String("all") + && submodule.ignore != QLatin1String("dirty")) { + res &= synchronousCleanList(workingDirectory + QLatin1Char('/') + submodule.dir, + files, ignoredFiles, errorMessage); + } + } return res; } @@ -2115,15 +2110,13 @@ VcsBase::Command *GitClient::executeGit(const QString &workingDirectory, const QStringList &arguments, VcsBase::VcsBaseEditorWidget* editor, bool useOutputToWindow, - VcsBase::Command::TerminationReportMode tm, - int editorLineNumber, - bool unixTerminalDisabled) + int editorLineNumber) { outputWindow()->appendCommand(workingDirectory, settings()->stringValue(GitSettings::binaryPathKey), arguments); VcsBase::Command *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber); command->addJob(arguments, settings()->intValue(GitSettings::timeoutKey)); - command->setTerminationReportMode(tm); - command->setUnixTerminalDisabled(unixTerminalDisabled); + command->setTerminationReportMode(VcsBase::Command::NoReport); + command->setUnixTerminalDisabled(false); command->execute(); return command; } @@ -2298,14 +2291,14 @@ GitClient::CommandInProgress GitClient::checkCommandInProgress(const QString &wo void GitClient::continueCommandIfNeeded(const QString &workingDirectory) { - switch (checkCommandInProgress(workingDirectory)) { + CommandInProgress command = checkCommandInProgress(workingDirectory); + switch (command) { case Rebase: - continuePreviousGitCommand(workingDirectory, tr("Continue Rebase"), - tr("Continue rebase?"), tr("Continue"), QLatin1String("rebase")); - break; case RebaseMerge: continuePreviousGitCommand(workingDirectory, tr("Continue Rebase"), - tr("Continue rebase?"), tr("Continue"), QLatin1String("rebase"), false); + tr("Rebase is in progress. What do you want to do?"), + tr("Continue"), QLatin1String("rebase"), + command != RebaseMerge); break; case Revert: continuePreviousGitCommand(workingDirectory, tr("Continue Revert"), @@ -2506,6 +2499,16 @@ bool GitClient::getCommitData(const QString &workingDirectory, // Run status. Note that it has exitcode 1 if there are no added files. QString output; + if (commitData.commitType == FixupCommit) { + QStringList arguments; + arguments << QLatin1String("HEAD") << QLatin1String("--not") + << QLatin1String("--remotes") << QLatin1String("-n1"); + synchronousLog(repoDirectory, arguments, &output, errorMessage); + if (output.isEmpty()) { + *errorMessage = msgNoCommits(false); + return false; + } + } const StatusResult status = gitStatus(repoDirectory, ShowAll, &output, errorMessage); switch (status) { case StatusChanged: @@ -2814,16 +2817,13 @@ void GitClient::revert(const QStringList &files, bool revertStaging) } } -bool GitClient::synchronousFetch(const QString &workingDirectory, const QString &remote) +void GitClient::fetch(const QString &workingDirectory, const QString &remote) { QStringList arguments(QLatin1String("fetch")); arguments << (remote.isEmpty() ? QLatin1String("--all") : remote); - // Disable UNIX terminals to suppress SSH prompting. - const unsigned flags = VcsBase::VcsBasePlugin::SshPasswordPrompt|VcsBase::VcsBasePlugin::ShowStdOutInLogWindow - |VcsBase::VcsBasePlugin::ShowSuccessMessage; - const Utils::SynchronousProcessResponse resp = synchronousGit(workingDirectory, arguments, flags); - return resp.result == Utils::SynchronousProcessResponse::Finished; + VcsBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true); + connectRepositoryChanged(workingDirectory, cmd); } bool GitClient::executeAndHandleConflicts(const QString &workingDirectory, @@ -2961,17 +2961,14 @@ void GitClient::subversionLog(const QString &workingDirectory) executeGit(workingDirectory, arguments, editor); } -bool GitClient::synchronousPush(const QString &workingDirectory, const QStringList &pushArgs) +void GitClient::push(const QString &workingDirectory, const QStringList &pushArgs) { - // Disable UNIX terminals to suppress SSH prompting. - const unsigned flags = VcsBase::VcsBasePlugin::SshPasswordPrompt|VcsBase::VcsBasePlugin::ShowStdOutInLogWindow - |VcsBase::VcsBasePlugin::ShowSuccessMessage; QStringList arguments(QLatin1String("push")); if (!pushArgs.isEmpty()) arguments += pushArgs; - const Utils::SynchronousProcessResponse resp = - synchronousGit(workingDirectory, arguments, flags); - return resp.result == Utils::SynchronousProcessResponse::Finished; + + VcsBase::Command *cmd = executeGit(workingDirectory, arguments, 0, true); + connectRepositoryChanged(workingDirectory, cmd); } bool GitClient::synchronousMerge(const QString &workingDirectory, const QString &branch) @@ -3051,6 +3048,11 @@ QString GitClient::msgNoChangedFiles() return tr("There are no modified files."); } +QString GitClient::msgNoCommits(bool includeRemote) +{ + return includeRemote ? tr("No commits were found") : tr("No local commits were found"); +} + void GitClient::stashPop(const QString &workingDirectory, const QString &stash) { QStringList arguments(QLatin1String("stash")); diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 414efe6521..a280ccc34d 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -61,7 +61,7 @@ namespace Utils { } namespace DiffEditor { - class DiffEditorEditable; + class DiffEditor; } namespace Git { @@ -138,6 +138,7 @@ public: QString findRepositoryForDirectory(const QString &dir); QString findGitDirForRepository(const QString &repositoryDir) const; + QString findRepositoryForGitDir(const QString &gitDir) const; void diff(const QString &workingDirectory, const QStringList &diffArgs, const QString &fileName); void diff(const QString &workingDirectory, const QStringList &diffArgs, @@ -237,10 +238,9 @@ public: bool cloneRepository(const QString &directory, const QByteArray &url); QString vcsGetRepositoryURL(const QString &directory); - bool synchronousFetch(const QString &workingDirectory, const QString &remote); + void fetch(const QString &workingDirectory, const QString &remote); bool synchronousPull(const QString &workingDirectory, bool rebase); - bool synchronousPush(const QString &workingDirectory, - const QStringList &pushArgs = QStringList()); + void push(const QString &workingDirectory, const QStringList &pushArgs = QStringList()); bool synchronousMerge(const QString &workingDirectory, const QString &branch); bool canRebase(const QString &workingDirectory) const; bool synchronousRebase(const QString &workingDirectory, @@ -315,12 +315,14 @@ public: void handleMergeConflicts(const QString &workingDir, const QString &commit, const QString &abortCommand); static QString msgNoChangedFiles(); + static QString msgNoCommits(bool includeRemote); static const char *noColorOption; static const char *decorateOption; public slots: - void show(const QString &source, const QString &id, const QStringList &args = QStringList()); + void show(const QString &source, const QString &id, + const QStringList &args = QStringList(), const QString &name = QString()); void saveSettings(); private slots: @@ -332,8 +334,9 @@ private: QTextCodec *getSourceCodec(const QString &file) const; VcsBase::VcsBaseEditorWidget *findExistingVCSEditor(const char *registerDynamicProperty, const QString &dynamicPropertyValue) const; - DiffEditor::DiffEditorEditable *findExistingDiffEditor(const char *registerDynamicProperty, - const QString &dynamicPropertyValue) const; + DiffEditor::DiffEditor *findExistingOrOpenNewDiffEditor(const char *registerDynamicProperty, + const QString &dynamicPropertyValue, + const QString &titlePattern) const; enum CodecType { CodecSource, CodecLogOutput, CodecNone }; VcsBase::VcsBaseEditorWidget *createVcsEditor(const Core::Id &kind, @@ -353,9 +356,7 @@ private: const QStringList &arguments, VcsBase::VcsBaseEditorWidget* editor = 0, bool useOutputToWindow = false, - VcsBase::Command::TerminationReportMode tm = VcsBase::Command::NoReport, - int editorLineNumber = -1, - bool unixTerminalDisabled = false); + int editorLineNumber = -1); // Fully synchronous git execution (QProcess-based). bool fullySynchronousGit(const QString &workingDirectory, diff --git a/src/plugins/git/gitconstants.h b/src/plugins/git/gitconstants.h index 35cf961956..ca311cb5f1 100644 --- a/src/plugins/git/gitconstants.h +++ b/src/plugins/git/gitconstants.h @@ -50,6 +50,9 @@ const char C_GIT_DIFF_EDITOR[] = "Git Diff Editor"; const char GIT_COMMIT_TEXT_EDITOR_ID[] = "Git Commit Editor"; const char GIT_COMMIT_TEXT_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("VCS", "Git Commit Editor"); const char C_GIT_COMMIT_TEXT_EDITOR[] = "Git Commit Editor"; +const char GIT_REBASE_EDITOR_ID[] = "Git Rebase Editor"; +const char GIT_REBASE_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("VCS", "Git Rebase Editor"); +const char C_GIT_REBASE_EDITOR[] = "Git Rebase Editor"; const char C_GITSUBMITEDITOR[] = "Git Submit Editor"; const char GITSUBMITEDITOR_ID[] = "Git Submit Editor"; diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp index 2c6062799b..165b1e7998 100644 --- a/src/plugins/git/giteditor.cpp +++ b/src/plugins/git/giteditor.cpp @@ -35,11 +35,12 @@ #include "gitsettings.h" #include "gitsubmiteditorwidget.h" #include "gitconstants.h" +#include "githighlighters.h" #include <utils/qtcassert.h> #include <vcsbase/vcsbaseoutputwindow.h> #include <texteditor/basetextdocument.h> -#include <QDebug> + #include <QFileInfo> #include <QRegExp> #include <QSet> @@ -231,8 +232,23 @@ void GitEditor::revertChange() void GitEditor::init() { VcsBase::VcsBaseEditorWidget::init(); - if (editor()->id() == Git::Constants::GIT_COMMIT_TEXT_EDITOR_ID) + Core::Id editorId = editor()->id(); + if (editorId == Git::Constants::GIT_COMMIT_TEXT_EDITOR_ID) new GitSubmitHighlighter(baseTextDocument().data()); + else if (editorId == Git::Constants::GIT_REBASE_EDITOR_ID) + new GitRebaseHighlighter(baseTextDocument().data()); +} + +bool GitEditor::open(QString *errorString, const QString &fileName, const QString &realFileName) +{ + bool res = VcsBaseEditorWidget::open(errorString, fileName, realFileName); + Core::Id editorId = editor()->id(); + if (editorId == Git::Constants::GIT_COMMIT_TEXT_EDITOR_ID + || editorId == Git::Constants::GIT_REBASE_EDITOR_ID) { + QFileInfo fi(fileName); + setSource(GitPlugin::instance()->gitClient()->findRepositoryForGitDir(fi.absolutePath())); + } + return res; } QString GitEditor::decorateVersion(const QString &revision) const @@ -284,5 +300,12 @@ QString GitEditor::revisionSubject(const QTextBlock &inBlock) const return QString(); } +bool GitEditor::supportChangeLinks() const +{ + return VcsBaseEditorWidget::supportChangeLinks() + || (editor()->id() == Git::Constants::GIT_COMMIT_TEXT_EDITOR_ID) + || (editor()->id() == Git::Constants::GIT_REBASE_EDITOR_ID); +} + } // namespace Internal } // namespace Git diff --git a/src/plugins/git/giteditor.h b/src/plugins/git/giteditor.h index 5010fd8193..b5539892c9 100644 --- a/src/plugins/git/giteditor.h +++ b/src/plugins/git/giteditor.h @@ -60,6 +60,7 @@ private slots: private: void init(); + bool open(QString *errorString, const QString &fileName, const QString &realFileName); QSet<QString> annotationChanges() const; QString changeUnderCursor(const QTextCursor &) const; VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const; @@ -68,6 +69,7 @@ private: bool isValidRevision(const QString &revision) const; void addChangeActions(QMenu *menu, const QString &change); QString revisionSubject(const QTextBlock &inBlock) const; + bool supportChangeLinks() const; mutable QRegExp m_changeNumberPattern; QString m_currentChange; diff --git a/src/plugins/git/githighlighters.cpp b/src/plugins/git/githighlighters.cpp new file mode 100644 index 0000000000..2f00c9f2db --- /dev/null +++ b/src/plugins/git/githighlighters.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 <texteditor/fontsettings.h> +#include <texteditor/texteditorconstants.h> +#include <texteditor/texteditorsettings.h> + +#include <utils/qtcassert.h> + +#include "githighlighters.h" + +namespace Git { +namespace Internal { + +static const char CHANGE_PATTERN[] = "\\b[a-f0-9]{7,40}\\b"; + +// Retrieve the comment char format from the text editor. +static QTextCharFormat commentFormat() +{ + const TextEditor::FontSettings settings = TextEditor::TextEditorSettings::instance()->fontSettings(); + return settings.toTextCharFormat(TextEditor::C_COMMENT); +} + +GitSubmitHighlighter::GitSubmitHighlighter(QTextEdit * parent) : + TextEditor::SyntaxHighlighter(parent) +{ + initialize(); +} + +GitSubmitHighlighter::GitSubmitHighlighter(TextEditor::BaseTextDocument *parent) : + TextEditor::SyntaxHighlighter(parent) +{ + initialize(); +} + +void GitSubmitHighlighter::initialize() +{ + m_commentFormat = commentFormat(); + m_keywordPattern.setPattern(QLatin1String("^[\\w-]+:")); + m_hashChar = QLatin1Char('#'); + QTC_CHECK(m_keywordPattern.isValid()); +} + +void GitSubmitHighlighter::highlightBlock(const QString &text) +{ + // figure out current state + State state = static_cast<State>(previousBlockState()); + if (text.isEmpty()) { + if (state == Header) + state = Other; + setCurrentBlockState(state); + return; + } else if (text.startsWith(m_hashChar)) { + setFormat(0, text.size(), m_commentFormat); + setCurrentBlockState(state); + return; + } else if (state == None) { + state = Header; + } + + setCurrentBlockState(state); + // Apply format. + switch (state) { + case None: + break; + case Header: { + QTextCharFormat charFormat = format(0); + charFormat.setFontWeight(QFont::Bold); + setFormat(0, text.size(), charFormat); + break; + } + case Other: + // Format key words ("Task:") italic + if (m_keywordPattern.indexIn(text, 0, QRegExp::CaretAtZero) == 0) { + QTextCharFormat charFormat = format(0); + charFormat.setFontItalic(true); + setFormat(0, m_keywordPattern.matchedLength(), charFormat); + } + break; + } +} + +GitRebaseHighlighter::RebaseAction::RebaseAction(const QString ®exp, + const TextEditor::FontSettings &settings, + TextEditor::TextStyle category) + : exp(regexp) +{ + format = settings.toTextCharFormat(category); +} + +GitRebaseHighlighter::GitRebaseHighlighter(TextEditor::BaseTextDocument *parent) : + TextEditor::SyntaxHighlighter(parent), + m_hashChar(QLatin1Char('#')), + m_changeNumberPattern(QLatin1String(CHANGE_PATTERN)) +{ + const TextEditor::FontSettings settings = TextEditor::TextEditorSettings::instance()->fontSettings(); + m_commentFormat = settings.toTextCharFormat(TextEditor::C_COMMENT); + m_changeFormat = settings.toTextCharFormat(TextEditor::C_DOXYGEN_COMMENT); + m_descFormat = settings.toTextCharFormat(TextEditor::C_STRING); + m_actions << RebaseAction(QLatin1String("^(p|pick)\\b"), settings, TextEditor::C_KEYWORD); + m_actions << RebaseAction(QLatin1String("^(r|reword)\\b"), settings, TextEditor::C_FIELD); + m_actions << RebaseAction(QLatin1String("^(e|edit)\\b"), settings, TextEditor::C_TYPE); + m_actions << RebaseAction(QLatin1String("^(s|squash)\\b"), settings, TextEditor::C_ENUMERATION); + m_actions << RebaseAction(QLatin1String("^(f|fixup)\\b"), settings, TextEditor::C_NUMBER); + m_actions << RebaseAction(QLatin1String("^(x|exec)\\b"), settings, TextEditor::C_LABEL); +} + +void GitRebaseHighlighter::highlightBlock(const QString &text) +{ + if (text.startsWith(m_hashChar)) { + setFormat(0, text.size(), m_commentFormat); + int changeIndex = 0; + while ((changeIndex = m_changeNumberPattern.indexIn(text, changeIndex)) != -1) { + const int changeLen = m_changeNumberPattern.matchedLength(); + setFormat(changeIndex, changeLen, m_changeFormat); + changeIndex += changeLen; + } + return; + } + + foreach (const RebaseAction &action, m_actions) { + if (action.exp.indexIn(text) != -1) { + const int len = action.exp.matchedLength(); + setFormat(0, len, action.format); + const int changeIndex = m_changeNumberPattern.indexIn(text, len); + if (changeIndex != -1) { + const int changeLen = m_changeNumberPattern.matchedLength(); + const int descStart = changeIndex + changeLen + 1; + setFormat(changeIndex, changeLen, m_changeFormat); + setFormat(descStart, text.size() - descStart, m_descFormat); + } + break; + } + } +} + +} // namespace Internal +} // namespace Git diff --git a/src/plugins/git/githighlighters.h b/src/plugins/git/githighlighters.h new file mode 100644 index 0000000000..3d7f6e0621 --- /dev/null +++ b/src/plugins/git/githighlighters.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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. +** +****************************************************************************/ + +#ifndef GITHIGHLIGHTERS_H +#define GITHIGHLIGHTERS_H + +#include <texteditor/syntaxhighlighter.h> +#include <texteditor/texteditorconstants.h> + +namespace TextEditor { +class FontSettings; +} + +namespace Git { +namespace Internal { + +// Highlighter for git submit messages. Make the first line bold, indicates +// comments as such (retrieving the format from the text editor) and marks up +// keywords (words in front of a colon as in 'Task: <bla>'). +class GitSubmitHighlighter : public TextEditor::SyntaxHighlighter +{ +public: + explicit GitSubmitHighlighter(QTextEdit *parent); + explicit GitSubmitHighlighter(TextEditor::BaseTextDocument *parent); + void highlightBlock(const QString &text); + + void initialize(); +private: + enum State { None = -1, Header, Other }; + QTextCharFormat m_commentFormat; + QRegExp m_keywordPattern; + QChar m_hashChar; +}; + +// Highlighter for interactive rebase todo. Indicates comments as such +// (retrieving the format from the text editor) and marks up keywords +class GitRebaseHighlighter : public TextEditor::SyntaxHighlighter +{ +public: + explicit GitRebaseHighlighter(TextEditor::BaseTextDocument *parent); + void highlightBlock(const QString &text); + +private: + class RebaseAction + { + public: + mutable QRegExp exp; + QTextCharFormat format; + RebaseAction(const QString ®exp, const TextEditor::FontSettings &settings, + TextEditor::TextStyle category); + }; + QTextCharFormat m_commentFormat; + QTextCharFormat m_changeFormat; + QTextCharFormat m_descFormat; + const QChar m_hashChar; + QRegExp m_changeNumberPattern; + QList<RebaseAction> m_actions; +}; + +} // namespace Internal +} // namespace Git + +#endif // GITHIGHLIGHTERS_H diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 665c332b21..2ffba4f0bc 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -111,15 +111,13 @@ static const VcsBase::VcsBaseEditorParameters editorParameters[] = { Git::Constants::GIT_COMMIT_TEXT_EDITOR_DISPLAY_NAME, Git::Constants::C_GIT_COMMIT_TEXT_EDITOR, "text/vnd.qtcreator.git.commit"}, +{ VcsBase::OtherContent, + Git::Constants::GIT_REBASE_EDITOR_ID, + Git::Constants::GIT_REBASE_EDITOR_DISPLAY_NAME, + Git::Constants::C_GIT_REBASE_EDITOR, + "text/vnd.qtcreator.git.rebase"}, }; -// Utility to find a parameter set by type -static inline const VcsBase::VcsBaseEditorParameters *findType(int ie) -{ - const VcsBase::EditorContentType et = static_cast<VcsBase::EditorContentType>(ie); - return VcsBase::VcsBaseEditorWidget::findType(editorParameters, sizeof(editorParameters)/sizeof(VcsBase::VcsBaseEditorParameters), et); -} - Q_DECLARE_METATYPE(Git::Internal::GitClientMemberFunc) using namespace Git; @@ -437,7 +435,7 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage) createRepositoryAction(localRepositoryMenu, tr("Reset..."), Core::Id("Git.Reset"), - globalcontext, false, SLOT(resetRepository())); + globalcontext, true, SLOT(resetRepository())); createRepositoryAction(localRepositoryMenu, tr("Interactive Rebase..."), Core::Id("Git.InteractiveRebase"), @@ -652,9 +650,9 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage) // -------------- gitContainer->addSeparator(globalcontext); - m_createRepositoryAction = new QAction(tr("Create Repository..."), this); - Core::Command *createRepositoryCommand = Core::ActionManager::registerAction(m_createRepositoryAction, "Git.CreateRepository", globalcontext); - connect(m_createRepositoryAction, SIGNAL(triggered()), this, SLOT(createRepository())); + QAction *repositoryAction = new QAction(tr("Create Repository..."), this); + Core::Command *createRepositoryCommand = Core::ActionManager::registerAction(repositoryAction, "Git.CreateRepository", globalcontext); + connect(repositoryAction, SIGNAL(triggered()), this, SLOT(createRepository())); gitContainer->addAction(createRepositoryCommand); if (0) { @@ -790,17 +788,19 @@ void GitPlugin::resetRepository() void GitPlugin::startRebase() { - QString workingDirectory = currentState().currentDirectoryOrTopLevel(); - if (workingDirectory.isEmpty() || !m_gitClient->canRebase(workingDirectory)) + const VcsBase::VcsBasePluginState state = currentState(); + QTC_ASSERT(state.hasTopLevel(), return); + const QString topLevel = state.topLevel(); + if (topLevel.isEmpty() || !m_gitClient->canRebase(topLevel)) return; - if (!m_gitClient->beginStashScope(workingDirectory, QLatin1String("Rebase-i"))) + if (!m_gitClient->beginStashScope(topLevel, QLatin1String("Rebase-i"))) return; LogChangeDialog dialog(false); dialog.setWindowTitle(tr("Interactive Rebase")); - if (dialog.runDialog(workingDirectory, QString(), false)) - m_gitClient->interactiveRebase(workingDirectory, dialog.commit(), false); + if (dialog.runDialog(topLevel, QString(), false)) + m_gitClient->interactiveRebase(topLevel, dialog.commit(), false); else - m_gitClient->endStashScope(workingDirectory); + m_gitClient->endStashScope(topLevel); } void GitPlugin::startChangeRelatedAction() @@ -956,7 +956,8 @@ void GitPlugin::startCommit(CommitType commitType) void GitPlugin::updateVersionWarning() { - if (m_gitClient->gitVersion() >= minimumRequiredVersion) + unsigned version = m_gitClient->gitVersion(); + if (!version || version >= minimumRequiredVersion) return; Core::IEditor *curEditor = Core::EditorManager::currentEditor(); if (!curEditor) @@ -976,8 +977,7 @@ void GitPlugin::updateVersionWarning() Core::IEditor *GitPlugin::openSubmitEditor(const QString &fileName, const CommitData &cd) { - Core::IEditor *editor = Core::EditorManager::openEditor(fileName, Constants::GITSUBMITEDITOR_ID, - Core::EditorManager::ModeSwitch); + Core::IEditor *editor = Core::EditorManager::openEditor(fileName, Constants::GITSUBMITEDITOR_ID); GitSubmitEditor *submitEditor = qobject_cast<GitSubmitEditor*>(editor); QTC_ASSERT(submitEditor, return 0); setSubmitEditor(submitEditor); @@ -1069,7 +1069,7 @@ bool GitPlugin::submitEditorAboutToClose() void GitPlugin::fetch() { - m_gitClient->synchronousFetch(currentState().topLevel(), QString()); + m_gitClient->fetch(currentState().topLevel(), QString()); } void GitPlugin::pull() @@ -1097,7 +1097,7 @@ void GitPlugin::push() { const VcsBase::VcsBasePluginState state = currentState(); QTC_ASSERT(state.hasTopLevel(), return); - m_gitClient->synchronousPush(state.topLevel()); + m_gitClient->push(state.topLevel()); } void GitPlugin::startMergeTool() diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h index 05cbc2575d..c7ff4a9e4a 100644 --- a/src/plugins/git/gitplugin.h +++ b/src/plugins/git/gitplugin.h @@ -202,7 +202,6 @@ private: static GitPlugin *m_instance; Locator::CommandLocator *m_commandLocator; - QAction *m_createRepositoryAction; QAction *m_submitCurrentAction; QAction *m_diffSelectedFilesAction; diff --git a/src/plugins/git/gitsubmiteditorwidget.cpp b/src/plugins/git/gitsubmiteditorwidget.cpp index 4e2689ffdc..8d057d4a6d 100644 --- a/src/plugins/git/gitsubmiteditorwidget.cpp +++ b/src/plugins/git/gitsubmiteditorwidget.cpp @@ -27,19 +27,14 @@ ** ****************************************************************************/ -#include "gitsubmiteditorwidget.h" #include "commitdata.h" +#include "gitsubmiteditorwidget.h" +#include "githighlighters.h" #include "logchangedialog.h" -#include <texteditor/texteditorsettings.h> -#include <texteditor/fontsettings.h> -#include <utils/qtcassert.h> - #include <QRegExpValidator> -#include <QSyntaxHighlighter> #include <QTextEdit> -#include <QDebug> #include <QDir> #include <QGroupBox> #include <QRegExp> @@ -48,72 +43,6 @@ namespace Git { namespace Internal { -// Retrieve the comment char format from the text editor. -static QTextCharFormat commentFormat() -{ - const TextEditor::FontSettings settings = TextEditor::TextEditorSettings::instance()->fontSettings(); - return settings.toTextCharFormat(TextEditor::C_COMMENT); -} - -GitSubmitHighlighter::GitSubmitHighlighter(QTextEdit * parent) : - TextEditor::SyntaxHighlighter(parent) -{ - initialize(); -} - -GitSubmitHighlighter::GitSubmitHighlighter(TextEditor::BaseTextDocument *parent) : - TextEditor::SyntaxHighlighter(parent) -{ - initialize(); -} - -void GitSubmitHighlighter::initialize() -{ - m_commentFormat = commentFormat(); - m_keywordPattern.setPattern(QLatin1String("^[\\w-]+:")); - m_hashChar = QLatin1Char('#'); - QTC_CHECK(m_keywordPattern.isValid()); -} - -void GitSubmitHighlighter::highlightBlock(const QString &text) -{ - // figure out current state - State state = static_cast<State>(previousBlockState()); - if (text.isEmpty()) { - if (state == Header) - state = Other; - setCurrentBlockState(state); - return; - } else if (text.startsWith(m_hashChar)) { - setFormat(0, text.size(), m_commentFormat); - setCurrentBlockState(state); - return; - } else if (state == None) { - state = Header; - } - - setCurrentBlockState(state); - // Apply format. - switch (state) { - case None: - break; - case Header: { - QTextCharFormat charFormat = format(0); - charFormat.setFontWeight(QFont::Bold); - setFormat(0, text.size(), charFormat); - break; - } - case Other: - // Format key words ("Task:") italic - if (m_keywordPattern.indexIn(text, 0, QRegExp::CaretAtZero) == 0) { - QTextCharFormat charFormat = format(0); - charFormat.setFontItalic(true); - setFormat(0, m_keywordPattern.matchedLength(), charFormat); - } - break; - } -} - // ------------------ GitSubmitEditorWidget::GitSubmitEditorWidget(QWidget *parent) : VcsBase::SubmitEditorWidget(parent), diff --git a/src/plugins/git/gitsubmiteditorwidget.h b/src/plugins/git/gitsubmiteditorwidget.h index 3872786ebe..7eff3d4c03 100644 --- a/src/plugins/git/gitsubmiteditorwidget.h +++ b/src/plugins/git/gitsubmiteditorwidget.h @@ -93,25 +93,6 @@ private: bool m_isInitialized; }; -// Highlighter for git submit messages. Make the first line bold, indicates -// comments as such (retrieving the format from the text editor) and marks up -// keywords (words in front of a colon as in 'Task: <bla>'). - -class GitSubmitHighlighter : public TextEditor::SyntaxHighlighter -{ -public: - explicit GitSubmitHighlighter(QTextEdit *parent); - explicit GitSubmitHighlighter(TextEditor::BaseTextDocument *parent); - void highlightBlock(const QString &text); - - void initialize(); -private: - enum State { None = -1, Header, Other }; - QTextCharFormat m_commentFormat; - QRegExp m_keywordPattern; - QChar m_hashChar; -}; - } // namespace Internal } // namespace Git diff --git a/src/plugins/git/logchangedialog.cpp b/src/plugins/git/logchangedialog.cpp index 78cf8b04d5..bb8f444c9e 100644 --- a/src/plugins/git/logchangedialog.cpp +++ b/src/plugins/git/logchangedialog.cpp @@ -31,6 +31,8 @@ #include "gitplugin.h" #include "gitclient.h" +#include <vcsbase/vcsbaseoutputwindow.h> + #include <QTreeView> #include <QLabel> #include <QPushButton> @@ -67,8 +69,13 @@ LogChangeWidget::LogChangeWidget(QWidget *parent) bool LogChangeWidget::init(const QString &repository, const QString &commit, bool includeRemote) { - if (!populateLog(repository, commit, includeRemote) || !m_model->rowCount()) + if (!populateLog(repository, commit, includeRemote)) + return false; + if (!m_model->rowCount()) { + VcsBase::VcsBaseOutputWindow::instance()->appendError( + GitPlugin::instance()->gitClient()->msgNoCommits(includeRemote)); return false; + } selectionModel()->select(m_model->index(0, 0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); return true; @@ -89,6 +96,16 @@ int LogChangeWidget::commitIndex() const return -1; } +QString LogChangeWidget::earliestCommit() const +{ + int rows = m_model->rowCount(); + if (rows) { + if (const QStandardItem *item = m_model->item(rows - 1, Sha1Column)) + return item->text(); + } + return QString(); +} + void LogChangeWidget::emitDoubleClicked(const QModelIndex &index) { if (index.isValid()) { @@ -181,7 +198,7 @@ LogChangeDialog::LogChangeDialog(bool isReset, QWidget *parent) : bool LogChangeDialog::runDialog(const QString &repository, const QString &commit, bool includeRemote) { if (!widget->init(repository, commit, includeRemote)) - return QDialog::Rejected; + return false; return QDialog::exec() == QDialog::Accepted; } diff --git a/src/plugins/git/logchangedialog.h b/src/plugins/git/logchangedialog.h index 4e298519ac..a4790701b4 100644 --- a/src/plugins/git/logchangedialog.h +++ b/src/plugins/git/logchangedialog.h @@ -56,6 +56,7 @@ public: bool includeRemote = true); QString commit() const; int commitIndex() const; + QString earliestCommit() const; signals: void doubleClicked(const QString &commit); diff --git a/src/plugins/git/remotedialog.cpp b/src/plugins/git/remotedialog.cpp index a027d62bf2..d24bc2789c 100644 --- a/src/plugins/git/remotedialog.cpp +++ b/src/plugins/git/remotedialog.cpp @@ -172,7 +172,7 @@ void RemoteDialog::pushToRemote() const int row = indexList.at(0).row(); const QString remoteName = m_remoteModel->remoteName(row); - m_remoteModel->client()->synchronousPush(m_remoteModel->workingDirectory(), + m_remoteModel->client()->push(m_remoteModel->workingDirectory(), QStringList() << remoteName); } @@ -184,7 +184,7 @@ void RemoteDialog::fetchFromRemote() int row = indexList.at(0).row(); const QString remoteName = m_remoteModel->remoteName(row); - m_remoteModel->client()->synchronousFetch(m_remoteModel->workingDirectory(), remoteName); + m_remoteModel->client()->fetch(m_remoteModel->workingDirectory(), remoteName); } void RemoteDialog::updateButtonState() diff --git a/src/plugins/git/settingspage.ui b/src/plugins/git/settingspage.ui index c72a4c3eb1..26b51f527f 100644 --- a/src/plugins/git/settingspage.ui +++ b/src/plugins/git/settingspage.ui @@ -140,7 +140,7 @@ <item row="2" column="3"> <widget class="QCheckBox" name="useDiffEditorCheckBox"> <property name="text"> - <string>Use Diff Editor</string> + <string>Show diff side-by-side</string> </property> </widget> </item> diff --git a/src/plugins/helloworld/helloworldplugin.cpp b/src/plugins/helloworld/helloworldplugin.cpp index 25d64aeb46..ea781f4026 100644 --- a/src/plugins/helloworld/helloworldplugin.cpp +++ b/src/plugins/helloworld/helloworldplugin.cpp @@ -60,7 +60,6 @@ public: setIcon(QIcon()); setPriority(0); setId("HelloWorld.HelloWorldMode"); - setType("HelloWorld.HelloWorldMode"); setContextHelpId(QString()); } }; diff --git a/src/plugins/imageviewer/imageviewerfactory.cpp b/src/plugins/imageviewer/imageviewerfactory.cpp index 55d501c5c4..d925ea6cc9 100644 --- a/src/plugins/imageviewer/imageviewerfactory.cpp +++ b/src/plugins/imageviewer/imageviewerfactory.cpp @@ -103,11 +103,6 @@ QString ImageViewerFactory::displayName() const return qApp->translate("OpenWith::Editors", Constants::IMAGEVIEWER_DISPLAY_NAME); } -Core::IDocument *ImageViewerFactory::open(const QString & /*fileName*/) -{ - return 0; -} - void ImageViewerFactory::extensionsInitialized() { d->actionHandler->createActions(); diff --git a/src/plugins/imageviewer/imageviewerfactory.h b/src/plugins/imageviewer/imageviewerfactory.h index 427eacadd4..77d372a265 100644 --- a/src/plugins/imageviewer/imageviewerfactory.h +++ b/src/plugins/imageviewer/imageviewerfactory.h @@ -50,7 +50,6 @@ public: QStringList mimeTypes() const; Core::Id id() const; QString displayName() const; - Core::IDocument *open(const QString &fileName); void extensionsInitialized(); diff --git a/src/plugins/locator/basefilefilter.cpp b/src/plugins/locator/basefilefilter.cpp index 14166a5bdf..8cd2a96e40 100644 --- a/src/plugins/locator/basefilefilter.cpp +++ b/src/plugins/locator/basefilefilter.cpp @@ -100,7 +100,7 @@ QList<FilterEntry> BaseFileFilter::matchesFor(QFutureInterface<Locator::FilterEn void BaseFileFilter::accept(Locator::FilterEntry selection) const { EditorManager::openEditor(selection.internalData.toString(), Id(), - EditorManager::ModeSwitch | EditorManager::CanContainLineNumber); + EditorManager::CanContainLineNumber); } void BaseFileFilter::generateFileNames() diff --git a/src/plugins/locator/filesystemfilter.cpp b/src/plugins/locator/filesystemfilter.cpp index 212d494b3d..4e7af5c91b 100644 --- a/src/plugins/locator/filesystemfilter.cpp +++ b/src/plugins/locator/filesystemfilter.cpp @@ -115,7 +115,7 @@ void FileSystemFilter::accept(FilterEntry selection) const return; } EditorManager::openEditor(selection.internalData.toString(), Id(), - EditorManager::ModeSwitch | EditorManager::CanContainLineNumber); + EditorManager::CanContainLineNumber); } bool FileSystemFilter::openConfigDialog(QWidget *parent, bool &needsRefresh) diff --git a/src/plugins/locator/locatorplugin.cpp b/src/plugins/locator/locatorplugin.cpp index caa5102f0b..e7758facbe 100644 --- a/src/plugins/locator/locatorplugin.cpp +++ b/src/plugins/locator/locatorplugin.cpp @@ -211,8 +211,6 @@ void LocatorPlugin::saveSettings() } /*! - \fn QList<ILocatorFilter*> LocatorPlugin::filters() - Return all filters, including the ones created by the user. */ QList<ILocatorFilter*> LocatorPlugin::filters() @@ -221,8 +219,6 @@ QList<ILocatorFilter*> LocatorPlugin::filters() } /*! - \fn QList<ILocatorFilter*> LocatorPlugin::customFilters() - This returns a subset of all the filters, that contains only the filters that have been created by the user at some point (maybe in a previous session). */ diff --git a/src/plugins/locator/opendocumentsfilter.cpp b/src/plugins/locator/opendocumentsfilter.cpp index f208a65ecf..c626b2de94 100644 --- a/src/plugins/locator/opendocumentsfilter.cpp +++ b/src/plugins/locator/opendocumentsfilter.cpp @@ -106,5 +106,5 @@ void OpenDocumentsFilter::refresh(QFutureInterface<void> &future) void OpenDocumentsFilter::accept(FilterEntry selection) const { EditorManager::openEditor(selection.internalData.toString(), Id(), - EditorManager::ModeSwitch | EditorManager::CanContainLineNumber); + EditorManager::CanContainLineNumber); } diff --git a/src/plugins/madde/maddedevice.cpp b/src/plugins/madde/maddedevice.cpp index f8b963246e..e8f3c5546f 100644 --- a/src/plugins/madde/maddedevice.cpp +++ b/src/plugins/madde/maddedevice.cpp @@ -41,7 +41,6 @@ using namespace RemoteLinux; namespace Madde { namespace Internal { -const char MaddeDeviceTestActionId[] = "Madde.DeviceTestAction"; MaddeDevice::Ptr MaddeDevice::create() { @@ -78,38 +77,6 @@ QString MaddeDevice::displayType() const return maddeDisplayType(type()); } -QList<Core::Id> MaddeDevice::actionIds() const -{ - return QList<Core::Id>() << Core::Id(MaddeDeviceTestActionId) - << Core::Id(Constants::GenericDeployKeyToDeviceActionId); -} - -QString MaddeDevice::displayNameForActionId(Core::Id actionId) const -{ - QTC_ASSERT(actionIds().contains(actionId), return QString()); - - if (actionId == MaddeDeviceTestActionId) - return tr("Test"); - if (actionId == Constants::GenericDeployKeyToDeviceActionId) - return tr("Deploy Public Key..."); - return QString(); // Can't happen. -} - -void MaddeDevice::executeAction(Core::Id actionId, QWidget *parent) const -{ - QTC_ASSERT(actionIds().contains(actionId), return); - - QDialog *d = 0; - const IDevice::ConstPtr device = sharedFromThis(); - if (actionId == MaddeDeviceTestActionId) - d = new LinuxDeviceTestDialog(device, new MaddeDeviceTester, parent); - else if (actionId == Constants::GenericDeployKeyToDeviceActionId) - d = PublicKeyDeploymentDialog::createDialog(device, parent); - if (d) - d->exec(); - delete d; -} - QString MaddeDevice::maddeDisplayType(Core::Id type) { if (type == Maemo5OsType) @@ -144,5 +111,10 @@ QSize MaddeDevice::packageManagerIconSize(Core::Id type) return QSize(); } +AbstractLinuxDeviceTester *MaddeDevice::createDeviceTester() const +{ + return new MaddeDeviceTester; +} + } // namespace Internal } // namespace Madde diff --git a/src/plugins/madde/maddedevice.h b/src/plugins/madde/maddedevice.h index 0d95614775..463c225231 100644 --- a/src/plugins/madde/maddedevice.h +++ b/src/plugins/madde/maddedevice.h @@ -49,9 +49,6 @@ public: Origin origin = ManuallyAdded, Core::Id id = Core::Id()); QString displayType() const; - QList<Core::Id> actionIds() const; - QString displayNameForActionId(Core::Id actionId) const; - void executeAction(Core::Id actionId, QWidget *parent) const; ProjectExplorer::IDevice::Ptr clone() const; static QString maddeDisplayType(Core::Id type); @@ -61,6 +58,8 @@ public: static QSize packageManagerIconSize(Core::Id type); + RemoteLinux::AbstractLinuxDeviceTester *createDeviceTester() const; + private: MaddeDevice(); MaddeDevice(const QString &name, Core::Id type, MachineType machineType, diff --git a/src/plugins/madde/maemopackagecreationwidget.cpp b/src/plugins/madde/maemopackagecreationwidget.cpp index 0511985bb0..90a1661d25 100644 --- a/src/plugins/madde/maemopackagecreationwidget.cpp +++ b/src/plugins/madde/maemopackagecreationwidget.cpp @@ -263,8 +263,7 @@ void MaemoPackageCreationWidget::editDebianFile() void MaemoPackageCreationWidget::editFile(const QString &filePath) { - Core::EditorManager::openEditor(filePath, Core::Id(), - Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(filePath); } } // namespace Internal diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp index e53009f4b4..12db4d74c5 100644 --- a/src/plugins/mercurial/mercurialplugin.cpp +++ b/src/plugins/mercurial/mercurialplugin.cpp @@ -558,8 +558,7 @@ void MercurialPlugin::showCommitWidget(const QList<VcsBaseClient::StatusItem> &s } Core::IEditor *editor = Core::EditorManager::openEditor(saver.fileName(), - Constants::COMMIT_ID, - Core::EditorManager::ModeSwitch); + Constants::COMMIT_ID); if (!editor) { outputWindow->appendError(tr("Unable to create an editor for the commit.")); return; diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index 70c573c883..8fd5957c80 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -649,8 +649,7 @@ void PerforcePlugin::startSubmitProject() Core::IEditor *PerforcePlugin::openPerforceSubmitEditor(const QString &fileName, const QStringList &depotFileNames) { - Core::IEditor *editor = Core::EditorManager::openEditor(fileName, Constants::PERFORCE_SUBMIT_EDITOR_ID, - Core::EditorManager::ModeSwitch); + Core::IEditor *editor = Core::EditorManager::openEditor(fileName, Constants::PERFORCE_SUBMIT_EDITOR_ID); PerforceSubmitEditor *submitEditor = static_cast<PerforceSubmitEditor*>(editor); setSubmitEditor(submitEditor); submitEditor->restrictToProjectFiles(depotFileNames); @@ -1180,7 +1179,7 @@ Core::IEditor *PerforcePlugin::showOutputInEditor(const QString &title, const QS if (codec) e->setCodec(codec); Core::IEditor *ie = e->editor(); - Core::EditorManager::activateEditor(ie, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(ie); return ie; } @@ -1262,7 +1261,7 @@ void PerforcePlugin::p4Diff(const PerforceDiffParameters &p) if (existingEditor) { existingEditor->createNew(result.stdOut); - Core::EditorManager::activateEditor(existingEditor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(existingEditor); return; } // Create new editor diff --git a/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp new file mode 100644 index 0000000000..1c9554755e --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp @@ -0,0 +1,109 @@ +/************************************************************************** +** +** Copyright (C) 2011 - 2013 Research In Motion +** +** Contact: Research In Motion (blackberry-qt@qnx.com) +** Contact: KDAB (info@kdab.com) +** +** 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 "devicecheckbuildstep.h" + +#include "../kitinformation.h" +#include "../target.h" +#include "devicemanager.h" +#include "idevice.h" +#include "idevicefactory.h" + +#include <QMessageBox> + +using namespace ProjectExplorer; + +DeviceCheckBuildStep::DeviceCheckBuildStep(BuildStepList *bsl, Core::Id id) + : BuildStep(bsl, id) +{ + setDefaultDisplayName(stepDisplayName()); +} + +DeviceCheckBuildStep::DeviceCheckBuildStep(BuildStepList *bsl, DeviceCheckBuildStep *bs) + : BuildStep(bsl, bs) +{ + setDefaultDisplayName(stepDisplayName()); +} + +bool DeviceCheckBuildStep::init() +{ + IDevice::ConstPtr device = DeviceKitInformation::device(target()->kit()); + if (!device) { + Core::Id deviceTypeId = DeviceTypeKitInformation::deviceTypeId(target()->kit()); + IDeviceFactory *factory = IDeviceFactory::find(deviceTypeId); + if (!factory || !factory->canCreate()) { + emit addOutput(tr("No device configured."), BuildStep::ErrorMessageOutput); + return false; + } + + QMessageBox msgBox(QMessageBox::Question, tr("Set Up Device"), + tr("There is no device set up for this kit. Do you want to add a device?"), + QMessageBox::Yes|QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + if (msgBox.exec() == QMessageBox::No) { + emit addOutput(tr("No device configured."), BuildStep::ErrorMessageOutput); + return false; + } + + IDevice::Ptr newDevice = factory->create(deviceTypeId); + if (newDevice.isNull()) { + emit addOutput(tr("No device configured."), BuildStep::ErrorMessageOutput); + return false; + } + + DeviceManager *dm = DeviceManager::instance(); + dm->addDevice(newDevice); + + DeviceKitInformation::setDevice(target()->kit(), newDevice); + } + + return true; +} + +void DeviceCheckBuildStep::run(QFutureInterface<bool> &fi) +{ + fi.reportResult(true); +} + +BuildStepConfigWidget *DeviceCheckBuildStep::createConfigWidget() +{ + return new SimpleBuildStepConfigWidget(this); +} + +Core::Id DeviceCheckBuildStep::stepId() +{ + return Core::Id("ProjectExplorer.DeviceCheckBuildStep"); +} + +QString DeviceCheckBuildStep::stepDisplayName() +{ + return tr("Check for a configured device"); +} diff --git a/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.h b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.h new file mode 100644 index 0000000000..96f982e649 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.h @@ -0,0 +1,61 @@ +/************************************************************************** +** +** Copyright (C) 2011 - 2013 Research In Motion +** +** Contact: Research In Motion (blackberry-qt@qnx.com) +** Contact: KDAB (info@kdab.com) +** +** 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. +** +****************************************************************************/ + +#ifndef PROJECTEXPLORER_DEVICECHECKBUILDSTEP_H +#define PROJECTEXPLORER_DEVICECHECKBUILDSTEP_H + +#include "../buildstep.h" +#include "../projectexplorer_export.h" + +namespace ProjectExplorer { + +class BuildStepList; + +class PROJECTEXPLORER_EXPORT DeviceCheckBuildStep : public BuildStep +{ + Q_OBJECT +public: + DeviceCheckBuildStep(BuildStepList *bsl, Core::Id id); + DeviceCheckBuildStep(ProjectExplorer::BuildStepList *bsl, DeviceCheckBuildStep *bs); + + bool init(); + + void run(QFutureInterface<bool> &fi); + + BuildStepConfigWidget *createConfigWidget(); + + static Core::Id stepId(); + static QString stepDisplayName(); +}; + +} // namespace ProjectExplorer + +#endif // PROJECTEXPLORER_DEVICECHECKBUILDSTEP_H diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 0d498a4f7a..09a069eae4 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -261,7 +261,7 @@ void FolderNavigationWidget::openItem(const QModelIndex &srcIndex) return; } // Open file. - Core::EditorManager::openEditor(m_fileSystemModel->filePath(srcIndex), Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(m_fileSystemModel->filePath(srcIndex)); } void FolderNavigationWidget::setCurrentTitle(QString dirName, const QString &fullPath) diff --git a/src/plugins/projectexplorer/kitmodel.cpp b/src/plugins/projectexplorer/kitmodel.cpp index 0b363001cd..087d822743 100644 --- a/src/plugins/projectexplorer/kitmodel.cpp +++ b/src/plugins/projectexplorer/kitmodel.cpp @@ -59,7 +59,7 @@ public: widget = KitManager::instance()->createConfigWidget(k); if (widget) { - if (k) + if (k && k->isAutoDetected()) widget->makeStickySubWidgetsReadOnly(); widget->setVisible(false); } diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp index 30d44ce554..af399f4862 100644 --- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp +++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp @@ -779,7 +779,9 @@ void MiniProjectTargetSelector::doLayout(bool keepSize) m_summaryLabel->move(0, summaryLabelY); // Height to be aligned with side bar button - int alignedWithActionHeight = actionBar->height() - statusBar->height(); + int alignedWithActionHeight = 210; + if (actionBar->isVisible()) + alignedWithActionHeight = actionBar->height() - statusBar->height(); int bottomMargin = 9; int totalHeight = 0; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index e89ce94967..e83723b7da 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -265,7 +265,6 @@ public: setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Project.png"))); setPriority(Constants::P_MODE_SESSION); setId(Constants::MODE_SESSION); - setType(Core::Id()); setContextHelpId(QLatin1String("Managing Projects")); } }; @@ -1522,8 +1521,6 @@ static inline QStringList projectFileGlobs() } /*! - \fn void ProjectExplorerPlugin::restoreSession() - This method is connected to the ICore::coreOpened signal. If there was no session explicitly loaded, it creates an empty new default session and puts the list of recent projects and sessions @@ -2873,7 +2870,7 @@ void ProjectExplorerPlugin::removeProject() void ProjectExplorerPlugin::openFile() { QTC_ASSERT(d->m_currentNode, return); - Core::EditorManager::openEditor(d->m_currentNode->path(), Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(d->m_currentNode->path()); } void ProjectExplorerPlugin::searchOnFileSystem() @@ -3027,6 +3024,8 @@ void ProjectExplorerPlugin::setSession(QAction *action) void ProjectExplorerPlugin::setProjectExplorerSettings(const Internal::ProjectExplorerSettings &pes) { + QTC_ASSERT(d->m_projectExplorerSettings.environmentId == pes.environmentId, return); + if (d->m_projectExplorerSettings == pes) return; d->m_projectExplorerSettings = pes; diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 8c381ecc48..fb71346958 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -113,6 +113,7 @@ HEADERS += projectexplorer.h \ devicesupport/desktopdevicefactory.h \ devicesupport/idevicewidget.h \ devicesupport/idevicefactory.h \ + devicesupport/devicecheckbuildstep.h \ devicesupport/devicemanager.h \ devicesupport/devicemanagermodel.h \ devicesupport/devicefactoryselectiondialog.h \ @@ -228,6 +229,7 @@ SOURCES += projectexplorer.cpp \ devicesupport/desktopdevice.cpp \ devicesupport/desktopdevicefactory.cpp \ devicesupport/idevicefactory.cpp \ + devicesupport/devicecheckbuildstep.cpp \ devicesupport/devicemanager.cpp \ devicesupport/devicemanagermodel.cpp \ devicesupport/devicefactoryselectiondialog.cpp \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index c8b5785c80..a63070d2b9 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -251,6 +251,8 @@ QtcPlugin { "devicesupport/desktopdevicefactory.h", "devicesupport/deviceapplicationrunner.cpp", "devicesupport/deviceapplicationrunner.h", + "devicesupport/devicecheckbuildstep.cpp", + "devicesupport/devicecheckbuildstep.h", "devicesupport/devicefactoryselectiondialog.cpp", "devicesupport/devicefactoryselectiondialog.h", "devicesupport/devicefactoryselectiondialog.ui", diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h index adf2b8a558..507bf4612a 100644 --- a/src/plugins/projectexplorer/projectexplorersettings.h +++ b/src/plugins/projectexplorer/projectexplorersettings.h @@ -81,7 +81,8 @@ inline bool operator==(const ProjectExplorerSettings &p1, const ProjectExplorerS && p1.useJom == p2.useJom && p1.autorestoreLastSession == p2.autorestoreLastSession && p1.prompToStopRunControl == p2.prompToStopRunControl - && p1.maxAppOutputLines == p2.maxAppOutputLines; + && p1.maxAppOutputLines == p2.maxAppOutputLines + && p1.environmentId == p2.environmentId; } } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.cpp b/src/plugins/projectexplorer/projectexplorersettingspage.cpp index 06bc43c44f..e9e934183a 100644 --- a/src/plugins/projectexplorer/projectexplorersettingspage.cpp +++ b/src/plugins/projectexplorer/projectexplorersettingspage.cpp @@ -80,10 +80,11 @@ ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const pes.useJom = m_ui.jomCheckbox->isChecked(); pes.prompToStopRunControl = m_ui.promptToStopRunControlCheckBox->isChecked(); pes.maxAppOutputLines = m_ui.maxAppOutputBox->value(); + pes.environmentId = m_environmentId; return pes; } -void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &pes) const +void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &pes) { m_ui.buildProjectBeforeDeployCheckBox->setChecked(pes.buildBeforeDeploy); m_ui.deployProjectBeforeRunCheckBox->setChecked(pes.deployBeforeRun); @@ -97,6 +98,7 @@ void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings & m_ui.jomCheckbox->setChecked(pes.useJom); m_ui.promptToStopRunControlCheckBox->setChecked(pes.prompToStopRunControl); m_ui.maxAppOutputBox->setValue(pes.maxAppOutputLines); + m_environmentId = pes.environmentId; } QString ProjectExplorerSettingsWidget::projectsDirectory() const diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.h b/src/plugins/projectexplorer/projectexplorersettingspage.h index f84d9981bb..75f63dcfb0 100644 --- a/src/plugins/projectexplorer/projectexplorersettingspage.h +++ b/src/plugins/projectexplorer/projectexplorersettingspage.h @@ -34,6 +34,7 @@ #include "ui_projectexplorersettingspage.h" #include <QPointer> +#include <QUuid> namespace ProjectExplorer { namespace Internal { @@ -47,7 +48,7 @@ public: explicit ProjectExplorerSettingsWidget(QWidget *parent = 0); ProjectExplorerSettings settings() const; - void setSettings(const ProjectExplorerSettings &s) const; + void setSettings(const ProjectExplorerSettings &s); QString projectsDirectory() const; void setProjectsDirectory(const QString &pd); @@ -70,6 +71,7 @@ private: Ui::ProjectExplorerSettingsPageUi m_ui; mutable QString m_searchKeywords; + QUuid m_environmentId; }; class ProjectExplorerSettingsPage : public Core::IOptionsPage diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp index f95da9ebb4..b1ffbec7ac 100644 --- a/src/plugins/projectexplorer/projectfilewizardextension.cpp +++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp @@ -52,6 +52,7 @@ #include <projectexplorer/editorconfiguration.h> #include <QtAlgorithms> +#include <QPointer> #include <QDebug> #include <QFileInfo> #include <QMultiMap> @@ -177,7 +178,7 @@ struct ProjectWizardContext QList<Core::IVersionControl*> versionControls; QList<Core::IVersionControl*> activeVersionControls; QList<ProjectEntry> projects; - ProjectWizardPage *page; + QPointer<ProjectWizardPage> page; // this is managed by the wizard! bool repositoryExists; // Is VCS 'add' sufficient, or should a repository be created? QString commonDirectory; const Core::IWizard *wizard; @@ -329,6 +330,9 @@ void ProjectFileWizardExtension::firstExtensionPageShown( void ProjectFileWizardExtension::initializeVersionControlChoices() { + if (m_context->page.isNull()) + return; + // Figure out version control situation: // 1) Directory is managed and VCS supports "Add" -> List it // 2) Directory is managed and VCS does not support "Add" -> None available diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp index 51f77f56d5..2df69b1bd6 100644 --- a/src/plugins/projectexplorer/projecttreewidget.cpp +++ b/src/plugins/projectexplorer/projecttreewidget.cpp @@ -372,7 +372,7 @@ void ProjectTreeWidget::openItem(const QModelIndex &mainIndex) Node *node = m_model->nodeForIndex(mainIndex); if (node->nodeType() != FileNodeType) return; - IEditor *editor = EditorManager::openEditor(node->path(), Id(), EditorManager::ModeSwitch); + IEditor *editor = EditorManager::openEditor(node->path()); if (node->line() >= 0) editor->gotoLine(node->line()); } diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 039255a38c..4561b1343d 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -104,6 +104,9 @@ bool ProcessHandle::equals(const ProcessHandle &rhs) const } +/*! + \brief Returns the widget used to configure this run configuration. Ownership is transferred to the caller +*/ RunConfigWidget *IRunConfigurationAspect::createConfigurationWidget() { return 0; @@ -200,12 +203,6 @@ bool RunConfiguration::ensureConfigured(QString *errorMessage) } -/*! - \fn virtual QWidget *ProjectExplorer::RunConfiguration::createConfigurationWidget() - - \brief Returns the widget used to configure this run configuration. Ownership is transferred to the caller -*/ - BuildConfiguration *RunConfiguration::activeBuildConfiguration() const { if (!target()) diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 445db5f031..cb493df466 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -373,8 +373,6 @@ bool SessionManager::save() } /*! - \fn bool SessionManager::closeAllProjects() - Closes all projects */ void SessionManager::closeAllProjects() diff --git a/src/plugins/projectexplorer/showineditortaskhandler.cpp b/src/plugins/projectexplorer/showineditortaskhandler.cpp index f01c9e3ced..3090fb47d7 100644 --- a/src/plugins/projectexplorer/showineditortaskhandler.cpp +++ b/src/plugins/projectexplorer/showineditortaskhandler.cpp @@ -31,7 +31,7 @@ #include "task.h" -#include <texteditor/basetexteditor.h> +#include <coreplugin/editormanager/editormanager.h> #include <QAction> #include <QFileInfo> @@ -49,7 +49,7 @@ bool ShowInEditorTaskHandler::canHandle(const ProjectExplorer::Task &task) const void ShowInEditorTaskHandler::handle(const ProjectExplorer::Task &task) { QFileInfo fi(task.file.toFileInfo()); - TextEditor::BaseTextEditorWidget::openEditorAt(fi.filePath(), task.movedLine); + Core::EditorManager::openEditorAt(fi.filePath(), task.movedLine); } QAction *ShowInEditorTaskHandler::createAction(QObject *parent) const diff --git a/src/plugins/pythoneditor/pythoneditorfactory.cpp b/src/plugins/pythoneditor/pythoneditorfactory.cpp index 5afe99883d..5dc783f6ae 100644 --- a/src/plugins/pythoneditor/pythoneditorfactory.cpp +++ b/src/plugins/pythoneditor/pythoneditorfactory.cpp @@ -56,16 +56,6 @@ QString EditorFactory::displayName() const return tr(Constants::C_EDITOR_DISPLAY_NAME); } -Core::IDocument *EditorFactory::open(const QString &fileName) -{ - Core::IEditor *iface = Core::EditorManager::instance()->openEditor(fileName, id()); - if (!iface) { - qWarning() << "CEditorFactory::open: openEditor failed for " << fileName; - return 0; - } - return iface->document(); -} - Core::IEditor *EditorFactory::createEditor(QWidget *parent) { EditorWidget *widget = new EditorWidget(parent); diff --git a/src/plugins/pythoneditor/pythoneditorfactory.h b/src/plugins/pythoneditor/pythoneditorfactory.h index b483e6e4dc..5879e6fe39 100644 --- a/src/plugins/pythoneditor/pythoneditorfactory.h +++ b/src/plugins/pythoneditor/pythoneditorfactory.h @@ -55,11 +55,6 @@ public: QString displayName() const; /** - Opens file in new editor - */ - Core::IDocument *open(const QString &fileName); - - /** Creates and initializes new editor widget */ Core::IEditor *createEditor(QWidget *parent); diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp index 37304766d6..93a5d304f7 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp @@ -422,7 +422,8 @@ QbsBuildStepFactory::QbsBuildStepFactory(QObject *parent) : QList<Core::Id> QbsBuildStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const { if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_BUILD - && qobject_cast<QbsBuildConfiguration *>(parent->parent())) + && qobject_cast<QbsBuildConfiguration *>(parent->parent()) + && qobject_cast<QbsProject *>(parent->target()->project())) return QList<Core::Id>() << Core::Id(Constants::QBS_BUILDSTEP_ID); return QList<Core::Id>(); } @@ -437,7 +438,8 @@ QString QbsBuildStepFactory::displayNameForId(const Core::Id id) const bool QbsBuildStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const { if (parent->id() != Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD) - || !qobject_cast<QbsBuildConfiguration *>(parent->parent())) + || !qobject_cast<QbsBuildConfiguration *>(parent->parent()) + || !qobject_cast<QbsProject *>(parent->target()->project())) return false; return id == Core::Id(Constants::QBS_BUILDSTEP_ID); } diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp index bac939de88..b08b11ad5b 100644 --- a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp @@ -44,15 +44,15 @@ #include <QFileInfo> +// -------------------------------------------------------------------- +// Constants: +// -------------------------------------------------------------------- + static const char QBS_INSTALL_ROOT[] = "Qbs.InstallRoot"; static const char QBS_REMOVE_FIRST[] = "Qbs.RemoveFirst"; static const char QBS_DRY_RUN[] = "Qbs.DryRun"; static const char QBS_KEEP_GOING[] = "Qbs.DryKeepGoing"; -// -------------------------------------------------------------------- -// Constants: -// -------------------------------------------------------------------- - namespace QbsProjectManager { namespace Internal { @@ -363,7 +363,8 @@ QbsInstallStepFactory::QbsInstallStepFactory(QObject *parent) : QList<Core::Id> QbsInstallStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const { if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_DEPLOY - && qobject_cast<ProjectExplorer::DeployConfiguration *>(parent->parent())) + && qobject_cast<ProjectExplorer::DeployConfiguration *>(parent->parent()) + && qobject_cast<QbsProject *>(parent->target()->project())) return QList<Core::Id>() << Core::Id(Constants::QBS_INSTALLSTEP_ID); return QList<Core::Id>(); } @@ -378,7 +379,8 @@ QString QbsInstallStepFactory::displayNameForId(const Core::Id id) const bool QbsInstallStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const { if (parent->id() != Core::Id(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY) - || !qobject_cast<ProjectExplorer::DeployConfiguration *>(parent->parent())) + || !qobject_cast<ProjectExplorer::DeployConfiguration *>(parent->parent()) + || !qobject_cast<QbsProject *>(parent->target()->project())) return false; return id == Core::Id(Constants::QBS_INSTALLSTEP_ID); } diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index 0fca740baa..7c0da5b5c4 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -230,6 +230,16 @@ void QbsFileNode::setLine(int l) m_line = l; } +bool QbsFileNode::update(const qbs::CodeLocation &loc) +{ + const QString oldPath = path(); + const int oldLine = line(); + + setPath(loc.fileName()); + setLine(loc.line()); + return (line() != oldLine || path() != oldPath); +} + // --------------------------------------------------------------------------- // QbsBaseProjectNode: // --------------------------------------------------------------------------- @@ -322,19 +332,29 @@ QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp, const QString &productPath grp->location().line()); addFileNodes(QList<ProjectExplorer::FileNode *>() << idx, this); - updateQbsGroupData(grp, productPath); + updateQbsGroupData(grp, productPath, true, true); } bool QbsGroupNode::isEnabled() const { - return static_cast<QbsProductNode *>(parentFolderNode())->isEnabled() && qbsGroupData()->isEnabled(); + if (!parentFolderNode() || !m_qbsGroupData) + return false; + return static_cast<QbsProductNode *>(parentFolderNode())->isEnabled() + && m_qbsGroupData->isEnabled(); } -void QbsGroupNode::updateQbsGroupData(const qbs::GroupData *grp, const QString &productPath) +void QbsGroupNode::updateQbsGroupData(const qbs::GroupData *grp, const QString &productPath, + bool productWasEnabled, bool productIsEnabled) { + Q_ASSERT(grp); + if (grp == m_qbsGroupData && productPath == m_productPath) return; + bool groupWasEnabled = productWasEnabled && m_qbsGroupData && m_qbsGroupData->isEnabled(); + bool groupIsEnabled = productIsEnabled && grp->isEnabled(); + bool updateExisting = groupWasEnabled != groupIsEnabled; + m_productPath = productPath; m_qbsGroupData = grp; @@ -347,18 +367,17 @@ void QbsGroupNode::updateQbsGroupData(const qbs::GroupData *grp, const QString & if (idx) break; } + if (idx->update(grp->location()) || updateExisting) + idx->emitNodeUpdated(); - // idx not found, which should never happen! - Q_ASSERT(idx); - idx->setPath(grp->location().fileName()); - idx->setLine(grp->location().line()); + setupFiles(this, grp->allFilePaths(), productPath, updateExisting); - setupFiles(this, grp->allFilePaths(), m_productPath); - emitNodeUpdated(); + if (updateExisting) + emitNodeUpdated(); } void QbsGroupNode::setupFiles(QbsBaseProjectNode *root, const QStringList &files, - const QString &productPath) + const QString &productPath, bool updateExisting) { // Build up a tree of nodes: FileTreeNode tree; @@ -376,11 +395,12 @@ void QbsGroupNode::setupFiles(QbsBaseProjectNode *root, const QStringList &files FileTreeNode::reorder(&tree, productPath); FileTreeNode::simplify(&tree); - setupFolder(root, &tree, productPath); + setupFolder(root, &tree, productPath, updateExisting); } void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root, - const FileTreeNode *fileTree, const QString &baseDir) + const FileTreeNode *fileTree, const QString &baseDir, + bool updateExisting) { // We only need to care about FileNodes and FolderNodes here. Everything else is // handled elsewhere. @@ -408,8 +428,9 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root, if (c->isFile()) { ProjectExplorer::FileNode *fn = root->findFile(path); if (fn) { - fn->emitNodeUpdated(); // enabled might have changed filesToRemove.removeOne(fn); + if (updateExisting) + fn->emitNodeUpdated(); } else { fn = new ProjectExplorer::FileNode(path, ProjectExplorer::UnknownFileType, false); filesToAdd.append(fn); @@ -422,10 +443,12 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root, root->projectNode()->addFolderNodes(QList<FolderNode *>() << fn, root); } else { foldersToRemove.removeOne(fn); + if (updateExisting) + fn->emitNodeUpdated(); } fn->setDisplayName(displayNameFromPath(c->path(), baseDir)); - setupFolder(fn, c, c->path()); + setupFolder(fn, c, c->path(), updateExisting); } } root->projectNode()->removeFileNodes(filesToRemove, root); @@ -442,42 +465,43 @@ QbsProductNode::QbsProductNode(const qbs::ProductData *prd) : m_qbsProductData(0) { setIcon(m_productIcon); + + ProjectExplorer::FileNode *idx = new QbsFileNode(prd->location().fileName(), + ProjectExplorer::ProjectFileType, false, + prd->location().line()); + addFileNodes(QList<ProjectExplorer::FileNode *>() << idx, this); + setQbsProductData(prd); } bool QbsProductNode::isEnabled() const { - return qbsProductData()->isEnabled(); + return m_qbsProductData ? m_qbsProductData->isEnabled() : false; } void QbsProductNode::setQbsProductData(const qbs::ProductData *prd) { + Q_ASSERT(prd); if (m_qbsProductData == prd) return; + bool productWasEnabled = m_qbsProductData ? m_qbsProductData->isEnabled() : true; + bool productIsEnabled = prd->isEnabled(); + bool updateExisting = productWasEnabled != productIsEnabled; + setDisplayName(prd->name()); setPath(prd->location().fileName()); const QString &productPath = QFileInfo(prd->location().fileName()).absolutePath(); - // Set Product file node used to jump to the product - QList<ProjectExplorer::FileNode *> files = fileNodes(); + // Find the QbsFileNode we added earlier: QbsFileNode *idx = 0; - if (files.isEmpty()) { - idx = new QbsFileNode(prd->location().fileName(), - ProjectExplorer::ProjectFileType, false, - prd->location().line()); - addFileNodes(QList<ProjectExplorer::FileNode *>() << idx, this); - } else { - // Find the QbsFileNode we added earlier: - foreach (ProjectExplorer::FileNode *fn, files) { - idx = qobject_cast<QbsFileNode *>(fn); - if (idx) { - idx->setPath(prd->location().fileName()); - idx->setLine(prd->location().line()); - break; - } - } + foreach (ProjectExplorer::FileNode *fn, fileNodes()) { + idx = qobject_cast<QbsFileNode *>(fn); + if (idx) + break; } + if (idx->update(prd->location()) || updateExisting) + idx->emitNodeUpdated(); QList<ProjectExplorer::ProjectNode *> toAdd; QList<ProjectExplorer::ProjectNode *> toRemove = subProjectNodes(); @@ -485,13 +509,13 @@ void QbsProductNode::setQbsProductData(const qbs::ProductData *prd) foreach (const qbs::GroupData &grp, prd->groups()) { if (grp.name() == prd->name() && grp.location() == prd->location()) { // Set implicit product group right onto this node: - QbsGroupNode::setupFiles(this, grp.allFilePaths(), productPath); + QbsGroupNode::setupFiles(this, grp.allFilePaths(), productPath, updateExisting); continue; } QbsGroupNode *gn = findGroupNode(grp.name()); if (gn) { toRemove.removeOne(gn); - gn->updateQbsGroupData(&grp, productPath); + gn->updateQbsGroupData(&grp, productPath, productWasEnabled, productIsEnabled); } else { gn = new QbsGroupNode(&grp, productPath); toAdd.append(gn); @@ -502,7 +526,8 @@ void QbsProductNode::setQbsProductData(const qbs::ProductData *prd) removeProjectNodes(toRemove); m_qbsProductData = prd; - emitNodeUpdated(); + if (updateExisting) + emitNodeUpdated(); } QList<ProjectExplorer::RunConfiguration *> QbsProductNode::runConfigurationsFor(ProjectExplorer::Node *node) diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h index 75e7ac88f1..46cd384a95 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.h +++ b/src/plugins/qbsprojectmanager/qbsnodes.h @@ -59,6 +59,8 @@ public: void setLine(int l); + bool update(const qbs::CodeLocation &loc); + private: int m_line; }; @@ -116,18 +118,19 @@ public: QbsGroupNode(const qbs::GroupData *grp, const QString &productPath); bool isEnabled() const; - void updateQbsGroupData(const qbs::GroupData *grp, const QString &productPath); + void updateQbsGroupData(const qbs::GroupData *grp, const QString &productPath, + bool productWasEnabled, bool productIsEnabled); const qbs::GroupData *qbsGroupData() const { return m_qbsGroupData; } QString productPath() const; static void setupFiles(QbsBaseProjectNode *root, const QStringList &files, - const QString &productPath); + const QString &productPath, bool updateExisting); private: static void setupFolder(ProjectExplorer::FolderNode *folder, - const FileTreeNode *subFileTree, const QString &baseDir); + const FileTreeNode *subFileTree, const QString &baseDir, bool updateExisting); const qbs::GroupData *m_qbsGroupData; QString m_productPath; diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index f01cdd4e52..92f7efbf52 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -385,6 +385,8 @@ void QbsProject::parse(const QVariantMap &config, const QString &dir) this, SLOT(handleQbsParsingTaskSetup(QString,int))); connect(m_qbsSetupProjectJob, SIGNAL(taskProgress(int,qbs::AbstractJob*)), this, SLOT(handleQbsParsingProgress(int))); + + emit projectParsingStarted(); } void QbsProject::prepareForParsing() diff --git a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp index 7b67273fb8..56688e1c53 100644 --- a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp @@ -209,11 +209,13 @@ void AbstractFormEditorTool::mouseReleaseEvent(const QList<QGraphicsItem*> & /*i } } -void AbstractFormEditorTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneMouseEvent *) +void AbstractFormEditorTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneMouseEvent *event) { - FormEditorItem *formEditorItem = topFormEditorItem(itemList); - if (formEditorItem) - view()->changeToCustomTool(formEditorItem->qmlItemNode().modelNode()); + if (event->button() == Qt::LeftButton) { + FormEditorItem *formEditorItem = topFormEditorItem(itemList); + if (formEditorItem) + view()->changeToCustomTool(formEditorItem->qmlItemNode().modelNode()); + } } void AbstractFormEditorTool::showContextMenu(QGraphicsSceneMouseEvent *event) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.cpp index a90b169458..d9e22c9bb9 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.cpp @@ -120,7 +120,8 @@ void FormEditorCrumbleBar::onCrumblePathElementClicked(const QVariant &data) } else { crumblePath()->popElement(); nextFileIsCalledInternally(); - Core::EditorManager::openEditor(clickedCrumbleBarInfo.fileName); + Core::EditorManager::openEditor(clickedCrumbleBarInfo.fileName, Core::Id(), + Core::EditorManager::DoNotMakeVisible); if (!clickedCrumbleBarInfo.componentId.isEmpty()) { currentDesignDocument()->changeToSubComponent( currentDesignDocument()->rewriterView()->modelNodeForId(clickedCrumbleBarInfo.componentId)); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp index 04484561dc..cf7cd7770a 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp @@ -31,11 +31,13 @@ #include <QWheelEvent> #include <QDebug> +#include <QScrollBar> namespace QmlDesigner { FormEditorGraphicsView::FormEditorGraphicsView(QWidget *parent) : - QGraphicsView(parent) + QGraphicsView(parent), + m_isPanning(false) { setTransformationAnchor(QGraphicsView::AnchorUnderMouse); setResizeAnchor(QGraphicsView::AnchorViewCenter); @@ -74,6 +76,44 @@ void FormEditorGraphicsView::wheelEvent(QWheelEvent *event) } +void FormEditorGraphicsView::mousePressEvent(QMouseEvent *event) +{ + if (event->buttons().testFlag(Qt::MiddleButton)) { + m_isPanning = true; + m_panStartX = event->x(); + m_panStartY = event->y(); + setCursor(Qt::ClosedHandCursor); + event->accept(); + } else { + QGraphicsView::mousePressEvent(event); + } +} + +void FormEditorGraphicsView::mouseMoveEvent(QMouseEvent *event) +{ + if (m_isPanning) { + horizontalScrollBar()->setValue(horizontalScrollBar()->value() - (event->x() - m_panStartX)); + verticalScrollBar()->setValue(verticalScrollBar()->value() - (event->y() - m_panStartY)); + m_panStartX = event->x(); + m_panStartY = event->y(); + event->accept(); + }else { + QGraphicsView::mouseMoveEvent(event); + } +} + +void FormEditorGraphicsView::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_isPanning) { + + m_isPanning = false; + setCursor(Qt::ArrowCursor); + event->accept(); + }else { + QGraphicsView::mouseReleaseEvent(event); + } +} + void FormEditorGraphicsView::setRootItemRect(const QRectF &rect) { m_rootItemRect = rect; diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h index dd29d41e18..8b53691f0f 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h @@ -46,8 +46,12 @@ public: protected: void drawBackground(QPainter *painter, const QRectF &rect); void wheelEvent(QWheelEvent *event); - + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); private: + bool m_isPanning; + int m_panStartX, m_panStartY; QRectF m_rootItemRect; }; diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp index 17f556d15d..8bfcd04206 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp @@ -91,7 +91,7 @@ void FormEditorItem::updateGeometry() prepareGeometryChange(); m_boundingRect = qmlItemNode().instanceBoundingRect().adjusted(0, 0, 1., 1.); m_paintedBoundingRect = qmlItemNode().instancePaintedBoundingRect().united(m_boundingRect); - setTransform(qmlItemNode().instanceTransform()); + setTransform(qmlItemNode().instanceTransformWithContentTransform()); setTransform(m_attentionTransform, true); //the property for zValue is called z in QGraphicsObject if (qmlItemNode().instanceValue("z").isValid()) @@ -142,7 +142,7 @@ void FormEditorItem::setAttentionScale(double sinusScale) m_attentionTransform.translate(-centerPoint.x(), -centerPoint.y()); m_inverseAttentionTransform = m_attentionTransform.inverted(); prepareGeometryChange(); - setTransform(qmlItemNode().instanceTransform()); + setTransform(qmlItemNode().instanceTransformWithContentTransform()); setTransform(m_attentionTransform, true); } else { m_attentionTransform.reset(); @@ -391,7 +391,7 @@ SnapLineMap FormEditorItem::rightSnappingOffsets() const void FormEditorItem::updateSnappingLines(const QList<FormEditorItem*> &exceptionList, FormEditorItem *transformationSpaceItem) { - m_snappingLineCreator.update(exceptionList, transformationSpaceItem); + m_snappingLineCreator.update(exceptionList, transformationSpaceItem, this); } diff --git a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp index 4d35342924..b1e1800ddf 100644 --- a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp +++ b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp @@ -116,8 +116,9 @@ void MoveManipulator::updateHashes() // foreach (FormEditorItem* item, m_itemList) // m_beginItemRectHash[item] = item->mapRectToParent(item->qmlItemNode().instanceBoundingRect()); + QTransform fromSceneToContentItemTransform = m_snapper.containerFormEditorItem()->qmlItemNode().instanceSceneContentItemTransform().inverted(); foreach (FormEditorItem* item, m_itemList) { - QPointF positionInParentSpace = m_snapper.containerFormEditorItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item)); + QPointF positionInParentSpace = fromSceneToContentItemTransform.map(m_beginPositionInSceneSpaceHash.value(item)); m_beginItemRectHash[item].translate(positionInParentSpace - m_beginPositionHash.value(item)); m_beginPositionHash.insert(item, positionInParentSpace); } @@ -147,17 +148,19 @@ void MoveManipulator::begin(const QPointF &beginPoint) m_beginItemRectHash.insert(item, m_snapper.containerFormEditorItem()->mapRectFromItem(item, item->qmlItemNode().instanceBoundingRect())); } + QTransform fromContentItemToSceneTransform = m_snapper.containerFormEditorItem()->qmlItemNode().instanceSceneContentItemTransform(); foreach (FormEditorItem* item, m_itemList) { if (item && item->qmlItemNode().isValid()) { QPointF positionInParentSpace(item->qmlItemNode().instancePosition()); - QPointF positionInScenesSpace = m_snapper.containerFormEditorItem()->mapToScene(positionInParentSpace); + QPointF positionInScenesSpace = fromContentItemToSceneTransform.map(positionInParentSpace); m_beginPositionInSceneSpaceHash.insert(item, positionInScenesSpace); } } + QTransform fromSceneToContentItemTransform = m_snapper.containerFormEditorItem()->qmlItemNode().instanceSceneContentItemTransform().inverted(); foreach (FormEditorItem* item, m_itemList) { if (item && item->qmlItemNode().isValid()) { - QPointF positionInParentSpace = m_snapper.containerFormEditorItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item)); + QPointF positionInParentSpace = fromSceneToContentItemTransform.map(m_beginPositionInSceneSpaceHash.value(item)); m_beginPositionHash.insert(item, positionInParentSpace); QmlAnchors anchors(item->qmlItemNode().anchors()); @@ -270,8 +273,9 @@ void MoveManipulator::update(const QPointF& updatePoint, Snapper::Snapping useSn if (m_itemList.isEmpty()) { return; } else { - QPointF updatePointInContainerSpace(m_snapper.containerFormEditorItem()->mapFromScene(updatePoint)); - QPointF beginPointInContainerSpace(m_snapper.containerFormEditorItem()->mapFromScene(m_beginPoint)); + QTransform fromSceneToContentItemTransform = m_snapper.containerFormEditorItem()->qmlItemNode().instanceSceneContentItemTransform().inverted(); + QPointF updatePointInContainerSpace(fromSceneToContentItemTransform.map(updatePoint)); + QPointF beginPointInContainerSpace(fromSceneToContentItemTransform.map(m_beginPoint)); QPointF offsetVector(updatePointInContainerSpace - beginPointInContainerSpace); diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp index 5d92f0f4aa..e35b2ede56 100644 --- a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp +++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp @@ -77,8 +77,9 @@ void ResizeManipulator::begin(const QPointF &/*beginPoint*/) if (m_resizeController.isValid()) { m_isActive = true; m_beginBoundingRect = m_resizeController.formEditorItem()->qmlItemNode().instanceBoundingRect(); - m_beginToSceneTransform = m_resizeController.formEditorItem()->qmlItemNode().instanceSceneTransform(); - m_beginFromSceneTransform = m_beginToSceneTransform.inverted(); + m_beginFromContentItemToSceneTransform = m_resizeController.formEditorItem()->qmlItemNode().instanceSceneContentItemTransform(); + m_beginFromSceneToContentItemTransform = m_beginFromContentItemToSceneTransform.inverted(); + m_beginFromItemToSceneTransform = m_resizeController.formEditorItem()->qmlItemNode().instanceSceneTransform(); m_beginToParentTransform = m_resizeController.formEditorItem()->qmlItemNode().instanceTransform(); m_rewriterTransaction = m_view->beginRewriterTransaction(); m_snapper.updateSnappingLines(m_resizeController.formEditorItem()); @@ -116,7 +117,7 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use if (!containerItem) return; - QPointF updatePointInLocalSpace = m_beginFromSceneTransform.map(updatePoint); + QPointF updatePointInLocalSpace = m_beginFromSceneToContentItemTransform.map(updatePoint); QmlAnchors anchors(formEditorItem->qmlItemNode().anchors()); QRectF boundingRect(m_beginBoundingRect); @@ -372,7 +373,7 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use if (snap) m_graphicsLineList = m_snapper.generateSnappingLines(boundingRect, m_layerItem.data(), - m_beginToSceneTransform); + m_beginFromItemToSceneTransform); } } @@ -484,8 +485,9 @@ void ResizeManipulator::clear() deleteSnapLines(); m_beginBoundingRect = QRectF(); - m_beginFromSceneTransform = QTransform(); - m_beginToSceneTransform = QTransform(); + m_beginFromSceneToContentItemTransform = QTransform(); + m_beginFromContentItemToSceneTransform = QTransform(); + m_beginFromItemToSceneTransform = QTransform(); m_beginToParentTransform = QTransform(); m_beginTopMargin = 0.0; m_beginLeftMargin = 0.0; diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h index 61a8e23044..2654a36598 100644 --- a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h +++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h @@ -72,8 +72,9 @@ private: QWeakPointer<FormEditorView> m_view; QList<QGraphicsItem*> m_graphicsLineList; ResizeController m_resizeController; // hold the controller so that the handle cant be deleted - QTransform m_beginFromSceneTransform; - QTransform m_beginToSceneTransform; + QTransform m_beginFromSceneToContentItemTransform; + QTransform m_beginFromContentItemToSceneTransform; + QTransform m_beginFromItemToSceneTransform; QTransform m_beginToParentTransform; QRectF m_beginBoundingRect; QPointF m_beginBottomRightPoint; diff --git a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp index 83ea59b3f5..0179af9d36 100644 --- a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp +++ b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.cpp @@ -32,6 +32,8 @@ #include "formeditoritem.h" #include "formeditorview.h" +#include <QtDebug> + namespace QmlDesigner { SnappingLineCreator::SnappingLineCreator(FormEditorItem *formEditorItem) @@ -117,7 +119,7 @@ void SnappingLineCreator::generateLines(const QList<FormEditorItem*> &exceptionL } } -void SnappingLineCreator::setContainerPadding(double containerPadding) +void SnappingLineCreator::setContainerPaddingByGloablPadding(double containerPadding) { m_topPadding = containerPadding; m_bottomPadding = containerPadding; @@ -125,6 +127,14 @@ void SnappingLineCreator::setContainerPadding(double containerPadding) m_rightPadding = containerPadding; } +void SnappingLineCreator::setContainerPaddingByContentItem(const QRectF &contentRectangle, const QRectF &itemBoundingRectangle) +{ + m_topPadding = contentRectangle.top() - itemBoundingRectangle.top(); + m_bottomPadding = itemBoundingRectangle.bottom() - contentRectangle.bottom(); + m_leftPadding = contentRectangle.left() - itemBoundingRectangle.left(); + m_rightPadding = itemBoundingRectangle.right() - contentRectangle.right(); +} + void SnappingLineCreator::setSpacing(double spacing) { m_topOffset = spacing; @@ -134,10 +144,11 @@ void SnappingLineCreator::setSpacing(double spacing) } void SnappingLineCreator::update(const QList<FormEditorItem*> &exceptionList, - FormEditorItem *transformationSpaceItem) + FormEditorItem *transformationSpaceItem, + FormEditorItem *containerFormEditorItem) { clearLines(); - setContainerPadding(m_formEditorItem->formEditorView()->containerPadding()); + setContainerPaddingItem(containerFormEditorItem); setSpacing(m_formEditorItem->formEditorView()->spacing()); generateLines(exceptionList, transformationSpaceItem); } @@ -192,4 +203,15 @@ SnapLineMap SnappingLineCreator::rightOffsets() const return m_rightOffsetMap; } +void SnappingLineCreator::setContainerPaddingItem(FormEditorItem *transformationSpaceItem) +{ + QmlItemNode containerItemNode = transformationSpaceItem->qmlItemNode(); + QRectF contentRect = containerItemNode.instanceContentItemBoundingRect(); + + if (contentRect.isValid()) + setContainerPaddingByContentItem(contentRect, containerItemNode.instanceBoundingRect()); + else + setContainerPaddingByGloablPadding(m_formEditorItem->formEditorView()->containerPadding()); +} + } diff --git a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.h b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.h index 7c6adc804b..e3b4e7e2ac 100644 --- a/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.h +++ b/src/plugins/qmldesigner/components/formeditor/snappinglinecreator.h @@ -48,7 +48,8 @@ public: SnappingLineCreator(FormEditorItem *formEditorItem); void update(const QList<FormEditorItem*> &exceptionList, - FormEditorItem *transformationSpaceItem); + FormEditorItem *transformationSpaceItem, + FormEditorItem *containerFormEditorItem); SnapLineMap topLines() const; @@ -63,7 +64,9 @@ public: SnapLineMap leftOffsets() const; SnapLineMap rightOffsets() const; - void setContainerPadding(double containerPadding); + void setContainerPaddingItem(FormEditorItem *transformationSpaceItem); + void setContainerPaddingByGloablPadding(double containerPadding); + void setContainerPaddingByContentItem(const QRectF &contentRectangle, const QRectF &itemBoundingRectangle); void setSpacing(double spacing); protected: diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index 63c54a28e0..9a93b93a01 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -309,7 +309,7 @@ void DesignDocument::changeToSubComponent(const ModelNode &componentNode) void DesignDocument::changeToExternalSubComponent(const QString &fileName) { - Core::EditorManager::openEditor(fileName); + Core::EditorManager::openEditor(fileName, Core::Id(), Core::EditorManager::DoNotMakeVisible); } void DesignDocument::goIntoSelectedComponent() diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h index 69ede61ee4..62604686b4 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.h +++ b/src/plugins/qmldesigner/components/integration/designdocument.h @@ -59,7 +59,7 @@ class CrumbleBarInfo; class ViewManager; class QmlModelView; -class DesignDocument: public QObject +class QMLDESIGNERCORE_EXPORT DesignDocument: public QObject { Q_OBJECT public: diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp index 61ee53a083..deec645b3e 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp @@ -289,7 +289,8 @@ void NavigatorView::changeToComponent(const QModelIndex &index) if (index.isValid() && m_treeModel->data(index, Qt::UserRole).isValid()) { ModelNode doubleClickNode = m_treeModel->nodeForIndex(index); if (doubleClickNode.metaInfo().isFileComponent()) - Core::EditorManager::openEditor(doubleClickNode.metaInfo().componentFileName()); + Core::EditorManager::openEditor(doubleClickNode.metaInfo().componentFileName(), + Core::Id(), Core::EditorManager::DoNotMakeVisible); } } diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp index 1d071692e2..f4a12681a4 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp @@ -343,7 +343,7 @@ PropertyEditor::PropertyEditor(QWidget *parent) : m_setupCompleted(false), m_singleShotTimer(new QTimer(this)) { - m_updateShortcut = new QShortcut(QKeySequence("F5"), m_stackedWidget); + m_updateShortcut = new QShortcut(QKeySequence("F3"), m_stackedWidget); connect(m_updateShortcut, SIGNAL(activated()), this, SLOT(reloadQml())); m_stackedWidget->setStyleSheet( @@ -952,7 +952,7 @@ void PropertyEditor::scriptFunctionsChanged(const ModelNode &node, const QString void PropertyEditor::select(const ModelNode &node) { - if (QmlItemNode(node).isValid()) + if (QmlObjectNode(node).isValid()) m_selectedNode = node; else m_selectedNode = ModelNode(); @@ -1087,6 +1087,22 @@ QString PropertyEditor::locateQmlFile(const NodeMetaInfo &info, const QString &r static QDir resourcesDir(resourcePropertyEditorPath); QDir importDir(info.importDirectoryPath() + QLatin1String(Constants::QML_DESIGNER_SUBFOLDER)); + const QString versionString = QLatin1String("_") + QString::number(info.majorVersion()) + + QLatin1String("_") + + QString::number(info.minorVersion()); + + QString relativePathWithoutEnding = relativePath; + relativePathWithoutEnding.chop(4); + const QString relativePathWithVersion = relativePathWithoutEnding + versionString + QLatin1String(".qml"); + + //Check for qml files with versions first + if (importDir.exists(relativePathWithVersion)) + return importDir.absoluteFilePath(relativePathWithVersion); + if (fileSystemDir.exists(relativePathWithVersion)) + return fileSystemDir.absoluteFilePath(relativePathWithVersion); + if (resourcesDir.exists(relativePathWithVersion)) + return resourcesDir.absoluteFilePath(relativePathWithVersion); + if (importDir.exists(relativePath)) return importDir.absoluteFilePath(relativePath); if (fileSystemDir.exists(relativePath)) diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml index 95101e3599..00c8eaba43 100644 --- a/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml +++ b/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml @@ -130,12 +130,6 @@ QWidget { } } - ColorGroupBox { - caption: qsTr("Text color") - finished: finishedNotify - backendColor: backendValues.textColor - } - QWidget { layout: HorizontalLayout { Label { diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstance.h b/src/plugins/qmldesigner/designercore/include/nodeinstance.h index 284059f103..2f21d5cd1e 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstance.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstance.h @@ -59,6 +59,7 @@ public: bool isValid() const; void makeInvalid(); QRectF boundingRect() const; + QRectF contentItemBoundingRect() const; bool hasContent() const; bool isAnchoredBySibling() const; bool isAnchoredByChildren() const; @@ -66,6 +67,7 @@ public: bool isResizable() const; QTransform transform() const; QTransform contentTransform() const; + QTransform contentItemTransform() const; QTransform sceneTransform() const; bool isInLayoutable() const; QPointF position() const; @@ -93,8 +95,10 @@ protected: InformationName setInformationSize(const QSizeF &size); InformationName setInformationBoundingRect(const QRectF &rectangle); + InformationName setInformationContentItemBoundingRect(const QRectF &rectangle); InformationName setInformationTransform(const QTransform &transform); InformationName setInformationContentTransform(const QTransform &contentTransform); + InformationName setInformationContentItemTransform(const QTransform &contentItemTransform); InformationName setInformationPenWith(int penWidth); InformationName setInformationPosition(const QPointF &position); InformationName setInformationIsInLayoutable(bool isInLayoutable); diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h index 1d37ad4416..cebb50b590 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h @@ -53,6 +53,8 @@ public: bool isValid() const; bool isRootNode() const; + static bool isItemOrWindow(const ModelNode &modelNode); + QmlModelStateGroup states() const; QList<QmlItemNode> children() const; QList<QmlObjectNode> resources() const; @@ -75,8 +77,12 @@ public: QRectF instanceBoundingRect() const; QRectF instancePaintedBoundingRect() const; + QRectF instanceContentItemBoundingRect() const; QTransform instanceTransform() const; + QTransform instanceTransformWithContentTransform() const; + QTransform instanceTransformWithContentItemTransform() const; QTransform instanceSceneTransform() const; + QTransform instanceSceneContentItemTransform() const; QPointF instanceScenePosition() const; QPointF instancePosition() const; QSizeF instanceSize() const; diff --git a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h index bbbecdbe6f..092b19f6c0 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h @@ -50,8 +50,10 @@ public: bool hasNodeParent() const; bool hasInstanceParent() const; + bool hasInstanceParentItem() const; void setParentProperty(const NodeAbstractProperty &parentProeprty); QmlObjectNode instanceParent() const; + QmlItemNode instanceParentItem() const; void setId(const QString &id); QString id() const; @@ -105,6 +107,7 @@ public: protected: NodeInstance nodeInstance() const; QmlObjectNode nodeForInstance(const NodeInstance &instance) const; + QmlItemNode itemForInstance(const NodeInstance &instance) const; protected: QList<QmlModelState> allDefinedStates() const; diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp index e787d46c39..efc4ad080b 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp @@ -53,10 +53,12 @@ public: qint32 parentInstanceId; ModelNode modelNode; QRectF boundingRect; + QRectF contentItemBoundingRect; QPointF position; QSizeF size; QTransform transform; QTransform contentTransform; + QTransform contentItemTransform; QTransform sceneTransform; int penWidth; bool isAnchoredBySibling; @@ -144,6 +146,14 @@ QRectF NodeInstance::boundingRect() const return QRectF(); } +QRectF NodeInstance::contentItemBoundingRect() const +{ + if (isValid()) + return d->contentItemBoundingRect; + else + return QRectF(); +} + bool NodeInstance::hasContent() const { if (isValid()) @@ -199,6 +209,14 @@ QTransform NodeInstance::contentTransform() const else return QTransform(); } + +QTransform NodeInstance::contentItemTransform() const +{ + if (isValid()) + return d->contentItemTransform; + else + return QTransform(); +} QTransform NodeInstance::sceneTransform() const { if (isValid()) @@ -333,6 +351,16 @@ InformationName NodeInstance::setInformationBoundingRect(const QRectF &rectangle return NoInformationChange; } +InformationName NodeInstance::setInformationContentItemBoundingRect(const QRectF &rectangle) +{ + if (d->contentItemBoundingRect != rectangle) { + d->contentItemBoundingRect = rectangle; + return ContentItemBoundingRect; + } + + return NoInformationChange; +} + InformationName NodeInstance::setInformationTransform(const QTransform &transform) { if (d->transform != transform) { @@ -353,6 +381,16 @@ InformationName NodeInstance::setInformationContentTransform(const QTransform &c return NoInformationChange; } +InformationName NodeInstance::setInformationContentItemTransform(const QTransform &contentItemTransform) +{ + if (d->contentItemTransform != contentItemTransform) { + d->contentItemTransform = contentItemTransform; + return ContentItemTransform; + } + + return NoInformationChange; +} + InformationName NodeInstance::setInformationPenWith(int penWidth) { if (d->penWidth != penWidth) { @@ -489,8 +527,10 @@ InformationName NodeInstance::setInformation(InformationName name, const QVarian switch (name) { case Size: return setInformationSize(information.toSizeF()); case BoundingRect: return setInformationBoundingRect(information.toRectF()); + case ContentItemBoundingRect: setInformationContentItemBoundingRect(information.toRectF()); case Transform: return setInformationTransform(information.value<QTransform>()); case ContentTransform: return setInformationContentTransform(information.value<QTransform>()); + case ContentItemTransform: return setInformationContentItemTransform(information.value<QTransform>()); case PenWidth: return setInformationPenWith(information.toInt()); case Position: return setInformationPosition(information.toPointF()); case IsInLayoutable: return setInformationIsInLayoutable(information.toBool()); diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp index f9626b18fc..0da7a5445c 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp @@ -37,9 +37,7 @@ namespace QmlDesigner { -namespace { - -bool isItemOrWindow(const ModelNode &modelNode) +bool QmlItemNode::isItemOrWindow(const ModelNode &modelNode) { if (modelNode.metaInfo().isSubclassOf("QtQuick.Item", -1, -1)) return true; @@ -50,8 +48,6 @@ bool isItemOrWindow(const ModelNode &modelNode) return false; } -} - bool QmlItemNode::isValid() const { return QmlModelNodeFacade::isValid() && modelNode().metaInfo().isValid() && isItemOrWindow(modelNode()); @@ -239,16 +235,36 @@ QRectF QmlItemNode::instancePaintedBoundingRect() const return nodeInstance().boundingRect(); } +QRectF QmlItemNode::instanceContentItemBoundingRect() const +{ + return nodeInstance().contentItemBoundingRect(); +} + QTransform QmlItemNode::instanceTransform() const { return nodeInstance().transform(); } +QTransform QmlItemNode::instanceTransformWithContentTransform() const +{ + return nodeInstance().transform() * nodeInstance().contentTransform(); +} + +QTransform QmlItemNode::instanceTransformWithContentItemTransform() const +{ + return nodeInstance().transform() * nodeInstance().contentItemTransform(); +} + QTransform QmlItemNode::instanceSceneTransform() const { return nodeInstance().sceneTransform(); } +QTransform QmlItemNode::instanceSceneContentItemTransform() const +{ + return nodeInstance().sceneTransform() * nodeInstance().contentItemTransform(); +} + QPointF QmlItemNode::instanceScenePosition() const { QmlItemNode parentNode = instanceParent().toQmlItemNode(); diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp index 42643ed82f..42c41dc6ab 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp @@ -444,6 +444,11 @@ QmlObjectNode QmlObjectNode::nodeForInstance(const NodeInstance &instance) const return QmlObjectNode(ModelNode(instance.modelNode(), qmlModelView())); } +QmlItemNode QmlObjectNode::itemForInstance(const NodeInstance &instance) const +{ + return QmlItemNode(ModelNode(instance.modelNode(), qmlModelView())); +} + bool QmlObjectNode::hasNodeParent() const { return modelNode().hasParentProperty(); @@ -454,6 +459,13 @@ bool QmlObjectNode::hasInstanceParent() const return nodeInstance().parentId() >= 0 && qmlModelView()->nodeInstanceView()->hasInstanceForId(nodeInstance().parentId()); } +bool QmlObjectNode::hasInstanceParentItem() const +{ + return nodeInstance().parentId() >= 0 + && qmlModelView()->nodeInstanceView()->hasInstanceForId(nodeInstance().parentId()) + && QmlItemNode::isItemOrWindow(qmlModelView()->modelNodeForInternalId(nodeInstance().parentId())); +} + void QmlObjectNode::setParentProperty(const NodeAbstractProperty &parentProeprty) { @@ -468,6 +480,14 @@ QmlObjectNode QmlObjectNode::instanceParent() const return QmlObjectNode(); } +QmlItemNode QmlObjectNode::instanceParentItem() const +{ + if (hasInstanceParentItem()) + return itemForInstance(qmlModelView()->nodeInstanceView()->instanceForId(nodeInstance().parentId())); + + return QmlItemNode(); +} + void QmlObjectNode::setId(const QString &id) { modelNode().setId(id); diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 50120f9fa4..9956ecab1a 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -47,6 +47,7 @@ #include <qmljs/qmljscheck.h> #include <qmljs/qmljsutils.h> #include <qmljs/qmljsmodelmanagerinterface.h> +#include <qmljs/qmljsqrcparser.h> #include <QSet> #include <QDir> @@ -362,10 +363,17 @@ public: } else if (importInfo.isValid() && importInfo.type() == ImportInfo::DirectoryImport) { QString path = importInfo.path(); QDir dir(m_doc->path()); + // should probably try to make it relatve to some import path, not to the document path QString relativeDir = dir.relativeFilePath(path); QString name = relativeDir.replace(QLatin1Char('/'), QLatin1Char('.')); if (!name.isEmpty()) typeName.prepend(name + QLatin1Char('.')); + } else if (importInfo.isValid() && importInfo.type() == ImportInfo::QrcDirectoryImport) { + QString path = QrcParser::normalizedQrcDirectoryPath(importInfo.path()); + path = path.mid(1, path.size() - ((path.size() > 1) ? 2 : 1)); + const QString name = path.replace(QLatin1Char('/'), QLatin1Char('.')); + if (!name.isEmpty()) + typeName.prepend(name + QLatin1Char('.')); } } } diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp index 029e5e082a..874587a64c 100644 --- a/src/plugins/qmldesigner/designersettings.cpp +++ b/src/plugins/qmldesigner/designersettings.cpp @@ -35,8 +35,7 @@ using namespace QmlDesigner; DesignerSettings::DesignerSettings() - : openDesignMode(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT), - itemSpacing(0), + : itemSpacing(0), containerPadding(0), canvasWidth(10000), canvasHeight(10000), @@ -50,9 +49,6 @@ void DesignerSettings::fromSettings(QSettings *settings) { settings->beginGroup(QLatin1String(QmlDesigner::Constants::QML_SETTINGS_GROUP)); settings->beginGroup(QLatin1String(QmlDesigner::Constants::QML_DESIGNER_SETTINGS_GROUP)); - openDesignMode = settings->value( - QLatin1String(QmlDesigner::Constants::QML_OPENDESIGNMODE_SETTINGS_KEY), - bool(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT)).toBool(); itemSpacing = settings->value( QLatin1String(QmlDesigner::Constants::QML_ITEMSPACING_KEY), QVariant(6)).toInt(); containerPadding = settings->value( @@ -76,7 +72,6 @@ void DesignerSettings::toSettings(QSettings *settings) const { settings->beginGroup(QLatin1String(QmlDesigner::Constants::QML_SETTINGS_GROUP)); settings->beginGroup(QLatin1String(QmlDesigner::Constants::QML_DESIGNER_SETTINGS_GROUP)); - settings->setValue(QLatin1String(QmlDesigner::Constants::QML_OPENDESIGNMODE_SETTINGS_KEY), openDesignMode); settings->setValue(QLatin1String(QmlDesigner::Constants::QML_ITEMSPACING_KEY), itemSpacing); settings->setValue(QLatin1String(QmlDesigner::Constants::QML_CONTAINERPADDING_KEY), containerPadding); settings->setValue(QLatin1String(QmlDesigner::Constants::QML_CANVASWIDTH_KEY), canvasWidth); @@ -92,8 +87,7 @@ void DesignerSettings::toSettings(QSettings *settings) const bool DesignerSettings::equals(const DesignerSettings &other) const { - return openDesignMode == other.openDesignMode - && containerPadding == other.containerPadding + return containerPadding == other.containerPadding && canvasWidth == other.canvasWidth && canvasHeight == other.canvasHeight && warningsInDesigner == other.warningsInDesigner diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index d38927a19b..a42d47155a 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -47,7 +47,6 @@ public: void toSettings(QSettings *) const; bool equals(const DesignerSettings &other) const; - bool openDesignMode; int itemSpacing; int containerPadding; int canvasWidth; diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index d01ae232b5..b8df512dc7 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -451,7 +451,8 @@ void DesignModeWidget::toolBarOnGoBackClicked() if (m_navigatorHistoryCounter > 0) { --m_navigatorHistoryCounter; m_keepNavigatorHistory = true; - Core::EditorManager::openEditor(m_navigatorHistory.at(m_navigatorHistoryCounter)); + Core::EditorManager::openEditor(m_navigatorHistory.at(m_navigatorHistoryCounter), + Core::Id(), Core::EditorManager::DoNotMakeVisible); m_keepNavigatorHistory = false; } } @@ -461,7 +462,8 @@ void DesignModeWidget::toolBarOnGoForwardClicked() if (m_navigatorHistoryCounter < (m_navigatorHistory.size() - 1)) { ++m_navigatorHistoryCounter; m_keepNavigatorHistory = true; - Core::EditorManager::openEditor(m_navigatorHistory.at(m_navigatorHistoryCounter)); + Core::EditorManager::openEditor(m_navigatorHistory.at(m_navigatorHistoryCounter), + Core::Id(), Core::EditorManager::DoNotMakeVisible); m_keepNavigatorHistory = false; } } diff --git a/src/plugins/qmldesigner/qmldesigner_dependencies.pri b/src/plugins/qmldesigner/qmldesigner_dependencies.pri index d341b0e0f6..654b5cb1c6 100644 --- a/src/plugins/qmldesigner/qmldesigner_dependencies.pri +++ b/src/plugins/qmldesigner/qmldesigner_dependencies.pri @@ -10,6 +10,7 @@ QTC_PLUGIN_DEPENDS += \ qtsupport \ projectexplorer INCLUDEPATH *= \ + $$PWD \ $$PWD/../../../share/qtcreator/qml/qmlpuppet/interfaces \ $$PWD/designercore \ $$PWD/designercore/include \ diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index b083ee8291..366eef4449 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -53,7 +53,6 @@ const char GO_INTO_COMPONENT[] = "QmlDesigner.GoIntoComponent"; // This setting is also accessed by the QMlJsEditor. const char QML_SETTINGS_GROUP[] = "QML"; const char QML_DESIGNER_SETTINGS_GROUP[] = "Designer"; -const char QML_OPENDESIGNMODE_SETTINGS_KEY[] = "OpenDesignMode"; const char QML_ITEMSPACING_KEY[] = "ItemSpacing"; const char QML_CONTAINERPADDING_KEY[] = "ContainerPadding"; const char QML_CANVASWIDTH_KEY[] = "CanvasWidth"; @@ -64,7 +63,6 @@ const char QML_WARNIN_FOR_FEATURES_IN_DESIGNER_KEY[] = "WarnAboutQtQuickFeatures const char QML_WARNIN_FOR_DESIGNER_FEATURES_IN_EDITOR_KEY[] = "WarnAboutQtQuickDesignerFeaturesInCodeEditor"; const char QML_SHOW_DEBUGVIEW[] = "ShowQtQuickDesignerDebugView"; const char QML_ENABLE_DEBUGVIEW[] = "EnableQtQuickDesignerDebugView"; -enum { QML_OPENDESIGNMODE_DEFAULT = 0 }; // 0 for text mode, 1 for design mode const char SETTINGS_CATEGORY_QML_ICON[] = ":/core/images/category_qml.png"; diff --git a/src/plugins/qmljseditor/qmljseditor.pro b/src/plugins/qmljseditor/qmljseditor.pro index d6201be052..9a40aa33ea 100644 --- a/src/plugins/qmljseditor/qmljseditor.pro +++ b/src/plugins/qmljseditor/qmljseditor.pro @@ -68,7 +68,6 @@ SOURCES += \ qmljswrapinloader.cpp RESOURCES += qmljseditor.qrc -OTHER_FILES += QmlJSEditor.mimetypes.xml FORMS += \ quicktoolbarsettingspage.ui \ diff --git a/src/plugins/qmljseditor/qmljseditor.qbs b/src/plugins/qmljseditor/qmljseditor.qbs index 32d3ef4d35..72c9294c14 100644 --- a/src/plugins/qmljseditor/qmljseditor.qbs +++ b/src/plugins/qmljseditor/qmljseditor.qbs @@ -17,7 +17,6 @@ QtcPlugin { Depends { name: "CPlusPlus" } files: [ - "QmlJSEditor.mimetypes.xml", "jsfilewizard.cpp", "jsfilewizard.h", "qmlexpressionundercursor.cpp", diff --git a/src/plugins/qmljseditor/qmljseditor.qrc b/src/plugins/qmljseditor/qmljseditor.qrc index 38e57bac80..35ecba5f6e 100644 --- a/src/plugins/qmljseditor/qmljseditor.qrc +++ b/src/plugins/qmljseditor/qmljseditor.qrc @@ -1,6 +1,5 @@ <RCC> <qresource prefix="/qmljseditor"> - <file>QmlJSEditor.mimetypes.xml</file> <file>images/qmlfile.png</file> </qresource> </RCC> diff --git a/src/plugins/qmljseditor/qmljseditoreditable.cpp b/src/plugins/qmljseditor/qmljseditoreditable.cpp index ee75f356c1..8af4f1a5cb 100644 --- a/src/plugins/qmljseditor/qmljseditoreditable.cpp +++ b/src/plugins/qmljseditor/qmljseditoreditable.cpp @@ -33,7 +33,6 @@ #include <qmljstools/qmljstoolsconstants.h> #include <texteditor/texteditorconstants.h> -#include <qmldesigner/qmldesignerconstants.h> #include <projectexplorer/projectexplorerconstants.h> #include <coreplugin/mimedatabase.h> @@ -52,41 +51,13 @@ QmlJSEditorEditable::QmlJSEditorEditable(QmlJSTextEditorWidget *editor) m_context.add(ProjectExplorer::Constants::LANG_QMLJS); } -// Use preferred mode from Bauhaus settings -static bool openInDesignMode() -{ - static bool bauhausDetected = false; - static bool bauhausPresent = false; - // Check if Bauhaus is loaded, that is, a Design mode widget is - // registered for the QML mime type. - if (!bauhausDetected) { - if (const Core::IMode *dm = Core::ModeManager::mode(Core::Constants::MODE_DESIGN)) - if (const Core::DesignMode *designMode = qobject_cast<const Core::DesignMode *>(dm)) - bauhausPresent = designMode->registeredMimeTypes().contains(QLatin1String(QmlJSTools::Constants::QML_MIMETYPE)); - bauhausDetected = true; - } - if (!bauhausPresent) - return false; - - return bool(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT); -} - -Core::Id QmlJSEditorEditable::preferredModeType() const +bool QmlJSEditorEditable::isDesignModePreferred() const { + // stay in design mode if we are there Core::IMode *mode = Core::ModeManager::currentMode(); - if (mode && (mode->type() == Core::Constants::MODE_DESIGN_TYPE - || mode->type() == Core::Constants::MODE_EDIT_TYPE)) - { - return mode->type(); - } - - // if we are in other mode than edit or design, use the hard-coded default. - // because the editor opening decision is modal, it would be confusing to - // have the user also access to this failsafe setting. - if (editorWidget()->mimeType() == QLatin1String(QmlJSTools::Constants::QML_MIMETYPE) - && openInDesignMode()) - return Core::Id(Core::Constants::MODE_DESIGN_TYPE); - return Core::Id(); + if (mode && mode->id() == Core::Constants::MODE_DESIGN) + return true; + return false; } void QmlJSEditorEditable::setTextCodec(QTextCodec *codec, TextCodecReason reason) diff --git a/src/plugins/qmljseditor/qmljseditoreditable.h b/src/plugins/qmljseditor/qmljseditoreditable.h index ac7d161588..07550c50e4 100644 --- a/src/plugins/qmljseditor/qmljseditoreditable.h +++ b/src/plugins/qmljseditor/qmljseditoreditable.h @@ -49,7 +49,7 @@ public: Core::Id id() const; bool isTemporary() const { return false; } bool open(QString *errorString, const QString &fileName, const QString &realFileName); - Core::Id preferredModeType() const; + bool isDesignModePreferred() const; void setTextCodec(QTextCodec *codec, TextCodecReason = TextCodecOtherReason); const Utils::CommentDefinition *commentDefinition() const; diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp index 21044644d2..afaafd6c33 100644 --- a/src/plugins/qmljseditor/qmljseditorplugin.cpp +++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp @@ -53,7 +53,6 @@ #include <coreplugin/icore.h> #include <coreplugin/coreconstants.h> -#include <coreplugin/mimedatabase.h> #include <coreplugin/id.h> #include <coreplugin/fileiconprovider.h> #include <coreplugin/actionmanager/actionmanager.h> @@ -114,9 +113,6 @@ QmlJSEditorPlugin::~QmlJSEditorPlugin() bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage) { - if (!Core::ICore::mimeDatabase()->addMimeTypes(QLatin1String(":/qmljseditor/QmlJSEditor.mimetypes.xml"), errorMessage)) - return false; - m_modelManager = QmlJS::ModelManagerInterface::instance(); addAutoReleasedObject(new QmlJSSnippetProvider); diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp index 50ebf9a6b2..af0d7b461b 100644 --- a/src/plugins/qmljseditor/qmljsfindreferences.cpp +++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp @@ -29,7 +29,6 @@ #include "qmljsfindreferences.h" -#include <texteditor/basetexteditor.h> #include <texteditor/basefilefind.h> #include <find/searchresultwindow.h> #include <extensionsystem/pluginmanager.h> @@ -985,12 +984,10 @@ void FindReferences::setPaused(bool paused) void FindReferences::openEditor(const Find::SearchResultItem &item) { if (item.path.size() > 0) { - TextEditor::BaseTextEditorWidget::openEditorAt(QDir::fromNativeSeparators(item.path.first()), - item.lineNumber, item.textMarkPos, Core::Id(), - Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()), + item.lineNumber, item.textMarkPos); } else { - Core::EditorManager::openEditor(QDir::fromNativeSeparators(item.text), - Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(QDir::fromNativeSeparators(item.text)); } } diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp index 7e816cf397..c33c1d13cd 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.cpp +++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp @@ -43,6 +43,7 @@ #include <qmljs/parser/qmljsast_p.h> #include <qmljs/parser/qmljsastfwd_p.h> #include <qmljs/qmljsutils.h> +#include <qmljs/qmljsqrcparser.h> #include <texteditor/itexteditor.h> #include <texteditor/basetexteditor.h> #include <texteditor/helpitem.h> @@ -134,9 +135,15 @@ static inline QString getModuleName(const ScopeChain &scopeChain, const Document } else if (importInfo.isValid() && importInfo.type() == ImportInfo::DirectoryImport) { const QString path = importInfo.path(); const QDir dir(qmlDocument->path()); + // should probably try to make it relatve to some import path, not to the document path QString relativeDir = dir.relativeFilePath(path); const QString name = relativeDir.replace(QLatin1Char('/'), QLatin1Char('.')); return name; + } else if (importInfo.isValid() && importInfo.type() == ImportInfo::QrcDirectoryImport) { + QString path = QrcParser::normalizedQrcDirectoryPath(importInfo.path()); + path = path.mid(1, path.size() - ((path.size() > 1) ? 2 : 1)); + const QString name = path.replace(QLatin1Char('/'), QLatin1Char('.')); + return name; } } return QString(); diff --git a/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml b/src/plugins/qmljstools/QmlJSTools.mimetypes.xml index a1bdef531e..a1bdef531e 100644 --- a/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml +++ b/src/plugins/qmljstools/QmlJSTools.mimetypes.xml diff --git a/src/plugins/qmljstools/qmlconsoleitemdelegate.cpp b/src/plugins/qmljstools/qmlconsoleitemdelegate.cpp index 03af88b55f..def7176d3b 100644 --- a/src/plugins/qmljstools/qmlconsoleitemdelegate.cpp +++ b/src/plugins/qmljstools/qmlconsoleitemdelegate.cpp @@ -34,6 +34,7 @@ #include <QTreeView> #include <QScrollBar> #include <QTextLayout> +#include <QUrl> const char CONSOLE_LOG_BACKGROUND_COLOR[] = "#E8EEF2"; const char CONSOLE_WARNING_BACKGROUND_COLOR[] = "#F6F4EB"; @@ -216,6 +217,9 @@ void QmlConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem if (showFileLineInfo) { // Check for file info QString file = index.data(QmlConsoleItemModel::FileRole).toString(); + const QUrl fileUrl = QUrl(file); + if (fileUrl.isLocalFile()) + file = fileUrl.toLocalFile(); if (!file.isEmpty()) { QFontMetrics fm(option.font); // Paint FileArea diff --git a/src/plugins/qmljstools/qmlconsoleview.cpp b/src/plugins/qmljstools/qmlconsoleview.cpp index c44ddd7f45..872b4ae867 100644 --- a/src/plugins/qmljstools/qmlconsoleview.cpp +++ b/src/plugins/qmljstools/qmlconsoleview.cpp @@ -31,7 +31,7 @@ #include "qmlconsoleitemdelegate.h" #include "qmlconsoleitemmodel.h" -#include <texteditor/basetexteditor.h> +#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/manhattanstyle.h> #include <utils/hostosinfo.h> @@ -44,6 +44,7 @@ #include <QScrollBar> #include <QStyleFactory> #include <QString> +#include <QUrl> using namespace QmlJS; @@ -225,13 +226,15 @@ void QmlConsoleView::onRowActivated(const QModelIndex &index) return; // See if we have file and line Info - QString filePath = model()->data(index, - QmlConsoleItemModel::FileRole).toString(); + QString filePath = model()->data(index, QmlConsoleItemModel::FileRole).toString(); + const QUrl fileUrl = QUrl(filePath); + if (fileUrl.isLocalFile()) + filePath = fileUrl.toLocalFile(); if (!filePath.isEmpty()) { QFileInfo fi(filePath); if (fi.exists() && fi.isFile() && fi.isReadable()) { int line = model()->data(index, QmlConsoleItemModel::LineRole).toInt(); - TextEditor::BaseTextEditorWidget::openEditorAt(fi.canonicalFilePath(), line); + Core::EditorManager::openEditorAt(fi.canonicalFilePath(), line); } } } @@ -244,6 +247,9 @@ void QmlConsoleView::copyToClipboard(const QModelIndex &index) QString contents = model()->data(index, QmlConsoleItemModel::ExpressionRole).toString(); // See if we have file and line Info QString filePath = model()->data(index, QmlConsoleItemModel::FileRole).toString(); + const QUrl fileUrl = QUrl(filePath); + if (fileUrl.isLocalFile()) + filePath = fileUrl.toLocalFile(); if (!filePath.isEmpty()) { contents = QString(QLatin1String("%1 %2: %3")).arg(contents).arg(filePath).arg( model()->data(index, QmlConsoleItemModel::LineRole).toString()); @@ -259,6 +265,9 @@ bool QmlConsoleView::canShowItemInTextEditor(const QModelIndex &index) // See if we have file and line Info QString filePath = model()->data(index, QmlConsoleItemModel::FileRole).toString(); + const QUrl fileUrl = QUrl(filePath); + if (fileUrl.isLocalFile()) + filePath = fileUrl.toLocalFile(); if (!filePath.isEmpty()) { QFileInfo fi(filePath); if (fi.exists() && fi.isFile() && fi.isReadable()) diff --git a/src/plugins/qmljstools/qmljsfunctionfilter.cpp b/src/plugins/qmljstools/qmljsfunctionfilter.cpp index 3c500314c9..33c1eb9356 100644 --- a/src/plugins/qmljstools/qmljsfunctionfilter.cpp +++ b/src/plugins/qmljstools/qmljsfunctionfilter.cpp @@ -30,7 +30,7 @@ #include "qmljsfunctionfilter.h" #include "qmljslocatordata.h" -#include <texteditor/basetexteditor.h> +#include <coreplugin/editormanager/editormanager.h> #include <QStringMatcher> @@ -111,6 +111,5 @@ QList<Locator::FilterEntry> FunctionFilter::matchesFor(QFutureInterface<Locator: void FunctionFilter::accept(Locator::FilterEntry selection) const { const LocatorData::Entry entry = qvariant_cast<LocatorData::Entry>(selection.internalData); - TextEditor::BaseTextEditorWidget::openEditorAt(entry.fileName, entry.line, entry.column, - Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditorAt(entry.fileName, entry.line, entry.column); } diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index 07e9ec06c1..d2c25d49f7 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -58,6 +58,7 @@ #include <QTextStream> #include <QTimer> #include <QRegExp> +#include <QtAlgorithms> #include <QDebug> @@ -406,6 +407,114 @@ void ModelManager::removeFiles(const QStringList &files) } } +namespace { +bool pInfoLessThanActive(const ModelManager::ProjectInfo &p1, const ModelManager::ProjectInfo &p2) +{ + QStringList s1 = p1.activeResourceFiles; + QStringList s2 = p2.activeResourceFiles; + if (s1.size() < s2.size()) + return true; + if (s1.size() > s2.size()) + return false; + for (int i = 0; i < s1.size(); ++i) { + if (s1.at(i) < s2.at(i)) + return true; + else if (s1.at(i) > s2.at(i)) + return false; + } + return false; +} + +bool pInfoLessThanAll(const ModelManager::ProjectInfo &p1, const ModelManager::ProjectInfo &p2) +{ + QStringList s1 = p1.allResourceFiles; + QStringList s2 = p2.allResourceFiles; + if (s1.size() < s2.size()) + return true; + if (s1.size() > s2.size()) + return false; + for (int i = 0; i < s1.size(); ++i) { + if (s1.at(i) < s2.at(i)) + return true; + else if (s1.at(i) > s2.at(i)) + return false; + } + return false; +} +} + +QStringList ModelManager::filesAtQrcPath(const QString &path, const QLocale *locale, + ProjectExplorer::Project *project, + QrcResourceSelector resources) +{ + QString normPath = QrcParser::normalizedQrcFilePath(path); + QList<ProjectInfo> pInfos; + if (project) + pInfos.append(projectInfo(project)); + else + pInfos = projectInfos(); + + QStringList res; + QSet<QString> pathsChecked; + foreach (const ModelManager::ProjectInfo &pInfo, pInfos) { + QStringList qrcFilePaths; + if (resources == ActiveQrcResources) + qrcFilePaths = pInfo.activeResourceFiles; + else + qrcFilePaths = pInfo.allResourceFiles; + foreach (const QString &qrcFilePath, qrcFilePaths) { + if (pathsChecked.contains(qrcFilePath)) + continue; + pathsChecked.insert(qrcFilePath); + QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath); + if (qrcFile.isNull()) + continue; + qrcFile->collectFilesAtPath(normPath, &res, locale); + } + } + res.sort(); // make the result predictable + return res; +} + +QMap<QString, QStringList> ModelManager::filesInQrcPath(const QString &path, + const QLocale *locale, + ProjectExplorer::Project *project, + bool addDirs, + QrcResourceSelector resources) +{ + QString normPath = QrcParser::normalizedQrcDirectoryPath(path); + QList<ProjectInfo> pInfos; + if (project) { + pInfos.append(projectInfo(project)); + } else { + pInfos = projectInfos(); + if (resources == ActiveQrcResources) // make the result predictable + qSort(pInfos.begin(), pInfos.end(), &pInfoLessThanActive); + else + qSort(pInfos.begin(), pInfos.end(), &pInfoLessThanAll); + } + QMap<QString, QStringList> res; + QSet<QString> pathsChecked; + foreach (const ModelManager::ProjectInfo &pInfo, pInfos) { + QStringList qrcFilePaths; + if (resources == ActiveQrcResources) + qrcFilePaths = pInfo.activeResourceFiles; + else + qrcFilePaths = pInfo.allResourceFiles; + foreach (const QString &qrcFilePath, qrcFilePaths) { + if (pathsChecked.contains(qrcFilePath)) + continue; + pathsChecked.insert(qrcFilePath); + QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath); + + if (qrcFile.isNull()) + continue; + qrcFile->collectFilesInPath(normPath, &res, addDirs, locale); + } + } + return res; +} + QList<ModelManager::ProjectInfo> ModelManager::projectInfos() const { QMutexLocker locker(&m_mutex); @@ -462,6 +571,12 @@ void ModelManager::updateProjectInfo(const ProjectInfo &pinfo) } updateSourceFiles(newFiles, false); + // update qrc cache + foreach (const QString &newQrc, pinfo.allResourceFiles) + m_qrcCache.addPath(newQrc); + foreach (const QString &oldQrc, oldInfo.allResourceFiles) + m_qrcCache.removePath(oldQrc); + // dump builtin types if the shipped definitions are probably outdated and the // Qt version ships qmlplugindump if (QtSupport::QtVersionNumber(pinfo.qtVersionString) > QtSupport::QtVersionNumber(4, 8, 5)) @@ -497,6 +612,11 @@ ModelManagerInterface::ProjectInfo ModelManager::projectInfoForPath(QString path void ModelManager::emitDocumentChangedOnDisk(Document::Ptr doc) { emit documentChangedOnDisk(doc); } +void ModelManager::updateQrcFile(const QString &path) +{ + m_qrcCache.updatePath(path); +} + void ModelManager::updateDocument(Document::Ptr doc) { { @@ -560,6 +680,23 @@ static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapsho scannedPaths->insert(importName); } } + } else if (import.type() == ImportInfo::QrcFileImport) { + QStringList importPaths = ModelManagerInterface::instance()->filesAtQrcPath(importName); + foreach (const QString &importPath, importPaths) { + if (! snapshot.document(importPath)) + *importedFiles += importPath; + } + } else if (import.type() == ImportInfo::QrcDirectoryImport) { + QMapIterator<QString,QStringList> dirContents(ModelManagerInterface::instance()->filesInQrcPath(importName)); + while (dirContents.hasNext()) { + dirContents.next(); + if (Document::isQmlLikeOrJsLanguage(Document::guessLanguageFromSuffix(dirContents.key()))) { + foreach (const QString &filePath, dirContents.value()) { + if (! snapshot.document(filePath)) + *importedFiles += filePath; + } + } + } } } } @@ -697,8 +834,11 @@ void ModelManager::parse(QFutureInterface<void> &future, const QString fileName = files.at(i); Document::Language language = languageOfFile(fileName); - if (language == Document::UnknownLanguage) + if (language == Document::UnknownLanguage) { + if (fileName.endsWith(QLatin1String(".qrc"))) + modelManager->updateQrcFile(fileName); continue; + } QString contents; int documentRevision = 0; diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h index 3b0763f904..1c42c03882 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.h +++ b/src/plugins/qmljstools/qmljsmodelmanager.h @@ -33,6 +33,7 @@ #include "qmljstools_global.h" #include <qmljs/qmljsmodelmanagerinterface.h> +#include <qmljs/qmljsqrcparser.h> #include <cplusplus/CppDocument.h> @@ -41,6 +42,7 @@ #include <QMutex> QT_FORWARD_DECLARE_CLASS(QTimer) +QT_FORWARD_DECLARE_CLASS(QLocale) namespace Core { class MimeType; @@ -50,6 +52,10 @@ namespace CPlusPlus { class CppModelManagerInterface; } +namespace QmlJS { +class QrcParser; +} + namespace QmlJSTools { QMLJSTOOLS_EXPORT QmlJS::Document::Language languageOfFile(const QString &fileName); @@ -77,6 +83,14 @@ public: bool emitDocumentOnDiskChanged); virtual void fileChangedOnDisk(const QString &path); virtual void removeFiles(const QStringList &files); + virtual QStringList filesAtQrcPath(const QString &path, const QLocale *locale = 0, + ProjectExplorer::Project *project = 0, + QrcResourceSelector resources = AllQrcResources); + virtual QMap<QString,QStringList> filesInQrcPath(const QString &path, + const QLocale *locale = 0, + ProjectExplorer::Project *project = 0, + bool addDirs = false, + QrcResourceSelector resources = AllQrcResources); virtual QList<ProjectInfo> projectInfos() const; virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const; @@ -87,6 +101,7 @@ public: void updateDocument(QmlJS::Document::Ptr doc); void updateLibraryInfo(const QString &path, const QmlJS::LibraryInfo &info); void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc); + void updateQrcFile(const QString &path); virtual QStringList importPaths() const; virtual QmlJS::QmlLanguageBundles activeBundles() const; @@ -147,6 +162,7 @@ private: QTimer *m_updateCppQmlTypesTimer; QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > m_queuedCppDocuments; QFuture<void> m_cppQmlTypesUpdater; + QmlJS::QrcCache m_qrcCache; CppDataHash m_cppDataHash; mutable QMutex m_cppDataMutex; diff --git a/src/plugins/qmljstools/qmljstools.pro b/src/plugins/qmljstools/qmljstools.pro index 93021dd6a8..c3fdd89e7d 100644 --- a/src/plugins/qmljstools/qmljstools.pro +++ b/src/plugins/qmljstools/qmljstools.pro @@ -60,6 +60,9 @@ SOURCES += \ RESOURCES += \ qmljstools.qrc +OTHER_FILES += \ + QmlJSTools.mimetypes.xml + FORMS += \ $$PWD/qmljscodestylesettingspage.ui diff --git a/src/plugins/qmljstools/qmljstools.qbs b/src/plugins/qmljstools/qmljstools.qbs index 682dc34de1..dc8b1f78b2 100644 --- a/src/plugins/qmljstools/qmljstools.qbs +++ b/src/plugins/qmljstools/qmljstools.qbs @@ -20,6 +20,7 @@ QtcPlugin { cpp.includePaths: base.concat("../../libs/3rdparty") files: [ + "QmlJSTools.mimetypes.xml", "qmljsbundleprovider.cpp", "qmljsbundleprovider.h", "qmljscodestylepreferencesfactory.cpp", diff --git a/src/plugins/qmljstools/qmljstools.qrc b/src/plugins/qmljstools/qmljstools.qrc index 9e396a3995..ab7f6f798c 100644 --- a/src/plugins/qmljstools/qmljstools.qrc +++ b/src/plugins/qmljstools/qmljstools.qrc @@ -6,5 +6,6 @@ <file>images/log.png</file> <file>images/expand.png</file> <file>images/error.png</file> + <file>QmlJSTools.mimetypes.xml</file> </qresource> </RCC> diff --git a/src/plugins/qmljstools/qmljstoolsplugin.cpp b/src/plugins/qmljstools/qmljstoolsplugin.cpp index 0d2889019c..50d76d8427 100644 --- a/src/plugins/qmljstools/qmljstoolsplugin.cpp +++ b/src/plugins/qmljstools/qmljstoolsplugin.cpp @@ -41,6 +41,7 @@ #include <coreplugin/coreconstants.h> #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/mimedatabase.h> #include <coreplugin/progressmanager/progressmanager.h> #include <QtPlugin> @@ -72,6 +73,10 @@ bool QmlJSToolsPlugin::initialize(const QStringList &arguments, QString *error) Q_UNUSED(arguments) Q_UNUSED(error) + if (!Core::ICore::mimeDatabase() + ->addMimeTypes(QLatin1String(":/qmljstools/QmlJSTools.mimetypes.xml"), error)) + return false; + m_settings = new QmlJSToolsSettings(this); // force registration of qmljstools settings // Objects diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.cpp b/src/plugins/qmlprofiler/qmlprofilerengine.cpp index 6b0185685f..ce65ee8e49 100644 --- a/src/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -65,7 +65,7 @@ class QmlProfilerEngine::QmlProfilerEnginePrivate { public: QmlProfilerEnginePrivate(QmlProfilerEngine *qq, const AnalyzerStartParameters &sp) : q(qq), m_runner(0), sp(sp) {} - ~QmlProfilerEnginePrivate() { delete m_runner; } + ~QmlProfilerEnginePrivate() { m_runner->disconnect(); delete m_runner; } bool attach(const QString &address, uint port); AbstractQmlProfilerRunner *createRunner(ProjectExplorer::RunConfiguration *runConfiguration, @@ -161,6 +161,7 @@ bool QmlProfilerEngine::start() QTC_ASSERT(d->m_profilerState, return false); if (d->m_runner) { + d->m_runner->disconnect(); delete d->m_runner; d->m_runner = 0; } @@ -189,7 +190,7 @@ bool QmlProfilerEngine::start() } if (d->m_runner) { - connect(d->m_runner, SIGNAL(stopped()), this, SLOT(processEnded())); + connect(d->m_runner, SIGNAL(stopped()), this, SLOT(notifyRemoteFinished())); connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), this, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); d->m_runner->start(); @@ -230,13 +231,16 @@ void QmlProfilerEngine::stop() } } -void QmlProfilerEngine::processEnded() +void QmlProfilerEngine::notifyRemoteFinished(bool success) { QTC_ASSERT(d->m_profilerState, return); switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppRunning : { - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + if (success) + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + else + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); AnalyzerManager::stopTool(); emit finished(); @@ -374,6 +378,7 @@ void QmlProfilerEngine::profilerStateChanged() // (a new one will be created at start) d->m_noDebugOutputTimer.stop(); if (d->m_runner) { + d->m_runner->disconnect(); delete d->m_runner; d->m_runner = 0; } diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.h b/src/plugins/qmlprofiler/qmlprofilerengine.h index fe8cc47313..2a7d24998f 100644 --- a/src/plugins/qmlprofiler/qmlprofilerengine.h +++ b/src/plugins/qmlprofiler/qmlprofilerengine.h @@ -62,7 +62,7 @@ public slots: void stop(); private slots: - void processEnded(); + void notifyRemoteFinished(bool success = true); void cancelProcess(); void logApplicationMessage(const QString &msg, Utils::OutputFormat format); diff --git a/src/plugins/qnx/bardescriptoreditorfactory.cpp b/src/plugins/qnx/bardescriptoreditorfactory.cpp index da3a933dce..ac300d3710 100644 --- a/src/plugins/qnx/bardescriptoreditorfactory.cpp +++ b/src/plugins/qnx/bardescriptoreditorfactory.cpp @@ -61,12 +61,6 @@ QString BarDescriptorEditorFactory::displayName() const return tr("Bar descriptor editor"); } -Core::IDocument *BarDescriptorEditorFactory::open(const QString &fileName) -{ - Core::IEditor *iface = Core::EditorManager::instance()->openEditor(fileName, id()); - return iface ? iface->document() : 0; -} - Core::IEditor *BarDescriptorEditorFactory::createEditor(QWidget *parent) { BarDescriptorEditorWidget *editorWidget = new BarDescriptorEditorWidget(parent); diff --git a/src/plugins/qnx/bardescriptoreditorfactory.h b/src/plugins/qnx/bardescriptoreditorfactory.h index 1e49ac3247..36bade0089 100644 --- a/src/plugins/qnx/bardescriptoreditorfactory.h +++ b/src/plugins/qnx/bardescriptoreditorfactory.h @@ -48,7 +48,6 @@ public: QStringList mimeTypes() const; Core::Id id() const; QString displayName() const; - Core::IDocument *open(const QString &fileName); Core::IEditor *createEditor(QWidget *parent); diff --git a/src/plugins/qnx/blackberryapplicationrunner.cpp b/src/plugins/qnx/blackberryapplicationrunner.cpp index 1943a0374e..1f24c5765f 100644 --- a/src/plugins/qnx/blackberryapplicationrunner.cpp +++ b/src/plugins/qnx/blackberryapplicationrunner.cpp @@ -59,6 +59,7 @@ BlackBerryApplicationRunner::BlackBerryApplicationRunner(bool debugMode, BlackBe : QObject(parent) , m_debugMode(debugMode) , m_slog2infoFound(false) + , m_currentLogs(false) , m_pid(-1) , m_appId(QString()) , m_running(false) @@ -155,6 +156,7 @@ ProjectExplorer::RunControl::StopResult BlackBerryApplicationRunner::stop() return ProjectExplorer::RunControl::AsynchronousStop; m_stopping = true; + m_currentLogs = false; if (m_testSlog2Process && m_testSlog2Process->isProcessRunning()) { m_testSlog2Process->cancel(); @@ -312,19 +314,33 @@ void BlackBerryApplicationRunner::handleTailOutput() if (m_slog2infoFound) { const QStringList multiLine = message.split(QLatin1Char('\n')); Q_FOREACH (const QString &line, multiLine) { - QDateTime dateTime = QDateTime::fromString(line.split(m_appId).first().mid(4).trimmed(), - QString::fromLatin1("dd HH:mm:ss.zzz")); - if (dateTime >= m_launchDateTime) { - QStringList validLineBeginnings; - validLineBeginnings << QLatin1String("qt-msg 0 ") - << QLatin1String("qt-msg* 0 ") - << QLatin1String("default* 9000 ") - << QLatin1String("default 9000 ") - << QLatin1String(" 0 "); - Q_FOREACH (const QString &beginning, validLineBeginnings) { - if (showQtMessage(beginning, line)) - break; - } + // Check if logs are from the recent launch + // Note: This is useless if/once slog2info -b displays only logs from recent launches + if (!m_currentLogs) { + QDateTime dateTime = QDateTime::fromString(line.split(m_appId).first().mid(4).trimmed(), + QString::fromLatin1("dd HH:mm:ss.zzz")); + + m_currentLogs = dateTime >= m_launchDateTime; + if (!m_currentLogs) + continue; + } + + // The line could be a part of a previous log message that contains a '\n' + // In that case only the message body is displayed + if (!line.contains(m_appId) && !line.isEmpty()) { + emit output(line + QLatin1Char('\n'), Utils::StdOutFormat); + continue; + } + + QStringList validLineBeginnings; + validLineBeginnings << QLatin1String("qt-msg 0 ") + << QLatin1String("qt-msg* 0 ") + << QLatin1String("default* 9000 ") + << QLatin1String("default 9000 ") + << QLatin1String(" 0 "); + Q_FOREACH (const QString &beginning, validLineBeginnings) { + if (showQtMessage(beginning, line)) + break; } } return; diff --git a/src/plugins/qnx/blackberryapplicationrunner.h b/src/plugins/qnx/blackberryapplicationrunner.h index 3b8eec9097..afe7bba7ee 100644 --- a/src/plugins/qnx/blackberryapplicationrunner.h +++ b/src/plugins/qnx/blackberryapplicationrunner.h @@ -104,6 +104,7 @@ private: bool m_debugMode; bool m_slog2infoFound; + bool m_currentLogs; QDateTime m_launchDateTime; diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro index 8f71ef4a23..16f02fa6f2 100644 --- a/src/plugins/qnx/qnx.pro +++ b/src/plugins/qnx/qnx.pro @@ -33,6 +33,8 @@ SOURCES += qnxplugin.cpp \ qnxdeviceconfigurationwizardpages.cpp \ qnxrunconfiguration.cpp \ qnxruncontrolfactory.cpp \ + qnxabstractrunsupport.cpp \ + qnxanalyzesupport.cpp \ qnxdebugsupport.cpp \ qnxdeploystepfactory.cpp \ qnxdeployconfigurationfactory.cpp \ @@ -90,7 +92,8 @@ SOURCES += qnxplugin.cpp \ bardescriptoreditorabstractpanelwidget.cpp \ blackberrysetupwizard.cpp \ blackberrysetupwizardpages.cpp \ - blackberryutils.cpp + blackberryutils.cpp \ + qnxdevicetester.cpp HEADERS += qnxplugin.h\ qnxconstants.h \ @@ -123,6 +126,8 @@ HEADERS += qnxplugin.h\ qnxdeviceconfigurationwizardpages.h \ qnxrunconfiguration.h \ qnxruncontrolfactory.h \ + qnxabstractrunsupport.h \ + qnxanalyzesupport.h \ qnxdebugsupport.h \ qnxdeploystepfactory.h \ qnxdeployconfigurationfactory.h \ @@ -180,7 +185,8 @@ HEADERS += qnxplugin.h\ bardescriptoreditorabstractpanelwidget.h \ blackberrysetupwizard.h \ blackberrysetupwizardpages.h \ - blackberryutils.h + blackberryutils.h \ + qnxdevicetester.h FORMS += \ blackberrydeviceconfigurationwizardsetuppage.ui \ diff --git a/src/plugins/qnx/qnx.qbs b/src/plugins/qnx/qnx.qbs index 530f180912..214e43e302 100644 --- a/src/plugins/qnx/qnx.qbs +++ b/src/plugins/qnx/qnx.qbs @@ -188,6 +188,10 @@ QtcPlugin { "qnxbaseqtconfigwidget.h", "qnxbaseqtconfigwidget.ui", "qnxconstants.h", + "qnxabstractrunsupport.cpp", + "qnxabstractrunsupport.h", + "qnxanalyzesupport.cpp", + "qnxanalyzesupport.h", "qnxdebugsupport.cpp", "qnxdebugsupport.h", "qnxdeployconfiguration.cpp", @@ -204,6 +208,8 @@ QtcPlugin { "qnxdeviceconfigurationwizard.h", "qnxdeviceconfigurationwizardpages.cpp", "qnxdeviceconfigurationwizardpages.h", + "qnxdevicetester.cpp", + "qnxdevicetester.h", "qnxplugin.cpp", "qnxplugin.h", "qnxqtversion.cpp", diff --git a/src/plugins/qnx/qnxabstractrunsupport.cpp b/src/plugins/qnx/qnxabstractrunsupport.cpp new file mode 100644 index 0000000000..cb97aa36f9 --- /dev/null +++ b/src/plugins/qnx/qnxabstractrunsupport.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qnxabstractrunsupport.h" +#include "qnxrunconfiguration.h" + +#include <projectexplorer/devicesupport/deviceapplicationrunner.h> +#include <projectexplorer/devicesupport/deviceusedportsgatherer.h> +#include <projectexplorer/kitinformation.h> +#include <projectexplorer/target.h> +#include <utils/portlist.h> +#include <utils/qtcassert.h> + +using namespace ProjectExplorer; +using namespace RemoteLinux; + +using namespace Qnx; +using namespace Qnx::Internal; + +QnxAbstractRunSupport::QnxAbstractRunSupport(QnxRunConfiguration *runConfig, QObject *parent) + : QObject(parent) + , m_remoteExecutable(runConfig->remoteExecutableFilePath()) + , m_commandPrefix(runConfig->commandPrefix()) + , m_device(DeviceKitInformation::device(runConfig->target()->kit())) + , m_state(Inactive) +{ + m_runner = new DeviceApplicationRunner(this); + m_portsGatherer = new DeviceUsedPortsGatherer(this); + + connect(m_portsGatherer, SIGNAL(error(QString)), SLOT(handleError(QString))); + connect(m_portsGatherer, SIGNAL(portListReady()), SLOT(handlePortListReady())); +} + +void QnxAbstractRunSupport::handleAdapterSetupRequested() +{ + QTC_ASSERT(m_state == Inactive, return); + + m_state = GatheringPorts; + m_portsGatherer->start(m_device); +} + +void QnxAbstractRunSupport::handlePortListReady() +{ + QTC_ASSERT(m_state == GatheringPorts, return); + m_portList = m_device->freePorts(); + startExecution(); +} + +void QnxAbstractRunSupport::handleRemoteProcessStarted() +{ + m_state = Running; +} + +void QnxAbstractRunSupport::handleRemoteProcessFinished(bool) +{ +} + +void QnxAbstractRunSupport::setFinished() +{ + if (m_state != GatheringPorts && m_state != Inactive) + m_runner->stop(m_device->processSupport()->killProcessByNameCommandLine(executable()).toUtf8()); + + m_state = Inactive; +} + +QnxAbstractRunSupport::State QnxAbstractRunSupport::state() const +{ + return m_state; +} + +void QnxAbstractRunSupport::setState(QnxAbstractRunSupport::State state) +{ + m_state = state; +} + +DeviceApplicationRunner *QnxAbstractRunSupport::appRunner() const +{ + return m_runner; +} + +QString QnxAbstractRunSupport::commandPrefix() const +{ + return m_commandPrefix; +} + +const IDevice::ConstPtr QnxAbstractRunSupport::device() const +{ + return m_device; +} + +void QnxAbstractRunSupport::handleProgressReport(const QString &) +{ +} + +void QnxAbstractRunSupport::handleRemoteOutput(const QByteArray &) +{ +} + +void QnxAbstractRunSupport::handleError(const QString &) +{ +} + +bool QnxAbstractRunSupport::setPort(int &port) +{ + port = m_portsGatherer->getNextFreePort(&m_portList); + if (port == -1) { + handleError(tr("Not enough free ports on device for debugging.")); + return false; + } + return true; +} + +QString QnxAbstractRunSupport::executable() const +{ + return m_remoteExecutable; +} diff --git a/src/plugins/qnx/qnxabstractrunsupport.h b/src/plugins/qnx/qnxabstractrunsupport.h new file mode 100644 index 0000000000..1e37059774 --- /dev/null +++ b/src/plugins/qnx/qnxabstractrunsupport.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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. +** +****************************************************************************/ + +#ifndef QNXABSTRACTRUNSUPPORT_H +#define QNXABSTRACTRUNSUPPORT_H + +#include <projectexplorer/devicesupport/idevice.h> +#include <utils/portlist.h> + +#include <QObject> +#include <QString> + +namespace ProjectExplorer { +class DeviceApplicationRunner; +class DeviceUsedPortsGatherer; +} + +namespace Qnx { +namespace Internal { + +class QnxRunConfiguration; + +class QnxAbstractRunSupport : public QObject +{ + Q_OBJECT +protected: + enum State { + Inactive, + GatheringPorts, + StartingRemoteProcess, + Running + }; +public: + QnxAbstractRunSupport(QnxRunConfiguration *runConfig, QObject *parent = 0); + +protected: + bool setPort(int &port); + virtual void startExecution() = 0; + + virtual QString executable() const; + + void setFinished(); + + State state() const; + void setState(State state); + + ProjectExplorer::DeviceApplicationRunner *appRunner() const; + QString commandPrefix() const; + const ProjectExplorer::IDevice::ConstPtr device() const; + +protected slots: + virtual void handleAdapterSetupRequested(); + + virtual void handleRemoteProcessStarted(); + virtual void handleRemoteProcessFinished(bool); + virtual void handleProgressReport(const QString &progressOutput); + virtual void handleRemoteOutput(const QByteArray &output); + virtual void handleError(const QString &); + +private slots: + void handlePortListReady(); + +private: + ProjectExplorer::DeviceUsedPortsGatherer * m_portsGatherer; + Utils::PortList m_portList; + const QString m_remoteExecutable; + const QString m_commandPrefix; + ProjectExplorer::IDevice::ConstPtr m_device; + ProjectExplorer::DeviceApplicationRunner *m_runner; + State m_state; +}; + +} // namespace Internal +} // namespace Qnx + +#endif // QNXABSTRACTRUNSUPPORT_H diff --git a/src/plugins/qnx/qnxanalyzesupport.cpp b/src/plugins/qnx/qnxanalyzesupport.cpp new file mode 100644 index 0000000000..ac7cea766c --- /dev/null +++ b/src/plugins/qnx/qnxanalyzesupport.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qnxanalyzesupport.h" + +#include <analyzerbase/ianalyzerengine.h> +#include <analyzerbase/analyzerstartparameters.h> +#include <projectexplorer/devicesupport/deviceapplicationrunner.h> + +#include <utils/qtcassert.h> + +using namespace ProjectExplorer; + +using namespace Qnx; +using namespace Qnx::Internal; + +QnxAnalyzeSupport::QnxAnalyzeSupport(QnxRunConfiguration *runConfig, + Analyzer::IAnalyzerEngine *engine) + : QnxAbstractRunSupport(runConfig, engine) + , m_engine(engine) + , m_qmlPort(-1) +{ + const DeviceApplicationRunner *runner = appRunner(); + connect(runner, SIGNAL(reportError(QString)), SLOT(handleError(QString))); + connect(runner, SIGNAL(remoteProcessStarted()), SLOT(handleRemoteProcessStarted())); + connect(runner, SIGNAL(finished(bool)), SLOT(handleRemoteProcessFinished(bool))); + connect(runner, SIGNAL(reportProgress(QString)), SLOT(handleProgressReport(QString))); + connect(runner, SIGNAL(remoteStdout(QByteArray)), SLOT(handleRemoteOutput(QByteArray))); + connect(runner, SIGNAL(remoteStderr(QByteArray)), SLOT(handleRemoteOutput(QByteArray))); + + connect(m_engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)), + SLOT(handleAdapterSetupRequested())); +} + +void QnxAnalyzeSupport::handleAdapterSetupRequested() +{ + QTC_ASSERT(state() == Inactive, return); + + showMessage(tr("Preparing remote side...\n"), Utils::NormalMessageFormat); + QnxAbstractRunSupport::handleAdapterSetupRequested(); +} + +void QnxAnalyzeSupport::startExecution() +{ + if (state() == Inactive) + return; + + if (!setPort(m_qmlPort) && m_qmlPort == -1) + return; + + setState(StartingRemoteProcess); + + const QString args = m_engine->startParameters().debuggeeArgs + + QString::fromLatin1(" -qmljsdebugger=port:%1,block").arg(m_qmlPort); + const QString command = QString::fromLatin1("%1 %2 %3").arg(commandPrefix(), executable(), args); + appRunner()->start(device(), command.toUtf8()); +} + +void QnxAnalyzeSupport::handleRemoteProcessStarted() +{ + QnxAbstractRunSupport::handleRemoteProcessStarted(); + if (m_engine) + m_engine->notifyRemoteSetupDone(m_qmlPort); +} + +void QnxAnalyzeSupport::handleRemoteProcessFinished(bool success) +{ + if (m_engine || state() == Inactive) + return; + + if (!success) + showMessage(tr("The %1 process closed unexpectedly.").arg(executable()), + Utils::NormalMessageFormat); + m_engine->notifyRemoteFinished(success); +} + +void QnxAnalyzeSupport::handleProfilingFinished() +{ + setFinished(); +} + +void QnxAnalyzeSupport::handleProgressReport(const QString &progressOutput) +{ + showMessage(progressOutput + QLatin1Char('\n'), Utils::NormalMessageFormat); +} + +void QnxAnalyzeSupport::handleRemoteOutput(const QByteArray &output) +{ + QTC_ASSERT(state() == Inactive || state() == Running, return); + + showMessage(QString::fromUtf8(output), Utils::StdOutFormat); +} + +void QnxAnalyzeSupport::handleError(const QString &error) +{ + if (state() == Running) { + showMessage(error, Utils::ErrorMessageFormat); + } else if (state() != Inactive) { + showMessage(tr("Initial setup failed: %1").arg(error), Utils::NormalMessageFormat); + setFinished(); + } +} + +void QnxAnalyzeSupport::showMessage(const QString &msg, Utils::OutputFormat format) +{ + if (state() != Inactive && m_engine) + m_engine->logApplicationMessage(msg, format); +} diff --git a/src/plugins/qnx/qnxanalyzesupport.h b/src/plugins/qnx/qnxanalyzesupport.h new file mode 100644 index 0000000000..66fa580abd --- /dev/null +++ b/src/plugins/qnx/qnxanalyzesupport.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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. +** +****************************************************************************/ + +#ifndef QNXANALYZESUPPORT_H +#define QNXANALYZESUPPORT_H + +#include "qnxabstractrunsupport.h" + +#include <projectexplorer/projectexplorerconstants.h> +#include <utils/outputformat.h> + +namespace Analyzer { class IAnalyzerEngine; } + +namespace Qnx { +namespace Internal { + +class QnxRunConfiguration; + +class QnxAnalyzeSupport : public QnxAbstractRunSupport +{ + Q_OBJECT +public: + QnxAnalyzeSupport(QnxRunConfiguration *runConfig, Analyzer::IAnalyzerEngine *engine); + +public slots: + void handleProfilingFinished(); + +private slots: + void handleAdapterSetupRequested(); + + void handleRemoteProcessStarted(); + void handleRemoteProcessFinished(bool success); + void handleProgressReport(const QString &progressOutput); + void handleRemoteOutput(const QByteArray &output); + void handleError(const QString &error); + +private: + void startExecution(); + void showMessage(const QString &, Utils::OutputFormat); + + Analyzer::IAnalyzerEngine *m_engine; + int m_qmlPort; +}; + +} // namespace Internal +} // namespace Qnx + +#endif // QNXANALYZESUPPORT_H diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp index fdc7b447c0..7b76080fc7 100644 --- a/src/plugins/qnx/qnxdebugsupport.cpp +++ b/src/plugins/qnx/qnxdebugsupport.cpp @@ -40,7 +40,6 @@ #include <projectexplorer/devicesupport/deviceusedportsgatherer.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/target.h> -#include <utils/portlist.h> #include <utils/qtcassert.h> using namespace ProjectExplorer; @@ -50,66 +49,44 @@ using namespace Qnx; using namespace Qnx::Internal; QnxDebugSupport::QnxDebugSupport(QnxRunConfiguration *runConfig, Debugger::DebuggerEngine *engine) - : QObject(engine) - , m_remoteExecutable(runConfig->remoteExecutableFilePath()) - , m_commandPrefix(runConfig->commandPrefix()) - , m_device(DeviceKitInformation::device(runConfig->target()->kit())) + : QnxAbstractRunSupport(runConfig, engine) , m_engine(engine) , m_pdebugPort(-1) , m_qmlPort(-1) , m_useCppDebugger(runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>()->useCppDebugger()) , m_useQmlDebugger(runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>()->useQmlDebugger()) - , m_state(Inactive) { - m_runner = new DeviceApplicationRunner(this); - m_portsGatherer = new DeviceUsedPortsGatherer(this); - - connect(m_portsGatherer, SIGNAL(error(QString)), SLOT(handleError(QString))); - connect(m_portsGatherer, SIGNAL(portListReady()), SLOT(handlePortListReady())); - - connect(m_runner, SIGNAL(reportError(QString)), SLOT(handleError(QString))); - connect(m_runner, SIGNAL(remoteProcessStarted()), this, SLOT(handleRemoteProcessStarted())); - connect(m_runner, SIGNAL(finished(bool)), SLOT(handleRemoteProcessFinished(bool))); - connect(m_runner, SIGNAL(reportProgress(QString)), this, SLOT(handleProgressReport(QString))); - connect(m_runner, SIGNAL(remoteStdout(QByteArray)), this, SLOT(handleRemoteOutput(QByteArray))); - connect(m_runner, SIGNAL(remoteStderr(QByteArray)), this, SLOT(handleRemoteOutput(QByteArray))); + const DeviceApplicationRunner *runner = appRunner(); + connect(runner, SIGNAL(reportError(QString)), SLOT(handleError(QString))); + connect(runner, SIGNAL(remoteProcessStarted()), SLOT(handleRemoteProcessStarted())); + connect(runner, SIGNAL(finished(bool)), SLOT(handleRemoteProcessFinished(bool))); + connect(runner, SIGNAL(reportProgress(QString)), SLOT(handleProgressReport(QString))); + connect(runner, SIGNAL(remoteStdout(QByteArray)), SLOT(handleRemoteOutput(QByteArray))); + connect(runner, SIGNAL(remoteStderr(QByteArray)), SLOT(handleRemoteOutput(QByteArray))); connect(m_engine, SIGNAL(requestRemoteSetup()), this, SLOT(handleAdapterSetupRequested())); } void QnxDebugSupport::handleAdapterSetupRequested() { - QTC_ASSERT(m_state == Inactive, return); + QTC_ASSERT(state() == Inactive, return); - m_state = GatheringPorts; if (m_engine) m_engine->showMessage(tr("Preparing remote side...\n"), Debugger::AppStuff); - m_portsGatherer->start(m_device); -} - -void QnxDebugSupport::handlePortListReady() -{ - QTC_ASSERT(m_state == GatheringPorts, return); - startExecution(); + QnxAbstractRunSupport::handleAdapterSetupRequested(); } void QnxDebugSupport::startExecution() { - if (m_state == Inactive) + if (state() == Inactive) return; - Utils::PortList portList = m_device->freePorts(); - if (m_useCppDebugger) - m_pdebugPort = m_portsGatherer->getNextFreePort(&portList); - if (m_useQmlDebugger) - m_qmlPort = m_portsGatherer->getNextFreePort(&portList); - - if ((m_useCppDebugger && m_pdebugPort == -1) || (m_useQmlDebugger && m_qmlPort == -1)) { - handleError(tr("Not enough free ports on device for debugging.")); + if (m_useCppDebugger && !setPort(m_pdebugPort)) + return; + if (m_useQmlDebugger && !setPort(m_qmlPort)) return; - } - m_state = StartingRemoteProcess; + setState(StartingRemoteProcess); if (m_useQmlDebugger) m_engine->startParameters().processArgs += QString::fromLocal8Bit(" -qmljsdebugger=port:%1,block").arg(m_qmlPort); @@ -117,27 +94,27 @@ void QnxDebugSupport::startExecution() QString remoteCommandLine; if (m_useCppDebugger) remoteCommandLine = QString::fromLatin1("%1 %2 %3") - .arg(m_commandPrefix, executable()).arg(m_pdebugPort); + .arg(commandPrefix(), executable()).arg(m_pdebugPort); else if (m_useQmlDebugger && !m_useCppDebugger) remoteCommandLine = QString::fromLatin1("%1 %2 %3") - .arg(m_commandPrefix, executable(), m_engine->startParameters().processArgs); + .arg(commandPrefix(), executable(), m_engine->startParameters().processArgs); - m_runner->start(m_device, remoteCommandLine.toUtf8()); + appRunner()->start(device(), remoteCommandLine.toUtf8()); } void QnxDebugSupport::handleRemoteProcessStarted() { - m_state = Debugging; + QnxAbstractRunSupport::handleRemoteProcessStarted(); if (m_engine) m_engine->notifyEngineRemoteSetupDone(m_pdebugPort, m_qmlPort); } void QnxDebugSupport::handleRemoteProcessFinished(bool success) { - if (m_engine || m_state == Inactive) + if (m_engine || state() == Inactive) return; - if (m_state == Debugging) { + if (state() == Running) { if (!success) m_engine->notifyInferiorIll(); @@ -152,17 +129,9 @@ void QnxDebugSupport::handleDebuggingFinished() setFinished(); } -void QnxDebugSupport::setFinished() -{ - if (m_state != GatheringPorts && m_state != Inactive) - m_runner->stop(m_device->processSupport()->killProcessByNameCommandLine(executable()).toUtf8()); - - m_state = Inactive; -} - QString QnxDebugSupport::executable() const { - return m_useCppDebugger? QLatin1String(Constants::QNX_DEBUG_EXECUTABLE) : m_remoteExecutable; + return m_useCppDebugger? QLatin1String(Constants::QNX_DEBUG_EXECUTABLE) : QnxAbstractRunSupport::executable(); } void QnxDebugSupport::handleProgressReport(const QString &progressOutput) @@ -173,7 +142,7 @@ void QnxDebugSupport::handleProgressReport(const QString &progressOutput) void QnxDebugSupport::handleRemoteOutput(const QByteArray &output) { - QTC_ASSERT(m_state == Inactive || m_state == Debugging, return); + QTC_ASSERT(state() == Inactive || state() == Running, return); if (m_engine) m_engine->showMessage(QString::fromUtf8(output), Debugger::AppOutput); @@ -181,12 +150,12 @@ void QnxDebugSupport::handleRemoteOutput(const QByteArray &output) void QnxDebugSupport::handleError(const QString &error) { - if (m_state == Debugging) { + if (state() == Running) { if (m_engine) { m_engine->showMessage(error, Debugger::AppError); m_engine->notifyInferiorIll(); } - } else if (m_state != Inactive) { + } else if (state() != Inactive) { setFinished(); if (m_engine) m_engine->notifyEngineRemoteSetupFailed(tr("Initial setup failed: %1").arg(error)); diff --git a/src/plugins/qnx/qnxdebugsupport.h b/src/plugins/qnx/qnxdebugsupport.h index 891b6acd87..1bcb84016f 100644 --- a/src/plugins/qnx/qnxdebugsupport.h +++ b/src/plugins/qnx/qnxdebugsupport.h @@ -32,23 +32,16 @@ #ifndef QNX_INTERNAL_QNXDEBUGSUPPORT_H #define QNX_INTERNAL_QNXDEBUGSUPPORT_H -#include <projectexplorer/devicesupport/idevice.h> - -#include <QObject> -#include <QString> +#include "qnxabstractrunsupport.h" namespace Debugger { class DebuggerEngine; } -namespace ProjectExplorer { -class DeviceApplicationRunner; -class DeviceUsedPortsGatherer; -} namespace Qnx { namespace Internal { class QnxRunConfiguration; -class QnxDebugSupport : public QObject +class QnxDebugSupport : public QnxAbstractRunSupport { Q_OBJECT public: @@ -66,34 +59,18 @@ private slots: void handleProgressReport(const QString &progressOutput); void handleRemoteOutput(const QByteArray &output); void handleError(const QString &error); - void handlePortListReady(); private: void startExecution(); - void setFinished(); QString executable() const; - enum State { - Inactive, - GatheringPorts, - StartingRemoteProcess, - Debugging - }; - - const QString m_remoteExecutable; - const QString m_commandPrefix; - ProjectExplorer::IDevice::ConstPtr m_device; - ProjectExplorer::DeviceApplicationRunner *m_runner; - ProjectExplorer::DeviceUsedPortsGatherer * m_portsGatherer; Debugger::DebuggerEngine *m_engine; int m_pdebugPort; int m_qmlPort; bool m_useCppDebugger; bool m_useQmlDebugger; - - State m_state; }; } // namespace Internal diff --git a/src/plugins/qnx/qnxdeployconfigurationfactory.cpp b/src/plugins/qnx/qnxdeployconfigurationfactory.cpp index e84ea7552b..f72e7c7143 100644 --- a/src/plugins/qnx/qnxdeployconfigurationfactory.cpp +++ b/src/plugins/qnx/qnxdeployconfigurationfactory.cpp @@ -35,6 +35,7 @@ #include "qnxdeployconfiguration.h" #include "qnxdeviceconfigurationfactory.h" +#include <projectexplorer/devicesupport/devicecheckbuildstep.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/target.h> #include <remotelinux/genericdirectuploadstep.h> @@ -77,7 +78,9 @@ ProjectExplorer::DeployConfiguration *QnxDeployConfigurationFactory::create(Proj ProjectExplorer::DeployConfiguration * const dc = new QnxDeployConfiguration(parent, id, displayNameForId(id)); - dc->stepList()->insertStep(0, new RemoteLinux::GenericDirectUploadStep(dc->stepList(), + dc->stepList()->insertStep(0, new ProjectExplorer::DeviceCheckBuildStep(dc->stepList(), + ProjectExplorer::DeviceCheckBuildStep::stepId())); + dc->stepList()->insertStep(1, new RemoteLinux::GenericDirectUploadStep(dc->stepList(), RemoteLinux::GenericDirectUploadStep::stepId())); return dc; } diff --git a/src/plugins/qnx/qnxdeploystepfactory.cpp b/src/plugins/qnx/qnxdeploystepfactory.cpp index 579214cb97..3b053761e6 100644 --- a/src/plugins/qnx/qnxdeploystepfactory.cpp +++ b/src/plugins/qnx/qnxdeploystepfactory.cpp @@ -34,6 +34,7 @@ #include "qnxdeviceconfigurationfactory.h" #include <projectexplorer/buildsteplist.h> +#include <projectexplorer/devicesupport/devicecheckbuildstep.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/target.h> @@ -56,13 +57,17 @@ QList<Core::Id> QnxDeployStepFactory::availableCreationIds(ProjectExplorer::Buil if (deviceType != QnxDeviceConfigurationFactory::deviceType()) return QList<Core::Id>(); - return QList<Core::Id>() << RemoteLinux::GenericDirectUploadStep::stepId(); + return QList<Core::Id>() << RemoteLinux::GenericDirectUploadStep::stepId() + << ProjectExplorer::DeviceCheckBuildStep::stepId(); } QString QnxDeployStepFactory::displayNameForId(const Core::Id id) const { if (id == RemoteLinux::GenericDirectUploadStep::stepId()) return RemoteLinux::GenericDirectUploadStep::displayName(); + else if (id == ProjectExplorer::DeviceCheckBuildStep::stepId()) + return ProjectExplorer::DeviceCheckBuildStep::stepDisplayName(); + return QString(); } @@ -75,7 +80,12 @@ ProjectExplorer::BuildStep *QnxDeployStepFactory::create(ProjectExplorer::BuildS { if (!canCreate(parent, id)) return 0; - return new RemoteLinux::GenericDirectUploadStep(parent, id); + + if (id == RemoteLinux::GenericDirectUploadStep::stepId()) + return new RemoteLinux::GenericDirectUploadStep(parent, id); + else if (id == ProjectExplorer::DeviceCheckBuildStep::stepId()) + return new ProjectExplorer::DeviceCheckBuildStep(parent, id); + return 0; } bool QnxDeployStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const @@ -103,5 +113,11 @@ ProjectExplorer::BuildStep *QnxDeployStepFactory::clone(ProjectExplorer::BuildSt { if (!canClone(parent, product)) return 0; - return new RemoteLinux::GenericDirectUploadStep(parent, static_cast<RemoteLinux::GenericDirectUploadStep *>(product)); + + if (RemoteLinux::GenericDirectUploadStep * const other = qobject_cast<RemoteLinux::GenericDirectUploadStep*>(product)) + return new RemoteLinux::GenericDirectUploadStep(parent, other); + else if (ProjectExplorer::DeviceCheckBuildStep * const other = qobject_cast<ProjectExplorer::DeviceCheckBuildStep*>(product)) + return new ProjectExplorer::DeviceCheckBuildStep(parent, other); + + return 0; } diff --git a/src/plugins/qnx/qnxdeviceconfiguration.cpp b/src/plugins/qnx/qnxdeviceconfiguration.cpp index 50cc3a89cd..7fb16988a6 100644 --- a/src/plugins/qnx/qnxdeviceconfiguration.cpp +++ b/src/plugins/qnx/qnxdeviceconfiguration.cpp @@ -30,6 +30,7 @@ ****************************************************************************/ #include "qnxdeviceconfiguration.h" +#include "qnxdevicetester.h" #include <projectexplorer/devicesupport/sshdeviceprocesslist.h> @@ -185,3 +186,8 @@ ProjectExplorer::DeviceProcessList *QnxDeviceConfiguration::createProcessListMod { return new QnxDeviceProcessList(sharedFromThis(), parent); } + +RemoteLinux::AbstractLinuxDeviceTester *QnxDeviceConfiguration::createDeviceTester() const +{ + return new QnxDeviceTester; +} diff --git a/src/plugins/qnx/qnxdeviceconfiguration.h b/src/plugins/qnx/qnxdeviceconfiguration.h index f1645d6793..1e2a9d0aef 100644 --- a/src/plugins/qnx/qnxdeviceconfiguration.h +++ b/src/plugins/qnx/qnxdeviceconfiguration.h @@ -54,6 +54,8 @@ public: ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const; ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const; + RemoteLinux::AbstractLinuxDeviceTester *createDeviceTester() const; + QString displayType() const; protected: diff --git a/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp b/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp index cc8b9929b0..c14d69530c 100644 --- a/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp +++ b/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp @@ -38,7 +38,6 @@ #include <projectexplorer/devicesupport/deviceusedportsgatherer.h> #include <remotelinux/genericlinuxdeviceconfigurationwizardpages.h> #include <remotelinux/linuxdevicetestdialog.h> -#include <remotelinux/linuxdevicetester.h> #include <utils/portlist.h> using namespace ProjectExplorer; @@ -77,8 +76,7 @@ IDevice::Ptr QnxDeviceConfigurationWizard::device() device->setSshParameters(sshParams); device->setFreePorts(Utils::PortList::fromString(QLatin1String("10000-10100"))); - RemoteLinux::GenericLinuxDeviceTester *devTester = new RemoteLinux::GenericLinuxDeviceTester(this); - RemoteLinux::LinuxDeviceTestDialog dlg(device, devTester, this); + RemoteLinux::LinuxDeviceTestDialog dlg(device, device->createDeviceTester(), this); dlg.exec(); return device; diff --git a/src/plugins/qnx/qnxdevicetester.cpp b/src/plugins/qnx/qnxdevicetester.cpp new file mode 100644 index 0000000000..c7ce356483 --- /dev/null +++ b/src/plugins/qnx/qnxdevicetester.cpp @@ -0,0 +1,163 @@ +/************************************************************************** +** +** Copyright (C) 2011 - 2013 Research In Motion +** +** Contact: Research In Motion (blackberry-qt@qnx.com) +** Contact: KDAB (info@kdab.com) +** +** 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 "qnxdevicetester.h" + +#include <ssh/sshremoteprocessrunner.h> +#include <utils/qtcassert.h> + +using namespace Qnx; +using namespace Qnx::Internal; + +QnxDeviceTester::QnxDeviceTester(QObject *parent) + : RemoteLinux::AbstractLinuxDeviceTester(parent) + , m_result(TestSuccess) + , m_state(Inactive) + , m_currentCommandIndex(-1) +{ + m_genericTester = new RemoteLinux::GenericLinuxDeviceTester(this); + + m_processRunner = new QSsh::SshRemoteProcessRunner(this); + connect(m_processRunner, SIGNAL(connectionError()), SLOT(handleConnectionError())); + connect(m_processRunner, SIGNAL(processClosed(int)), SLOT(handleProcessFinished(int))); + + m_commandsToTest << QLatin1String("awk") + << QLatin1String("grep") + << QLatin1String("kill") + << QLatin1String("netstat") + << QLatin1String("print") + << QLatin1String("printf") + << QLatin1String("ps") + << QLatin1String("read") + << QLatin1String("sed") + << QLatin1String("sleep") + << QLatin1String("uname"); +} + +void QnxDeviceTester::testDevice(const ProjectExplorer::IDevice::ConstPtr &deviceConfiguration) +{ + QTC_ASSERT(m_state == Inactive, return); + + m_deviceConfiguration = deviceConfiguration; + + connect(m_genericTester, SIGNAL(progressMessage(QString)), SIGNAL(progressMessage(QString))); + connect(m_genericTester, SIGNAL(errorMessage(QString)), SIGNAL(errorMessage(QString))); + connect(m_genericTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)), + SLOT(handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult))); + + m_state = GenericTest; + m_genericTester->testDevice(deviceConfiguration); +} + +void QnxDeviceTester::stopTest() +{ + QTC_ASSERT(m_state != Inactive, return); + + switch (m_state) { + case Inactive: + break; + case GenericTest: + m_genericTester->stopTest(); + break; + case CommandsTest: + m_processRunner->cancel(); + break; + } + + m_result = TestFailure; + setFinished(); +} + +void QnxDeviceTester::handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result) +{ + QTC_ASSERT(m_state == GenericTest, return); + + if (result == TestFailure) { + m_result = TestFailure; + setFinished(); + return; + } + + m_state = CommandsTest; + testNextCommand(); +} + +void QnxDeviceTester::handleProcessFinished(int exitStatus) +{ + QTC_ASSERT(m_state == CommandsTest, return); + + const QString command = m_commandsToTest[m_currentCommandIndex]; + if (exitStatus == QSsh::SshRemoteProcess::NormalExit) { + if (m_processRunner->processExitCode() == 0) { + emit progressMessage(tr("%1 found.\n").arg(command)); + } else { + emit errorMessage(tr("%1 not found.\n").arg(command)); + m_result = TestFailure; + } + } else { + emit errorMessage(tr("An error occurred checking for %1.\n").arg(command)); + m_result = TestFailure; + } + testNextCommand(); +} + +void QnxDeviceTester::handleConnectionError() +{ + QTC_ASSERT(m_state == CommandsTest, return); + + m_result = TestFailure; + emit errorMessage(tr("SSH connection error: %1\n").arg(m_processRunner->lastConnectionErrorString())); + setFinished(); +} + +void QnxDeviceTester::testNextCommand() +{ + ++m_currentCommandIndex; + + if (m_currentCommandIndex >= m_commandsToTest.size()) { + setFinished(); + return; + } + + QString command = m_commandsToTest[m_currentCommandIndex]; + emit progressMessage(tr("Checking for %1...").arg(command)); + + m_processRunner->run("command -v " + command.toLatin1(), m_deviceConfiguration->sshParameters()); +} + +void QnxDeviceTester::setFinished() +{ + m_state = Inactive; + disconnect(m_genericTester, 0, this, 0); + if (m_processRunner) + disconnect(m_processRunner, 0, this, 0); + emit finished(m_result); +} diff --git a/src/plugins/qnx/qnxdevicetester.h b/src/plugins/qnx/qnxdevicetester.h new file mode 100644 index 0000000000..ccec636f08 --- /dev/null +++ b/src/plugins/qnx/qnxdevicetester.h @@ -0,0 +1,84 @@ +/************************************************************************** +** +** Copyright (C) 2011 - 2013 Research In Motion +** +** Contact: Research In Motion (blackberry-qt@qnx.com) +** Contact: KDAB (info@kdab.com) +** +** 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. +** +****************************************************************************/ + +#ifndef QNX_INTERNAL_QNXDEVICETESTER_H +#define QNX_INTERNAL_QNXDEVICETESTER_H + +#include <remotelinux/linuxdevicetester.h> + +#include <QStringList> + +namespace QSsh { +class SshRemoteProcessRunner; +} + +namespace Qnx { +namespace Internal { + +class QnxDeviceTester : public RemoteLinux::AbstractLinuxDeviceTester +{ + Q_OBJECT +public: + explicit QnxDeviceTester(QObject *parent = 0); + + void testDevice(const ProjectExplorer::IDevice::ConstPtr &deviceConfiguration); + void stopTest(); + +private slots: + void handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result); + + void handleProcessFinished(int exitStatus); + void handleConnectionError(); + +private: + enum State { + Inactive, + GenericTest, + CommandsTest + }; + + void testNextCommand(); + void setFinished(); + + RemoteLinux::GenericLinuxDeviceTester *m_genericTester; + ProjectExplorer::IDevice::ConstPtr m_deviceConfiguration; + TestResult m_result; + State m_state; + + int m_currentCommandIndex; + QStringList m_commandsToTest; + QSsh::SshRemoteProcessRunner *m_processRunner; +}; + +} // namespace Internal +} // namespace Qnx + +#endif // QNX_INTERNAL_QNXDEVICETESTER_H diff --git a/src/plugins/qnx/qnxruncontrolfactory.cpp b/src/plugins/qnx/qnxruncontrolfactory.cpp index 29f58f2715..d80363b39f 100644 --- a/src/plugins/qnx/qnxruncontrolfactory.cpp +++ b/src/plugins/qnx/qnxruncontrolfactory.cpp @@ -33,6 +33,7 @@ #include "qnxconstants.h" #include "qnxrunconfiguration.h" #include "qnxdebugsupport.h" +#include "qnxanalyzesupport.h" #include "qnxqtversion.h" #include "qnxruncontrol.h" #include "qnxutils.h" @@ -44,6 +45,10 @@ #include <debugger/debuggerrunconfigurationaspect.h> #include <debugger/debuggerstartparameters.h> #include <debugger/debuggerkitinformation.h> +#include <analyzerbase/analyzerstartparameters.h> +#include <analyzerbase/analyzermanager.h> +#include <analyzerbase/analyzerruncontrol.h> +#include <projectexplorer/environmentaspect.h> #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/project.h> #include <projectexplorer/target.h> @@ -51,6 +56,7 @@ #include <qtsupport/qtkitinformation.h> #include <utils/portlist.h> +using namespace Analyzer; using namespace Debugger; using namespace ProjectExplorer; using namespace Qnx; @@ -107,6 +113,32 @@ DebuggerStartParameters createStartParameters(const QnxRunConfiguration *runConf return params; } +AnalyzerStartParameters createAnalyzerStartParameters(const QnxRunConfiguration *runConfig, RunMode mode) +{ + AnalyzerStartParameters params; + Target *target = runConfig->target(); + Kit *k = target->kit(); + + const IDevice::ConstPtr device = DeviceKitInformation::device(k); + if (device.isNull()) + return params; + + if (mode == QmlProfilerRunMode) + params.startMode = StartQmlRemote; + params.debuggee = runConfig->remoteExecutableFilePath(); + params.debuggeeArgs = runConfig->arguments(); + params.connParams = DeviceKitInformation::device(runConfig->target()->kit())->sshParameters(); + params.analyzerCmdPrefix = runConfig->commandPrefix(); + params.displayName = runConfig->displayName(); + params.sysroot = SysRootKitInformation::sysRoot(runConfig->target()->kit()).toString(); + params.analyzerHost = params.connParams.host; + params.analyzerPort = params.connParams.port; + + if (EnvironmentAspect *environment = runConfig->extraAspect<EnvironmentAspect>()) + params.environment = environment->environment(); + + return params; +} QnxRunControlFactory::QnxRunControlFactory(QObject *parent) : IRunControlFactory(parent) @@ -115,7 +147,7 @@ QnxRunControlFactory::QnxRunControlFactory(QObject *parent) bool QnxRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const { - if (mode != NormalRunMode && mode != DebugRunMode) + if (mode != NormalRunMode && mode != DebugRunMode && mode != QmlProfilerRunMode) return false; if (!runConfiguration->isEnabled() @@ -125,7 +157,7 @@ bool QnxRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mo const QnxRunConfiguration * const rc = qobject_cast<QnxRunConfiguration *>(runConfiguration); - if (mode == DebugRunMode) { + if (mode == DebugRunMode || mode == QmlProfilerRunMode) { const QnxDeviceConfiguration::ConstPtr dev = DeviceKitInformation::device(runConfiguration->target()->kit()) .dynamicCast<const QnxDeviceConfiguration>(); if (dev.isNull()) @@ -141,16 +173,38 @@ RunControl *QnxRunControlFactory::create(RunConfiguration *runConfig, RunMode mo QnxRunConfiguration *rc = qobject_cast<QnxRunConfiguration *>(runConfig); Q_ASSERT(rc); - if (mode == NormalRunMode) + switch (mode) { + case NormalRunMode: return new QnxRunControl(rc); + case DebugRunMode: { + const DebuggerStartParameters params = createStartParameters(rc); + DebuggerRunControl * const runControl = DebuggerPlugin::createDebugger(params, rc, errorMessage); + if (!runControl) + return 0; - const DebuggerStartParameters params = createStartParameters(rc); - DebuggerRunControl * const runControl = DebuggerPlugin::createDebugger(params, rc, errorMessage); - if (!runControl) - return 0; + QnxDebugSupport *debugSupport = new QnxDebugSupport(rc, runControl->engine()); + connect(runControl, SIGNAL(finished()), debugSupport, SLOT(handleDebuggingFinished())); - QnxDebugSupport *debugSupport = new QnxDebugSupport(rc, runControl->engine()); - connect(runControl, SIGNAL(finished()), debugSupport, SLOT(handleDebuggingFinished())); - - return runControl; + return runControl; + } + case QmlProfilerRunMode: { + IAnalyzerTool *tool = AnalyzerManager::toolFromRunMode(mode); + if (!tool) { + if (errorMessage) + *errorMessage = tr("No analyzer tool selected."); + return 0; + } + const AnalyzerStartParameters params = createAnalyzerStartParameters(rc, mode); + AnalyzerRunControl * const runControl = new AnalyzerRunControl(tool, params, runConfig); + QnxAnalyzeSupport * const analyzeSupport = new QnxAnalyzeSupport(rc, runControl->engine()); + connect(runControl, SIGNAL(finished()), analyzeSupport, SLOT(handleProfilingFinished())); + return runControl; + } + case NoRunMode: + case CallgrindRunMode: + case MemcheckRunMode: + case DebugRunModeWithBreakOnMain: + QTC_ASSERT(false, return 0); + } + return 0; } diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index 92954b6be8..26568c4dd6 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -56,6 +56,7 @@ #include <utils/hostosinfo.h> #include <utils/stringutils.h> #include <proparser/prowriter.h> +#include <proparser/qmakevfs.h> #include <algorithm> #include <QDebug> @@ -1135,8 +1136,9 @@ void Qt4PriFileNode::changeFiles(const FileType fileType, lines = contents.split(QLatin1Char('\n')); } + QMakeVfs vfs; QtSupport::ProMessageHandler handler; - QMakeParser parser(0, &handler); + QMakeParser parser(0, &vfs, &handler); includeFile = parser.parsedProBlock(contents, m_projectFilePath, 1); } @@ -1886,6 +1888,10 @@ void Qt4ProFileNode::applyEvaluate(EvalResult evalResult, bool async) QLatin1String("OBJECTIVE_HEADERS"), m_projectDir, buildDirectory); newVarValues[UiDirVar] = QStringList() << uiDirPath(m_readerExact); newVarValues[MocDirVar] = QStringList() << mocDirPath(m_readerExact); + newVarValues[ResourceVar] = fileListForVar(m_readerExact, m_readerCumulative, + QLatin1String("RESOURCES"), m_projectDir, buildDirectory); + newVarValues[ExactResourceVar] = fileListForVar(m_readerExact, 0, + QLatin1String("RESOURCES"), m_projectDir, buildDirectory); newVarValues[PkgConfigVar] = m_readerExact->values(QLatin1String("PKGCONFIG")); newVarValues[PrecompiledHeaderVar] = m_readerExact->absoluteFileValues(QLatin1String("PRECOMPILED_HEADER"), diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h index c4d01190bb..745b745966 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.h +++ b/src/plugins/qt4projectmanager/qt4nodes.h @@ -86,6 +86,8 @@ enum Qt4Variable { CppSourceVar, ObjCSourceVar, ObjCHeaderVar, + ResourceVar, + ExactResourceVar, UiDirVar, MocDirVar, PkgConfigVar, diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 123dbca22d..aa81184031 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -46,6 +46,7 @@ #include <coreplugin/documentmanager.h> #include <cpptools/cppmodelmanagerinterface.h> #include <qmljstools/qmljsmodelmanager.h> +#include <projectexplorer/buildmanager.h> #include <projectexplorer/buildtargetinfo.h> #include <projectexplorer/deploymentdata.h> #include <projectexplorer/toolchain.h> @@ -53,6 +54,7 @@ #include <projectexplorer/target.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectmacroexpander.h> +#include <proparser/qmakevfs.h> #include <qtsupport/profilereader.h> #include <qtsupport/qtkitinformation.h> @@ -344,6 +346,7 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) : m_nodesWatcher(new Internal::Qt4NodesWatcher(this)), m_fileInfo(new Qt4ProjectFile(fileName, this)), m_projectFiles(new Qt4ProjectFiles), + m_qmakeVfs(new QMakeVfs), m_qmakeGlobals(0), m_asyncUpdateFutureInterface(0), m_pendingEvaluateFuturesCount(0), @@ -358,6 +361,10 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) : m_asyncUpdateTimer.setSingleShot(true); m_asyncUpdateTimer.setInterval(3000); connect(&m_asyncUpdateTimer, SIGNAL(timeout()), this, SLOT(asyncUpdate())); + + connect(ProjectExplorerPlugin::instance()->buildManager(), + SIGNAL(buildQueueFinished(bool)), + SLOT(buildFinished(bool))); } Qt4Project::~Qt4Project() @@ -365,6 +372,7 @@ Qt4Project::~Qt4Project() m_codeModelFuture.cancel(); m_asyncUpdateState = ShuttingDown; m_manager->unregisterProject(this); + delete m_qmakeVfs; delete m_projectFiles; m_cancelEvaluate = true; // Deleting the root node triggers a few things, make sure rootProjectNode @@ -627,6 +635,8 @@ void Qt4Project::updateQmlJSCodeModel() bool hasQmlLib = false; foreach (Qt4ProFileNode *node, proFiles) { projectInfo.importPaths.append(node->variableValue(QmlImportPathVar)); + projectInfo.activeResourceFiles.append(node->variableValue(ExactResourceVar)); + projectInfo.allResourceFiles.append(node->variableValue(ResourceVar)); if (!hasQmlLib) { QStringList qtLibs = node->variableValue(QtVar); hasQmlLib = qtLibs.contains(QLatin1String("declarative")) || @@ -645,6 +655,8 @@ void Qt4Project::updateQmlJSCodeModel() setProjectLanguages(pl); projectInfo.importPaths.removeDuplicates(); + projectInfo.activeResourceFiles.removeDuplicates(); + projectInfo.allResourceFiles.removeDuplicates(); setProjectLanguage(ProjectExplorer::Constants::LANG_QMLJS, !projectInfo.sourceFiles.isEmpty()); @@ -843,6 +855,9 @@ void Qt4Project::asyncUpdate() { if (debug) qDebug()<<"async update, timer expired, doing now"; + + m_qmakeVfs->invalidateCache(); + Q_ASSERT(!m_asyncUpdateFutureInterface); m_asyncUpdateFutureInterface = new QFutureInterface<void>(); @@ -873,6 +888,12 @@ void Qt4Project::asyncUpdate() m_asyncUpdateState = AsyncUpdateInProgress; } +void Qt4Project::buildFinished(bool success) +{ + if (success) + m_qmakeVfs->invalidateContents(); +} + ProjectExplorer::IProjectManager *Qt4Project::projectManager() const { return m_manager; @@ -998,7 +1019,7 @@ QtSupport::ProFileReader *Qt4Project::createProFileReader(const Qt4ProFileNode * } ++m_qmakeGlobalsRefCnt; - QtSupport::ProFileReader *reader = new QtSupport::ProFileReader(m_qmakeGlobals); + QtSupport::ProFileReader *reader = new QtSupport::ProFileReader(m_qmakeGlobals, m_qmakeVfs); reader->setOutputDir(qt4ProFileNode->buildDir()); diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h index 2f40208153..a4bb93b1b3 100644 --- a/src/plugins/qt4projectmanager/qt4project.h +++ b/src/plugins/qt4projectmanager/qt4project.h @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE class ProFileGlobals; +class QMakeVfs; QT_END_NAMESPACE namespace ProjectExplorer { class DeploymentData; } @@ -158,6 +159,7 @@ protected: private slots: void asyncUpdate(); + void buildFinished(bool success); void activeTargetWasChanged(); @@ -198,6 +200,8 @@ private: // cached lists of all of files Internal::Qt4ProjectFiles *m_projectFiles; + QMakeVfs *m_qmakeVfs; + // cached data during project rescan ProFileGlobals *m_qmakeGlobals; int m_qmakeGlobalsRefCnt; diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.cpp b/src/plugins/qt4projectmanager/qt4projectmanager.cpp index 33926d2363..b3d2c3d0d9 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanager.cpp @@ -247,7 +247,8 @@ void Qt4Manager::addLibrary(const QString &fileName, ProFileEditorWidget *editor editable = editor->editor(); } else { editable = qobject_cast<TextEditor::BaseTextEditor *> - (Core::EditorManager::openEditor(fileName, Qt4ProjectManager::Constants::PROFILE_EDITOR_ID)); + (Core::EditorManager::openEditor(fileName, Qt4ProjectManager::Constants::PROFILE_EDITOR_ID, + Core::EditorManager::DoNotMakeVisible)); } if (!editable) return; diff --git a/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp b/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp index d7ca07f3a1..a6c5d62a8e 100644 --- a/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp +++ b/src/plugins/qt4projectmanager/wizards/abstractmobileappwizard.cpp @@ -283,7 +283,7 @@ bool AbstractMobileAppWizard::postGenerateFiles(const QWizard *w, if (success) { const QString fileToOpen = fileToOpenPostGeneration(); if (!fileToOpen.isEmpty()) { - Core::EditorManager::openEditor(fileToOpen, Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(fileToOpen); ProjectExplorer::ProjectExplorerPlugin::instance()->setCurrentFile(0, fileToOpen); } } diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 093123caa8..fcb447bf82 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -36,6 +36,7 @@ #include "qtversionmanager.h" #include "profilereader.h" +#include <proparser/qmakevfs.h> #include <projectexplorer/toolchainmanager.h> #include <projectexplorer/toolchain.h> #include <projectexplorer/projectexplorer.h> @@ -780,12 +781,13 @@ void BaseQtVersion::ensureMkSpecParsed() const if (mkspecPath().isEmpty()) return; + QMakeVfs vfs; ProFileGlobals option; option.setProperties(versionInfo()); ProMessageHandler msgHandler(true); ProFileCacheManager::instance()->incRefCount(); - QMakeParser parser(ProFileCacheManager::instance()->cache(), &msgHandler); - ProFileEvaluator evaluator(&option, &parser, &msgHandler); + QMakeParser parser(ProFileCacheManager::instance()->cache(), &vfs, &msgHandler); + ProFileEvaluator evaluator(&option, &parser, &vfs, &msgHandler); evaluator.loadNamedSpec(mkspecPath().toString(), false); parseMkSpec(&evaluator); diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp index c40aebeb04..0ad1763da3 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp @@ -431,7 +431,7 @@ void ExamplesWelcomePage::openProject(const QString &projectFile, const QStringL Core::ICore::openFiles(filesToOpen); if (project->needsConfiguration()) project->configureAsExampleProject(platforms); - Core::ModeManager::activateModeType(Core::Constants::MODE_EDIT_TYPE); + Core::ModeManager::activateMode(Core::Constants::MODE_EDIT); if (help.isValid()) Core::ICore::helpManager()->handleHelpRequest(help.toString() + QLatin1String("?view=split")); } diff --git a/src/plugins/qtsupport/profilereader.cpp b/src/plugins/qtsupport/profilereader.cpp index b538c0e6cc..747c4f14ff 100644 --- a/src/plugins/qtsupport/profilereader.cpp +++ b/src/plugins/qtsupport/profilereader.cpp @@ -65,9 +65,9 @@ void ProMessageHandler::fileMessage(const QString &) } -ProFileReader::ProFileReader(ProFileGlobals *option) - : QMakeParser(ProFileCacheManager::instance()->cache(), this) - , ProFileEvaluator(option, this, this) +ProFileReader::ProFileReader(ProFileGlobals *option, QMakeVfs *vfs) + : QMakeParser(ProFileCacheManager::instance()->cache(), vfs, this) + , ProFileEvaluator(option, this, vfs, this) , m_ignoreLevel(0) { } diff --git a/src/plugins/qtsupport/profilereader.h b/src/plugins/qtsupport/profilereader.h index 2ba4c99aa6..3bd8a914b8 100644 --- a/src/plugins/qtsupport/profilereader.h +++ b/src/plugins/qtsupport/profilereader.h @@ -69,7 +69,7 @@ class QTSUPPORT_EXPORT ProFileReader : public ProMessageHandler, public QMakePar Q_OBJECT public: - ProFileReader(ProFileGlobals *option); + ProFileReader(ProFileGlobals *option, QMakeVfs *vfs); ~ProFileReader(); QList<ProFile*> includeFiles() const; diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp index 34b7d38f1c..1c4ffd624d 100644 --- a/src/plugins/qtsupport/qtoutputformatter.cpp +++ b/src/plugins/qtsupport/qtoutputformatter.cpp @@ -29,11 +29,12 @@ #include "qtoutputformatter.h" -#include <texteditor/basetexteditor.h> +#include <coreplugin/editormanager/editormanager.h> #include <projectexplorer/project.h> -#include <QUrl> +#include <QPlainTextEdit> #include <QTextCursor> +#include <QUrl> using namespace ProjectExplorer; using namespace QtSupport; @@ -195,7 +196,7 @@ void QtOutputFormatter::handleLink(const QString &href) const int line = qmlLineColumnLink.cap(2).toInt(); const int column = qmlLineColumnLink.cap(3).toInt(); - TextEditor::BaseTextEditorWidget::openEditorAt(m_projectFinder.findFile(fileUrl), line, column - 1); + Core::EditorManager::openEditorAt(m_projectFinder.findFile(fileUrl), line, column - 1); return; } @@ -206,7 +207,7 @@ void QtOutputFormatter::handleLink(const QString &href) if (qmlLineLink.indexIn(href) != -1) { const QUrl fileUrl = QUrl(qmlLineLink.cap(1)); const int line = qmlLineLink.cap(2).toInt(); - TextEditor::BaseTextEditorWidget::openEditorAt(m_projectFinder.findFile(fileUrl), line); + Core::EditorManager::openEditorAt(m_projectFinder.findFile(fileUrl), line); return; } @@ -233,7 +234,7 @@ void QtOutputFormatter::handleLink(const QString &href) if (!fileName.isEmpty()) { fileName = m_projectFinder.findFile(QUrl::fromLocalFile(fileName)); - TextEditor::BaseTextEditorWidget::openEditorAt(fileName, line, 0); + Core::EditorManager::openEditorAt(fileName, line); return; } } diff --git a/src/plugins/qtsupport/qtversionfactory.cpp b/src/plugins/qtsupport/qtversionfactory.cpp index 7ff99b6ff4..cac661f629 100644 --- a/src/plugins/qtsupport/qtversionfactory.cpp +++ b/src/plugins/qtsupport/qtversionfactory.cpp @@ -31,6 +31,8 @@ #include "profilereader.h" #include "baseqtversion.h" +#include <proparser/qmakevfs.h> + #include <extensionsystem/pluginmanager.h> #include <utils/environment.h> @@ -61,12 +63,13 @@ BaseQtVersion *QtVersionFactory::createQtVersionFromQMakePath(const Utils::FileN return 0; Utils::FileName mkspec = BaseQtVersion::mkspecFromVersionInfo(versionInfo); + QMakeVfs vfs; ProFileGlobals globals; globals.setProperties(versionInfo); ProMessageHandler msgHandler(true); ProFileCacheManager::instance()->incRefCount(); - QMakeParser parser(ProFileCacheManager::instance()->cache(), &msgHandler); - ProFileEvaluator evaluator(&globals, &parser, &msgHandler); + QMakeParser parser(ProFileCacheManager::instance()->cache(), &vfs, &msgHandler); + ProFileEvaluator evaluator(&globals, &parser, &vfs, &msgHandler); evaluator.loadNamedSpec(mkspec.toString(), false); QList<QtVersionFactory *> factories = ExtensionSystem::PluginManager::getObjects<QtVersionFactory>(); diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 70796e54cd..8c530ac3ac 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -214,7 +214,7 @@ void LinuxDevice::executeAction(Core::Id actionId, QWidget *parent) const QDialog *d = 0; const LinuxDevice::ConstPtr device = sharedFromThis().staticCast<const LinuxDevice>(); if (actionId == Constants::GenericTestDeviceActionId) - d = new LinuxDeviceTestDialog(device, new GenericLinuxDeviceTester, parent); + d = new LinuxDeviceTestDialog(device, createDeviceTester(), parent); else if (actionId == Constants::GenericDeployKeyToDeviceActionId) d = PublicKeyDeploymentDialog::createDialog(device, parent); if (d) @@ -264,4 +264,9 @@ DeviceProcessList *LinuxDevice::createProcessListModel(QObject *parent) const return new LinuxDeviceProcessList(sharedFromThis(), parent); } +AbstractLinuxDeviceTester *LinuxDevice::createDeviceTester() const +{ + return new GenericLinuxDeviceTester; +} + } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h index 0daa95e58e..0ec84cd44e 100644 --- a/src/plugins/remotelinux/linuxdevice.h +++ b/src/plugins/remotelinux/linuxdevice.h @@ -41,6 +41,7 @@ namespace Utils { class PortList; } namespace RemoteLinux { namespace Internal { class LinuxDevicePrivate; } +class AbstractLinuxDeviceTester; class REMOTELINUX_EXPORT LinuxDeviceProcessSupport : public ProjectExplorer::DeviceProcessSupport { @@ -73,6 +74,7 @@ public: ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const; bool canCreateProcessModel() const { return true; } ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const; + virtual AbstractLinuxDeviceTester *createDeviceTester() const; protected: LinuxDevice() {} diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 1565adf128..5d03160596 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -572,7 +572,9 @@ void SubversionPlugin::svnDiff(const Subversion::Internal::SubversionDiffParamet QFileInfo(p.files.front()).fileName() : p.diffName; QStringList args(QLatin1String("diff")); - args.append(QLatin1String("--internal-diff")); + Version v = svnVersion(); + if (v.majorVersion >= 1 && v.minorVersion >= 7) // --internal-diff is new in v1.7.0 + args.append(QLatin1String("--internal-diff")); args.append(p.arguments); args << p.files; @@ -587,7 +589,7 @@ void SubversionPlugin::svnDiff(const Subversion::Internal::SubversionDiffParamet // Show in the same editor if diff has been executed before if (Core::IEditor *existingEditor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) { existingEditor->createNew(response.stdOut); - Core::EditorManager::activateEditor(existingEditor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(existingEditor); setDiffBaseDirectory(existingEditor, p.workingDir); return; } @@ -611,8 +613,7 @@ void SubversionPlugin::svnDiff(const Subversion::Internal::SubversionDiffParamet SubversionSubmitEditor *SubversionPlugin::openSubversionSubmitEditor(const QString &fileName) { Core::IEditor *editor = Core::EditorManager::openEditor(fileName, - Constants::SUBVERSIONCOMMITEDITOR_ID, - Core::EditorManager::ModeSwitch); + Constants::SUBVERSIONCOMMITEDITOR_ID); SubversionSubmitEditor *submitEditor = qobject_cast<SubversionSubmitEditor*>(editor); QTC_CHECK(submitEditor); setSubmitEditor(submitEditor); @@ -899,7 +900,7 @@ void SubversionPlugin::filelog(const QString &workingDir, const QString tag = VcsBase::VcsBaseEditorWidget::editorTag(VcsBase::LogOutput, workingDir, files); if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); - Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(editor); } else { const QString title = QString::fromLatin1("svn log %1").arg(id); const QString source = VcsBase::VcsBaseEditorWidget::getSource(workingDir, files); @@ -977,7 +978,7 @@ void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &fil if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); VcsBase::VcsBaseEditorWidget::gotoLineOfEditor(editor, lineNumber); - Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(editor); } else { const QString title = QString::fromLatin1("svn annotate %1").arg(id); Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VcsBase::AnnotateOutput, source, codec); @@ -1042,7 +1043,7 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr) const QString tag = VcsBase::VcsBaseEditorWidget::editorTag(VcsBase::DiffOutput, source, QStringList(), changeNr); if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(description); - Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(editor); } else { const QString title = QString::fromLatin1("svn describe %1#%2").arg(fi.fileName(), changeNr); Core::IEditor *newEditor = showOutputInEditor(title, description, VcsBase::DiffOutput, source, codec); @@ -1110,6 +1111,32 @@ QStringList SubversionPlugin::addAuthenticationOptions(const QStringList &args, return rc; } +SubversionPlugin::Version SubversionPlugin::svnVersion() +{ + if (m_svnVersionBinary != m_settings.binaryPath()) { + QStringList args; + args << QLatin1String("--version") << QLatin1String("-q"); + const Utils::SynchronousProcessResponse response = + VcsBase::VcsBasePlugin::runVcs(QDir().absolutePath(), m_settings.binaryPath(), + args, m_settings.timeOutMs(), 0); + if (response.result == Utils::SynchronousProcessResponse::Finished && + response.exitCode == 0) { + m_svnVersionBinary = m_settings.binaryPath(); + m_svnVersion = response.stdOut.trimmed(); + } else { + m_svnVersionBinary.clear(); + m_svnVersion.clear(); + } + } + + SubversionPlugin::Version v; + if (::sscanf(m_svnVersion.toLatin1().constData(), "%d.%d.%d", + &v.majorVersion, &v.minorVersion, &v.patchVersion) != 3) + v.majorVersion = v.minorVersion = v.patchVersion = -1; + + return v; +} + SubversionResponse SubversionPlugin::runSvn(const QString &workingDir, const QString &userName, const QString &password, const QStringList &arguments, int timeOut, @@ -1161,7 +1188,7 @@ Core::IEditor *SubversionPlugin::showOutputInEditor(const QString &title, const if (codec) e->setCodec(codec); Core::IEditor *ie = e->editor(); - Core::EditorManager::activateEditor(ie, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(ie); return ie; } @@ -1187,14 +1214,6 @@ SubversionPlugin *SubversionPlugin::instance() bool SubversionPlugin::vcsAdd(const QString &workingDir, const QString &rawFileName) { - if (Utils::HostOsInfo::isMacHost()) // See below. - return vcsAdd14(workingDir, rawFileName); - return vcsAdd15(workingDir, rawFileName); -} - -// Post 1.4 add: Use "--parents" to add directories -bool SubversionPlugin::vcsAdd15(const QString &workingDir, const QString &rawFileName) -{ const QString file = QDir::toNativeSeparators(rawFileName); QStringList args; args << QLatin1String("add") << QLatin1String("--parents") << file; @@ -1204,40 +1223,6 @@ bool SubversionPlugin::vcsAdd15(const QString &workingDir, const QString &rawFil return !response.error; } -// Pre 1.5 add: Add directories in a loop. To be deprecated -// once Mac ships newer svn-versions -bool SubversionPlugin::vcsAdd14(const QString &workingDir, const QString &rawFileName) -{ - const QChar slash = QLatin1Char('/'); - const QStringList relativePath = rawFileName.split(slash); - // Add directories (dir1/dir2/file.cpp) in a loop. - if (relativePath.size() > 1) { - QString path; - const int lastDir = relativePath.size() - 1; - for (int p = 0; p < lastDir; p++) { - if (!path.isEmpty()) - path += slash; - path += relativePath.at(p); - if (!checkSVNSubDir(QDir(path))) { - QStringList addDirArgs; - addDirArgs << QLatin1String("add") << QLatin1String("--non-recursive") << QDir::toNativeSeparators(path); - const SubversionResponse addDirResponse = - runSvn(workingDir, addDirArgs, m_settings.timeOutMs(), - SshPasswordPrompt|ShowStdOutInLogWindow); - if (addDirResponse.error) - return false; - } - } - } - // Add file - QStringList args; - args << QLatin1String("add") << QDir::toNativeSeparators(rawFileName); - const SubversionResponse response = - runSvn(workingDir, args, m_settings.timeOutMs(), - SshPasswordPrompt|ShowStdOutInLogWindow); - return !response.error; -} - bool SubversionPlugin::vcsDelete(const QString &workingDir, const QString &rawFileName) { const QString file = QDir::toNativeSeparators(rawFileName); diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h index 2020313a60..b92e5309af 100644 --- a/src/plugins/subversion/subversionplugin.h +++ b/src/plugins/subversion/subversionplugin.h @@ -93,8 +93,6 @@ public: // IVersionControl bool vcsAdd(const QString &workingDir, const QString &fileName); - bool vcsAdd14(const QString &workingDir, const QString &fileName); - bool vcsAdd15(const QString &workingDir, const QString &fileName); bool vcsDelete(const QString &workingDir, const QString &fileName); bool vcsMove(const QString &workingDir, const QString &from, const QString &to); bool managesDirectory(const QString &directory, QString *topLevel = 0) const; @@ -108,6 +106,15 @@ public: const QString &userName = QString(), const QString &password = QString()); + class Version { + public: + int majorVersion; + int minorVersion; + int patchVersion; + }; + + Version svnVersion(); + public slots: void vcsAnnotate(const QString &workingDir, const QString &file, const QString &revision = QString(), int lineNumber = -1); @@ -206,6 +213,9 @@ private: QAction *m_menuAction; bool m_submitActionTriggered; + QString m_svnVersionBinary; + QString m_svnVersion; + static SubversionPlugin *m_subversionPluginInstance; }; diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index 8f1ccf1e64..250eae2ddc 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -36,7 +36,8 @@ #include <coreplugin/progressmanager/futureprogress.h> #include <coreplugin/dialogs/readonlyfilesdialog.h> #include <coreplugin/documentmanager.h> -#include <texteditor/basetexteditor.h> +#include <find/ifindsupport.h> +#include <texteditor/itexteditor.h> #include <texteditor/refactoringchanges.h> #include <utils/stylehelper.h> #include <utils/qtcassert.h> @@ -309,14 +310,11 @@ void BaseFileFind::openEditor(const Find::SearchResultItem &item) SearchResult *result = qobject_cast<SearchResult *>(sender()); Core::IEditor *openedEditor = 0; if (item.path.size() > 0) { - openedEditor = TextEditor::BaseTextEditorWidget::openEditorAt(QDir::fromNativeSeparators(item.path.first()), - item.lineNumber, - item.textMarkPos, - Core::Id(), - Core::EditorManager::ModeSwitch); + openedEditor = Core::EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()), + item.lineNumber, + item.textMarkPos); } else { - openedEditor = Core::EditorManager::openEditor(QDir::fromNativeSeparators(item.text), - Core::Id(), Core::EditorManager::ModeSwitch); + openedEditor = Core::EditorManager::openEditor(QDir::fromNativeSeparators(item.text)); } if (d->m_currentFindSupport) d->m_currentFindSupport->clearResults(); diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 2b3f5eef3a..a9aa9e97dd 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -154,25 +154,6 @@ private: using namespace Internal; -Core::IEditor *BaseTextEditorWidget::openEditorAt(const QString &fileName, int line, int column, - Core::Id editorKind, - Core::EditorManager::OpenEditorFlags flags, - bool *newEditor) -{ - Core::EditorManager *editorManager = Core::EditorManager::instance(); - editorManager->cutForwardNavigationHistory(); - editorManager->addCurrentPositionToNavigationHistory(); - Core::IEditor *editor = Core::EditorManager::openEditor(fileName, editorKind, - flags, newEditor); - TextEditor::ITextEditor *texteditor = qobject_cast<TextEditor::ITextEditor *>(editor); - if (texteditor && line != -1) { - texteditor->gotoLine(line, column); - return texteditor; - } - - return editor; -} - QString BaseTextEditorWidget::plainTextFromSelection(const QTextCursor &cursor) const { // Copy the selected text as plain text @@ -4910,8 +4891,6 @@ bool BaseTextEditorWidget::openLink(const Link &link, bool inNextSplit) Core::EditorManager *editorManager = Core::EditorManager::instance(); if (inNextSplit) { - if (!editorManager->hasSplitter()) - editorManager->splitSideBySide(); editorManager->gotoOtherSplit(); } else if (baseTextDocument()->fileName() == link.targetFileName) { editorManager->addCurrentPositionToNavigationHistory(); @@ -4920,9 +4899,7 @@ bool BaseTextEditorWidget::openLink(const Link &link, bool inNextSplit) return true; } - return openEditorAt(link.targetFileName, link.targetLine, link.targetColumn, Core::Id(), - Core::EditorManager::IgnoreNavigationHistory - | Core::EditorManager::ModeSwitch); + return Core::EditorManager::openEditorAt(link.targetFileName, link.targetLine, link.targetColumn); } void BaseTextEditorWidget::updateLink(QMouseEvent *e) diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index c109bc4396..4a1f17e571 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -131,11 +131,6 @@ public: BaseTextEditorWidget(QWidget *parent); ~BaseTextEditorWidget(); - static Core::IEditor *openEditorAt(const QString &fileName, int line, int column = 0, - Core::Id editorId = Core::Id(), - Core::EditorManager::OpenEditorFlags flags = Core::EditorManager::IgnoreNavigationHistory, - bool *newEditor = 0); - const Utils::ChangeSet &changeSet() const; void setChangeSet(const Utils::ChangeSet &changeSet); diff --git a/src/plugins/texteditor/codeassist/basicproposalitemlistmodel.cpp b/src/plugins/texteditor/codeassist/basicproposalitemlistmodel.cpp index 2c0c1112cc..b6c479b9c8 100644 --- a/src/plugins/texteditor/codeassist/basicproposalitemlistmodel.cpp +++ b/src/plugins/texteditor/codeassist/basicproposalitemlistmodel.cpp @@ -118,13 +118,11 @@ struct ContentLessThan } // Anonymous BasicProposalItemListModel::BasicProposalItemListModel() - : m_isSortingAllowed(true) {} BasicProposalItemListModel::BasicProposalItemListModel(const QList<BasicProposalItem *> &items) : m_currentItems(items) , m_originalItems(items) - , m_isSortingAllowed(true) { mapPersistentIds(); } @@ -141,16 +139,6 @@ void BasicProposalItemListModel::loadContent(const QList<BasicProposalItem *> &i mapPersistentIds(); } -void BasicProposalItemListModel::setSortingAllowed(bool isAllowed) -{ - m_isSortingAllowed = isAllowed; -} - -bool BasicProposalItemListModel::isSortingAllowed() const -{ - return m_isSortingAllowed; -} - void BasicProposalItemListModel::mapPersistentIds() { for (int i = 0; i < m_originalItems.size(); ++i) @@ -270,8 +258,6 @@ bool BasicProposalItemListModel::isSortable(const QString &prefix) const { Q_UNUSED(prefix); - if (!isSortingAllowed()) - return false; if (m_currentItems.size() < kMaxSort) return true; return false; diff --git a/src/plugins/texteditor/codeassist/basicproposalitemlistmodel.h b/src/plugins/texteditor/codeassist/basicproposalitemlistmodel.h index e9769a192f..9de70b4374 100644 --- a/src/plugins/texteditor/codeassist/basicproposalitemlistmodel.h +++ b/src/plugins/texteditor/codeassist/basicproposalitemlistmodel.h @@ -78,7 +78,6 @@ private: QHash<QString, int> m_idByText; QList<BasicProposalItem *> m_originalItems; - bool m_isSortingAllowed; }; } // TextEditor diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index b4c0f9cb42..8a57304e87 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -40,7 +40,6 @@ #include <texteditor/basetexteditor.h> #include <texteditor/texteditorsettings.h> #include <texteditor/completionsettings.h> -#include <texteditor/codeassist/basicproposalitemlistmodel.h> #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> @@ -266,15 +265,8 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, } } - if (IAssistProposal *newProposal = processor->perform(assistInterface)) { - if (kind == QuickFix) { - TextEditor::BasicProposalItemListModel *proposalModel = - static_cast<TextEditor::BasicProposalItemListModel *>(newProposal->model()); - proposalModel->setSortingAllowed(false); - } - + if (IAssistProposal *newProposal = processor->perform(assistInterface)) displayProposal(newProposal, reason); - } delete processor; } diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h b/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h index ed2309be21..a641fa5df2 100644 --- a/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h +++ b/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h @@ -30,7 +30,6 @@ #ifndef HIGHLIGHTDEFINITIONMETADATA_H #define HIGHLIGHTDEFINITIONMETADATA_H -#include <QString> #include <QStringList> #include <QUrl> @@ -40,14 +39,7 @@ namespace Internal { class HighlightDefinitionMetaData { public: - HighlightDefinitionMetaData(); - - static const QLatin1String kPriority; - static const QLatin1String kName; - static const QLatin1String kExtensions; - static const QLatin1String kMimeType; - static const QLatin1String kVersion; - static const QLatin1String kUrl; + HighlightDefinitionMetaData() : priority(0) {} public: int priority; diff --git a/src/plugins/texteditor/generichighlighter/manager.cpp b/src/plugins/texteditor/generichighlighter/manager.cpp index 167256f1e7..109b667387 100644 --- a/src/plugins/texteditor/generichighlighter/manager.cpp +++ b/src/plugins/texteditor/generichighlighter/manager.cpp @@ -67,6 +67,13 @@ using namespace TextEditor; using namespace Internal; +const char kPriority[] = "priority"; +const char kName[] = "name"; +const char kExtensions[] = "extensions"; +const char kMimeType[] = "mimetype"; +const char kVersion[] = "version"; +const char kUrl[] = "url"; + Manager::Manager() : m_isDownloadingDefinitionsSpec(false), m_hasQueuedRegistration(false) @@ -360,14 +367,13 @@ QSharedPointer<HighlightDefinitionMetaData> Manager::parseMetadata(const QFileIn metaData->fileName = fileInfo.fileName(); metaData->id = fileInfo.absoluteFilePath(); - metaData->name = atts.value(HighlightDefinitionMetaData::kName).toString(); - metaData->version = atts.value(HighlightDefinitionMetaData::kVersion).toString(); - metaData->priority = atts.value(HighlightDefinitionMetaData::kPriority).toString() - .toInt(); - metaData->patterns = atts.value(HighlightDefinitionMetaData::kExtensions) + metaData->name = atts.value(QLatin1String(kName)).toString(); + metaData->version = atts.value(QLatin1String(kVersion)).toString(); + metaData->priority = atts.value(QLatin1String(kPriority)).toString().toInt(); + metaData->patterns = atts.value(QLatin1String(kExtensions)) .toString().split(kSemiColon, QString::SkipEmptyParts); - QStringList mimeTypes = atts.value(HighlightDefinitionMetaData::kMimeType). + QStringList mimeTypes = atts.value(QLatin1String(kMimeType)). toString().split(kSemiColon, QString::SkipEmptyParts); if (mimeTypes.isEmpty()) { // There are definitions which do not specify a MIME type, but specify file @@ -400,9 +406,9 @@ QList<HighlightDefinitionMetaData> Manager::parseAvailableDefinitionsList(QIODev const QXmlStreamAttributes &atts = reader.attributes(); HighlightDefinitionMetaData metaData; - metaData.name = atts.value(HighlightDefinitionMetaData::kName).toString(); - metaData.version = atts.value(HighlightDefinitionMetaData::kVersion).toString(); - QString url(atts.value(HighlightDefinitionMetaData::kUrl).toString()); + metaData.name = atts.value(QLatin1String(kName)).toString(); + metaData.version = atts.value(QLatin1String(kVersion)).toString(); + QString url = atts.value(QLatin1String(kUrl)).toString(); metaData.url = QUrl(url); const int slash = url.lastIndexOf(kSlash); if (slash != -1) diff --git a/src/plugins/texteditor/itexteditor.cpp b/src/plugins/texteditor/itexteditor.cpp index beb34d75a6..75248dd1b3 100644 --- a/src/plugins/texteditor/itexteditor.cpp +++ b/src/plugins/texteditor/itexteditor.cpp @@ -29,8 +29,6 @@ #include "itexteditor.h" -#include <coreplugin/editormanager/editormanager.h> - #include <QTextCodec> using namespace TextEditor; @@ -66,7 +64,6 @@ QMap<QString, QTextCodec *> TextEditor::ITextEditor::openedTextEditorsEncodings( return workingCopy; } - ITextEditorDocument *ITextEditor::textDocument() { return qobject_cast<ITextEditorDocument *>(document()); diff --git a/src/plugins/texteditor/itexteditor.h b/src/plugins/texteditor/itexteditor.h index 2e1ae06e38..dd9a3fcb7f 100644 --- a/src/plugins/texteditor/itexteditor.h +++ b/src/plugins/texteditor/itexteditor.h @@ -35,6 +35,7 @@ #include "itextmark.h" #include <coreplugin/textdocument.h> +#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/ieditor.h> #include <QMap> diff --git a/src/plugins/texteditor/linenumberfilter.cpp b/src/plugins/texteditor/linenumberfilter.cpp index bec075131d..b6dd394cea 100644 --- a/src/plugins/texteditor/linenumberfilter.cpp +++ b/src/plugins/texteditor/linenumberfilter.cpp @@ -97,9 +97,7 @@ void LineNumberFilter::accept(FilterEntry selection) const data.first = currLine; } editor->gotoLine(data.first, data.second); - editor->widget()->setFocus(); - ICore::raiseWindow(editor->widget()); - Core::ModeManager::activateModeType(Id(Core::Constants::MODE_EDIT_TYPE)); + Core::EditorManager::activateEditor(editor); } } diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp index f5638ae600..e8b73f582a 100644 --- a/src/plugins/texteditor/refactoringchanges.cpp +++ b/src/plugins/texteditor/refactoringchanges.cpp @@ -136,12 +136,12 @@ BaseTextEditorWidget *RefactoringChanges::openEditor(const QString &fileName, bo { Core::EditorManager::OpenEditorFlags flags = Core::EditorManager::IgnoreNavigationHistory; if (!activate) - flags |= Core::EditorManager::NoActivate; + flags |= Core::EditorManager::DoNotChangeCurrentEditor; if (line != -1) { // openEditorAt uses a 1-based line and a 0-based column! column -= 1; } - Core::IEditor *editor = BaseTextEditorWidget::openEditorAt( + Core::IEditor *editor = Core::EditorManager::openEditorAt( fileName, line, column, Core::Id(), flags); if (editor) diff --git a/src/plugins/texteditor/syntaxhighlighter.cpp b/src/plugins/texteditor/syntaxhighlighter.cpp index ed75207816..de9c5acd09 100644 --- a/src/plugins/texteditor/syntaxhighlighter.cpp +++ b/src/plugins/texteditor/syntaxhighlighter.cpp @@ -553,8 +553,6 @@ void SyntaxHighlighter::applyFormatToSpaces(const QString &text, const QTextChar } /*! - \fn QTextCharFormat SyntaxHighlighter::format(int position) const - Returns the format at \a position inside the syntax highlighter's current text block. */ diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro index a5193ff862..eaca9ab8d9 100644 --- a/src/plugins/texteditor/texteditor.pro +++ b/src/plugins/texteditor/texteditor.pro @@ -56,7 +56,6 @@ SOURCES += texteditorplugin.cpp \ generichighlighter/highlightersettingspage.cpp \ generichighlighter/highlightersettings.cpp \ generichighlighter/managedefinitionsdialog.cpp \ - generichighlighter/highlightdefinitionmetadata.cpp \ generichighlighter/definitiondownloader.cpp \ refactoringchanges.cpp \ refactoroverlay.cpp \ diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index 9792f6a884..6998dbf478 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -212,7 +212,6 @@ QtcPlugin { "highlightdefinition.h", "highlightdefinitionhandler.cpp", "highlightdefinitionhandler.h", - "highlightdefinitionmetadata.cpp", "highlightdefinitionmetadata.h", "highlighter.cpp", "highlighter.h", diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp index e47a350424..ce2da09161 100644 --- a/src/plugins/texteditor/texteditorplugin.cpp +++ b/src/plugins/texteditor/texteditorplugin.cpp @@ -137,7 +137,7 @@ void ScratchFileWizard::createFile() file.setAutoRemove(false); QTC_ASSERT(file.open(), return; ); file.close(); - Core::EditorManager::openEditor(file.fileName(), Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(file.fileName()); } // ExtensionSystem::PluginInterface diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index 48f5f1d7f5..efaaba214d 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -62,7 +62,7 @@ #include <cplusplus/Overview.h> #include <cppeditor/cppeditorconstants.h> #include <extensionsystem/iplugin.h> -#include <texteditor/basetexteditor.h> +#include <texteditor/itexteditor.h> #include <utils/qtcassert.h> #include <utils/fancymainwindow.h> @@ -322,7 +322,7 @@ void CallgrindToolPrivate::selectFunction(const Function *func) if (QFile::exists(func->file())) { ///TODO: custom position support? int line = func->lineNumber(); - TextEditor::BaseTextEditorWidget::openEditorAt(func->file(), qMax(line, 0)); + Core::EditorManager::openEditorAt(func->file(), qMax(line, 0)); } } diff --git a/src/plugins/valgrind/memcheckerrorview.cpp b/src/plugins/valgrind/memcheckerrorview.cpp index 8943616975..3f421b280a 100644 --- a/src/plugins/valgrind/memcheckerrorview.cpp +++ b/src/plugins/valgrind/memcheckerrorview.cpp @@ -41,9 +41,9 @@ #include "xmlprotocol/suppression.h" #include <coreplugin/coreconstants.h> -#include <projectexplorer/projectexplorer.h> +#include <coreplugin/editormanager/editormanager.h> #include <projectexplorer/project.h> -#include <texteditor/basetexteditor.h> +#include <projectexplorer/projectexplorer.h> #include <utils/qtcassert.h> #include <QDir> @@ -52,6 +52,7 @@ #include <QAction> #include <QApplication> #include <QClipboard> +#include <QContextMenuEvent> #include <QLabel> #include <QListView> #include <QMenu> @@ -59,6 +60,7 @@ #include <QScrollBar> #include <QSortFilterProxyModel> #include <QStyledItemDelegate> +#include <QTextDocument> #include <QVBoxLayout> using namespace Valgrind::XmlProtocol; @@ -432,7 +434,7 @@ void MemcheckErrorDelegate::openLinkInEditor(const QString &link) const int pathEnd = link.lastIndexOf(QLatin1Char(':')); const QString path = link.mid(pathStart, pathEnd - pathStart); const int line = link.mid(pathEnd + 1).toInt(0); - TextEditor::BaseTextEditorWidget::openEditorAt(path, qMax(line, 0)); + Core::EditorManager::openEditorAt(path, qMax(line, 0)); } MemcheckErrorView::MemcheckErrorView(QWidget *parent) diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index 5e82687068..39e91f9bc0 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -54,15 +54,14 @@ #include <projectexplorer/session.h> #include <projectexplorer/buildconfiguration.h> -#include <coreplugin/coreconstants.h> -#include <coreplugin/icore.h> -#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/command.h> +#include <coreplugin/coreconstants.h> +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/icore.h> #include <coreplugin/id.h> -#include <texteditor/basetexteditor.h> - #include <utils/fancymainwindow.h> #include <utils/styledbar.h> #include <utils/qtcassert.h> @@ -502,7 +501,7 @@ void MemcheckTool::suppressionActionTriggered() const QString file = action->data().toString(); QTC_ASSERT(!file.isEmpty(), return); - TextEditor::BaseTextEditorWidget::openEditorAt(file, 0); + Core::EditorManager::openEditorAt(file, 0); } void MemcheckTool::parserError(const Valgrind::XmlProtocol::Error &error) diff --git a/src/plugins/valgrind/suppressiondialog.cpp b/src/plugins/valgrind/suppressiondialog.cpp index b235bdf0e4..8e1a4c25a4 100644 --- a/src/plugins/valgrind/suppressiondialog.cpp +++ b/src/plugins/valgrind/suppressiondialog.cpp @@ -203,9 +203,11 @@ void SuppressionDialog::accept() QTC_ASSERT(!m_suppressionEdit->toPlainText().trimmed().isEmpty(), return); Utils::FileSaver saver(path, QIODevice::Append); - QTextStream stream(saver.file()); - stream << m_suppressionEdit->toPlainText(); - saver.setResult(&stream); + if (!saver.hasError()) { + QTextStream stream(saver.file()); + stream << m_suppressionEdit->toPlainText(); + saver.setResult(&stream); + } if (!saver.finalize(this)) return; diff --git a/src/plugins/vcsbase/cleandialog.cpp b/src/plugins/vcsbase/cleandialog.cpp index ed8a46bd78..b5366102ae 100644 --- a/src/plugins/vcsbase/cleandialog.cpp +++ b/src/plugins/vcsbase/cleandialog.cpp @@ -279,7 +279,7 @@ void CleanDialog::slotDoubleClicked(const QModelIndex &index) if (const QStandardItem *item = d->m_filesModel->itemFromIndex(index)) if (!item->data(Internal::isDirectoryRole).toBool()) { const QString fname = item->data(Internal::fileNameRole).toString(); - Core::EditorManager::openEditor(fname, Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(fname); } } diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index 059dff26c0..bf4b8ce6e1 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -576,7 +576,7 @@ VcsBase::VcsBaseEditorWidget *VcsBaseClient::createVcsEditor(Core::Id kind, QStr } baseEditor->setForceReadOnly(true); - Core::EditorManager::activateEditor(outputEditor, Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(outputEditor); return baseEditor; } diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index ecf43b2005..321cca7e32 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -297,14 +297,6 @@ void ChangeTextCursorHandler::fillContextMenu(QMenu *menu, EditorContentType typ { VcsBaseEditorWidget *widget = editorWidget(); switch (type) { - case LogOutput: { // Describe current / Annotate file of current - menu->addSeparator(); - menu->addAction(createCopyRevisionAction(m_currentChange)); - menu->addAction(createDescribeAction(m_currentChange)); - if (widget->isFileLogAnnotateEnabled()) - menu->addAction(createAnnotateAction(m_currentChange, false)); - break; - } case AnnotateOutput: { // Describe current / annotate previous bool currentValid = widget->isValidRevision(m_currentChange); menu->addSeparator(); @@ -321,7 +313,12 @@ void ChangeTextCursorHandler::fillContextMenu(QMenu *menu, EditorContentType typ } break; } - default: + default: // Describe current / Annotate file of current + menu->addSeparator(); + menu->addAction(createCopyRevisionAction(m_currentChange)); + menu->addAction(createDescribeAction(m_currentChange)); + if (widget->isFileLogAnnotateEnabled()) + menu->addAction(createAnnotateAction(m_currentChange, false)); break; } widget->addChangeActions(menu, m_currentChange); @@ -663,6 +660,17 @@ void VcsBaseEditorWidget::setLogEntryPattern(const QRegExp &pattern) d->m_logEntryPattern = pattern; } +bool VcsBaseEditorWidget::supportChangeLinks() const +{ + switch (d->m_parameters->type) { + case LogOutput: + case AnnotateOutput: + return true; + default: + return false; + } +} + void VcsBaseEditorWidget::init() { d->m_editor = editor(); @@ -910,17 +918,13 @@ void VcsBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e) { QPointer<QMenu> menu = createStandardContextMenu(); // 'click on change-interaction' - switch (d->m_parameters->type) { - case LogOutput: - case AnnotateOutput: { + if (supportChangeLinks()) { const QTextCursor cursor = cursorForPosition(e->pos()); - Internal::AbstractTextCursorHandler *handler = d->findTextCursorHandler(cursor); - if (handler != 0) + if (Internal::AbstractTextCursorHandler *handler = d->findTextCursorHandler(cursor)) handler->fillContextMenu(menu, d->m_parameters->type); - // Fall-through for log (might have diff) - if (d->m_parameters->type != LogOutput) - break; } + switch (d->m_parameters->type) { + case LogOutput: // log might have diff case DiffOutput: { menu->addSeparator(); connect(menu->addAction(tr("Send to CodePaster...")), SIGNAL(triggered()), @@ -963,7 +967,7 @@ void VcsBaseEditorWidget::mouseMoveEvent(QMouseEvent *e) bool overrideCursor = false; Qt::CursorShape cursorShape; - if (d->m_parameters->type == LogOutput || d->m_parameters->type == AnnotateOutput) { + if (supportChangeLinks()) { // Link emulation behaviour for 'click on change-interaction' const QTextCursor cursor = cursorForPosition(e->pos()); Internal::AbstractTextCursorHandler *handler = d->findTextCursorHandler(cursor); @@ -987,7 +991,7 @@ void VcsBaseEditorWidget::mouseReleaseEvent(QMouseEvent *e) { const bool wasDragging = d->m_mouseDragging; d->m_mouseDragging = false; - if (!wasDragging && (d->m_parameters->type == LogOutput || d->m_parameters->type == AnnotateOutput)) { + if (!wasDragging && supportChangeLinks()) { if (e->button() == Qt::LeftButton &&!(e->modifiers() & Qt::ShiftModifier)) { const QTextCursor cursor = cursorForPosition(e->pos()); Internal::AbstractTextCursorHandler *handler = d->findTextCursorHandler(cursor); @@ -1111,7 +1115,7 @@ void VcsBaseEditorWidget::jumpToChangeFromDiff(QTextCursor cursor) if (!exists) return; - Core::IEditor *ed = Core::EditorManager::openEditor(fileName, Core::Id(), Core::EditorManager::ModeSwitch); + Core::IEditor *ed = Core::EditorManager::openEditor(fileName); if (TextEditor::ITextEditor *editor = qobject_cast<TextEditor::ITextEditor *>(ed)) editor->gotoLine(chunkStart + lineCount); } diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h index 955c194d90..6971b701cf 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.h +++ b/src/plugins/vcsbase/vcsbaseeditor.h @@ -103,6 +103,7 @@ protected: void setDiffFilePattern(const QRegExp &pattern); // Pattern for log entry. hash/revision number must be in the first capture group void setLogEntryPattern(const QRegExp &pattern); + virtual bool supportChangeLinks() const; public: virtual void init(); diff --git a/src/plugins/vcsbase/vcsbaseoutputwindow.cpp b/src/plugins/vcsbase/vcsbaseoutputwindow.cpp index 3728253f55..9dd32497ed 100644 --- a/src/plugins/vcsbase/vcsbaseoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsbaseoutputwindow.cpp @@ -189,7 +189,7 @@ void OutputWindowPlainTextEdit::contextMenuEvent(QContextMenuEvent *event) } if (action == openAction) { const QString fileName = action->data().toString(); - Core::EditorManager::openEditor(fileName, Core::Id(), Core::EditorManager::ModeSwitch); + Core::EditorManager::openEditor(fileName); } } delete menu; diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index 7193f0deff..c572e5d542 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -405,15 +405,6 @@ QString VcsBasePluginState::topLevel() const return hasFile() ? data->m_state.currentFileTopLevel : data->m_state.currentProjectTopLevel; } -QString VcsBasePluginState::currentDirectoryOrTopLevel() const -{ - if (hasFile()) - return data->m_state.currentFileDirectory; - else if (data->m_state.hasProject()) - return data->m_state.currentProjectTopLevel; - return QString(); -} - bool VcsBasePluginState::equals(const Internal::State &rhs) const { return data->m_state.equals(rhs); @@ -549,6 +540,9 @@ void VcsBasePlugin::initializeVcs(Core::IVersionControl *vc) SIGNAL(stateChanged(VcsBase::Internal::State,Core::IVersionControl*)), this, SLOT(slotStateChanged(VcsBase::Internal::State,Core::IVersionControl*))); + // VCSes might have become (un-)available, so clear the VCS directory cache + connect(vc, SIGNAL(configurationChanged()), + Core::ICore::vcsManager(), SLOT(clearVersionControlCache())); } void VcsBasePlugin::extensionsInitialized() @@ -688,9 +682,7 @@ bool VcsBasePlugin::raiseSubmitEditor() const { if (!d->m_submitEditor) return false; - Core::EditorManager::activateEditor( - d->m_submitEditor, - Core::EditorManager::IgnoreNavigationHistory | Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(d->m_submitEditor, Core::EditorManager::IgnoreNavigationHistory); return true; } diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h index 630f1d907a..092d4be727 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.h +++ b/src/plugins/vcsbase/vcsbaseplugin.h @@ -102,7 +102,6 @@ public: // the file one. QString topLevel() const; - QString currentDirectoryOrTopLevel() const; bool equals(const VcsBasePluginState &rhs) const; friend VCSBASE_EXPORT QDebug operator<<(QDebug in, const VcsBasePluginState &state); diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index d71c8866f9..b4c7e3e2d5 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -573,8 +573,7 @@ VcsBaseSubmitEditor::PromptSubmitResult { SubmitEditorWidget *submitWidget = static_cast<SubmitEditorWidget *>(this->widget()); - Core::EditorManager::activateEditor( - this, Core::EditorManager::IgnoreNavigationHistory | Core::EditorManager::ModeSwitch); + Core::EditorManager::activateEditor(this, Core::EditorManager::IgnoreNavigationHistory); QString errorMessage; QMessageBox::StandardButton answer = QMessageBox::Yes; diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp index 36c53cda76..8e5b1ddfa9 100644 --- a/src/plugins/welcome/welcomeplugin.cpp +++ b/src/plugins/welcome/welcomeplugin.cpp @@ -143,7 +143,6 @@ WelcomeMode::WelcomeMode() : setIcon(qtLogo); setPriority(Core::Constants::P_MODE_WELCOME); setId(Core::Constants::MODE_WELCOME); - setType(Core::Constants::MODE_WELCOME_TYPE); setContextHelpId(QLatin1String("Qt Creator Manual")); setContext(Core::Context(Core::Constants::C_WELCOME_MODE)); diff --git a/src/shared/proparser/ioutils.cpp b/src/shared/proparser/ioutils.cpp index 6706f80bee..79a336fa1d 100644 --- a/src/shared/proparser/ioutils.cpp +++ b/src/shared/proparser/ioutils.cpp @@ -76,6 +76,11 @@ bool IoUtils::isRelativePath(const QString &path) return true; } +QStringRef IoUtils::pathName(const QString &fileName) +{ + return fileName.leftRef(fileName.lastIndexOf(QLatin1Char('/')) + 1); +} + QStringRef IoUtils::fileName(const QString &fileName) { return fileName.midRef(fileName.lastIndexOf(QLatin1Char('/')) + 1); diff --git a/src/shared/proparser/ioutils.h b/src/shared/proparser/ioutils.h index 865e4a7511..e4773ca50d 100644 --- a/src/shared/proparser/ioutils.h +++ b/src/shared/proparser/ioutils.h @@ -52,6 +52,7 @@ public: static bool exists(const QString &fileName) { return fileType(fileName) != FileNotFound; } static bool isRelativePath(const QString &fileName); static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); } + static QStringRef pathName(const QString &fileName); // Requires normalized path static QStringRef fileName(const QString &fileName); // Requires normalized path static QString resolvePath(const QString &baseDir, const QString &fileName); static QString shellQuoteUnix(const QString &arg); diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 47012d99fd..c955851928 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -43,9 +43,9 @@ void ProFileEvaluator::initialize() QMakeEvaluator::initStatics(); } -ProFileEvaluator::ProFileEvaluator(ProFileGlobals *option, QMakeParser *parser, +ProFileEvaluator::ProFileEvaluator(ProFileGlobals *option, QMakeParser *parser, QMakeVfs *vfs, QMakeHandler *handler) - : d(new QMakeEvaluator(option, parser, handler)) + : d(new QMakeEvaluator(option, parser, vfs, handler)) { } diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h index a172536411..8d6fec86c3 100644 --- a/src/shared/proparser/profileevaluator.h +++ b/src/shared/proparser/profileevaluator.h @@ -40,6 +40,7 @@ QT_BEGIN_NAMESPACE +class QMakeVfs; class QMakeParser; class QMakeEvaluator; class QMakeHandler; @@ -65,7 +66,8 @@ public: // Call this from a concurrency-free context static void initialize(); - ProFileEvaluator(ProFileGlobals *option, QMakeParser *parser, QMakeHandler *handler); + ProFileEvaluator(ProFileGlobals *option, QMakeParser *parser, QMakeVfs *vfs, + QMakeHandler *handler); ~ProFileEvaluator(); ProFileEvaluator::TemplateType templateType() const; diff --git a/src/shared/proparser/proparser.pri b/src/shared/proparser/proparser.pri index 900151d75f..a3667e5291 100644 --- a/src/shared/proparser/proparser.pri +++ b/src/shared/proparser/proparser.pri @@ -14,6 +14,7 @@ HEADERS += \ profileevaluator.h \ proitems.h \ prowriter.h \ + qmakevfs.h \ ioutils.h SOURCES += \ @@ -24,6 +25,7 @@ SOURCES += \ qmakebuiltins.cpp \ proitems.cpp \ prowriter.cpp \ + qmakevfs.cpp \ ioutils.cpp RESOURCES += proparser.qrc diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 6e2cd8afcd..eb58632c84 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -32,6 +32,7 @@ #include "qmakeevaluator_p.h" #include "qmakeglobals.h" #include "qmakeparser.h" +#include "qmakevfs.h" #include "ioutils.h" #include <qbytearray.h> @@ -269,46 +270,17 @@ quoteValue(const ProString &val) return ret; } -static bool -doWriteFile(const QString &name, QIODevice::OpenMode mode, const QString &contents, QString *errStr) -{ - QByteArray bytes = contents.toLocal8Bit(); - QFile cfile(name); - if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { - if (cfile.readAll() == bytes) - return true; - cfile.close(); - } - if (!cfile.open(mode | QIODevice::WriteOnly | QIODevice::Text)) { - *errStr = cfile.errorString(); - return false; - } - cfile.write(bytes); - cfile.close(); - if (cfile.error() != QFile::NoError) { - *errStr = cfile.errorString(); - return false; - } - return true; -} - QMakeEvaluator::VisitReturn QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, const QString &contents) { - QFileInfo qfi(fn); - if (!QDir::current().mkpath(qfi.path())) { - evalError(fL1S("Cannot create %1directory %2.") - .arg(ctx, QDir::toNativeSeparators(qfi.path()))); - return ReturnFalse; - } QString errStr; - if (!doWriteFile(qfi.filePath(), mode, contents, &errStr)) { + if (!m_vfs->writeFile(fn, mode, contents, &errStr)) { evalError(fL1S("Cannot write %1file %2: %3.") - .arg(ctx, QDir::toNativeSeparators(qfi.filePath()), errStr)); + .arg(ctx, QDir::toNativeSeparators(fn), errStr)); return ReturnFalse; } - m_parser->discardFileFromCache(qfi.filePath()); + m_parser->discardFileFromCache(fn); return ReturnTrue; } @@ -1413,6 +1385,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } const QString &file = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1))); + // Don't use VFS here: + // - it supports neither listing nor even directories + // - it's unlikely that somebody would test for files they created themselves if (IoUtils::exists(file)) return ReturnTrue; int slsh = file.lastIndexOf(QLatin1Char('/')); @@ -1444,7 +1419,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( evalError(fL1S("write_file(name, [content var, [append]]) requires one to three arguments.")); return ReturnFalse; } -#ifdef PROEVALUATOR_FULL QIODevice::OpenMode mode = QIODevice::Truncate; QString contents; if (args.count() >= 2) { @@ -1456,9 +1430,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( mode = QIODevice::Append; } return writeFile(QString(), resolvePath(args.at(0).toQString(m_tmp1)), mode, contents); -#else - return ReturnTrue; -#endif } case T_TOUCH: { if (args.count() != 2) { @@ -1510,7 +1481,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( evalError(fL1S("cache(var, [set|add|sub] [transient] [super], [srcvar]) requires one to three arguments.")); return ReturnFalse; } -#ifdef PROEVALUATOR_FULL bool persist = true; bool super = false; enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet; @@ -1636,9 +1606,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( fn = m_cachefile; } return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr); -#else - return ReturnTrue; -#endif } default: evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1))); diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 9ba0d70b16..db6af6f730 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -32,6 +32,7 @@ #include "qmakeglobals.h" #include "qmakeparser.h" +#include "qmakevfs.h" #include "ioutils.h" #include <qbytearray.h> @@ -162,13 +163,13 @@ const ProKey &QMakeEvaluator::map(const ProKey &var) } -QMakeEvaluator::QMakeEvaluator(QMakeGlobals *option, - QMakeParser *parser, QMakeHandler *handler) +QMakeEvaluator::QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser, QMakeVfs *vfs, + QMakeHandler *handler) : #ifdef PROEVALUATOR_DEBUG m_debugLevel(option->debugLevel), #endif - m_option(option), m_parser(parser), m_handler(handler) + m_option(option), m_parser(parser), m_handler(handler), m_vfs(vfs) { // So that single-threaded apps don't have to call initialize() for now. initStatics(); @@ -921,7 +922,7 @@ void QMakeEvaluator::visitProVariable( if (varName == statics.strTEMPLATE) setTemplate(); else if (varName == statics.strQMAKE_PLATFORM) - updateFeaturePaths(); + m_featureRoots = 0; #ifdef PROEVALUATOR_FULL else if (varName == statics.strREQUIRES) checkRequirements(values(varName)); @@ -1049,7 +1050,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) superdir = m_outputDir; forever { QString superfile = superdir + QLatin1String("/.qmake.super"); - if (IoUtils::exists(superfile)) { + if (m_vfs->exists(superfile)) { m_superfile = QDir::cleanPath(superfile); break; } @@ -1064,10 +1065,10 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) QString dir = m_outputDir; forever { conffile = sdir + QLatin1String("/.qmake.conf"); - if (!IoUtils::exists(conffile)) + if (!m_vfs->exists(conffile)) conffile.clear(); cachefile = dir + QLatin1String("/.qmake.cache"); - if (!IoUtils::exists(cachefile)) + if (!m_vfs->exists(cachefile)) cachefile.clear(); if (!conffile.isEmpty() || !cachefile.isEmpty()) { if (dir != sdir) @@ -1145,6 +1146,7 @@ bool QMakeEvaluator::loadSpecInternal() #endif valuesRef(ProKey("QMAKESPEC")) << ProString(m_qmakespec); m_qmakespecName = IoUtils::fileName(m_qmakespec).toString(); + // This also ensures that m_featureRoots is valid. if (evaluateFeatureFile(QLatin1String("spec_post.prf")) != ReturnTrue) return false; // The MinGW and x-build specs may change the separator; $$shell_{path,quote}() need it @@ -1158,7 +1160,7 @@ bool QMakeEvaluator::loadSpec() m_hostBuild ? m_option->qmakespec : m_option->xqmakespec); { - QMakeEvaluator evaluator(m_option, m_parser, m_handler); + QMakeEvaluator evaluator(m_option, m_parser, m_vfs, m_handler); if (!m_superfile.isEmpty()) { valuesRef(ProKey("_QMAKE_SUPER_CACHE_")) << ProString(m_superfile); if (evaluator.evaluateFile( @@ -1315,7 +1317,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile( locker.unlock(); #endif - QMakeEvaluator *baseEval = new QMakeEvaluator(m_option, m_parser, m_handler); + QMakeEvaluator *baseEval = new QMakeEvaluator(m_option, m_parser, m_vfs, m_handler); baseEnv->evaluator = baseEval; baseEval->m_superfile = m_superfile; baseEval->m_conffile = m_conffile; @@ -1481,7 +1483,7 @@ void QMakeEvaluator::updateFeaturePaths() foreach (const QString &root, feature_roots) if (IoUtils::exists(root)) ret << root; - m_featureRoots = ret; + m_featureRoots = new QMakeFeatureRoots(ret); } ProString QMakeEvaluator::propertyValue(const ProKey &name) const @@ -1810,7 +1812,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFile( #endif return ok; } else { - if (!(flags & LoadSilent) && !IoUtils::exists(fileName)) + if (!(flags & LoadSilent) && !m_vfs->exists(fileName)) evalError(fL1S("WARNING: Include file %1 not found").arg(fileName)); return ReturnFalse; } @@ -1839,34 +1841,55 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile( if (!fn.endsWith(QLatin1String(".prf"))) fn += QLatin1String(".prf"); - if (m_featureRoots.isEmpty()) + if (!m_featureRoots) updateFeaturePaths(); - int start_root = 0; +#ifdef PROEVALUATOR_THREAD_SAFE + m_featureRoots->mutex.lock(); +#endif QString currFn = currentFileName(); - if (IoUtils::fileName(currFn) == IoUtils::fileName(fn)) { - for (int root = 0; root < m_featureRoots.size(); ++root) - if (currFn == m_featureRoots.at(root) + fn) { - start_root = root + 1; - break; + if (IoUtils::fileName(currFn) != IoUtils::fileName(fn)) + currFn.clear(); + // Null values cannot regularly exist in the hash, so they indicate that the value still + // needs to be determined. Failed lookups are represented via non-null empty strings. + QString *fnp = &m_featureRoots->cache[qMakePair(fn, currFn)]; + if (fnp->isNull()) { + int start_root = 0; + const QStringList &paths = m_featureRoots->paths; + if (!currFn.isEmpty()) { + QStringRef currPath = IoUtils::pathName(currFn); + for (int root = 0; root < paths.size(); ++root) + if (currPath == paths.at(root)) { + start_root = root + 1; + break; + } + } + for (int root = start_root; root < paths.size(); ++root) { + QString fname = paths.at(root) + fn; + if (IoUtils::exists(fname)) { + fn = fname; + goto cool; } - } - for (int root = start_root; root < m_featureRoots.size(); ++root) { - QString fname = m_featureRoots.at(root) + fn; - if (IoUtils::exists(fname)) { - fn = fname; - goto cool; } - } #ifdef QMAKE_BUILTIN_PRFS - fn.prepend(QLatin1String(":/qmake/features/")); - if (QFileInfo(fn).exists()) - goto cool; + fn.prepend(QLatin1String(":/qmake/features/")); + if (QFileInfo(fn).exists()) + goto cool; #endif - if (!silent) - evalError(fL1S("Cannot find feature %1").arg(fileName)); - return ReturnFalse; + fn = QLatin1String(""); // Indicate failed lookup. See comment above. - cool: + cool: + *fnp = fn; + } else { + fn = *fnp; + } +#ifdef PROEVALUATOR_THREAD_SAFE + m_featureRoots->mutex.unlock(); +#endif + if (fn.isEmpty()) { + if (!silent) + evalError(fL1S("Cannot find feature %1").arg(fileName)); + return ReturnFalse; + } ProStringList &already = valuesRef(ProKey("QMAKE_INTERNAL_INCLUDED_FEATURES")); ProString afn(fn); if (already.contains(afn)) { @@ -1893,7 +1916,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile( QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFileInto( const QString &fileName, ProValueMap *values, LoadFlags flags) { - QMakeEvaluator visitor(m_option, m_parser, m_handler); + QMakeEvaluator visitor(m_option, m_parser, m_vfs, m_handler); visitor.m_caller = this; visitor.m_outputDir = m_outputDir; visitor.m_featureRoots = m_featureRoots; diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 63d34e8f76..188b8c05ce 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -43,9 +43,13 @@ #include <qstack.h> #include <qstring.h> #include <qstringlist.h> +#include <qshareddata.h> #ifndef QT_BOOTSTRAPPED # include <qprocess.h> #endif +#ifdef PROEVALUATOR_THREAD_SAFE +# include <qmutex.h> +#endif QT_BEGIN_NAMESPACE @@ -71,6 +75,20 @@ public: virtual void doneWithEval(ProFile *parent) = 0; }; +typedef QPair<QString, QString> QMakeFeatureKey; // key, parent +typedef QHash<QMakeFeatureKey, QString> QMakeFeatureHash; + +class QMAKE_EXPORT QMakeFeatureRoots : public QSharedData +{ +public: + QMakeFeatureRoots(const QStringList &_paths) : paths(_paths) {} + const QStringList paths; + mutable QMakeFeatureHash cache; +#ifdef PROEVALUATOR_THREAD_SAFE + mutable QMutex mutex; +#endif +}; + // We use a QLinkedList based stack instead of a QVector based one (QStack), so that // the addresses of value maps stay constant. The qmake generators rely on that. class QMAKE_EXPORT ProValueMapStack : public QLinkedList<ProValueMap> @@ -96,7 +114,7 @@ public: static void initStatics(); static void initFunctionStatics(); - QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser, + QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser, QMakeVfs *vfs, QMakeHandler *handler); ~QMakeEvaluator(); @@ -271,7 +289,7 @@ public: QStringList m_qmakepath; QStringList m_qmakefeatures; QStringList m_mkspecPaths; - QStringList m_featureRoots; + QExplicitlySharedDataPointer<QMakeFeatureRoots> m_featureRoots; ProString m_dirSep; ProFunctionDefs m_functionDefs; ProStringList m_returnValue; @@ -282,6 +300,7 @@ public: QMakeGlobals *m_option; QMakeParser *m_parser; QMakeHandler *m_handler; + QMakeVfs *m_vfs; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeEvaluator::LoadFlags) diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp index ae0fdd0fac..9dd10ac448 100644 --- a/src/shared/proparser/qmakeparser.cpp +++ b/src/shared/proparser/qmakeparser.cpp @@ -29,6 +29,7 @@ #include "qmakeparser.h" +#include "qmakevfs.h" #include "ioutils.h" using namespace QMakeInternal; @@ -130,9 +131,10 @@ void QMakeParser::initialize() statics.strLITERAL_WHITESPACE = QLatin1String("LITERAL_WHITESPACE"); } -QMakeParser::QMakeParser(ProFileCache *cache, QMakeParserHandler *handler) +QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler *handler) : m_cache(cache) , m_handler(handler) + , m_vfs(vfs) { // So that single-threaded apps don't have to call initialize() for now. initialize(); @@ -218,24 +220,14 @@ void QMakeParser::discardFileFromCache(const QString &fileName) bool QMakeParser::read(ProFile *pro) { - QFile file(pro->fileName()); - if (!file.open(QIODevice::ReadOnly)) { - if (m_handler && IoUtils::exists(pro->fileName())) + QString content; + QString errStr; + if (!m_vfs->readFile(pro->fileName(), &content, &errStr)) { + if (m_handler && m_vfs->exists(pro->fileName())) m_handler->message(QMakeParserHandler::ParserIoError, - fL1S("Cannot read %1: %2").arg(pro->fileName(), file.errorString())); + fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr)); return false; } - - QByteArray bcont = file.readAll(); - if (bcont.startsWith("\xef\xbb\xbf")) { - // UTF-8 BOM will cause subtle errors - m_handler->message(QMakeParserHandler::ParserIoError, - fL1S("Unexpected UTF-8 BOM in %1").arg(pro->fileName())); - return false; - } - QString content(QString::fromLocal8Bit(bcont)); - bcont.clear(); - file.close(); return read(pro, content, 1, FullGrammar); } diff --git a/src/shared/proparser/qmakeparser.h b/src/shared/proparser/qmakeparser.h index 6fc599f617..87cd8c2244 100644 --- a/src/shared/proparser/qmakeparser.h +++ b/src/shared/proparser/qmakeparser.h @@ -67,6 +67,7 @@ public: }; class ProFileCache; +class QMakeVfs; class QMAKE_EXPORT QMakeParser { @@ -74,7 +75,7 @@ public: // Call this from a concurrency-free context static void initialize(); - QMakeParser(ProFileCache *cache, QMakeParserHandler *handler); + QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler *handler); enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar }; // fileName is expected to be absolute and cleanPath()ed. @@ -163,6 +164,7 @@ private: ProFileCache *m_cache; QMakeParserHandler *m_handler; + QMakeVfs *m_vfs; // This doesn't help gcc 3.3 ... template<typename T> friend class QTypeInfo; diff --git a/src/shared/proparser/qmakevfs.cpp b/src/shared/proparser/qmakevfs.cpp new file mode 100644 index 0000000000..69373c4a9e --- /dev/null +++ b/src/shared/proparser/qmakevfs.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qmakevfs.h" + +#include "ioutils.h" +using namespace QMakeInternal; + +#include <qdir.h> +#include <qfile.h> +#include <qfileinfo.h> + +#define fL1S(s) QString::fromLatin1(s) + +QMakeVfs::QMakeVfs() +#ifndef PROEVALUATOR_FULL + : m_magicMissing(fL1S("missing")) + , m_magicExisting(fL1S("existing")) +#endif +{ +} + +bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QString &contents, + QString *errStr) +{ +#ifndef PROEVALUATOR_FULL +# ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker locker(&m_mutex); +# endif + QString *cont = &m_files[fn]; + if (mode & QIODevice::Append) + *cont += contents; + else + *cont = contents; + Q_UNUSED(errStr) + return true; +#else + QFileInfo qfi(fn); + if (!QDir::current().mkpath(qfi.path())) { + *errStr = fL1S("Cannot create parent directory"); + return false; + } + QByteArray bytes = contents.toLocal8Bit(); + QFile cfile(fn); + if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { + if (cfile.readAll() == bytes) + return true; + cfile.close(); + } + if (!cfile.open(mode | QIODevice::WriteOnly | QIODevice::Text)) { + *errStr = cfile.errorString(); + return false; + } + cfile.write(bytes); + cfile.close(); + if (cfile.error() != QFile::NoError) { + *errStr = cfile.errorString(); + return false; + } + return true; +#endif +} + +bool QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr) +{ +#ifndef PROEVALUATOR_FULL +# ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker locker(&m_mutex); +# endif + QHash<QString, QString>::ConstIterator it = m_files.constFind(fn); + if (it != m_files.constEnd()) { + if (it->constData() == m_magicMissing.constData()) { + *errStr = fL1S("No such file or directory"); + return false; + } + if (it->constData() != m_magicExisting.constData()) { + *contents = *it; + return true; + } + } +#endif + + QFile file(fn); + if (!file.open(QIODevice::ReadOnly)) { +#ifndef PROEVALUATOR_FULL + if (!IoUtils::exists(fn)) { + m_files[fn] = m_magicMissing; + *errStr = fL1S("No such file or directory"); + } else +#endif + *errStr = file.errorString(); + return false; + } +#ifndef PROEVALUATOR_FULL + m_files[fn] = m_magicExisting; +#endif + + QByteArray bcont = file.readAll(); + if (bcont.startsWith("\xef\xbb\xbf")) { + // UTF-8 BOM will cause subtle errors + *errStr = fL1S("Unexpected UTF-8 BOM"); + return false; + } + *contents = QString::fromLocal8Bit(bcont); + return true; +} + +bool QMakeVfs::exists(const QString &fn) +{ +#ifndef PROEVALUATOR_FULL +# ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker locker(&m_mutex); +# endif + QHash<QString, QString>::ConstIterator it = m_files.constFind(fn); + if (it != m_files.constEnd()) + return it->constData() != m_magicMissing.constData(); +#endif + bool ex = IoUtils::exists(fn); +#ifndef PROEVALUATOR_FULL + m_files[fn] = ex ? m_magicExisting : m_magicMissing; +#endif + return ex; +} + +#ifndef PROEVALUATOR_FULL +// This should be called when the sources may have changed (e.g., VCS update). +void QMakeVfs::invalidateCache() +{ +# ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker locker(&m_mutex); +# endif + QHash<QString, QString>::Iterator it = m_files.begin(), eit = m_files.end(); + while (it != eit) { + if (it->constData() == m_magicMissing.constData() + ||it->constData() == m_magicExisting.constData()) + it = m_files.erase(it); + else + ++it; + } +} + +// This should be called when generated files may have changed (e.g., actual build). +void QMakeVfs::invalidateContents() +{ +# ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker locker(&m_mutex); +# endif + m_files.clear(); +} +#endif + +QT_END_NAMESPACE diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.cpp b/src/shared/proparser/qmakevfs.h index f29daa6c84..045765a362 100644 --- a/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.cpp +++ b/src/shared/proparser/qmakevfs.h @@ -27,17 +27,47 @@ ** ****************************************************************************/ -#include "highlightdefinitionmetadata.h" +#ifndef QMAKEVFS_H +#define QMAKEVFS_H -using namespace TextEditor; -using namespace Internal; +#include "qmake_global.h" -const QLatin1String HighlightDefinitionMetaData::kPriority("priority"); -const QLatin1String HighlightDefinitionMetaData::kName("name"); -const QLatin1String HighlightDefinitionMetaData::kExtensions("extensions"); -const QLatin1String HighlightDefinitionMetaData::kMimeType("mimetype"); -const QLatin1String HighlightDefinitionMetaData::kVersion("version"); -const QLatin1String HighlightDefinitionMetaData::kUrl("url"); +# include <QIODevice> +#ifndef PROEVALUATOR_FULL +# include <QHash> +# include <QString> +# ifdef PROEVALUATOR_THREAD_SAFE +# include <qmutex.h> +# endif +#endif -HighlightDefinitionMetaData::HighlightDefinitionMetaData() : priority(0) -{} +QT_BEGIN_NAMESPACE + +class QMAKE_EXPORT QMakeVfs +{ +public: + QMakeVfs(); + + bool writeFile(const QString &fn, QIODevice::OpenMode mode, const QString &contents, QString *errStr); + bool readFile(const QString &fn, QString *contents, QString *errStr); + bool exists(const QString &fn); + +#ifndef PROEVALUATOR_FULL + void invalidateCache(); + void invalidateContents(); +#endif + +private: +#ifndef PROEVALUATOR_FULL +# ifdef PROEVALUATOR_THREAD_SAFE + QMutex m_mutex; +# endif + QHash<QString, QString> m_files; + QString m_magicMissing; + QString m_magicExisting; +#endif +}; + +QT_END_NAMESPACE + +#endif // QMAKEVFS_H diff --git a/src/shared/qtsingleapplication/qtlocalpeer.cpp b/src/shared/qtsingleapplication/qtlocalpeer.cpp index c1c68938af..07cfc74ed0 100644 --- a/src/shared/qtsingleapplication/qtlocalpeer.cpp +++ b/src/shared/qtsingleapplication/qtlocalpeer.cpp @@ -46,7 +46,7 @@ static PProcessIdToSessionId pProcessIdToSessionId = 0; namespace SharedTools { -const char *QtLocalPeer::ack = "ack"; +static const char ack[] = "ack"; QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId) : QObject(parent), id(appId) diff --git a/src/shared/qtsingleapplication/qtlocalpeer.h b/src/shared/qtsingleapplication/qtlocalpeer.h index e721a05de9..fad6501790 100644 --- a/src/shared/qtsingleapplication/qtlocalpeer.h +++ b/src/shared/qtsingleapplication/qtlocalpeer.h @@ -57,9 +57,6 @@ protected: QString socketName; QLocalServer* server; QtLockedFile lockFile; - -private: - static const char* ack; }; } // namespace SharedTools |