diff --git a/.gitignore b/.gitignore index 97887bbbb43..48c74fa1610 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ Thumbs.db *.rc *.embed.manifest /.qmake.cache +/.qmake.stash # qtcreator generated files *.pro.user* diff --git a/qtcreator.pro b/qtcreator.pro index 7271ab940c4..1e250446d5e 100644 --- a/qtcreator.pro +++ b/qtcreator.pro @@ -43,6 +43,8 @@ exists(src/shared/qbs/qbs.pro) { system("echo QBS_LIB_INSTALL_DIR = $${QTC_PREFIX}/$${IDE_LIBRARY_BASENAME}/qtcreator >> $$qmake_cache") system("echo QBS_RESOURCES_BUILD_DIR = $${maybe_backslash}\"$${IDE_DATA_PATH}/qbs$${maybe_backslash}\" >> $$qmake_cache") system("echo QBS_RESOURCES_INSTALL_DIR = $${QTC_PREFIX}/share/qtcreator/qbs >> $$qmake_cache") + system("echo QBS_PLUGINS_BUILD_DIR = $${maybe_backslash}\"$${IDE_BUILD_TREE}/lib/qtcreator/$${maybe_backslash}\" >> $$qmake_cache") + system("echo QBS_PLUGINS_INSTALL_DIR = $${QTC_PREFIX}/lib/qtcreator >> $$qmake_cache") system("echo CONFIG += qbs_no_dev_install >> $$qmake_cache") } diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index fb1c612d98b..2bfa0f1f8f7 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -833,47 +833,54 @@ class Dumper(DumperBase): def extractByte(self, addr): return struct.unpack("b", self.readRawMemory(addr, 1))[0] - def extractStaticMetaObjectHelper(self, typeobj): + + def extractStaticMetaObjectHelper(self, typeName): """ Checks whether type has a Q_OBJECT macro. Returns the staticMetaObject, or 0. """ + # No templates for now. + if typeName.find('<') >= 0: + return 0 + + staticMetaObjectName = typeName + "::staticMetaObject" + if hasattr(gdb, 'lookup_global_symbol'): + result = gdb.lookup_global_symbol(staticMetaObjectName) + result = result.value() if result else 0 + else: + # Older GDB... + try: + result = gdb.parse_and_eval(staticMetaObjectName) + except: + result = 0 + + # We need to distinguish Q_OBJECT from Q_GADGET: + # a Q_OBJECT SMO has a non-null superdata (unless it's QObject itself), + # a Q_GADGET SMO has a null superdata (hopefully) + if result and typeName != self.qtNamespace() + "QObject": + if not self.extractPointer(result): + # This looks like a Q_GADGET + result = 0 + + return result + + def extractStaticMetaObject(self, typeobj): + """ + Checks recursively whether a type derives from QObject. + """ typeName = str(typeobj) result = self.knownStaticMetaObjects.get(typeName, None) if result is not None: # Is 0 or the static metaobject. return result - staticMetaObjectName = typeName + "::staticMetaObject" - try: - result = gdb.lookup_global_symbol(staticMetaObjectName) - result = result.value() if result else 0 - self.knownStaticMetaObjects[typeName] = result - return result - except: - pass + result = self.extractStaticMetaObjectHelper(typeName) + if not result: + fields = typeobj.fields() + if len(fields) and fields[0].is_base_class: + result = self.extractStaticMetaObject(fields[0].type) - # Older GDB... - try: - result = gdb.parse_and_eval(staticMetaObjectName) - self.knownStaticMetaObjects[typeName] = result - return result - except: - self.knownStaticMetaObjects[typeName] = 0 - return 0 - - def extractStaticMetaObject(self, typeobj): - """ - Checks recursively whether a type derives from QObject. - """ - result = self.extractStaticMetaObjectHelper(typeobj) - if result: - return result - fields = typeobj.fields() - if not len(fields): - return 0 - if not fields[0].is_base_class: - return 0 - return self.extractStaticMetaObject(fields[0].type) + self.knownStaticMetaObjects[typeName] = result + return result def put(self, value): diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index d9d94e5ff24..a84927cb253 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -1824,6 +1824,9 @@ def qdump__QTextDocument(d, value): d.putCallItem("toPlainText", value, "toPlainText") +def qform__QUrl(): + return "Inline,Separate Window" + def qdump__QUrl(d, value): if d.qtVersion() < 0x050000: privAddress = d.extractPointer(value) @@ -1884,6 +1887,14 @@ def qdump__QUrl(d, value): url += ''.join(["%02x00" % ord(c) for c in str(port)]) url += path d.putValue(url, Hex4EncodedLittleEndian) + + format = d.currentItemFormat() + if format == 1: + d.putDisplay(StopDisplay) + elif format == 2: + d.putField("editformat", DisplayUtf16String) + d.putField("editvalue", url) + d.putNumChild(8) if d.isExpanded(): stringType = d.lookupType(d.qtNamespace() + "QString") diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 21440bc86c1..41439ad7904 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1951,10 +1951,19 @@ void Preprocessor::handleUndefDirective(PPToken *tk) lex(tk); // consume "undef" token if (tk->is(T_IDENTIFIER)) { const ByteArrayRef macroName = tk->asByteArrayRef(); - const Macro *macro = m_env->remove(macroName); + const unsigned offset = tk->offset + m_state.m_offsetRef; + // Track macro use if previously defined + if (m_client) { + if (const Macro *existingMacro = m_env->resolve(macroName)) + m_client->notifyMacroReference(offset, tk->lineno, *existingMacro); + } + synchronizeOutputLines(*tk); + Macro *macro = m_env->remove(macroName); - if (m_client && macro) + if (m_client && macro) { + macro->setOffset(offset); m_client->macroAdded(*macro); + } lex(tk); // consume macro name #ifndef NO_DEBUG } else { diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index f594486de33..dae5f1a835c 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -198,6 +198,9 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind result << QLatin1String("-fmacro-backtrace-limit=0"); result << QLatin1String("-fretain-comments-from-system-headers"); + if (!pPart->projectConfigFile.isEmpty()) + result << QLatin1String("-include") << pPart->projectConfigFile; + result << buildDefines(pPart->toolchainDefines, false); result << buildDefines(pPart->projectDefines, false); diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index a4658cb99ce..4bce4fa8e2b 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -349,7 +349,22 @@ bool CMakeProject::parseCMakeLists() // This explicitly adds -I. to the include paths part->includePaths += projectDirectory(); - part->includePaths += cbpparser.includeFiles(); + + foreach (const QString &includeFile, cbpparser.includeFiles()) { + // CodeBlocks is utterly ignorant of frameworks on Mac, and won't report framework + // paths. The work-around is to check if the include path ends in ".framework", and + // if so, add the parent directory as framework path. + if (includeFile.endsWith(QLatin1String(".framework"))) { + const int slashIdx = includeFile.lastIndexOf(QLatin1Char('/')); + if (slashIdx != -1) { + part->frameworkPaths += includeFile.left(slashIdx); + continue; + } + } + + part->includePaths += includeFile; + } + part->projectDefines += cbpparser.defines(); CppTools::ProjectFileAdder adder(part->files); diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp index 93f31496029..271b883f032 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp +++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp @@ -283,7 +283,6 @@ Command *ActionManager::registerShortcut(QShortcut *shortcut, Id id, const Conte } else { sc = new Shortcut(id); d->m_idCmdMap.insert(id, sc); - d->readUserSettings(id, sc); } if (sc->shortcut()) { @@ -299,6 +298,7 @@ Command *ActionManager::registerShortcut(QShortcut *shortcut, Id id, const Conte sc->setShortcut(shortcut); sc->setScriptable(scriptable); sc->setContext(context); + d->readUserSettings(id, sc); emit m_instance->commandListChanged(); emit m_instance->commandAdded(id.toString()); diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp index c9d1e996d85..af679852914 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp @@ -200,6 +200,8 @@ void ShortcutSettings::resetTargetIdentifier() if (current && current->data(0, Qt::UserRole).isValid()) { ShortcutItem *scitem = qvariant_cast(current->data(0, Qt::UserRole)); setKeySequence(scitem->m_cmd->defaultKeySequence()); + foreach (ShortcutItem *item, m_scitems) + markCollisions(item); } } diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 55b9db99b02..dbc0ee8bcc2 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -351,9 +351,9 @@ void MainWindow::extensionsInitialized() emit m_coreImpl->coreAboutToOpen(); show(); - emit m_coreImpl->coreOpened(); // Delay restoreWindowState, since it is overridden by LayoutRequest event QTimer::singleShot(0, this, SLOT(restoreWindowState())); + QTimer::singleShot(0, m_coreImpl, SIGNAL(coreOpened())); } void MainWindow::closeEvent(QCloseEvent *event) diff --git a/src/plugins/coreplugin/toolsettings.cpp b/src/plugins/coreplugin/toolsettings.cpp index 18043415260..da5d1f4f778 100644 --- a/src/plugins/coreplugin/toolsettings.cpp +++ b/src/plugins/coreplugin/toolsettings.cpp @@ -89,6 +89,7 @@ static QString getUserFilePath(const QString &proposalFileName) static QString idFromDisplayName(const QString &displayName) { QString id = displayName; + id.remove(QRegExp(QLatin1String("&(?!&)"))); QChar *c = id.data(); while (!c->isNull()) { if (!c->isLetterOrNumber()) diff --git a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp index 461ce25a8e4..c602bd25d0b 100644 --- a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp +++ b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp @@ -560,14 +560,16 @@ void CppCodeModelInspectorDumper::dumpProjectInfos( projectName = project->displayName(); projectFilePath = project->projectFilePath(); } + if (!part->projectConfigFile.isEmpty()) + m_out << i3 << "Project Config File: " << part->projectConfigFile << "\n"; m_out << i2 << "Project Part \"" << part->projectFile << "\"{{{3\n"; - m_out << i3 << "Project Part Name: " << part->displayName << "\n"; - m_out << i3 << "Project Name : " << projectName << "\n"; - m_out << i3 << "Project File : " << projectFilePath << "\n"; - m_out << i3 << "C Version : " << toString(part->cVersion) << "\n"; - m_out << i3 << "CXX Version : " << toString(part->cxxVersion) << "\n"; - m_out << i3 << "CXX Extensions : " << toString(part->cxxExtensions) << "\n"; - m_out << i3 << "Qt Version : " << toString(part->qtVersion) << "\n"; + m_out << i3 << "Project Part Name : " << part->displayName << "\n"; + m_out << i3 << "Project Name : " << projectName << "\n"; + m_out << i3 << "Project File : " << projectFilePath << "\n"; + m_out << i3 << "C Version : " << toString(part->cVersion) << "\n"; + m_out << i3 << "CXX Version : " << toString(part->cxxVersion) << "\n"; + m_out << i3 << "CXX Extensions : " << toString(part->cxxExtensions) << "\n"; + m_out << i3 << "Qt Version : " << toString(part->qtVersion) << "\n"; if (!part->files.isEmpty()) { m_out << i3 << "Files:{{{4\n"; @@ -2246,6 +2248,9 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr & << qMakePair(QString::fromLatin1("CXX Extensions"), toString(part->cxxExtensions)) << qMakePair(QString::fromLatin1("Qt Version"), toString(part->qtVersion)) ; + if (!part->projectConfigFile.isEmpty()) + table.prepend(qMakePair(QString::fromLatin1("Project Config File"), + part->projectConfigFile)); m_partGenericInfoModel->configure(table); resizeColumns(m_ui->partGeneralView); diff --git a/src/plugins/cppeditor/cppincludehierarchy_test.cpp b/src/plugins/cppeditor/cppincludehierarchy_test.cpp index d37448dd162..e9235b5cdf1 100644 --- a/src/plugins/cppeditor/cppincludehierarchy_test.cpp +++ b/src/plugins/cppeditor/cppincludehierarchy_test.cpp @@ -40,6 +40,8 @@ #include #include +Q_DECLARE_METATYPE(QList) + using namespace CPlusPlus; using namespace CppEditor::Internal; using namespace CppTools; diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp index 08d51889459..543e0d4deb8 100644 --- a/src/plugins/cpptools/cppcodeformatter.cpp +++ b/src/plugins/cpptools/cppcodeformatter.cpp @@ -179,6 +179,9 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block) case declaration_start: switch (kind) { + case T_CLASS: + case T_STRUCT: turnInto(class_start); continue; + case T_ENUM: turnInto(enum_start); continue; case T_RBRACE: leave(true); continue; case T_SEMICOLON: leave(true); break; case T_EQUAL: enter(assign_open_or_initializer); break; diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 5a0e96a3696..1363bef7b67 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -65,7 +65,7 @@ namespace CppTools { uint qHash(const ProjectPart &p) { uint h = qHash(p.toolchainDefines) ^ qHash(p.projectDefines) ^ p.cVersion ^ p.cxxVersion - ^ p.cxxExtensions ^ p.qtVersion; + ^ p.cxxExtensions ^ p.qtVersion ^ qHash(p.projectConfigFile); foreach (const QString &i, p.includePaths) h ^= qHash(i); @@ -83,6 +83,8 @@ bool operator==(const ProjectPart &p1, return false; if (p1.projectDefines != p2.projectDefines) return false; + if (p1.projectConfigFile != p2.projectConfigFile) + return false; if (p1.cVersion != p2.cVersion) return false; if (p1.cxxVersion != p2.cxxVersion) @@ -393,6 +395,8 @@ QByteArray CppModelManager::internalDefinedMacros() const foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) { addUnique(part->toolchainDefines.split('\n'), ¯os, &alreadyIn); addUnique(part->projectDefines.split('\n'), ¯os, &alreadyIn); + if (!part->projectConfigFile.isEmpty()) + macros += readProjectConfigFile(part); } } return macros; @@ -434,6 +438,7 @@ void CppModelManager::dumpModelManagerConfiguration() qDebug() << "cxxVersion:" << cxxVersion; qDebug() << "cxxExtensions:" << cxxExtensions; qDebug() << "Qt version:" << part->qtVersion; + qDebug() << "project config file:" << part->projectConfigFile; qDebug() << "precompiled header:" << part->precompiledHeaders; qDebug() << "toolchain defines:" << part->toolchainDefines; qDebug() << "project defines:" << part->projectDefines; diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.cpp b/src/plugins/cpptools/cppmodelmanagerinterface.cpp index 0f65f162255..5b31d4a2a25 100644 --- a/src/plugins/cpptools/cppmodelmanagerinterface.cpp +++ b/src/plugins/cpptools/cppmodelmanagerinterface.cpp @@ -223,4 +223,24 @@ void CppModelManagerInterface::ProjectInfo::appendProjectPart(const ProjectPart: m_defines.append('\n'); m_defines.append(part->toolchainDefines); m_defines.append(part->projectDefines); + if (!part->projectConfigFile.isEmpty()) { + m_defines.append('\n'); + m_defines += readProjectConfigFile(part); + m_defines.append('\n'); + } } + +QByteArray CppModelManagerInterface::readProjectConfigFile(const ProjectPart::Ptr &part) +{ + QByteArray result; + + QFile f(part->projectConfigFile); + if (f.open(QIODevice::ReadOnly)) { + QTextStream is(&f); + result = is.readAll().toUtf8(); + f.close(); + } + + return result; +} + diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h index 188367c68ad..5bd7be3cc27 100644 --- a/src/plugins/cpptools/cppmodelmanagerinterface.h +++ b/src/plugins/cpptools/cppmodelmanagerinterface.h @@ -106,6 +106,7 @@ public: QString projectFile; ProjectExplorer::Project *project; QList files; + QString projectConfigFile; // currently only used by the Generic Project Manager QByteArray projectDefines; QByteArray toolchainDefines; QStringList includePaths; @@ -290,6 +291,9 @@ public slots: virtual void updateModifiedSourceFiles() = 0; virtual void GC() = 0; + +protected: + static QByteArray readProjectConfigFile(const ProjectPart::Ptr &part); }; } // namespace CppTools diff --git a/src/plugins/cpptools/cppsnapshotupdater.cpp b/src/plugins/cpptools/cppsnapshotupdater.cpp index 85a282ae34e..4d4de1021c7 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.cpp +++ b/src/plugins/cpptools/cppsnapshotupdater.cpp @@ -60,6 +60,7 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) QStringList includePaths; QStringList frameworkPaths; QStringList precompiledHeaders; + QString projectConfigFile; updateProjectPart(); @@ -73,6 +74,7 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) configFile += m_projectPart->projectDefines; includePaths = m_projectPart->includePaths; frameworkPaths = m_projectPart->frameworkPaths; + projectConfigFile = m_projectPart->projectConfigFile; if (m_usePrecompiledHeaders) precompiledHeaders = m_projectPart->precompiledHeaders; } @@ -99,6 +101,11 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) invalidateSnapshot = true; } + if (projectConfigFile != m_projectConfigFile) { + m_projectConfigFile = projectConfigFile; + invalidateSnapshot = true; + } + if (precompiledHeaders != m_precompiledHeaders) { m_precompiledHeaders = precompiledHeaders; invalidateSnapshot = true; @@ -160,6 +167,8 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) preproc.setIncludePaths(m_includePaths); preproc.setFrameworkPaths(m_frameworkPaths); preproc.run(configurationFileName); + if (!m_projectConfigFile.isEmpty()) + preproc.run(m_projectConfigFile); if (m_usePrecompiledHeaders) { foreach (const QString &precompiledHeader, m_precompiledHeaders) preproc.run(precompiledHeader); diff --git a/src/plugins/cpptools/cppsnapshotupdater.h b/src/plugins/cpptools/cppsnapshotupdater.h index c5d14189465..92741cf006d 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.h +++ b/src/plugins/cpptools/cppsnapshotupdater.h @@ -78,6 +78,7 @@ private: QByteArray m_editorDefines; QStringList m_includePaths; QStringList m_frameworkPaths; + QString m_projectConfigFile; QStringList m_precompiledHeaders; CPlusPlus::Snapshot m_snapshot; CPlusPlus::DependencyTable m_deps; diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 1d3aed67ae1..afe74fbd98f 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -138,9 +138,9 @@ QString DiffEditorPlugin::getFileContents(const QString &fileName) const #include "sidebysidediffeditorwidget.h" -void DiffEditor::Internal::DiffEditorPlugin::testAssemblyRows() +void DiffEditor::Internal::DiffEditorPlugin::testFixPositions() { - SideBySideDiffEditorWidget::testAssemblyRows(); + SideBySideDiffEditorWidget::testFixPositions(); } #endif // WITH_TESTS diff --git a/src/plugins/diffeditor/diffeditorplugin.h b/src/plugins/diffeditor/diffeditorplugin.h index e40a10014d3..703c97496fd 100644 --- a/src/plugins/diffeditor/diffeditorplugin.h +++ b/src/plugins/diffeditor/diffeditorplugin.h @@ -54,7 +54,7 @@ private slots: void diff(); #ifdef WITH_TESTS - void testAssemblyRows(); + void testFixPositions(); #endif // WITH_TESTS private: diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp index f9ea7705c18..e64fb83c59d 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp @@ -73,22 +73,23 @@ public: Separator, Invalid }; - TextLineData() : textLineType(Invalid), changed(true) {} - TextLineData(const QString &txt) : textLineType(TextLine), text(txt), changed(true) {} - TextLineData(TextLineType t) : textLineType(t), changed(true) {} + TextLineData() : textLineType(Invalid) {} + TextLineData(const QString &txt) : textLineType(TextLine), text(txt) {} + TextLineData(TextLineType t) : textLineType(t) {} TextLineType textLineType; QString text; - bool changed; // true if anything was changed in this line (inserted or removed), taking whitespaces into account }; class RowData { public: + RowData() : equal(false) {} RowData(const TextLineData &l) - : leftLine(l), rightLine(l) {} + : leftLine(l), rightLine(l), equal(true) {} RowData(const TextLineData &l, const TextLineData &r) - : leftLine(l), rightLine(r) {} + : leftLine(l), rightLine(r), equal(false) {} TextLineData leftLine; TextLineData rightLine; + bool equal; }; class ChunkData { @@ -96,6 +97,7 @@ public: ChunkData() : contextChunk(false) {} QList rows; bool contextChunk; + // start position, end position, TextLineData::Separator lines not taken into account QMap changedLeftPositions; // counting from the beginning of the chunk QMap changedRightPositions; // counting from the beginning of the chunk }; @@ -112,52 +114,16 @@ public: ////////////////////// static QList assemblyRows(const QStringList &lines, - const QMap &lineSpans, - const QMap &equalLines, - const QMap &changedPositions, - QMap *outputChangedPositions) + const QMap &lineSpans) { QList data; - int previousSpanOffset = 0; - int spanOffset = 0; - int pos = 0; - bool usePreviousSpanOffsetForStartPosition = false; - QMap::ConstIterator changedIt = changedPositions.constBegin(); - QMap::ConstIterator changedEnd = changedPositions.constEnd(); const int lineCount = lines.count(); for (int i = 0; i <= lineCount; i++) { - for (int j = 0; j < lineSpans.value(i); j++) { + for (int j = 0; j < lineSpans.value(i); j++) data.append(TextLineData(TextLineData::Separator)); - spanOffset++; - } - if (i < lineCount) { - const int textLength = lines.at(i).count() + 1; - pos += textLength; + if (i < lineCount) data.append(lines.at(i)); - if (equalLines.contains(i)) - data.last().changed = false; - } - while (changedIt != changedEnd) { - if (changedIt.key() >= pos) - break; - - if (changedIt.value() >= pos) { - usePreviousSpanOffsetForStartPosition = true; - previousSpanOffset = spanOffset; - break; - } - - const int startSpanOffset = usePreviousSpanOffsetForStartPosition - ? previousSpanOffset : spanOffset; - usePreviousSpanOffsetForStartPosition = false; - - const int startPos = changedIt.key() + startSpanOffset; - const int endPos = changedIt.value() + spanOffset; - if (outputChangedPositions) - outputChangedPositions->insert(startPos, endPos); - ++changedIt; - } } return data; } @@ -223,15 +189,11 @@ static ChunkData calculateOriginalData(const QList &leftDiffList, QStringList leftLines; QStringList rightLines; - // - QMap leftChangedPositions; - QMap rightChangedPositions; // QMap leftSpans; QMap rightSpans; - // - QMap leftEqualLines; - QMap rightEqualLines; + // + QMap equalLines; int leftLineNumber = 0; int rightLineNumber = 0; @@ -251,13 +213,13 @@ static ChunkData calculateOriginalData(const QList &leftDiffList, if (leftDiff.command == Diff::Delete) { // process delete - handleDifference(leftDiff.text, &leftLines, &leftChangedPositions, &leftLineNumber, &leftCharNumber); + handleDifference(leftDiff.text, &leftLines, &chunkData.changedLeftPositions, &leftLineNumber, &leftCharNumber); lastLineEqual = lastLinesEqual(leftLines, rightLines); i++; } if (rightDiff.command == Diff::Insert) { // process insert - handleDifference(rightDiff.text, &rightLines, &rightChangedPositions, &rightLineNumber, &rightCharNumber); + handleDifference(rightDiff.text, &rightLines, &chunkData.changedRightPositions, &rightLineNumber, &rightCharNumber); lastLineEqual = lastLinesEqual(leftLines, rightLines); j++; } @@ -310,16 +272,12 @@ static ChunkData calculateOriginalData(const QList &leftDiffList, } // check if lines are equal - if (line < newLeftLines.count() - 1 || i == leftDiffList.count()) { - // left line is equal + if ((line < commonLineCount - 1) // before the last common line in equality + || (line == commonLineCount - 1 // or the last common line in equality + && i == leftDiffList.count() // and it's the last iteration + && j == rightDiffList.count())) { if (line > 0 || lastLineEqual) - leftEqualLines.insert(leftLineNumber, true); - } - - if (line < newRightLines.count() - 1 || j == rightDiffList.count()) { - // right line is equal - if (line > 0 || lastLineEqual) - rightEqualLines.insert(rightLineNumber, true); + equalLines.insert(leftLineNumber, rightLineNumber); } if (line > 0) @@ -333,15 +291,9 @@ static ChunkData calculateOriginalData(const QList &leftDiffList, } QList leftData = assemblyRows(leftLines, - leftSpans, - leftEqualLines, - leftChangedPositions, - &chunkData.changedLeftPositions); + leftSpans); QList rightData = assemblyRows(rightLines, - rightSpans, - rightEqualLines, - rightChangedPositions, - &chunkData.changedRightPositions); + rightSpans); // fill ending separators for (int i = leftData.count(); i < rightData.count(); i++) @@ -350,8 +302,22 @@ static ChunkData calculateOriginalData(const QList &leftDiffList, rightData.append(TextLineData(TextLineData::Separator)); const int visualLineCount = leftData.count(); - for (int i = 0; i < visualLineCount; i++) - chunkData.rows.append(RowData(leftData.at(i), rightData.at(i))); + int leftLine = -1; + int rightLine = -1; + for (int i = 0; i < visualLineCount; i++) { + const TextLineData &leftTextLine = leftData.at(i); + const TextLineData &rightTextLine = rightData.at(i); + RowData row(leftTextLine, rightTextLine); + + if (leftTextLine.textLineType == TextLineData::TextLine) + ++leftLine; + if (rightTextLine.textLineType == TextLineData::TextLine) + ++rightLine; + if (equalLines.value(leftLine, -1) == rightLine) + row.equal = true; + + chunkData.rows.append(row); + } return chunkData; } @@ -1194,13 +1160,13 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi int i = 0; while (i < originalData.rows.count()) { const RowData &row = originalData.rows[i]; - if (!row.leftLine.changed && !row.rightLine.changed) { + if (row.equal) { // count how many equal int equalRowStart = i; i++; while (i < originalData.rows.count()) { const RowData originalRow = originalData.rows.at(i); - if (originalRow.leftLine.changed || originalRow.rightLine.changed) + if (!originalRow.equal) break; i++; } @@ -1225,6 +1191,8 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi int rightCharCounter = 0; QMap::ConstIterator leftChangedIt = originalData.changedLeftPositions.constBegin(); QMap::ConstIterator rightChangedIt = originalData.changedRightPositions.constBegin(); + const QMap::ConstIterator leftChangedItEnd = originalData.changedLeftPositions.constEnd(); + const QMap::ConstIterator rightChangedItEnd = originalData.changedRightPositions.constEnd(); while (i < originalData.rows.count()) { if (!hiddenRows.contains(i)) { ChunkData chunkData; @@ -1237,11 +1205,13 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi RowData rowData = originalData.rows.at(i); chunkData.rows.append(rowData); - leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n' - rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n' + if (rowData.leftLine.textLineType == TextLineData::TextLine) + leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n' + if (rowData.rightLine.textLineType == TextLineData::TextLine) + rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n' i++; } - while (leftChangedIt != originalData.changedLeftPositions.constEnd()) { + while (leftChangedIt != leftChangedItEnd) { if (leftChangedIt.key() < leftOffset || leftChangedIt.key() > leftCharCounter) break; @@ -1251,7 +1221,7 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi chunkData.changedLeftPositions.insert(startPos - leftOffset, endPos - leftOffset); leftChangedIt++; } - while (rightChangedIt != originalData.changedRightPositions.constEnd()) { + while (rightChangedIt != rightChangedItEnd) { if (rightChangedIt.key() < rightOffset || rightChangedIt.key() > rightCharCounter) break; @@ -1271,8 +1241,10 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi RowData rowData = originalData.rows.at(i); chunkData.rows.append(rowData); - leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n' - rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n' + if (rowData.leftLine.textLineType == TextLineData::TextLine) + leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n' + if (rowData.rightLine.textLineType == TextLineData::TextLine) + rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n' i++; } fileData.chunks.append(chunkData); @@ -1441,6 +1413,86 @@ QList SideBySideDiffEditorWidget::colorPositions( return lineSelections; } +void fixPositions(QMap::ConstIterator *it, + const QMap::ConstIterator &itEnd, + int fileOffset, + int charCounter, + int spanCounter, + int *lastSpanCounter, + QMap *changedPositions) +{ + while (*it != itEnd) { + if (it->key() >= charCounter) + break; + + if (it->value() >= charCounter) { + if (*lastSpanCounter != -1) + break; + + *lastSpanCounter = spanCounter; + break; + } + + const int startSpanOffset = *lastSpanCounter != -1 + ? *lastSpanCounter : spanCounter; + *lastSpanCounter = -1; + + const int startPos = it->key() + startSpanOffset + fileOffset; + const int endPos = it->value() + spanCounter + fileOffset; + changedPositions->insert(startPos, endPos); + ++(*it); + } +} + +static void fixPositions(const ChunkData &chunkData, + const int leftFileOffset, + const int rightFileOffset, + QMap *leftCharPos, + QMap *rightCharPos) +{ + QMap::ConstIterator leftIt = chunkData.changedLeftPositions.constBegin(); + const QMap::ConstIterator leftItEnd = chunkData.changedLeftPositions.constEnd(); + QMap::ConstIterator rightIt = chunkData.changedRightPositions.constBegin(); + const QMap::ConstIterator rightItEnd = chunkData.changedRightPositions.constEnd(); + if (leftIt == leftItEnd && rightIt == rightItEnd) + return; + + int leftCharCounter = 0; + int rightCharCounter = 0; + int leftSpanCounter = 0; + int rightSpanCounter = 0; + int leftLastSpanCounter = -1; + int rightLastSpanCounter = -1; + for (int i = 0; i < chunkData.rows.count(); i++) { + const RowData &row = chunkData.rows.at(i); + + if (row.leftLine.textLineType == TextLineData::TextLine) + leftCharCounter += row.leftLine.text.count() + 1; // +1 for '\n' + else + ++leftSpanCounter; + + if (row.rightLine.textLineType == TextLineData::TextLine) + rightCharCounter += row.rightLine.text.count() + 1; // +1 for '\n' + else + ++rightSpanCounter; + + fixPositions(&leftIt, + leftItEnd, + leftFileOffset, + leftCharCounter, + leftSpanCounter, + &leftLastSpanCounter, + leftCharPos); + fixPositions(&rightIt, + rightItEnd, + rightFileOffset, + rightCharCounter, + rightSpanCounter, + &rightLastSpanCounter, + rightCharPos); + } +} + void SideBySideDiffEditorWidget::colorDiff(const QList &fileDataList) { QPalette pal = m_leftEditor->extraArea()->palette(); @@ -1489,19 +1541,7 @@ void SideBySideDiffEditorWidget::colorDiff(const QList &fileDataList) leftLastSkippedBlockStartPos = leftPos; rightLastSkippedBlockStartPos = rightPos; - QMapIterator itLeft(chunkData.changedLeftPositions); - while (itLeft.hasNext()) { - itLeft.next(); - - leftCharPos[itLeft.key() + leftFileOffset] = itLeft.value() + leftFileOffset; - } - - QMapIterator itRight(chunkData.changedRightPositions); - while (itRight.hasNext()) { - itRight.next(); - - rightCharPos[itRight.key() + rightFileOffset] = itRight.value() + rightFileOffset; - } + fixPositions(chunkData, leftFileOffset, rightFileOffset, &leftCharPos, &rightCharPos); for (int k = 0; k < chunkData.rows.count(); k++) { RowData rowData = chunkData.rows.at(k); @@ -1509,7 +1549,7 @@ void SideBySideDiffEditorWidget::colorDiff(const QList &fileDataList) leftPos += rowData.leftLine.text.count() + 1; // +1 for '\n' rightPos += rowData.rightLine.text.count() + 1; // +1 for '\n' - if (rowData.leftLine.changed) { + if (!rowData.equal) { if (rowData.leftLine.textLineType == TextLineData::TextLine) { leftLinePos[leftLastDiffBlockStartPos] = leftPos; leftLastSkippedBlockStartPos = leftPos; @@ -1517,12 +1557,6 @@ void SideBySideDiffEditorWidget::colorDiff(const QList &fileDataList) leftSkippedPos[leftLastSkippedBlockStartPos] = leftPos; leftLastDiffBlockStartPos = leftPos; } - } else { - leftLastDiffBlockStartPos = leftPos; - leftLastSkippedBlockStartPos = leftPos; - } - - if (rowData.rightLine.changed) { if (rowData.rightLine.textLineType == TextLineData::TextLine) { rightLinePos[rightLastDiffBlockStartPos] = rightPos; rightLastSkippedBlockStartPos = rightPos; @@ -1531,6 +1565,8 @@ void SideBySideDiffEditorWidget::colorDiff(const QList &fileDataList) rightLastDiffBlockStartPos = rightPos; } } else { + leftLastDiffBlockStartPos = leftPos; + leftLastSkippedBlockStartPos = leftPos; rightLastDiffBlockStartPos = rightPos; rightLastSkippedBlockStartPos = rightPos; } @@ -1616,8 +1652,7 @@ void SideBySideDiffEditorWidget::slotLeftJumpToOriginalFileRequested(int diffFil if (rowData.rightLine.textLineType == TextLineData::TextLine) rightLineNumber++; if (leftLineNumber == lineNumber) { - int colNr = !rowData.leftLine.changed && !rowData.rightLine.changed - ? columnNumber : 0; + int colNr = rowData.equal ? columnNumber : 0; jumpToOriginalFile(leftFileName, rightLineNumber, colNr); return; } @@ -1840,27 +1875,36 @@ void SideBySideDiffEditorWidget::synchronizeFoldings(SideDiffEditorWidget *sourc #ifdef WITH_TESTS #include -void DiffEditor::SideBySideDiffEditorWidget::testAssemblyRows() +void DiffEditor::SideBySideDiffEditorWidget::testFixPositions() { - QStringList lines; - lines << QLatin1String("abcd efgh"); // line 0 - lines << QLatin1String("ijkl mnop"); // line 1 + ChunkData chunkData; + chunkData.rows.append(RowData(TextLineData(QLatin1String("abcd efgh")), TextLineData(QLatin1String("abcd ")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(QLatin1String("ijkl mnop")), TextLineData(QLatin1String(" mnop")))); - QMap lineSpans; - lineSpans[1] = 6; // before line 1 insert 6 span lines + chunkData.changedLeftPositions.insert(5, 14); // changed text from position 5 to position 14, occupy 9 characters: "efgh\nijkl" - QMap changedPositions; - changedPositions[5] = 14; // changed text from position 5 to position 14, occupy 9 characters: "efgh\nijkl" + QMap expectedLeftChangedPositions; + expectedLeftChangedPositions[5] = 20; // "efgh\n[\n\n\n\n\n\n]ijkl" - [\n] means inserted span - QMap equalLines; // no equal lines + QMap outputLeftChangedPositions; + QMap outputRightChangedPositions; - QMap expectedChangedPositions; - expectedChangedPositions[5] = 20; // "efgh\n[\n\n\n\n\n\n]ijkl" - [\n] means inserted span + fixPositions(chunkData, 0, 0, &outputLeftChangedPositions, &outputRightChangedPositions); + QVERIFY(outputLeftChangedPositions == expectedLeftChangedPositions); - QMap outputChangedPositions; + QMap expectedLeftMovedPositions; + expectedLeftMovedPositions[15] = 30; // moved by 10 + outputLeftChangedPositions.clear(); + outputRightChangedPositions.clear(); - assemblyRows(lines, lineSpans, equalLines, changedPositions, &outputChangedPositions); - QVERIFY(outputChangedPositions == expectedChangedPositions); + fixPositions(chunkData, 10, 0, &outputLeftChangedPositions, &outputRightChangedPositions); + QVERIFY(outputLeftChangedPositions == expectedLeftMovedPositions); } #endif // WITH_TESTS diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.h b/src/plugins/diffeditor/sidebysidediffeditorwidget.h index 5686fbf0a7d..cf7cbbd8849 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.h +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.h @@ -63,7 +63,7 @@ public: DiffEditorGuiController *diffEditorGuiController() const; #ifdef WITH_TESTS - static void testAssemblyRows(); + static void testFixPositions(); #endif // WITH_TESTS private slots: diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 7f1fc081adf..046f777b6e8 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -973,7 +973,7 @@ public: // cursor keys. This breaks some of the logic later on // relying on text() being empty for "special" keys. // FIXME: Check the real conditions. - if (x.unicode() <= ' ') + if (x.unicode() < ' ') m_text.clear(); else if (x.isLetter()) m_key = x.toUpper().unicode(); @@ -1061,7 +1061,7 @@ public: return m_key < a.m_key; // Text for some mapped key cannot be determined (e.g. ) so if text is not set for // one of compared keys ignore it. - if (!m_text.isEmpty() && !a.m_text.isEmpty()) + if (!m_text.isEmpty() && !a.m_text.isEmpty() && m_text != _(" ")) return m_text < a.m_text; return m_modifiers < a.m_modifiers; } diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index 68d77143513..a8d4bdadab3 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -218,15 +218,6 @@ void GenericProject::parseProject(RefreshOptions options) // TODO: Possibly load some configuration from the project file //QSettings projectInfo(m_fileName, QSettings::IniFormat); - - m_defines.clear(); - - QFile configFile(configFileName()); - if (configFile.open(QFile::ReadOnly)) { - // convert from local/file encoding to UTF-8 - QTextStream configStream(&configFile); - m_defines = configStream.readAll().toUtf8(); - } } if (options & Files) @@ -265,7 +256,7 @@ void GenericProject::refresh(RefreshOptions options) } part->cxxVersion = CppTools::ProjectPart::CXX11; // assume C++11 - part->projectDefines += m_defines; + part->projectConfigFile = configFileName(); // ### add _defines. @@ -348,11 +339,6 @@ QStringList GenericProject::files() const return m_files; } -QByteArray GenericProject::defines() const -{ - return m_defines; -} - QString GenericProject::displayName() const { return m_projectName; diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h index 18ca8798c67..30a657ff253 100644 --- a/src/plugins/genericprojectmanager/genericproject.h +++ b/src/plugins/genericprojectmanager/genericproject.h @@ -81,7 +81,6 @@ public: void refresh(RefreshOptions options); - QByteArray defines() const; QStringList projectIncludePaths() const; QStringList files() const; @@ -108,7 +107,6 @@ private: QStringList m_files; QHash m_rawListEntries; QStringList m_projectIncludePaths; - QByteArray m_defines; GenericProjectNode *m_rootNode; QFuture m_codeModelFuture; diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.cpp b/src/plugins/genericprojectmanager/genericprojectwizard.cpp index a7d700efc8b..f8059adb2c2 100644 --- a/src/plugins/genericprojectmanager/genericprojectwizard.cpp +++ b/src/plugins/genericprojectmanager/genericprojectwizard.cpp @@ -48,6 +48,11 @@ namespace GenericProjectManager { namespace Internal { +static const char *const ConfigFileTemplate = + "// Add predefined macros for your project here. For example:\n" + "// #define THE_ANSWER 42\n" + ; + ////////////////////////////////////////////////////////////////////////////// // // GenericProjectWizardDialog @@ -189,7 +194,7 @@ Core::GeneratedFiles GenericProjectWizard::generateFiles(const QWizard *w, generatedIncludesFile.setContents(includePaths.join(QLatin1String("\n"))); Core::GeneratedFile generatedConfigFile(configFileName); - generatedConfigFile.setContents(QLatin1String("// ADD PREDEFINED MACROS HERE!\n")); + generatedConfigFile.setContents(QLatin1String(ConfigFileTemplate)); Core::GeneratedFiles files; files.append(generatedFilesFile); diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp index a18c9a0d397..8798f4657d5 100644 --- a/src/plugins/git/branchdialog.cpp +++ b/src/plugins/git/branchdialog.cpp @@ -128,6 +128,7 @@ void BranchDialog::enableButtons() m_ui->diffButton->setEnabled(hasActions); m_ui->checkoutButton->setEnabled(hasActions && !currentSelected); m_ui->rebaseButton->setEnabled(hasActions && !currentSelected); + m_ui->resetButton->setEnabled(hasActions && currentLocal && !currentSelected); m_ui->mergeButton->setEnabled(hasActions && !currentSelected); m_ui->cherryPickButton->setEnabled(hasActions && !currentSelected); m_ui->trackButton->setEnabled(hasActions && currentLocal && !currentSelected && !isTag); @@ -323,8 +324,8 @@ void BranchDialog::log() void BranchDialog::reset() { - QString currentName = m_model->fullName(m_model->currentBranch(), true); - QString branchName = m_model->fullName(selectedIndex(), true); + QString currentName = m_model->fullName(m_model->currentBranch()); + QString branchName = m_model->fullName(selectedIndex()); if (currentName.isEmpty() || branchName.isEmpty()) return; diff --git a/src/plugins/git/branchdialog.ui b/src/plugins/git/branchdialog.ui index 8f7be998ad6..320c78bbd69 100644 --- a/src/plugins/git/branchdialog.ui +++ b/src/plugins/git/branchdialog.ui @@ -130,13 +130,6 @@ - - - - Reset - - - @@ -158,6 +151,13 @@ + + + + Reset + + + diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp index 75e5c7cbc93..93cce7de063 100644 --- a/src/plugins/git/branchmodel.cpp +++ b/src/plugins/git/branchmodel.cpp @@ -692,14 +692,18 @@ QModelIndex BranchModel::nodeToIndex(BranchNode *node) const void BranchModel::removeNode(const QModelIndex &idx) { - QModelIndex tmp = idx; // tmp is a leaf, so count must be 0. - while (indexToNode(tmp)->count() == 0) { - QModelIndex tmpParent = parent(tmp); - beginRemoveRows(tmpParent, tmp.row(), tmp.row()); - indexToNode(tmpParent)->children.removeAt(tmp.row()); - delete indexToNode(tmp); + QModelIndex nodeIndex = idx; // idx is a leaf, so count must be 0. + BranchNode *node = indexToNode(nodeIndex); + while (node->count() == 0 && node->parent != m_rootNode) { + BranchNode *parentNode = node->parent; + const QModelIndex parentIndex = nodeToIndex(parentNode); + const int nodeRow = nodeIndex.row(); + beginRemoveRows(parentIndex, nodeRow, nodeRow); + parentNode->children.removeAt(nodeRow); + delete node; endRemoveRows(); - tmp = tmpParent; + node = parentNode; + nodeIndex = parentIndex; } } diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 22c094c1711..507a11dbb4f 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -2001,7 +2001,8 @@ bool GitClient::synchronousHeadRefs(const QString &workingDirectory, QStringList << QLatin1String("--abbrev=10") << QLatin1String("--dereference"); QByteArray outputText; QByteArray errorText; - const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText); + const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText, + VcsBasePlugin::SuppressCommandLogging); if (!rc) { msgCannotRun(args, workingDirectory, errorText, errorMessage); return false; @@ -2051,9 +2052,19 @@ QString GitClient::synchronousTopic(const QString &workingDirectory) (derefInd == -1) ? -1 : derefInd - remoteStart.size()); } } + if (!remoteBranch.isEmpty()) + return remoteBranch; - // No tag - return remoteBranch.isEmpty() ? tr("Detached HEAD") : remoteBranch; + // No tag or remote branch - try git describe + QByteArray output; + QStringList arguments; + arguments << QLatin1String("describe"); + if (fullySynchronousGit(workingDirectory, arguments, &output, 0, VcsBasePlugin::NoOutput)) { + const QString describeOutput = commandOutputFromLocal8Bit(output.trimmed()); + if (!describeOutput.isEmpty()) + return describeOutput; + } + return tr("Detached HEAD"); } bool GitClient::synchronousRevParseCmd(const QString &workingDirectory, const QString &ref, diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp index e84e052ddcb..1427d84ca85 100644 --- a/src/plugins/projectexplorer/projectmodels.cpp +++ b/src/plugins/projectexplorer/projectmodels.cpp @@ -823,6 +823,9 @@ void FlatModel::removeFromCache(QList list) void FlatModel::changedSortKey(FolderNode *folderNode, Node *node) { + if (!m_childNodes.contains(folderNode)) + return; // The directory was not yet mapped, so there is no need to sort it. + QList nodes = m_childNodes.value(folderNode); int oldIndex = nodes.indexOf(node); diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 04066d750e3..622644cd248 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -313,24 +313,6 @@ void FolderNode::setIcon(const QIcon &icon) m_icon = icon; } -FileNode *FolderNode::findFile(const QString &path) -{ - foreach (FileNode *n, fileNodes()) { - if (n->path() == path) - return n; - } - return 0; -} - -FolderNode *FolderNode::findSubFolder(const QString &path) -{ - foreach (FolderNode *n, subFolderNodes()) { - if (n->path() == path) - return n; - } - return 0; -} - bool FolderNode::addFiles(const QStringList &filePaths, QStringList *notAdded) { if (projectNode()) diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index 6592bcd1667..f15de786bf5 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -174,9 +174,6 @@ public: void setDisplayName(const QString &name); void setIcon(const QIcon &icon); - FileNode *findFile(const QString &path); - FolderNode *findSubFolder(const QString &path); - virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0); virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0); virtual bool deleteFiles(const QStringList &filePaths); diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index 5ad45828fde..8ea6551dcd3 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -424,7 +424,14 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root, // Handle files: if (c->isFile()) { - ProjectExplorer::FileNode *fn = root->findFile(path); + ProjectExplorer::FileNode *fn = 0; + foreach (ProjectExplorer::FileNode *f, root->fileNodes()) { + // There can be one match only here! + if (f->path() != path) + continue; + fn = f; + break; + } if (fn) { filesToRemove.removeOne(fn); if (updateExisting) @@ -435,7 +442,14 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root, } continue; } else { - FolderNode *fn = root->findSubFolder(c->path()); + ProjectExplorer::FolderNode *fn = 0; + foreach (ProjectExplorer::FolderNode *f, root->subFolderNodes()) { + // There can be one match only here! + if (f->path() != path) + continue; + fn = f; + break; + } if (!fn) { fn = new FolderNode(c->path()); root->addFolderNodes(QList() << fn); diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 8a4e1112787..03c15752262 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -63,6 +63,8 @@ #include +#include +#include #include using namespace Core; @@ -462,9 +464,8 @@ void QbsProject::parse(const QVariantMap &config, const Environment &env, const params.setIgnoreDifferentProjectFilePath(false); params.setEnvironment(env.toProcessEnvironment()); const qbs::Preferences prefs(QbsManager::settings(), profileName); - const QString qbsDir = qbsDirectory(); - params.setSearchPaths(prefs.searchPaths(qbsDir)); - params.setPluginPaths(prefs.pluginPaths(qbsDir)); + params.setSearchPaths(prefs.searchPaths(resourcesBaseDirectory())); + params.setPluginPaths(prefs.pluginPaths(pluginsBaseDirectory())); // Do the parsing: prepareForParsing(); @@ -705,7 +706,7 @@ void QbsProject::updateDeploymentInfo(const qbs::Project &project) activeTarget()->setDeploymentData(deploymentData); } -QString QbsProject::qbsDirectory() const +QString QbsProject::resourcesBaseDirectory() const { const QString qbsInstallDir = QLatin1String(QBS_INSTALL_DIR); if (!qbsInstallDir.isEmpty()) @@ -713,5 +714,14 @@ QString QbsProject::qbsDirectory() const return ICore::resourcePath() + QLatin1String("/qbs"); } +QString QbsProject::pluginsBaseDirectory() const +{ + const QString qbsInstallDir = QLatin1String(QBS_INSTALL_DIR); + if (!qbsInstallDir.isEmpty()) + return qbsInstallDir + QLatin1String("/lib/"); + return QDir::cleanPath(QCoreApplication::applicationDirPath() + + QLatin1String("/../lib/qtcreator")); +} + } // namespace Internal } // namespace QbsProjectManager diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h index 1ca9003717e..51d4031553a 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.h +++ b/src/plugins/qbsprojectmanager/qbsproject.h @@ -131,7 +131,8 @@ private: void updateQmlJsCodeModel(const qbs::ProjectData &prj); void updateApplicationTargets(const qbs::ProjectData &projectData); void updateDeploymentInfo(const qbs::Project &project); - QString qbsDirectory() const; + QString resourcesBaseDirectory() const; + QString pluginsBaseDirectory() const; QbsManager *const m_manager; const QString m_projectName; diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index 0f5c805604d..8659e5e8ba8 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -66,6 +66,8 @@ Rectangle { property date recordingStartDate property real elapsedTime + color: "#dcdcdc" + // ***** connections with external objects Connections { target: zoomControl @@ -230,158 +232,20 @@ Rectangle { } Flickable { - id: vertflick + id: labelsflick flickableDirection: Flickable.VerticalFlick - anchors.fill: parent - clip: true - contentHeight: labels.height - boundsBehavior: Flickable.StopAtBounds - - // ScrollView will try to deinteractivate it. We don't want that - // as the horizontal flickable is interactive, too. We do occasionally - // switch to non-interactive ourselves, though. - property bool stayInteractive: true - onInteractiveChanged: interactive = stayInteractive - onStayInteractiveChanged: interactive = stayInteractive - - // ***** child items - TimeMarks { - id: backgroundMarks - y: vertflick.contentY - height: vertflick.height - width: root.width - labels.width - anchors.left: labels.right - } - - Flickable { - function setContentWidth() { - var duration = Math.abs(zoomControl.endTime() - zoomControl.startTime()); - if (duration > 0) - contentWidth = qmlProfilerModelProxy.traceDuration() * width / duration; - } - - id: flick - anchors.top: parent.top - anchors.topMargin: labels.y - anchors.right: parent.right - anchors.left: labels.right - contentWidth: 0 - height: labels.height + labelsTail.height - flickableDirection: Flickable.HorizontalFlick - boundsBehavior: Flickable.StopAtBounds - - onContentXChanged: view.updateZoomControl() - onWidthChanged: setContentWidth() - - clip:true - - SelectionRange { - id: selectionRange - visible: root.selectionRangeMode && creationState !== 0 - height: parent.height - z: 2 - } - - TimelineRenderer { - id: view - - profilerModelProxy: qmlProfilerModelProxy - - x: flick.contentX - y: vertflick.contentY - width: flick.width - height: vertflick.height - - onEndTimeChanged: requestPaint() - onYChanged: requestPaint() - onHeightChanged: requestPaint() - - function updateZoomControl() { - var newStartTime = Math.round(flick.contentX * (endTime - startTime) / flick.width) + - qmlProfilerModelProxy.traceStartTime(); - if (Math.abs(newStartTime - startTime) > 1) { - var newEndTime = Math.round((flick.contentX + flick.width) * - (endTime - startTime) / - flick.width) + - qmlProfilerModelProxy.traceStartTime(); - zoomControl.setRange(newStartTime, newEndTime); - } - } - - function updateFlickRange(start, end) { - if (start !== startTime || end !== endTime) { - startTime = start; - endTime = end; - var newStartX = (startTime - qmlProfilerModelProxy.traceStartTime()) * - flick.width / (endTime-startTime); - if (isFinite(newStartX) && Math.abs(newStartX - flick.contentX) >= 1) - flick.contentX = newStartX; - } - } - - onSelectedItemChanged: { - if (selectedItem !== -1) { - // display details - rangeDetails.showInfo(qmlProfilerModelProxy.getEventDetails(selectedModel, selectedItem)); - rangeDetails.setLocation(qmlProfilerModelProxy.getEventLocation(selectedModel, selectedItem)); - - // center view (horizontally) - var windowLength = view.endTime - view.startTime; - var eventStartTime = qmlProfilerModelProxy.getStartTime(selectedModel, selectedItem); - var eventEndTime = eventStartTime + - qmlProfilerModelProxy.getDuration(selectedModel, selectedItem); - - if (eventEndTime < view.startTime || eventStartTime > view.endTime) { - var center = (eventStartTime + eventEndTime)/2; - var from = Math.min(qmlProfilerModelProxy.traceEndTime()-windowLength, - Math.max(0, Math.floor(center - windowLength/2))); - - zoomControl.setRange(from, from + windowLength); - - } - } else { - root.hideRangeDetails(); - } - } - - onItemPressed: { - var location = qmlProfilerModelProxy.getEventLocation(modelIndex, pressedItem); - if (location.hasOwnProperty("file")) // not empty - root.gotoSourceLocation(location.file, location.line, location.column); - } - - // hack to pass mouse events to the other mousearea if enabled - startDragArea: selectionRange.ready ? selectionRange.getLeft() : -flick.contentX - endDragArea: selectionRange.ready ? selectionRange.getRight() : -flick.contentX-1 - } - MouseArea { - id: selectionRangeControl - enabled: false - width: flick.width - height: flick.height - x: flick.contentX - hoverEnabled: enabled - z: 2 - - onReleased: { - selectionRange.releasedOnCreation(); - } - onPressed: { - selectionRange.pressedOnCreation(); - } - onCanceled: { - selectionRange.releasedOnCreation(); - } - onPositionChanged: { - selectionRange.movedOnCreation(); - } - } - } + interactive: false + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + width: labels.width + contentY: flick.contentY Rectangle { id: labels + anchors.left: parent.left width: 150 - color: "#dcdcdc" + color: root.color height: col.height property int rowCount: qmlProfilerModelProxy.categoryCount(); @@ -394,28 +258,163 @@ Rectangle { } } } + } - Rectangle { - id: labelsTail - anchors.top: labels.bottom - height: Math.max(0, vertflick.height - labels.height) - width: labels.width - color: labels.color + // border between labels and timeline + Rectangle { + id: labelsborder + anchors.left: labelsflick.right + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 1 + color: "#858585" + } + + Flickable { + id: flick + contentHeight: labels.height + contentWidth: 0 + flickableDirection: Flickable.HorizontalAndVerticalFlick + boundsBehavior: Flickable.StopAtBounds + clip:true + + // ScrollView will try to deinteractivate it. We don't want that + // as the horizontal flickable is interactive, too. We do occasionally + // switch to non-interactive ourselves, though. + property bool stayInteractive: true + onInteractiveChanged: interactive = stayInteractive + onStayInteractiveChanged: interactive = stayInteractive + + function setContentWidth() { + var duration = Math.abs(zoomControl.endTime() - zoomControl.startTime()); + if (duration > 0) + contentWidth = qmlProfilerModelProxy.traceDuration() * width / duration; } - // border between labels and timeline - Rectangle { - anchors.left: labels.right - anchors.top: labels.top - anchors.bottom: labelsTail.bottom - width: 1 - color: "#858585" + onContentXChanged: view.updateZoomControl() + onWidthChanged: setContentWidth() + + // ***** child items + TimeMarks { + id: backgroundMarks + y: flick.contentY + x: flick.contentX + height: flick.height + width: scroller.width + } + + SelectionRange { + id: selectionRange + visible: root.selectionRangeMode && creationState !== 0 + z: 2 + } + + TimelineRenderer { + id: view + + profilerModelProxy: qmlProfilerModelProxy + + x: flick.contentX + y: flick.contentY + + // paint "under" the vertical scrollbar, so that it always matches with the timemarks + width: scroller.width + height: flick.height + + onEndTimeChanged: requestPaint() + onYChanged: requestPaint() + onHeightChanged: requestPaint() + + function updateZoomControl() { + var newStartTime = Math.round(flick.contentX * (endTime - startTime) / flick.width) + + qmlProfilerModelProxy.traceStartTime(); + if (Math.abs(newStartTime - startTime) > 1) { + var newEndTime = Math.round((flick.contentX + flick.width) * + (endTime - startTime) / + flick.width) + + qmlProfilerModelProxy.traceStartTime(); + zoomControl.setRange(newStartTime, newEndTime); + } + } + + function updateFlickRange(start, end) { + if (start !== startTime || end !== endTime) { + startTime = start; + endTime = end; + var newStartX = (startTime - qmlProfilerModelProxy.traceStartTime()) * + flick.width / (endTime-startTime); + if (isFinite(newStartX) && Math.abs(newStartX - flick.contentX) >= 1) + flick.contentX = newStartX; + } + } + + onSelectedItemChanged: { + if (selectedItem !== -1) { + // display details + rangeDetails.showInfo(qmlProfilerModelProxy.getEventDetails(selectedModel, selectedItem)); + rangeDetails.setLocation(qmlProfilerModelProxy.getEventLocation(selectedModel, selectedItem)); + + // center view (horizontally) + var windowLength = view.endTime - view.startTime; + var eventStartTime = qmlProfilerModelProxy.getStartTime(selectedModel, selectedItem); + var eventEndTime = eventStartTime + + qmlProfilerModelProxy.getDuration(selectedModel, selectedItem); + + if (eventEndTime < view.startTime || eventStartTime > view.endTime) { + var center = (eventStartTime + eventEndTime)/2; + var from = Math.min(qmlProfilerModelProxy.traceEndTime()-windowLength, + Math.max(0, Math.floor(center - windowLength/2))); + + zoomControl.setRange(from, from + windowLength); + + } + } else { + root.hideRangeDetails(); + } + } + + onItemPressed: { + var location = qmlProfilerModelProxy.getEventLocation(modelIndex, pressedItem); + if (location.hasOwnProperty("file")) // not empty + root.gotoSourceLocation(location.file, location.line, location.column); + } + + // hack to pass mouse events to the other mousearea if enabled + startDragArea: selectionRange.ready ? selectionRange.getLeft() : -flick.contentX + endDragArea: selectionRange.ready ? selectionRange.getRight() : -flick.contentX-1 + } + MouseArea { + id: selectionRangeControl + enabled: false + width: flick.width + height: flick.height + x: flick.contentX + y: flick.contentY + hoverEnabled: enabled + z: 2 + + onReleased: { + selectionRange.releasedOnCreation(); + } + onPressed: { + selectionRange.pressedOnCreation(); + } + onCanceled: { + selectionRange.releasedOnCreation(); + } + onPositionChanged: { + selectionRange.movedOnCreation(); + } } } ScrollView { - contentItem: vertflick - anchors.fill: parent + id: scroller + contentItem: flick + anchors.left: labelsborder.right + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right } SelectionRangeDetails { diff --git a/src/plugins/qmlprofiler/qml/SelectionRange.qml b/src/plugins/qmlprofiler/qml/SelectionRange.qml index f565571294e..47a1bd94b4e 100644 --- a/src/plugins/qmlprofiler/qml/SelectionRange.qml +++ b/src/plugins/qmlprofiler/qml/SelectionRange.qml @@ -107,8 +107,7 @@ RangeMover { // creation control function releasedOnCreation() { if (selectionRange.creationState === 2) { - flick.interactive = true; - vertflick.stayInteractive = true; + flick.stayInteractive = true; selectionRange.creationState = 3; selectionRangeControl.enabled = false; } @@ -116,8 +115,7 @@ RangeMover { function pressedOnCreation() { if (selectionRange.creationState === 1) { - flick.interactive = false; - vertflick.stayInteractive = false; + flick.stayInteractive = false; selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX); selectionRange.creationState = 2; } diff --git a/src/plugins/qmlprofiler/qml/TimeDisplay.qml b/src/plugins/qmlprofiler/qml/TimeDisplay.qml index 12cecf435f1..4327d427312 100644 --- a/src/plugins/qmlprofiler/qml/TimeDisplay.qml +++ b/src/plugins/qmlprofiler/qml/TimeDisplay.qml @@ -54,17 +54,18 @@ Canvas { context.fillStyle = "white"; context.fillRect(0, 0, width, height); + var realWidth = width - 1; // account for left border var totalTime = endTime - startTime; - var spacing = width / totalTime; + var spacing = realWidth / totalTime; var initialBlockLength = 120; - var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) ); + var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / realWidth * initialBlockLength ) / Math.LN2 ) ); var pixelsPerBlock = timePerBlock * spacing; var pixelsPerSection = pixelsPerBlock / 5; - var blockCount = width / pixelsPerBlock; + var blockCount = realWidth / pixelsPerBlock; var realStartTime = Math.floor(startTime/timePerBlock) * timePerBlock; - var realStartPos = (startTime-realStartTime) * spacing; + var realStartPos = (startTime - realStartTime) * spacing - 1; timePerPixel = timePerBlock/pixelsPerBlock; diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml index f9ac8e3590e..94e8fd058b0 100644 --- a/src/plugins/qmlprofiler/qml/TimeMarks.qml +++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml @@ -128,7 +128,7 @@ Canvas { // bottom if (height > labels.height - y) { context.fillStyle = "#f5f5f5"; - context.fillRect(0, labels.height - y, width, Math.min(height - labels.height + y, labelsTail.height)); + context.fillRect(0, labels.height - y, width, height - labels.height + y); } } } diff --git a/src/plugins/vcsbase/vcsbaseconstants.h b/src/plugins/vcsbase/vcsbaseconstants.h index 01356cda9ae..1dd5c8a9936 100644 --- a/src/plugins/vcsbase/vcsbaseconstants.h +++ b/src/plugins/vcsbase/vcsbaseconstants.h @@ -49,6 +49,9 @@ const char VCS_ID_SUBVERSION[] = "J.Subversion"; const char VCS_ID_PERFORCE[] = "P.Perforce"; const char VCS_ID_CVS[] = "Z.CVS"; +const char VAR_VCS_NAME[] = "CurrentProject:VcsName"; +const char VAR_VCS_TOPIC[] = "CurrentProject:VcsTopic"; + } // namespace Constants } // namespace VcsBase diff --git a/src/plugins/vcsbase/vcsbaseoutputwindow.cpp b/src/plugins/vcsbase/vcsbaseoutputwindow.cpp index 6a8cc4626a6..94b5d645f0a 100644 --- a/src/plugins/vcsbase/vcsbaseoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsbaseoutputwindow.cpp @@ -264,13 +264,15 @@ void OutputWindowPlainTextEdit::setFormat(enum VcsBaseOutputWindow::MessageStyle } // namespace Internal // ------------------- VcsBaseOutputWindowPrivate -struct VcsBaseOutputWindowPrivate +class VcsBaseOutputWindowPrivate { +public: static VcsBaseOutputWindow *instance; Internal::OutputWindowPlainTextEdit *plainTextEdit(); QPointer m_plainTextEdit; QString repository; + QRegExp passwordRegExp; }; // Create log editor on demand. Some errors might be logged @@ -288,9 +290,25 @@ VcsBaseOutputWindow *VcsBaseOutputWindowPrivate::instance = 0; VcsBaseOutputWindow::VcsBaseOutputWindow() : d(new VcsBaseOutputWindowPrivate) { + d->passwordRegExp = QRegExp(QLatin1String("://([^@:]+):([^@]+)@")); + Q_ASSERT(d->passwordRegExp.isValid()); VcsBaseOutputWindowPrivate::instance = this; } +QString VcsBaseOutputWindow::filterPasswordFromUrls(const QString &input) +{ + int pos = 0; + QString result = input; + while ((pos = d->passwordRegExp.indexIn(result, pos)) >= 0) { + QString tmp = result.left(pos + 3) + d->passwordRegExp.cap(1) + QLatin1String(":***@"); + int newStart = tmp.count(); + tmp += result.mid(pos + d->passwordRegExp.matchedLength()); + result = tmp; + pos = newStart; + } + return result; +} + VcsBaseOutputWindow::~VcsBaseOutputWindow() { VcsBaseOutputWindowPrivate::instance = 0; @@ -442,7 +460,7 @@ QString VcsBaseOutputWindow::msgExecutionLogEntry(const QString &workingDir, void VcsBaseOutputWindow::appendCommand(const QString &text) { - append(text, Command, true); + append(filterPasswordFromUrls(text), Command, true); } void VcsBaseOutputWindow::appendCommand(const QString &workingDirectory, diff --git a/src/plugins/vcsbase/vcsbaseoutputwindow.h b/src/plugins/vcsbase/vcsbaseoutputwindow.h index 8e2636a2ae9..84fa6999bb7 100644 --- a/src/plugins/vcsbase/vcsbaseoutputwindow.h +++ b/src/plugins/vcsbase/vcsbaseoutputwindow.h @@ -36,7 +36,7 @@ namespace VcsBase { -struct VcsBaseOutputWindowPrivate; +class VcsBaseOutputWindowPrivate; class VCSBASE_EXPORT VcsBaseOutputWindow : public Core::IOutputPane { @@ -121,6 +121,8 @@ public slots: private: VcsBaseOutputWindow(); + QString filterPasswordFromUrls(const QString &input); + VcsBaseOutputWindowPrivate *d; }; diff --git a/src/plugins/vcsbase/vcsplugin.cpp b/src/plugins/vcsbase/vcsplugin.cpp index bcd28297b3a..350bd5c63d2 100644 --- a/src/plugins/vcsbase/vcsplugin.cpp +++ b/src/plugins/vcsbase/vcsplugin.cpp @@ -28,12 +28,20 @@ ****************************************************************************/ #include "vcsplugin.h" + +#include "vcsbaseconstants.h" + #include "commonsettingspage.h" #include "nicknamedialog.h" #include "vcsbaseoutputwindow.h" #include "corelistener.h" +#include #include +#include +#include +#include +#include #include #include @@ -74,6 +82,15 @@ bool VcsPlugin::initialize(const QStringList &arguments, QString *errorMessage) connect(m_settingsPage, SIGNAL(settingsChanged(VcsBase::Internal::CommonVcsSettings)), this, SLOT(slotSettingsChanged())); slotSettingsChanged(); + + connect(Core::VariableManager::instance(), SIGNAL(variableUpdateRequested(QByteArray)), + this, SLOT(updateVariable(QByteArray))); + + Core::VariableManager::registerVariable(Constants::VAR_VCS_NAME, + tr("Name of the version control system in use by the current project.")); + Core::VariableManager::registerVariable(Constants::VAR_VCS_TOPIC, + tr("The current version control topic (branch or tag) identification of the current project.")); + return true; } @@ -122,6 +139,32 @@ void VcsPlugin::slotSettingsChanged() populateNickNameModel(); } +void VcsPlugin::updateVariable(const QByteArray &variable) +{ + static ProjectExplorer::Project *cachedProject = 0; + static Core::IVersionControl *cachedVc = 0; + static QString cachedTopLevel; + + ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::currentProject(); + if (cachedProject != project) { + cachedVc = Core::VcsManager::findVersionControlForDirectory(project->projectDirectory(), + &cachedTopLevel); + cachedProject = project; + } + + if (variable == Constants::VAR_VCS_NAME) { + if (cachedVc) + Core::VariableManager::insert(variable, cachedVc->displayName()); + else + Core::VariableManager::remove(variable); + } else if (variable == Constants::VAR_VCS_TOPIC) { + if (cachedVc) + Core::VariableManager::insert(variable, cachedVc->vcsTopic(cachedTopLevel)); + else + Core::VariableManager::remove(variable); + } +} + } // namespace Internal } // namespace VcsBase diff --git a/src/plugins/vcsbase/vcsplugin.h b/src/plugins/vcsbase/vcsplugin.h index fd73b0d89a3..c0baf218562 100644 --- a/src/plugins/vcsbase/vcsplugin.h +++ b/src/plugins/vcsbase/vcsplugin.h @@ -72,6 +72,7 @@ signals: private slots: void slotSettingsChanged(); + void updateVariable(const QByteArray &variable); private: void populateNickNameModel(); diff --git a/src/shared/qbs b/src/shared/qbs index de8682b7d4f..0816b8e476d 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit de8682b7d4fccdef5c93759336e51ab73ecd5021 +Subproject commit 0816b8e476d20e00cbcffd1e71162adf93e85658 diff --git a/src/src.qbs b/src/src.qbs index d0aa9a4957c..d7ba55a39a5 100644 --- a/src/src.qbs +++ b/src/src.qbs @@ -27,6 +27,7 @@ Project { property path libRPaths: qbs.targetOS.contains("osx") ? ["@loader_path/.."] : ["$ORIGIN/.."] property path resourcesInstallDir: project.ide_data_path + "/qbs" + property string pluginsInstallDir: "lib/qtcreator" references: [ qbsBaseDir + "/src/lib/libs.qbs", diff --git a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp index 0704fbc8af5..8528d8e4339 100644 --- a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp +++ b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp @@ -127,6 +127,7 @@ private Q_SLOTS: void functionDefaultArgument(); void attributeInAccessSpecifier(); void braceReturn(); + void staticVarDeclWithTypeDecl(); }; struct Line { @@ -2111,6 +2112,43 @@ void tst_CodeFormatter::braceReturn() checkIndent(data); } +void tst_CodeFormatter::staticVarDeclWithTypeDecl() +{ + QList data; + data << Line("static class: public Foo {") + << Line("public:") + << Line(" int bar();") + << Line("} mooze;") + << Line("") + << Line("static enum Col {") + << Line(" red,") + << Line(" yellow,") + << Line(" green") + << Line("} Loc;") + << Line("") + << Line("static enum {") + << Line(" red,") + << Line(" yellow,") + << Line(" green") + << Line("} Loc;") + << Line("") + << Line("enum class Col {") + << Line(" red,") + << Line(" yellow,") + << Line(" green") + << Line("};") + << Line("") + << Line("static enum class Col") + << Line("{") + << Line(" red,") + << Line(" yellow,") + << Line(" green") + << Line("} Loc;") + << Line("") + ; + checkIndent(data); +} + QTEST_MAIN(tst_CodeFormatter) #include "tst_codeformatter.moc" diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index ca3460335d2..808bd75a007 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -32,6 +32,7 @@ #include #include #include +#include //TESTED_COMPONENT=src/libs/cplusplus using namespace CPlusPlus; @@ -116,9 +117,17 @@ public: } virtual void passedMacroDefinitionCheck(unsigned /*offset*/, - unsigned /*line*/, - const Macro &/*macro*/) {} - virtual void failedMacroDefinitionCheck(unsigned /*offset*/, const ByteArrayRef &/*name*/) {} + unsigned line, + const Macro ¯o) + { + m_definitionsResolvedFromLines[macro.name()].append(line); + } + + virtual void failedMacroDefinitionCheck(unsigned /*offset*/, + const ByteArrayRef &name) + { + m_unresolvedDefines.insert(name.toByteArray()); + } virtual void notifyMacroReference(unsigned offset, unsigned line, const Macro ¯o) { @@ -249,6 +258,12 @@ public: QHash > macroUsesLine() const { return m_macroUsesLine; } + QHash > definitionsResolvedFromLines() const + { return m_definitionsResolvedFromLines; } + + QSet unresolvedDefines() const + { return m_unresolvedDefines; } + const QList macroArgsCount() const { return m_macroArgsCount; } @@ -266,6 +281,8 @@ private: QList m_definedMacros; QList m_definedMacrosLine; QHash > m_macroUsesLine; + QHash > m_definitionsResolvedFromLines; + QSet m_unresolvedDefines; QList m_macroArgsCount; }; @@ -326,6 +343,7 @@ private slots: void extra_va_args(); void defined(); void defined_data(); + void defined_usage(); void empty_macro_args(); void macro_args_count(); void invalid_param_count(); @@ -356,6 +374,7 @@ private slots: void include_guard_data(); void empty_trailing_lines(); void empty_trailing_lines_data(); + void undef(); }; // Remove all #... lines, and 'simplify' string, to allow easily comparing the result @@ -1058,6 +1077,36 @@ void tst_Preprocessor::defined_data() "#endif\n"; } +void tst_Preprocessor::defined_usage() +{ + QByteArray output; + Environment env; + MockClient client(&env, &output); + Preprocessor pp(&client, &env); + QByteArray source = + "#define X\n" + "#define Y\n" + "#ifdef X\n" + "#endif\n" + "#ifdef Y\n" + "#endif\n" + "#ifndef X\n" + "#endif\n" + "#ifndef Y\n" + "#endif\n" + "#ifdef ABSENT\n" + "#endif\n" + "#ifndef ABSENT2\n" + "#endif\n" + ; + pp.run(QLatin1String(""), source); + QHash > definitionsResolvedFromLines = + client.definitionsResolvedFromLines(); + QCOMPARE(definitionsResolvedFromLines["X"], QList() << 3 << 7); + QCOMPARE(definitionsResolvedFromLines["Y"], QList() << 5 << 9); + QCOMPARE(client.unresolvedDefines(), QSet() << "ABSENT" << "ABSENT2"); +} + void tst_Preprocessor::dont_eagerly_expand_data() { QTest::addColumn("input"); @@ -1691,6 +1740,46 @@ void tst_Preprocessor::empty_trailing_lines_data() ); } +void tst_Preprocessor::undef() +{ + Environment env; + QByteArray output; + MockClient client(&env, &output); + Preprocessor preprocess(&client, &env); + QByteArray input = + "#define FOO\n" + "#define FOO2\n" + "#undef FOO\n" + "#undef BAR\n"; + preprocess.run(QLatin1String(""), input); + QCOMPARE(env.macroCount(), 4U); + Macro *macro = env.macroAt(0); + QCOMPARE(macro->name(), QByteArray("FOO")); + QCOMPARE(macro->offset(), 8U); + QCOMPARE(macro->line(), 1U); + QVERIFY(!macro->isHidden()); + macro = env.macroAt(1); + QCOMPARE(macro->name(), QByteArray("FOO2")); + QCOMPARE(macro->offset(), 20U); + QCOMPARE(macro->line(), 2U); + QVERIFY(!macro->isHidden()); + macro = env.macroAt(2); + QCOMPARE(macro->name(), QByteArray("FOO")); + QCOMPARE(macro->offset(), 32U); + QCOMPARE(macro->line(), 3U); + QVERIFY(macro->isHidden()); + macro = env.macroAt(3); + QCOMPARE(macro->name(), QByteArray("BAR")); + QCOMPARE(macro->offset(), 43U); + QCOMPARE(macro->line(), 4U); + QVERIFY(macro->isHidden()); + QList macros = client.definedMacros(); + QVERIFY(macros.contains("FOO")); + QVERIFY(macros.contains("FOO2")); + QCOMPARE(client.macroUsesLine()["FOO"], (QList() << 3U)); + QVERIFY(client.macroUsesLine()["BAR"].isEmpty()); +} + void tst_Preprocessor::compare_input_output(bool keepComments) { QFETCH(QByteArray, input); diff --git a/tests/system/objects.map b/tests/system/objects.map index 20e6055b4e2..6dbacef2a53 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -131,6 +131,7 @@ :Qt Creator.Help_Search for:_QLineEdit {leftWidget=':Qt Creator.Search for:_QLabel' type='QLineEdit' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Issues_QListView {type='QListView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow' windowTitle='Issues'} :Qt Creator.Project.Menu.File_QMenu {name='Project.Menu.File' type='QMenu'} +:Qt Creator.Project.Menu.Folder_QMenu {name='Project.Menu.Folder' type='QMenu' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.QtCreator.MenuBar_QMenuBar {name='QtCreator.MenuBar' type='QMenuBar' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.ReRun_QToolButton {toolTip='Re-run this run-configuration' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Replace All_QToolButton {name='replaceAllButton' text='Replace All' type='QToolButton' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} diff --git a/tests/system/suite_general/tst_rename_file/test.py b/tests/system/suite_general/tst_rename_file/test.py index a8cc687d0f0..c3252e82566 100644 --- a/tests/system/suite_general/tst_rename_file/test.py +++ b/tests/system/suite_general/tst_rename_file/test.py @@ -82,7 +82,10 @@ def renameFile(projectDir, proFile, branch, oldname, newname): openItemContextMenu(treeview, itemText, 5, 5, 0) except: openItemContextMenu(treeview, addBranchWildcardToRoot(itemText), 5, 5, 0) - activateItem(waitForObjectItem(":Qt Creator.Project.Menu.File_QMenu", "Rename...")) + if oldname.endswith(".qrc"): + activateItem(waitForObjectItem(":Qt Creator.Project.Menu.Folder_QMenu", "Rename File")) + else: + activateItem(waitForObjectItem(":Qt Creator.Project.Menu.File_QMenu", "Rename...")) type(waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit"), newname) type(waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit"), "") test.verify(waitFor("os.path.exists(newFilePath)", 1000), diff --git a/tests/system/suite_general/tst_session_handling/test.py b/tests/system/suite_general/tst_session_handling/test.py index ce3d8264e19..9d81da376d0 100644 --- a/tests/system/suite_general/tst_session_handling/test.py +++ b/tests/system/suite_general/tst_session_handling/test.py @@ -44,7 +44,7 @@ def main(): for project in projects: openQmakeProject(project) progressBarWait(20000) - checkNavigator(49, "Verifying whether all projects have been opened.") + checkNavigator(68, "Verifying whether all projects have been opened.") openDocument("propertyanimation.QML.qml.color-animation\\.qml") openDocument("declarative-music-browser.Headers.utility\\.h") checkOpenDocuments(2, "Verifying whether 2 files are open.") @@ -57,7 +57,7 @@ def main(): switchSession(sessionName) test.verify(waitFor("sessionName in str(mainWindow.windowTitle)", 2000), "Verifying window title contains created session name.") - checkNavigator(49, "Verifying whether all projects have been re-opened.") + checkNavigator(68, "Verifying whether all projects have been re-opened.") checkOpenDocuments(2, "Verifying whether 2 files have been re-opened.") if test.verify("utility.h" in str(mainWindow.windowTitle), "Verifying whether utility.h has been opened."):