diff --git a/dist/changes-4.3.0.md b/dist/changes-4.3.0.md new file mode 100644 index 00000000000..79e4574c5c3 --- /dev/null +++ b/dist/changes-4.3.0.md @@ -0,0 +1,215 @@ +Qt Creator version 4.3 contains bug fixes and new features. + +The most important changes are listed in this document. For a complete +list of changes, see the Git log for the Qt Creator sources that +you can check out from the public Git repository. For example: + + git clone git://code.qt.io/qt-creator/qt-creator.git + git log --cherry-pick --pretty=oneline origin/4.2..v4.3.0 + +General + +* Added option to search `Files in File System` with Silver Searcher (`ag`) + (experimental `SilverSearcher` plugin) +* Added exclusion patterns to `Advanced Find` and custom locator filters +* Added navigation pane on right side of edit mode + +Editing + +* Added optional shortcut for duplicating current selection + +All Projects + +* Added support for `.qrc` files in project tree for all projects +* Added Qt Creator variable `CurrentRun:Runnable:FilePath` +* Added choice of build system to most project wizards (QTCREATORBUG-17308) + +QMake Projects + +* Fixed wrong warning when specifying absolute path to mkspec + (QTCREATORBUG-17237) + +CMake Projects + +* Added support for `server-mode` with CMake 3.7 or later + * Added products and targets to project tree + * Added option to build individual products and targets + * Removed the need for `CodeBlocks` extra generator +* Added header files to project tree, even if not listed explicitly in + project files +* Added import of configuration of existing builds + +Generic Projects + +* Added expansion of Qt Creator variables in project files + +C++ Support + +* Added support for `clang-query` in `Advanced Find` to experimental + `ClangRefactoring` plugin +* Added switching project and language context for parsing files to editor + toolbar +* Added support for `--gcctoolchain` option +* Improved performance of first completion in file on Windows +* Fixed handling of Objective-C/C++ +* Fixed cursor position after correcting `.` to `->` (QTCREATORBUG-17697) +* Fixed that quotes were added when splitting raw string literals + (QTCREATORBUG-17717) + +QML Support + +* Added option to automatically format QML files on save +* Added menu item for adding expression evaluators from QML code editor + (QTCREATORBUG-17754) + +Nim Support + +* Added automatic reparsing when files are added to or removed from project +* Added Nim compiler setting to kits +* Fixed that loading projects blocked Qt Creator +* Fixed crash when opening empty projects + +Debugging + +* Added pretty printing of `unordered_multi(set|map)` +* Fixed that expression evaluators were not evaluated when added + (QTCREATORBUG-17763) +* QML + * Fixed accessing items by `id` in `Debugger Console` (QTCREATORBUG-17177) +* CDB + * Changed to Python based pretty printing backend, resulting in faster + startup and more, faster, and unified pretty printers + +QML Profiler + +* Added performance information to QML code editor (QTCREATORBUG-17757) +* Improved performance of rendering timeline and loading trace files +* Improved error and progress reporting for loading and saving trace files +* Fixed pixmap cache size information when loading profile + (QTCREATORBUG-17424) + +Qt Quick Designer + +* Added support for HiDPI +* Added text editor view +* Added tool bar for common actions +* Added changing type of item by changing type name in property editor +* Added support for `qsTranslate` (QTCREATORBUG-17714) +* Added actions for adding items, selecting visible item, and adding tab bar + to stacked containers +* Fixed that error messages could be shown twice +* Fixed handling of escaped unicode characters (QTCREATORBUG-12616) + +Version Control Systems + +* Git + * Added option to only show the first parent of merge commits in log + * Added action to skip a commit during rebase (QTCREATORBUG-17350) + * Added option to sign-off commits + * Fixed handling of already merged files in merge tool +* Gerrit + * Added detection of Gerrit remotes (SSH only) + * Added support for accessing Gerrit via HTTP(S) + +Test Integration + +* Removed `experimental` state +* Improved display of test results (QTCREATORBUG-17104) +* Added option to limit searching for tests to folders matching pattern + (QTCREATORBUG-16705) +* Fixed detection of inherited test methods (QTCREATORBUG-17522) +* Fixed missing update of test list when QML files are added or removed + (QTCREATORBUG-17805) + +SCXML Editor + +* Fixed adding elements to `else` case (QTCREATORBUG-17674) +* Fixed that copying and pasting state created invalid name + +Beautifier + +* Uncrustify + * Added option to select config file to use + +Platform Specific + +Windows + +* Fixed that it was not possible to save files with arbitrary extension + (QTCREATORBUG-15862) + +Android + +* Improved package signing (QTCREATORBUG-17545, QTCREATORBUG-17304) + +iOS + +* Added option to select developer team and provisioning profile used for + signing (QTCREATORBUG-16936) +* Fixed that starting simulator blocked Qt Creator + +Remote Linux + +* Added incremental deployment to `tar` package deployment + +QNX + +* Added support for 64bit platforms + +Credits for these changes go to: +Alessandro Portale +Alexander Drozdov +Alexandru Croitor +Andre Hartmann +Andreas Pakulat +André Pönitz +Arnold Dumas +BogDan Vatra +Christian Gagneraud +Christian Kandeler +Christian Stenger +Cristian Adam +Daniel Kamil Kozar +Daniel Trevitz +David Schulz +Eike Ziller +Filippo Cucchetto +Florian Apolloner +Francois Ferrand +Frank Meerkötter +Friedemann Kleint +Hugo Holgersson +Jake Petroules +James McDonnell +Jaroslaw Kobus +Jesus Fernandez +Juhapekka Piiroinen +Jörg Bornemann +Kari Oikarinen +Kavindra Palaraja +Konstantin Podsvirov +Leena Miettinen +Lorenz Haas +Lukas Holecek +Marco Benelli +Marco Bubke +Mathias Hasselmann +Max Blagay +Michael Dönnebrink +Michal Steller +Montel Laurent +Nikita Baryshnikov +Nikolai Kosjar +Oleg Yadrov +Orgad Shaneh +Oswald Buddenhagen +Przemyslaw Gorszkowski +Robert Löhning +Serhii Moroz +Tasuku Suzuki +Thiago Macieira +Thomas Hartmann +Tim Jenssen +Tobias Hunger +Ulf Hermann +Vikas Pachdha diff --git a/scripts/deployqtHelper_mac.sh b/scripts/deployqtHelper_mac.sh index 231825f9ae4..5039c89e821 100755 --- a/scripts/deployqtHelper_mac.sh +++ b/scripts/deployqtHelper_mac.sh @@ -29,6 +29,7 @@ [ $(uname -s) != "Darwin" ] && echo "Run this script on Mac OS X" && exit 2; app_path="$1" +resource_path="$app_path/Contents/Resources" bin_src="$2" translation_src="$3" plugin_src="$4" @@ -76,28 +77,28 @@ if [ -d "$quick2_src" ]; then fi # copy qt creator qt.conf -if [ ! -f "$app_path/Contents/Resources/qt.conf" ]; then +if [ ! -f "$resource_path/qt.conf" ]; then echo "- Copying qt.conf" - cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/qt.conf" "$app_path/Contents/Resources/qt.conf" || exit 1 + cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/qt.conf" "$resource_path/qt.conf" || exit 1 fi # copy ios tools' qt.conf -if [ ! -f "$app_path/Contents/Resources/ios/qt.conf" ]; then +if [ ! -f "$resource_path/ios/qt.conf" ]; then echo "- Copying ios/qt.conf" - cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/ios_qt.conf" "$app_path/Contents/Resources/ios/qt.conf" || exit 1 + cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/ios_qt.conf" "$resource_path/ios/qt.conf" || exit 1 fi # copy qml2puppet's qt.conf -if [ ! -f "$app_path/Contents/Resources/qmldesigner/qt.conf" ]; then +if [ ! -f "$resource_path/qmldesigner/qt.conf" ]; then echo "- Copying qmldesigner/qt.conf" - cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/qmldesigner_qt.conf" "$app_path/Contents/Resources/qmldesigner/qt.conf" || exit 1 + cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/qmldesigner_qt.conf" "$resource_path/qmldesigner/qt.conf" || exit 1 fi # copy Qt translations # check for known existing translation to avoid copying multiple times -if [ ! -f "$app_path/Contents/Resources/translations/qt_de.qm" ]; then +if [ ! -f "$resource_path/translations/qt_de.qm" ]; then echo "- Copying Qt translations" - cp "$translation_src"/*.qm "$app_path/Contents/Resources/translations/" || exit 1 + cp "$translation_src"/*.qm "$resource_path/translations/" || exit 1 fi # copy libclang if needed @@ -106,32 +107,27 @@ if [ $LLVM_INSTALL_DIR ]; then echo "- Copying libclang" mkdir -p "$app_path/Contents/Frameworks" || exit 1 # use recursive copy to make it copy symlinks as symlinks - mkdir -p "$app_path/Contents/Resources/clang/bin" - mkdir -p "$app_path/Contents/Resources/clang/lib" + mkdir -p "$resource_path/clang/bin" + mkdir -p "$resource_path/clang/lib" cp -Rf "$LLVM_INSTALL_DIR"/lib/libclang.*dylib "$app_path/Contents/Frameworks/" || exit 1 - cp -Rf "$LLVM_INSTALL_DIR"/lib/clang "$app_path/Contents/Resources/clang/lib/" || exit 1 + cp -Rf "$LLVM_INSTALL_DIR"/lib/clang "$resource_path/clang/lib/" || exit 1 clangsource="$LLVM_INSTALL_DIR"/bin/clang clanglinktarget="$(readlink "$clangsource")" - cp -Rf "$clangsource" "$app_path/Contents/Resources/clang/bin/" || exit 1 + cp -Rf "$clangsource" "$resource_path/clang/bin/" || exit 1 if [ $clanglinktarget ]; then - cp -Rf "$(dirname "$clangsource")/$clanglinktarget" "$app_path/Contents/Resources/clang/bin/$clanglinktarget" || exit 1 + cp -Rf "$(dirname "$clangsource")/$clanglinktarget" "$resource_path/clang/bin/$clanglinktarget" || exit 1 fi fi - _CLANG_CODEMODEL_LIB="$app_path/Contents/PlugIns/libClangCodeModel_debug.dylib" - if [ ! -f "$_CLANG_CODEMODEL_LIB" ]; then - _CLANG_CODEMODEL_LIB="$app_path/Contents/PlugIns/libClangCodeModel.dylib" - fi - # this will just fail when run a second time on libClangCodeModel - xcrun install_name_tool -delete_rpath "$LLVM_INSTALL_DIR/lib" "$_CLANG_CODEMODEL_LIB" || true - xcrun install_name_tool -add_rpath "@loader_path/../Frameworks" "$_CLANG_CODEMODEL_LIB" || true - clangbackendArgument="-executable=$app_path/Contents/Resources/clangbackend" + clangbackendArgument="-executable=$resource_path/clangbackend" + clangpchmanagerArgument="-executable=$resource_path/clangpchmanagerbackend" + clangrefactoringArgument="-executable=$resource_path/clangrefactoringbackend" fi #### macdeployqt if [ ! -d "$app_path/Contents/Frameworks/QtCore.framework" ]; then - qml2puppetapp="$app_path/Contents/Resources/qmldesigner/qml2puppet" + qml2puppetapp="$resource_path/qmldesigner/qml2puppet" if [ -f "$qml2puppetapp" ]; then qml2puppetArgument="-executable=$qml2puppetapp" fi @@ -141,12 +137,13 @@ if [ ! -d "$app_path/Contents/Frameworks/QtCore.framework" ]; then echo "- Running macdeployqt ($(which macdeployqt))" macdeployqt "$app_path" \ - "-executable=$app_path/Contents/Resources/qtpromaker" \ - "-executable=$app_path/Contents/Resources/sdktool" \ - "-executable=$app_path/Contents/Resources/ios/iostool" \ - "-executable=$app_path/Contents/Resources/buildoutputparser" \ - "-executable=$app_path/Contents/Resources/cpaster" \ "-executable=$app_path/Contents/MacOS/qtdiag" \ + "-executable=$resource_path/qtpromaker" \ + "-executable=$resource_path/sdktool" \ + "-executable=$resource_path/ios/iostool" \ + "-executable=$resource_path/buildoutputparser" \ + "-executable=$resource_path/cpaster" \ + "-executable=$resource_path/qbs_processlauncher" \ "-executable=$qbsapp" \ "-executable=$qbsapp-config" \ "-executable=$qbsapp-config-ui" \ @@ -154,6 +151,8 @@ if [ ! -d "$app_path/Contents/Frameworks/QtCore.framework" ]; then "-executable=$qbsapp-setup-android" \ "-executable=$qbsapp-setup-qt" \ "-executable=$qbsapp-setup-toolchains" \ - "$qml2puppetArgument" "$clangbackendArgument" || exit 1 + "-executable=$qbsapp-create-project" \ + "$qml2puppetArgument" \ + "$clangbackendArgument" "$clangpchmanagerArgument" "$clangrefactoringArgument" || exit 1 fi diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index 211b595efe9..fd8c65dd95c 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -124,6 +124,7 @@ class Dumper(DumperBase): # read raw memory in case the integerString can not be interpreted pass val.isBaseClass = val.name == val.type.name + val.nativeValue = nativeValue val.lIsInScope = True val.laddress = nativeValue.address() return val @@ -459,7 +460,37 @@ class Dumper(DumperBase): return cdbext.parseAndEvaluate(exp) def nativeDynamicTypeName(self, address, baseType): - return None # FIXME: Seems sufficient, no idea why. + return None # Does not work with cdb + + def nativeValueDereferenceReference(self, value): + return self.nativeValueDereferencePointer(value) + + def nativeValueDereferencePointer(self, value): + def nativeVtCastValue(nativeValue): + # If we have a pointer to a derived instance of the pointer type cdb adds a + # synthetic '__vtcast_' member as the first child + if nativeValue.hasChildren(): + vtcastCandidate = nativeValue.childFromIndex(0) + vtcastCandidateName = vtcastCandidate.name() + if vtcastCandidateName.startswith('__vtcast_'): + # found a __vtcast member + # make sure that it is not an actual field + for field in nativeValue.type().fields(): + if field.name() == vtcastCandidateName: + return None + return vtcastCandidate + return None + + nativeValue = value.nativeValue + castVal = nativeVtCastValue(nativeValue) + if castVal is not None: + val = self.fromNativeValue(castVal) + else: + val = self.Value(self) + val.laddress = value.pointer() + val.type = value.type.dereference() + + return val def callHelper(self, rettype, value, function, args): raise Exception("cdb does not support calling functions") diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index aaad6180b03..9a019f87c36 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -3105,13 +3105,13 @@ class DumperBase: val.laddress = self.laddress val.type = self.dumper.nativeDynamicType(val.laddress, self.type.dereference()) else: - val = self.dumper.nativeValueDereferenceReference(self.nativeValue) + val = self.dumper.nativeValueDereferenceReference(self) elif self.type.code == TypeCodePointer: if self.nativeValue is None: val.laddress = self.pointer() val.type = self.dumper.nativeDynamicType(val.laddress, self.type.dereference()) else: - val = self.dumper.nativeValueDereferencePointer(self.nativeValue) + val = self.dumper.nativeValueDereferencePointer(self) else: error("WRONG: %s" % self.type.code) #warn("DEREFERENCING FROM: %s" % self) diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 33c19a20658..acf22e47862 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -1050,11 +1050,12 @@ class Dumper(DumperBase): n = ("'%sQWidget'" % ns) if lenns else 'QWidget' self.reportResult('selected="0x%x",expr="(%s*)0x%x"' % (p, n, p), args) - def nativeValueDereferencePointer(self, nativeValue): - deref = nativeValue.dereference() + def nativeValueDereferencePointer(self, value): + deref = value.nativeValue.dereference() return self.fromNativeValue(deref.cast(deref.dynamic_type)) - def nativeValueDereferenceReference(self, nativeValue): + def nativeValueDereferenceReference(self, value): + nativeValue = value.nativeValue return self.fromNativeValue(nativeValue.cast(nativeValue.type.target())) def nativeDynamicTypeName(self, address, baseType): diff --git a/src/libs/qtcreatorcdbext/pycdbextmodule.cpp b/src/libs/qtcreatorcdbext/pycdbextmodule.cpp index 4d16671c023..4ca11a777d3 100644 --- a/src/libs/qtcreatorcdbext/pycdbextmodule.cpp +++ b/src/libs/qtcreatorcdbext/pycdbextmodule.cpp @@ -102,9 +102,13 @@ static PyObject *cdbext_parseAndEvaluate(PyObject *, PyObject *args) // -> Value if (debugPyCdbextModule) DebugPrint() << "evaluate expression: " << expr; CIDebugControl *control = ExtensionCommandContext::instance()->control(); + ULONG oldExpressionSyntax; + control->GetExpressionSyntax(&oldExpressionSyntax); control->SetExpressionSyntax(DEBUG_EXPR_CPLUSPLUS); DEBUG_VALUE value; - if (FAILED(control->Evaluate(expr, DEBUG_VALUE_INT64, &value, NULL))) + HRESULT hr = control->Evaluate(expr, DEBUG_VALUE_INT64, &value, NULL); + control->SetExpressionSyntax(oldExpressionSyntax); + if (FAILED(hr)) Py_RETURN_NONE; return Py_BuildValue("K", value.I64); } diff --git a/src/libs/timeline/qml/TimelineContent.qml b/src/libs/timeline/qml/TimelineContent.qml index 74a929769a6..aae9b122294 100644 --- a/src/libs/timeline/qml/TimelineContent.qml +++ b/src/libs/timeline/qml/TimelineContent.qml @@ -68,6 +68,7 @@ ScrollView { // switch to non-interactive ourselves, though. property bool stayInteractive: true onStayInteractiveChanged: flick.interactive = stayInteractive + onWidthChanged: scroll() Flickable { id: flick @@ -88,13 +89,12 @@ ScrollView { recursionGuard = false; } - onWidthChanged: scroll() - // Update the zoom control on scrolling. onContentXChanged: guarded(function() { - var newStartTime = contentX * zoomer.rangeDuration / width + zoomer.windowStart; + var newStartTime = contentX * zoomer.rangeDuration / scroller.width + + zoomer.windowStart; if (isFinite(newStartTime) && Math.abs(newStartTime - zoomer.rangeStart) >= 1) { - var newEndTime = (contentX + width) * zoomer.rangeDuration / width + var newEndTime = (contentX + scroller.width) * zoomer.rangeDuration / scroller.width + zoomer.windowStart; if (isFinite(newEndTime)) zoomer.setRange(newStartTime, newEndTime); @@ -108,10 +108,10 @@ ScrollView { contentWidth = 0; contentX = 0; } else { - var newWidth = zoomer.windowDuration * width / zoomer.rangeDuration; + var newWidth = zoomer.windowDuration * scroller.width / zoomer.rangeDuration; if (isFinite(newWidth) && Math.abs(newWidth - contentWidth) >= 1) contentWidth = newWidth; - var newStartX = (zoomer.rangeStart - zoomer.windowStart) * width / + var newStartX = (zoomer.rangeStart - zoomer.windowStart) * scroller.width / zoomer.rangeDuration; if (isFinite(newStartX) && Math.abs(newStartX - contentX) >= 1) contentX = newStartX; diff --git a/src/libs/timeline/timelinemodel.cpp b/src/libs/timeline/timelinemodel.cpp index f765decaacb..438c2c36a5c 100644 --- a/src/libs/timeline/timelinemodel.cpp +++ b/src/libs/timeline/timelinemodel.cpp @@ -322,12 +322,14 @@ int TimelineModel::firstIndex(qint64 startTime) const int TimelineModel::TimelineModelPrivate::firstIndexNoParents(qint64 startTime) const { // in the "endtime" list, find the first event that ends after startTime - if (endTimes.isEmpty()) + + // lowerBound() cannot deal with empty lists, and it never finds the last element. + if (endTimes.isEmpty() || endTimes.last().end <= startTime) return -1; - if (endTimes.count() == 1 || endTimes.first().end > startTime) + + // lowerBound() never returns "invalid", so handle this manually. + if (endTimes.first().end > startTime) return endTimes.first().startIndex; - if (endTimes.last().end <= startTime) - return -1; return endTimes[lowerBound(endTimes, startTime) + 1].startIndex; } @@ -340,16 +342,55 @@ int TimelineModel::lastIndex(qint64 endTime) const { Q_D(const TimelineModel); // in the "starttime" list, find the last event that starts before endtime + + // lowerBound() never returns "invalid", so handle this manually. if (d->ranges.isEmpty() || d->ranges.first().start >= endTime) return -1; - if (d->ranges.count() == 1) - return 0; + + // lowerBound() never finds the last element. if (d->ranges.last().start < endTime) return d->ranges.count() - 1; return d->lowerBound(d->ranges, endTime); } +/*! + Looks up a range between the last one that starts before, and the first one that ends after the + given timestamp. This might not be a range that covers the timestamp, even if one exists. + However, it's likely that the range is close to the given timestamp. + */ +int TimelineModel::bestIndex(qint64 timestamp) const +{ + Q_D(const TimelineModel); + + if (d->ranges.isEmpty()) + return -1; + + // Last range that starts before timestamp (without parents) + const int start = d->ranges.last().start < timestamp + ? d->ranges.count() - 1 : d->lowerBound(d->ranges, timestamp); + + int endTimeIndex; + if (d->endTimes.first().end >= timestamp) + endTimeIndex = 0; + else if (d->endTimes.last().end < timestamp) + endTimeIndex = d->endTimes.count() - 1; + else + endTimeIndex = d->lowerBound(d->endTimes, timestamp) + 1; + + // First range that ends after + const int end = d->endTimes[endTimeIndex].startIndex; + + // Best is probably between those + return (start + end) / 2; +} + +int TimelineModel::parentIndex(int index) const +{ + Q_D(const TimelineModel); + return d->ranges[index].parent; +} + QVariantMap TimelineModel::location(int index) const { Q_UNUSED(index); diff --git a/src/libs/timeline/timelinemodel.h b/src/libs/timeline/timelinemodel.h index 5f4ed27ec3c..514d7ad5209 100644 --- a/src/libs/timeline/timelinemodel.h +++ b/src/libs/timeline/timelinemodel.h @@ -76,6 +76,8 @@ public: int firstIndex(qint64 startTime) const; int lastIndex(qint64 endTime) const; + int bestIndex(qint64 timestamp) const; + int parentIndex(int index) const; bool expanded() const; bool hidden() const; diff --git a/src/libs/timeline/timelinerenderer.cpp b/src/libs/timeline/timelinerenderer.cpp index 5aa12efc08e..983fbfa5095 100644 --- a/src/libs/timeline/timelinerenderer.cpp +++ b/src/libs/timeline/timelinerenderer.cpp @@ -70,10 +70,8 @@ TimelineRenderer::TimelineRenderer(QQuickItem *parent) : void TimelineRenderer::TimelineRendererPrivate::resetCurrentSelection() { - currentSelection.startTime = -1; - currentSelection.endTime = -1; - currentSelection.row = -1; - currentSelection.eventIndex = -1; + currentEventIndex = -1; + currentRow = -1; } TimelineRenderState *TimelineRenderer::TimelineRendererPrivate::findRenderState() @@ -182,7 +180,7 @@ void TimelineRenderer::mouseReleaseEvent(QMouseEvent *event) { Q_D(TimelineRenderer); d->findCurrentSelection(event->pos().x(), event->pos().y(), width()); - setSelectedItem(d->currentSelection.eventIndex); + setSelectedItem(d->currentEventIndex); } void TimelineRenderer::mouseMoveEvent(QMouseEvent *event) @@ -195,10 +193,10 @@ void TimelineRenderer::hoverMoveEvent(QHoverEvent *event) Q_D(TimelineRenderer); if (!d->selectionLocked) { d->findCurrentSelection(event->pos().x(), event->pos().y(), width()); - if (d->currentSelection.eventIndex != -1) - setSelectedItem(d->currentSelection.eventIndex); + if (d->currentEventIndex != -1) + setSelectedItem(d->currentEventIndex); } - if (d->currentSelection.eventIndex == -1) + if (d->currentEventIndex == -1) event->setAccepted(false); } @@ -229,6 +227,88 @@ void TimelineRenderer::wheelEvent(QWheelEvent *event) } } +TimelineRenderer::TimelineRendererPrivate::MatchResult +TimelineRenderer::TimelineRendererPrivate::checkMatch(MatchParameters *params, int index, + qint64 itemStart, qint64 itemEnd) +{ + const qint64 offset = qAbs(itemEnd - params->exactTime) + qAbs(itemStart - params->exactTime); + if (offset >= params->bestOffset) + return NoMatch; + + // match + params->bestOffset = offset; + currentEventIndex = index; + + // Exact match. If we can get better than this, then we have multiple overlapping + // events in one row. There is no point in sorting those out as you cannot properly + // discern them anyway. + return (itemEnd >= params->exactTime && itemStart <= params->exactTime) + ? ExactMatch : ApproximateMatch; +} + +TimelineRenderer::TimelineRendererPrivate::MatchResult +TimelineRenderer::TimelineRendererPrivate::matchForward(MatchParameters *params, int index) +{ + if (index < 0) + return NoMatch; + + if (index >= model->count()) + return Cutoff; + + if (model->row(index) != currentRow) + return NoMatch; + + const qint64 itemEnd = model->endTime(index); + if (itemEnd < params->startTime) + return NoMatch; + + const qint64 itemStart = model->startTime(index); + if (itemStart > params->endTime) + return Cutoff; + + // Further iteration will only increase the startOffset. + if (itemStart - params->exactTime >= params->bestOffset) + return Cutoff; + + return checkMatch(params, index, itemStart, itemEnd); +} + +TimelineRenderer::TimelineRendererPrivate::MatchResult +TimelineRenderer::TimelineRendererPrivate::matchBackward(MatchParameters *params, int index) +{ + if (index < 0) + return Cutoff; + + if (index >= model->count()) + return NoMatch; + + if (model->row(index) != currentRow) + return NoMatch; + + const qint64 itemStart = model->startTime(index); + if (itemStart > params->endTime) + return NoMatch; + + // There can be small events that don't reach the cursor position after large events + // that do but are in a different row. In that case, the parent index will be valid and will + // point to the large event. If that is also outside the range, we are really done. + const qint64 itemEnd = model->endTime(index); + if (itemEnd < params->startTime) { + const int parentIndex = model->parentIndex(index); + const qint64 parentEnd = parentIndex == -1 ? itemEnd : model->endTime(parentIndex); + return (parentEnd < params->startTime) ? Cutoff : NoMatch; + } + + if (params->exactTime - itemStart >= params->bestOffset) { + // We cannot get better anymore as the startTimes are totally ordered. + // Thus, the startOffset will only get bigger and we're only adding a + // positive number (end offset) in checkMatch() when comparing with bestOffset. + return Cutoff; + } + + return checkMatch(params, index, itemStart, itemEnd); +} + void TimelineRenderer::TimelineRendererPrivate::findCurrentSelection(int mouseX, int mouseY, int width) { @@ -239,67 +319,48 @@ void TimelineRenderer::TimelineRendererPrivate::findCurrentSelection(int mouseX, if (duration <= 0) return; + MatchParameters params; + // Make the "selected" area 3 pixels wide by adding/subtracting 1 to catch very narrow events. - qint64 startTime = (mouseX - 1) * duration / width + zoomer->windowStart(); - qint64 endTime = (mouseX + 1) * duration / width + zoomer->windowStart(); - qint64 exactTime = (startTime + endTime) / 2; - int row = rowFromPosition(mouseY); + params.startTime = (mouseX - 1) * duration / width + zoomer->windowStart(); + params.endTime = (mouseX + 1) * duration / width + zoomer->windowStart(); + params.exactTime = (params.startTime + params.endTime) / 2; + const int row = rowFromPosition(mouseY); // already covered? Only make sure d->selectedItem is correct. - if (currentSelection.eventIndex != -1 && - exactTime >= currentSelection.startTime && - exactTime < currentSelection.endTime && - row == currentSelection.row) { + if (currentEventIndex != -1 && + params.exactTime >= model->startTime(currentEventIndex) && + params.exactTime < model->endTime(currentEventIndex) && + row == currentRow) { return; } - // find if there's items in the time range - int eventFrom = model->firstIndex(startTime); - int eventTo = model->lastIndex(endTime); + currentRow = row; + currentEventIndex = -1; - currentSelection.eventIndex = -1; - if (eventFrom == -1 || eventTo < eventFrom || eventTo >= model->count()) + const int middle = model->bestIndex(params.exactTime); + if (middle == -1) return; - // find if we are in the right column - qint64 bestOffset = std::numeric_limits::max(); - for (int i=eventTo; i>=eventFrom; --i) { - if (model->row(i) != row) - continue; + params.bestOffset = std::numeric_limits::max(); + const qint64 itemStart = model->startTime(middle); + const qint64 itemEnd = model->endTime(middle); + if (model->row(middle) == row && itemEnd >= params.startTime && itemStart <= params.endTime) { + if (checkMatch(¶ms, middle, itemStart, itemEnd) == ExactMatch) + return; + } - // There can be small events that don't reach the cursor position after large events - // that do but are in a different row. - qint64 itemEnd = model->endTime(i); - if (itemEnd < startTime) - continue; - - qint64 itemStart = model->startTime(i); - - qint64 startOffset = exactTime - itemStart; - if (startOffset >= bestOffset) { - // We cannot get better anymore as the startTimes are totally ordered and we're moving - // backwards. Thus, the startOffset will only get bigger and we're only adding a - // positive number (end offset) below when comparing with bestOffset. - break; + MatchResult forward = NoMatch; + MatchResult backward = NoMatch; + for (int offset = 1; forward != Cutoff || backward != Cutoff; ++offset) { + if (backward != Cutoff + && (backward = matchBackward(¶ms, middle - offset)) == ExactMatch) { + return; + } + if (forward != Cutoff + && (forward = matchForward(¶ms, middle + offset)) == ExactMatch) { + return; } - - qint64 offset = qAbs(itemEnd - exactTime) + qAbs(startOffset); - if (offset >= bestOffset) - continue; - - // match - currentSelection.eventIndex = i; - currentSelection.startTime = itemStart; - currentSelection.endTime = itemEnd; - currentSelection.row = row; - - // Exact match. If we can get better than this, then we have multiple overlapping - // events in one row. There is no point in sorting those out as you cannot properly - // discern them anyway. - if (itemEnd >= exactTime && itemStart <= exactTime) - break; - - bestOffset = offset; } } diff --git a/src/libs/timeline/timelinerenderer_p.h b/src/libs/timeline/timelinerenderer_p.h index 398a1c637ec..714206dc5d0 100644 --- a/src/libs/timeline/timelinerenderer_p.h +++ b/src/libs/timeline/timelinerenderer_p.h @@ -33,12 +33,31 @@ namespace Timeline { class TimelineRenderer::TimelineRendererPrivate : public TimelineAbstractRenderer::TimelineAbstractRendererPrivate { public: + enum MatchResult { + NoMatch, + Cutoff, + ApproximateMatch, + ExactMatch + }; + + struct MatchParameters { + qint64 startTime; + qint64 endTime; + qint64 exactTime; + qint64 bestOffset; + }; + TimelineRendererPrivate(); ~TimelineRendererPrivate(); void clear(); int rowFromPosition(int y) const; + + MatchResult checkMatch(MatchParameters *params, int index, qint64 itemStart, qint64 itemEnd); + MatchResult matchForward(MatchParameters *params, int index); + MatchResult matchBackward(MatchParameters *params, int index); + void findCurrentSelection(int mouseX, int mouseY, int width); static const int SafeFloatMax = 1 << 12; @@ -47,12 +66,8 @@ public: TimelineRenderState *findRenderState(); - struct { - qint64 startTime; - qint64 endTime; - int row; - int eventIndex; - } currentSelection; + int currentEventIndex; + int currentRow; QVector > renderStates; TimelineRenderState *lastState; diff --git a/src/libs/utils/sizedarray.h b/src/libs/utils/sizedarray.h index 65f8a38e55a..7a5e8ee7831 100644 --- a/src/libs/utils/sizedarray.h +++ b/src/libs/utils/sizedarray.h @@ -108,9 +108,9 @@ public: return m_size == 0; } - void fillWithZero() + void initializeElements() { - std::array::fill(T(0)); + std::array::fill(T{}); } private: diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp index 6b1b7101701..9ecd8d97adf 100644 --- a/src/plugins/autotest/testconfiguration.cpp +++ b/src/plugins/autotest/testconfiguration.cpp @@ -84,9 +84,13 @@ void TestConfiguration::completeTestInformation(int runMode) return part->buildSystemTarget; }); + const Utils::FileName fn = Utils::FileName::fromString(m_projectFile); const BuildTargetInfo targetInfo - = Utils::findOrDefault(target->applicationTargets().list, [&buildSystemTargets] (const BuildTargetInfo &bti) { - return buildSystemTargets.contains(bti.targetName); + = Utils::findOrDefault(target->applicationTargets().list, + [&buildSystemTargets, &fn] (const BuildTargetInfo &bti) { + return Utils::anyOf(buildSystemTargets, [&fn, &bti](const QString &b) { + return b == bti.targetName || (b.contains(bti.targetName) && bti.projectFilePath == fn); + }); }); const Utils::FileName executable = targetInfo.targetFilePath; // empty if BTI is default created for (RunConfiguration *runConfig : target->runConfigurations()) { diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index acb59683f26..18314beb6f0 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -140,8 +140,7 @@ static void performTestRun(QFutureInterface &futureInterface, QString commandFilePath = testConfiguration->executableFilePath(); if (commandFilePath.isEmpty()) { futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal, - TestRunner::tr("Could not find command \"%1\". (%2)") - .arg(testConfiguration->executableFilePath()) + TestRunner::tr("Executable path is empty. (%1)") .arg(testConfiguration->displayName())))); continue; } diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp index d7d389ed3a7..a4a733d0cd2 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp @@ -29,7 +29,6 @@ #include "autotoolsbuildconfiguration.h" #include "autotoolsprojectconstants.h" #include "autotoolsprojectnode.h" -#include "autotoolsprojectfile.h" #include "autotoolsopenprojectwizard.h" #include "makestep.h" #include "makefileparserthread.h" @@ -69,11 +68,11 @@ using namespace AutotoolsProjectManager::Internal; using namespace ProjectExplorer; AutotoolsProject::AutotoolsProject(const Utils::FileName &fileName) : + Project(Constants::MAKEFILE_MIMETYPE, fileName), m_fileWatcher(new Utils::FileSystemWatcher(this)), m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this)) { setId(Constants::AUTOTOOLS_PROJECT_ID); - setDocument(new AutotoolsProjectFile(fileName)); setProjectContext(Core::Context(Constants::PROJECT_CONTEXT)); setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); } diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectfile.cpp b/src/plugins/autotoolsprojectmanager/autotoolsprojectfile.cpp deleted file mode 100644 index 49a3d1e6ff2..00000000000 --- a/src/plugins/autotoolsprojectmanager/autotoolsprojectfile.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Openismus GmbH. -** Author: Peter Penz (ppenz@openismus.com) -** Author: Patricia Santana Cruz (patriciasantanacruz@gmail.com) -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "autotoolsprojectfile.h" -#include "autotoolsproject.h" -#include "autotoolsprojectconstants.h" - -namespace AutotoolsProjectManager { -namespace Internal { - -AutotoolsProjectFile::AutotoolsProjectFile(const Utils::FileName &fileName) -{ - setId("Autotools.ProjectFile"); - setMimeType(QLatin1String(Constants::MAKEFILE_MIMETYPE)); - setFilePath(fileName); -} - -} // namespace Internal -} // namespace AutotoolsProjectManager diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectfile.h b/src/plugins/autotoolsprojectmanager/autotoolsprojectfile.h deleted file mode 100644 index 8c41e19bd5b..00000000000 --- a/src/plugins/autotoolsprojectmanager/autotoolsprojectfile.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Openismus GmbH. -** Author: Peter Penz (ppenz@openismus.com) -** Author: Patricia Santana Cruz (patriciasantanacruz@gmail.com) -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -namespace AutotoolsProjectManager { -namespace Internal { - -/** - * @brief Implementation of the Core::IDocument interface. - * - * Is used in AutotoolsProject and describes the root - * of a project. In the context of autotools the implementation - * is mostly empty, as the modification of a project is - * done by several Makefile.am files and the configure.ac file. - * - * @see AutotoolsProject - */ -class AutotoolsProjectFile : public Core::IDocument -{ -public: - AutotoolsProjectFile(const Utils::FileName &fileName); -}; - -} // namespace Internal -} // namespace AutotoolsProjectManager diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro index 3e30bf328c0..a58d556dda6 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro +++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro @@ -2,7 +2,6 @@ include(../../qtcreatorplugin.pri) HEADERS = autotoolsprojectplugin.h\ autotoolsopenprojectwizard.h\ - autotoolsprojectfile.h\ autotoolsprojectnode.h\ autotoolsproject.h\ autotoolsbuildsettingswidget.h\ @@ -16,7 +15,6 @@ HEADERS = autotoolsprojectplugin.h\ makefileparser.h SOURCES = autotoolsprojectplugin.cpp\ autotoolsopenprojectwizard.cpp\ - autotoolsprojectfile.cpp\ autotoolsprojectnode.cpp\ autotoolsproject.cpp\ autotoolsbuildsettingswidget.cpp\ diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs index 8c76c5d41f4..02ab46557ce 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs +++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs @@ -25,8 +25,6 @@ QtcPlugin { "autotoolsproject.cpp", "autotoolsproject.h", "autotoolsprojectconstants.h", - "autotoolsprojectfile.cpp", - "autotoolsprojectfile.h", "autotoolsprojectnode.cpp", "autotoolsprojectnode.h", "autotoolsprojectplugin.cpp", diff --git a/src/plugins/autotoolsprojectmanager/makestep.cpp b/src/plugins/autotoolsprojectmanager/makestep.cpp index 99658dd7147..ce8be4c9b9d 100644 --- a/src/plugins/autotoolsprojectmanager/makestep.cpp +++ b/src/plugins/autotoolsprojectmanager/makestep.cpp @@ -262,7 +262,7 @@ void MakeStepConfigWidget::updateDetails() Utils::QtcProcess::addArgs(&arguments, m_makeStep->additionalArguments()); ProcessParameters param; - param.setMacroExpander(bc->macroExpander()); + param.setMacroExpander(m_makeStep->macroExpander()); param.setEnvironment(bc->environment()); param.setWorkingDirectory(bc->buildDirectory().toString()); param.setCommand(tcList.at(0)->makeCommand(bc->environment())); diff --git a/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.cpp b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.cpp index 96f040c9906..9fdfaa7a1eb 100644 --- a/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.cpp +++ b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.cpp @@ -52,7 +52,6 @@ UncrustifyOptionsPageWidget::UncrustifyOptionsPageWidget(UncrustifySettings *set "HOME", QDir::toNativeSeparators(QDir::home().absolutePath()))); ui->uncrusifyFilePath->setExpectedKind(Utils::PathChooser::File); ui->uncrusifyFilePath->setPromptDialogFilter(tr("Uncrustify file (*.cfg)")); - ui->uncrusifyFilePath->setFileName(Utils::FileName::fromString(QDir::toNativeSeparators(QDir::home().absoluteFilePath("uncrustify.cfg")))); ui->command->setExpectedKind(Utils::PathChooser::ExistingCommand); ui->command->setPromptDialogTitle(BeautifierPlugin::msgCommandPromptDialogTitle( diff --git a/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.ui b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.ui index 190f9dd8ecc..46290698943 100644 --- a/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.ui +++ b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.ui @@ -133,15 +133,6 @@ 1 - - mime - useOtherFiles - useSpecificFile - uncrusifyFilePath - useHomeFile - useCustomStyle - formatEntireFileFallback - diff --git a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp index 07d57419188..1090d10a24b 100644 --- a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp +++ b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp @@ -72,7 +72,7 @@ TextEditor::TextStyle toTextStyle(ClangBackEnd::HighlightingType type) TextEditor::TextStyles toTextStyles(ClangBackEnd::HighlightingTypes types) { TextEditor::TextStyles textStyles; - textStyles.mixinStyles.fillWithZero(); + textStyles.mixinStyles.initializeElements(); textStyles.mainStyle = toTextStyle(types.mainHighlightingType); diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index cf9d0f0ca45..4bf0f0dcdc5 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -73,14 +73,10 @@ using namespace Internal; /*! \class CMakeProject */ -CMakeProject::CMakeProject(const FileName &fileName) - : m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this)) +CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEMIMETYPE, fileName), + m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this)) { setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID); - auto doc = new TextEditor::TextDocument; - doc->setFilePath(fileName); - setDocument(doc); - setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT)); setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); @@ -531,24 +527,35 @@ void CMakeProject::createGeneratedCodeModelSupport() { qDeleteAll(m_extraCompilers); m_extraCompilers.clear(); - QList factories = + const QList factories = ExtraCompilerFactory::extraCompilerFactories(); + const QSet fileExtensions + = Utils::transform(factories, [](const ExtraCompilerFactory *f) { return f->sourceTag(); }); + // Find all files generated by any of the extra compilers, in a rather crude way. - foreach (const QString &file, files(SourceFiles)) { - foreach (ExtraCompilerFactory *factory, factories) { - if (file.endsWith('.' + factory->sourceTag())) { - QStringList generated = filesGeneratedFrom(file); - if (!generated.isEmpty()) { - const FileNameList fileNames = transform(generated, - [](const QString &s) { - return FileName::fromString(s); - }); - m_extraCompilers.append(factory->create(this, FileName::fromString(file), - fileNames)); - } - } - } + const QStringList fileList = files(SourceFiles, [&fileExtensions](const FileNode *fn) { + const QString fp = fn->filePath().toString(); + const int pos = fp.lastIndexOf('.'); + return pos >= 0 && fileExtensions.contains(fp.mid(pos + 1)); + }); + + // Generate the necessary information: + for (const QString &file : fileList) { + ExtraCompilerFactory *factory = Utils::findOrDefault(factories, [&file](const ExtraCompilerFactory *f) { + return file.endsWith('.' + f->sourceTag()); + }); + QTC_ASSERT(factory, continue); + + QStringList generated = filesGeneratedFrom(file); + if (generated.isEmpty()) + continue; + + const FileNameList fileNames + = transform(generated, + [](const QString &s) { return FileName::fromString(s); }); + m_extraCompilers.append(factory->create(this, FileName::fromString(file), + fileNames)); } CppTools::GeneratedCodeModelSupport::update(m_extraCompilers); diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index 33d0614ab95..92256420251 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -285,7 +285,10 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root, cmakeFilesSource, cmakeFilesBuild, cmakeFilesOther); QHash cmakeListsNodes = addCMakeLists(root, cmakeLists); - addProjects(cmakeListsNodes, m_projects, allFiles); + QList knownHeaders; + addProjects(cmakeListsNodes, m_projects, knownHeaders); + + addHeaderNodes(root, knownHeaders, allFiles); } void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps) @@ -575,19 +578,12 @@ static ProjectNode *createProjectNode(const QHash &cmakeListsNodes, const QList &projects, - const QList &allFiles) + QList &knownHeaderNodes) { - QHash> includeFiles; - for (const FileNode *f : allFiles) { - if (f->fileType() != FileType::Header) - continue; - includeFiles[f->filePath().parentDir()].append(f); - } - for (const Project *p : projects) { ProjectNode *pNode = createProjectNode(cmakeListsNodes, p->sourceDirectory, p->name); QTC_ASSERT(pNode, qDebug() << p->sourceDirectory.toUserOutput() ; continue); - addTargets(cmakeListsNodes, p->targets, includeFiles); + addTargets(cmakeListsNodes, p->targets, knownHeaderNodes); } } @@ -609,15 +605,15 @@ static CMakeTargetNode *createTargetNode(const QHash &cmakeListsNodes, - const QList &targets, - const QHash> &headers) +void ServerModeReader::addTargets(const QHash &cmakeListsNodes, + const QList &targets, + QList &knownHeaderNodes) { for (const Target *t : targets) { CMakeTargetNode *tNode = createTargetNode(cmakeListsNodes, t->sourceDirectory, t->name); - QTC_ASSERT(tNode, qDebug() << "No target node for" << t->sourceDirectory << t->name; return); + QTC_ASSERT(tNode, qDebug() << "No target node for" << t->sourceDirectory << t->name; continue); tNode->setTargetInformation(t->artifacts, t->type); - addFileGroups(tNode, t->sourceDirectory, t->buildDirectory, t->fileGroups, headers); + addFileGroups(tNode, t->sourceDirectory, t->buildDirectory, t->fileGroups, knownHeaderNodes); } } @@ -625,7 +621,7 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot, const Utils::FileName &sourceDirectory, const Utils::FileName &buildDirectory, const QList &fileGroups, - const QHash> &headers) + QList &knownHeaderNodes) { QList toList; QSet alreadyListed; @@ -635,30 +631,14 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot, alreadyListed.insert(fn); return count != alreadyListed.count(); }); - const QList newFileNodes = Utils::transform(newSources, [f](const Utils::FileName &fn) { - return new FileNode(fn, Node::fileTypeForFileName(fn), f->isGenerated); + const QList newFileNodes + = Utils::transform(newSources, [f, &knownHeaderNodes](const Utils::FileName &fn) { + auto node = new FileNode(fn, Node::fileTypeForFileName(fn), f->isGenerated); + if (node->fileType() == FileType::Header) + knownHeaderNodes.append(node); + return node; }); toList.append(newFileNodes); - - // Add scanned header files: - const FileNameList headerPaths = headers.keys(); - for (const IncludePath *i : f->includePaths) { - for (const FileName &hp : headerPaths) { - if (hp != i->path && hp != sourceDirectory && !hp.isChildOf(i->path)) - continue; - const QList &headerFiles = headers.value(hp); - const QList unseenHeaders = Utils::filtered(headerFiles, [&alreadyListed](const FileNode *fn) { - const int count = alreadyListed.count(); - alreadyListed.insert(fn->filePath()); - return count != alreadyListed.count(); - }); - toList.append(Utils::transform(unseenHeaders, [](const FileNode *fn) { - auto copy = new FileNode(fn->filePath(), fn->fileType(), fn->isGenerated()); - copy->setEnabled(false); - return copy; - })); - } - } } // Split up files in groups (based on location): @@ -679,5 +659,29 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot, addCMakeVFolder(targetRoot, Utils::FileName(), 10, tr(""), otherFileNodes); } +void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList knownHeaders, + const QList &allFiles) +{ + auto headerNode = new VirtualFolderNode(root->filePath(), Node::DefaultPriority - 5); + headerNode->setDisplayName(tr("")); + root->addNode(headerNode); + + // knownHeaders are already listed in their targets: + QSet seenHeaders = Utils::transform(knownHeaders, &FileNode::filePath); + + // Add scanned headers: + for (const FileNode *fn : allFiles) { + if (fn->fileType() != FileType::Header || !fn->filePath().isChildOf(root->filePath())) + continue; + const int count = seenHeaders.count(); + seenHeaders.insert(fn->filePath()); + if (seenHeaders.count() != count) { + auto node = new FileNode(*fn); + node->setEnabled(false); + headerNode->addNestedNode(node); + } + } +} + } // namespace Internal } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h index 7eb831df8ec..01c98182ea3 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.h +++ b/src/plugins/cmakeprojectmanager/servermodereader.h @@ -117,15 +117,18 @@ private: addCMakeLists(CMakeProjectNode *root, const QList &cmakeLists); void addProjects(const QHash &cmakeListsNodes, const QList &projects, - const QList &allFiles); + QList &knownHeaderNodes); void addTargets(const QHash &cmakeListsNodes, const QList &targets, - const QHash> &headers); + QList &knownHeaderNodes); void addFileGroups(ProjectExplorer::ProjectNode *targetRoot, const Utils::FileName &sourceDirectory, - const Utils::FileName &buildDirectory, - const QList &fileGroups, - const QHash> &headers); + const Utils::FileName &buildDirectory, const QList &fileGroups, + QList &knowHeaderNodes); + + void addHeaderNodes(ProjectExplorer::ProjectNode *root, + const QList knownHeaders, + const QList &allFiles); bool m_hasData = false; diff --git a/src/plugins/coreplugin/diffservice.h b/src/plugins/coreplugin/diffservice.h index 3b282170ddc..25f2d698487 100644 --- a/src/plugins/coreplugin/diffservice.h +++ b/src/plugins/coreplugin/diffservice.h @@ -37,6 +37,7 @@ class CORE_EXPORT DiffService public: virtual ~DiffService() {} + virtual void diffFiles(const QString &leftFileName, const QString &rightFileName) = 0; virtual void diffModifiedFiles(const QStringList &fileNames) = 0; }; diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 0683a66ef4d..44c010ba8f2 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -604,6 +604,9 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileN } } + if (skipOpeningBigTextFile(fileName)) + return nullptr; + IEditor *editor = 0; auto overrideCursor = Utils::OverrideCursor(QCursor(Qt::WaitCursor)); @@ -2618,9 +2621,6 @@ EditorManager::ExternalEditorList IEditor *EditorManager::openEditor(const QString &fileName, Id editorId, OpenEditorFlags flags, bool *newEditor) { - if (EditorManagerPrivate::skipOpeningBigTextFile(fileName)) - return 0; - if (flags & EditorManager::OpenInOtherSplit) EditorManager::gotoOtherSplit(); @@ -2631,9 +2631,6 @@ IEditor *EditorManager::openEditor(const QString &fileName, Id editorId, IEditor *EditorManager::openEditorAt(const QString &fileName, int line, int column, Id editorId, OpenEditorFlags flags, bool *newEditor) { - if (EditorManagerPrivate::skipOpeningBigTextFile(fileName)) - return 0; - if (flags & EditorManager::OpenInOtherSplit) EditorManager::gotoOtherSplit(); diff --git a/src/plugins/cpptools/modelmanagertesthelper.cpp b/src/plugins/cpptools/modelmanagertesthelper.cpp index f347cd81af4..9eebbee15d3 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.cpp +++ b/src/plugins/cpptools/modelmanagertesthelper.cpp @@ -36,7 +36,9 @@ using namespace CppTools::Internal; using namespace CppTools::Tests; -TestProject::TestProject(const QString &name, QObject *parent) : m_name (name) +TestProject::TestProject(const QString &name, QObject *parent) : + ProjectExplorer::Project("x-binary/foo", Utils::FileName()), + m_name(name) { setParent(parent); setId(Core::Id::fromString(name)); diff --git a/src/plugins/cpptools/semantichighlighter.cpp b/src/plugins/cpptools/semantichighlighter.cpp index 91bf57b3f70..d29a8db354c 100644 --- a/src/plugins/cpptools/semantichighlighter.cpp +++ b/src/plugins/cpptools/semantichighlighter.cpp @@ -138,7 +138,7 @@ static TextStyles mixinStyle(TextStyle main, TextStyle mixin) { TextStyles res; res.mainStyle = main; - res.mixinStyles.fillWithZero(); + res.mixinStyles.initializeElements(); res.mixinStyles.push_back(mixin); return res; } diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 2692cdf7594..3531e882a68 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -1210,7 +1210,7 @@ void CdbEngine::activateFrame(int index) stackHandler()->setCurrentIndex(index); gotoLocation(frame); if (m_pythonVersion > 0x030000) - runCommand({".frame " + QString::number(index), NoFlags}); + runCommand({".frame 0x" + QString::number(index, 16), NoFlags}); updateLocals(); } diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index e324d60aa35..be04222148c 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -426,6 +426,22 @@ DiffEditorServiceImpl::DiffEditorServiceImpl(QObject *parent) : { } +void DiffEditorServiceImpl::diffFiles(const QString &leftFileName, const QString &rightFileName) +{ + const QString documentId = Constants::DIFF_EDITOR_PLUGIN + + QLatin1String(".DiffFiles.") + leftFileName + QLatin1Char('.') + rightFileName; + const QString title = tr("Diff Files"); + auto const document = qobject_cast( + DiffEditorController::findOrCreateDocument(documentId, title)); + if (!document) + return; + + if (!DiffEditorController::controller(document)) + new DiffExternalFilesController(document, leftFileName, rightFileName); + EditorManager::activateEditorForDocument(document); + document->reload(); +} + void DiffEditorServiceImpl::diffModifiedFiles(const QStringList &fileNames) { const QString documentId = Constants::DIFF_EDITOR_PLUGIN diff --git a/src/plugins/diffeditor/diffeditorplugin.h b/src/plugins/diffeditor/diffeditorplugin.h index 688ba1ccfc3..848de9b6cf6 100644 --- a/src/plugins/diffeditor/diffeditorplugin.h +++ b/src/plugins/diffeditor/diffeditorplugin.h @@ -44,6 +44,7 @@ class DiffEditorServiceImpl : public QObject, public Core::DiffService public: explicit DiffEditorServiceImpl(QObject *parent = nullptr); + void diffFiles(const QString &leftFileName, const QString &rightFileName) override; void diffModifiedFiles(const QStringList &fileNames) override; }; diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index 7c6954bd89c..d125b588894 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -157,11 +157,11 @@ private: // //////////////////////////////////////////////////////////////////////////////////// -GenericProject::GenericProject(const Utils::FileName &fileName) - : m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this)) +GenericProject::GenericProject(const Utils::FileName &fileName) : + Project(Constants::GENERICMIMETYPE, fileName, [this]() { refresh(Everything); }), + m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this)) { setId(Constants::GENERICPROJECT_ID); - setDocument(new GenericProjectFile(this, fileName, GenericProject::Everything)); setProjectContext(Context(GenericProjectManager::Constants::PROJECTCONTEXT)); setProjectLanguages(Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); @@ -174,14 +174,15 @@ GenericProject::GenericProject(const Utils::FileName &fileName) m_includesFileName = QFileInfo(dir, projectName + ".includes").absoluteFilePath(); m_configFileName = QFileInfo(dir, projectName + ".config").absoluteFilePath(); - m_filesIDocument = new GenericProjectFile(this, FileName::fromString(m_filesFileName), GenericProject::Files); - m_includesIDocument = new GenericProjectFile(this, FileName::fromString(m_includesFileName), GenericProject::Configuration); - m_configIDocument = new GenericProjectFile(this, FileName::fromString(m_configFileName), GenericProject::Configuration); - - DocumentManager::addDocument(document()); - DocumentManager::addDocument(m_filesIDocument); - DocumentManager::addDocument(m_includesIDocument); - DocumentManager::addDocument(m_configIDocument); + m_filesIDocument + = new ProjectDocument(Constants::GENERICMIMETYPE, FileName::fromString(m_filesFileName), + [this]() { refresh(Files); }); + m_includesIDocument + = new ProjectDocument(Constants::GENERICMIMETYPE, FileName::fromString(m_includesFileName), + [this]() { refresh(Configuration); }); + m_configIDocument + = new ProjectDocument(Constants::GENERICMIMETYPE, FileName::fromString(m_configFileName), + [this]() { refresh(Configuration); }); } GenericProject::~GenericProject() diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h index 2b05eaf9bb1..118ec01f41f 100644 --- a/src/plugins/genericprojectmanager/genericproject.h +++ b/src/plugins/genericprojectmanager/genericproject.h @@ -32,8 +32,6 @@ namespace CppTools { class CppProjectUpdater; } namespace GenericProjectManager { namespace Internal { -class GenericProjectFile; - class GenericProject : public ProjectExplorer::Project { Q_OBJECT @@ -76,9 +74,9 @@ private: QString m_filesFileName; QString m_includesFileName; QString m_configFileName; - GenericProjectFile *m_filesIDocument; - GenericProjectFile *m_includesIDocument; - GenericProjectFile *m_configIDocument; + ProjectExplorer::ProjectDocument *m_filesIDocument; + ProjectExplorer::ProjectDocument *m_includesIDocument; + ProjectExplorer::ProjectDocument *m_configIDocument; QStringList m_rawFileList; QStringList m_files; QHash m_rawListEntries; diff --git a/src/plugins/help/helpwidget.cpp b/src/plugins/help/helpwidget.cpp index 8951536cfe3..3c0d14eca07 100644 --- a/src/plugins/help/helpwidget.cpp +++ b/src/plugins/help/helpwidget.cpp @@ -52,9 +52,6 @@ #include #include -#include -#include -#include #include #include #include diff --git a/src/plugins/help/textbrowserhelpviewer.cpp b/src/plugins/help/textbrowserhelpviewer.cpp index d002c5cf983..6d77aeadb69 100644 --- a/src/plugins/help/textbrowserhelpviewer.cpp +++ b/src/plugins/help/textbrowserhelpviewer.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp index 35795954ebb..39c8ac3e80f 100644 --- a/src/plugins/nim/project/nimproject.cpp +++ b/src/plugins/nim/project/nimproject.cpp @@ -54,12 +54,9 @@ namespace Nim { const int MIN_TIME_BETWEEN_PROJECT_SCANS = 4500; -NimProject::NimProject(const FileName &fileName) +NimProject::NimProject(const FileName &fileName) : Project(Constants::C_NIM_MIMETYPE, fileName) { setId(Constants::C_NIMPROJECT_ID); - auto doc = new TextEditor::TextDocument; - doc->setFilePath(fileName); - setDocument(doc); m_projectScanTimer.setSingleShot(true); connect(&m_projectScanTimer, &QTimer::timeout, this, &NimProject::collectProjectFiles); diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp index 1f4f87cf03e..d428b0bef30 100644 --- a/src/plugins/projectexplorer/buildstep.cpp +++ b/src/plugins/projectexplorer/buildstep.cpp @@ -115,6 +115,7 @@ BuildStep::BuildStep(BuildStepList *bsl, Core::Id id) : ProjectConfiguration(bsl, id), m_enabled(true) { Q_ASSERT(bsl); + ctor(); } BuildStep::BuildStep(BuildStepList *bsl, BuildStep *bs) : @@ -122,6 +123,15 @@ BuildStep::BuildStep(BuildStepList *bsl, BuildStep *bs) : { Q_ASSERT(bsl); setDisplayName(bs->displayName()); + ctor(); +} + +void BuildStep::ctor() +{ + Utils::MacroExpander *expander = macroExpander(); + expander->setDisplayName(tr("Build Step")); + expander->setAccumulating(true); + expander->registerSubProvider([this] { return projectConfiguration()->macroExpander(); }); } bool BuildStep::fromMap(const QVariantMap &map) diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h index c1c6949edec..bd907d9ddec 100644 --- a/src/plugins/projectexplorer/buildstep.h +++ b/src/plugins/projectexplorer/buildstep.h @@ -95,6 +95,8 @@ signals: void enabledChanged(); private: + void ctor(); + bool m_enabled; }; diff --git a/src/plugins/projectexplorer/processstep.cpp b/src/plugins/projectexplorer/processstep.cpp index 2cae277a6d8..9b95a0870c1 100644 --- a/src/plugins/projectexplorer/processstep.cpp +++ b/src/plugins/projectexplorer/processstep.cpp @@ -30,6 +30,8 @@ #include "target.h" #include "kit.h" +#include + #include #include @@ -204,6 +206,7 @@ ProcessStepConfigWidget::ProcessStepConfigWidget(ProcessStep *step) : connect(m_ui.commandArgumentsLineEdit, &QLineEdit::textEdited, this, &ProcessStepConfigWidget::commandArgumentsLineEditTextEdited); + Core::VariableChooser::addSupportForChildWidgets(this, m_step->macroExpander()); } void ProcessStepConfigWidget::updateDetails() diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index cf01c42801e..578cc033ec8 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -37,6 +37,7 @@ #include "settingsaccessor.h" #include +#include #include #include #include @@ -84,19 +85,54 @@ const char PLUGIN_SETTINGS_KEY[] = "ProjectExplorer.Project.PluginSettings"; namespace ProjectExplorer { +// -------------------------------------------------------------------- +// ProjectDocument: +// -------------------------------------------------------------------- + +ProjectDocument::ProjectDocument(const QString &mimeType, const Utils::FileName &fileName, + const ProjectDocument::ProjectCallback &callback) : + m_callback(callback) +{ + setFilePath(fileName); + setMimeType(mimeType); + if (m_callback) + Core::DocumentManager::addDocument(this); +} + +Core::IDocument::ReloadBehavior +ProjectDocument::reloadBehavior(Core::IDocument::ChangeTrigger state, + Core::IDocument::ChangeType type) const +{ + Q_UNUSED(state); + Q_UNUSED(type); + return BehaviorSilent; +} + +bool ProjectDocument::reload(QString *errorString, Core::IDocument::ReloadFlag flag, + Core::IDocument::ChangeType type) +{ + Q_UNUSED(errorString); + Q_UNUSED(flag); + Q_UNUSED(type); + + if (m_callback) + m_callback(); + return true; +} + // ------------------------------------------------------------------------- // Project // ------------------------------------------------------------------------- class ProjectPrivate { public: - ProjectPrivate(Project *owner) : m_containerNode(owner) {} + ProjectPrivate(Core::IDocument *document) : m_document(document) { } ~ProjectPrivate(); Core::Id m_id; Core::IDocument *m_document = nullptr; ProjectNode *m_rootProjectNode = nullptr; - ContainerNode m_containerNode; + ContainerNode *m_containerNode = nullptr; QList m_targets; Target *m_activeTarget = nullptr; EditorConfiguration m_editorConfiguration; @@ -118,15 +154,22 @@ ProjectPrivate::~ProjectPrivate() m_rootProjectNode = nullptr; delete oldNode; + delete m_containerNode; + delete m_document; delete m_accessor; } -Project::Project() : d(new ProjectPrivate(this)) +Project::Project(const QString &mimeType, const Utils::FileName &fileName, + const ProjectDocument::ProjectCallback &callback) : + d(new ProjectPrivate(new ProjectDocument(mimeType, fileName, callback))) { d->m_macroExpander.setDisplayName(tr("Project")); d->m_macroExpander.registerVariable("Project:Name", tr("Project Name"), [this] { return displayName(); }); + + // Only set up containernode after d is set so that it will find the project directory! + d->m_containerNode = new ContainerNode(this); } Project::~Project() @@ -417,13 +460,6 @@ void Project::setId(Core::Id id) d->m_id = id; } -void Project::setDocument(Core::IDocument *doc) -{ - QTC_ASSERT(doc, return); - QTC_ASSERT(!d->m_document, return); - d->m_document = doc; -} - void Project::setRootProjectNode(ProjectNode *root) { if (d->m_rootProjectNode == root) @@ -442,7 +478,7 @@ void Project::setRootProjectNode(ProjectNode *root) ProjectNode *oldNode = d->m_rootProjectNode; d->m_rootProjectNode = root; if (root) - root->setParentFolderNode(&d->m_containerNode); + root->setParentFolderNode(d->m_containerNode); ProjectTree::emitSubtreeChanged(root); emit fileListChanged(); @@ -571,7 +607,7 @@ ProjectNode *Project::rootProjectNode() const ContainerNode *Project::containerNode() const { - return &d->m_containerNode; + return d->m_containerNode; } Project::RestoreResult Project::fromMap(const QVariantMap &map, QString *errorMessage) diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index f5f5fc49fd3..343643b2813 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -30,6 +30,7 @@ #include "kit.h" #include +#include #include @@ -38,11 +39,7 @@ #include -namespace Core { -class IDocument; -class Context; -} - +namespace Core { class Context; } namespace Utils { class MacroExpander; } namespace ProjectExplorer { @@ -58,6 +55,24 @@ class ProjectPrivate; class Session; class Target; +// Auto-registers with the DocumentManager if a callback is set! +class PROJECTEXPLORER_EXPORT ProjectDocument : public Core::IDocument +{ +public: + using ProjectCallback = std::function; + + ProjectDocument(const QString &mimeType, const Utils::FileName &fileName, + const ProjectCallback &callback = {}); + + Core::IDocument::ReloadBehavior reloadBehavior(Core::IDocument::ChangeTrigger state, + Core::IDocument::ChangeType type) const final; + bool reload(QString *errorString, Core::IDocument::ReloadFlag flag, + Core::IDocument::ChangeType type) final; + +private: + ProjectCallback m_callback; +}; + // Documentation inside. class PROJECTEXPLORER_EXPORT Project : public QObject { @@ -73,7 +88,8 @@ public: EnabledRole }; - Project(); + Project(const QString &mimeType, const Utils::FileName &fileName, + const ProjectDocument::ProjectCallback &callback = {}); ~Project() override; virtual QString displayName() const = 0; @@ -116,8 +132,8 @@ public: GeneratedFiles = 0x2, AllFiles = SourceFiles | GeneratedFiles }; - virtual QStringList files(FilesMode fileMode, - const std::function &filter = {}) const; + QStringList files(FilesMode fileMode, + const std::function &filter = {}) const; virtual QStringList filesGeneratedFrom(const QString &sourceFile) const; static QString makeUnique(const QString &preferredName, const QStringList &usedNames); @@ -178,7 +194,6 @@ protected: void setPreferredKitPredicate(const Kit::Predicate &predicate); void setId(Core::Id id); - void setDocument(Core::IDocument *doc); // takes ownership! void setRootProjectNode(ProjectNode *root); // takes ownership! void setProjectContext(Core::Context context); void setProjectLanguages(Core::Context language); diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 126bc193078..7f1764e4144 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -115,7 +115,10 @@ #include #include #include +#include #include +#include +#include #include #include @@ -211,6 +214,7 @@ const char REMOVEFILE[] = "ProjectExplorer.RemoveFile"; const char DUPLICATEFILE[] = "ProjectExplorer.DuplicateFile"; const char DELETEFILE[] = "ProjectExplorer.DeleteFile"; const char RENAMEFILE[] = "ProjectExplorer.RenameFile"; +const char DIFFFILE[] = "ProjectExplorer.DiffFile"; const char SETSTARTUP[] = "ProjectExplorer.SetStartup"; const char PROJECTTREE_COLLAPSE_ALL[] = "ProjectExplorer.CollapseAll"; @@ -255,6 +259,17 @@ static Kit *currentKit() return target ? target->kit() : nullptr; } +static bool isTextFile(const QString &fileName) +{ + return Utils::mimeTypeForFile(fileName).inherits( + TextEditor::Constants::C_TEXTEDITOR_MIMETYPE_TEXT); +} + +static bool isDiffServiceAvailable() +{ + return ExtensionSystem::PluginManager::getObject(); +} + class ProjectExplorerPluginPrivate : public QObject { Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::ProjectExplorerPlugin) @@ -303,6 +318,7 @@ public: void duplicateFile(); void deleteFile(); void handleRenameFile(); + void handleDiffFile(); void handleSetStartupProject(); void setStartupProject(ProjectExplorer::Project *project); @@ -375,6 +391,7 @@ public: QAction *m_removeProjectAction; QAction *m_deleteFileAction; QAction *m_renameFileAction; + QAction *m_diffFileAction; QAction *m_openFileAction; QAction *m_projectTreeCollapseAllAction; QAction *m_searchOnFileSystem; @@ -1063,6 +1080,12 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er cmd = ActionManager::registerAction(dd->m_renameFileAction, Constants::RENAMEFILE, projecTreeContext); mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER); + + // diff file action + dd->m_diffFileAction = new QAction(tr("Diff Against Current File"), this); + cmd = ActionManager::registerAction(dd->m_diffFileAction, Constants::DIFFFILE, projecTreeContext); + mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER); + // Not yet used by anyone, so hide for now // mfolder->addAction(cmd, Constants::G_FOLDER_FILES); // msubProject->addAction(cmd, Constants::G_FOLDER_FILES); @@ -1302,6 +1325,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd, &ProjectExplorerPluginPrivate::deleteFile); connect(dd->m_renameFileAction, &QAction::triggered, dd, &ProjectExplorerPluginPrivate::handleRenameFile); + connect(dd->m_diffFileAction, &QAction::triggered, + dd, &ProjectExplorerPluginPrivate::handleDiffFile); connect(dd->m_setStartupProjectAction, &QAction::triggered, dd, &ProjectExplorerPluginPrivate::handleSetStartupProject); connect(dd->m_projectTreeCollapseAllAction, &QAction::triggered, @@ -2097,7 +2122,7 @@ static QString pathOrDirectoryFor(Node *node, bool dir) while ((!fi.exists() || !fi.isDir()) && !fi.isRoot()) fi.setFile(fi.absolutePath()); location = fi.absoluteFilePath(); - } else { + } else if (!path.isEmpty()) { QFileInfo fi = path.toFileInfo(); // remove any /suffixes, which e.g. ResourceNode uses // Note this should be removed again by making node->path() a true path again @@ -2884,6 +2909,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions() m_duplicateFileAction->setEnabled(false); m_deleteFileAction->setEnabled(false); m_renameFileAction->setEnabled(false); + m_diffFileAction->setEnabled(false); m_addExistingFilesAction->setVisible(true); m_addExistingDirectoryAction->setVisible(true); @@ -2894,6 +2920,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions() m_duplicateFileAction->setVisible(false); m_deleteFileAction->setVisible(true); m_runActionContextMenu->setVisible(false); + m_diffFileAction->setVisible(isDiffServiceAvailable()); m_openTerminalHere->setVisible(true); m_showInGraphicalShell->setVisible(true); @@ -2961,6 +2988,10 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions() m_removeFileAction->setVisible(!enableDelete || enableRemove); m_renameFileAction->setEnabled(actions.contains(Rename)); + const bool currentNodeIsTextFile = isTextFile( + ProjectTree::currentNode()->filePath().toString()); + m_diffFileAction->setEnabled(isDiffServiceAvailable() + && currentNodeIsTextFile && TextEditor::TextDocument::currentTextDocument()); m_duplicateFileAction->setVisible(actions.contains(DuplicateFile)); m_duplicateFileAction->setEnabled(actions.contains(DuplicateFile)); @@ -3244,6 +3275,39 @@ void ProjectExplorerPluginPrivate::handleRenameFile() } } +void ProjectExplorerPluginPrivate::handleDiffFile() +{ + // current editor's file + auto textDocument = TextEditor::TextDocument::currentTextDocument(); + + if (!textDocument) + return; + + const QString leftFileName = textDocument->filePath().toString(); + + if (leftFileName.isEmpty()) + return; + + // current item's file + Node *currentNode = ProjectTree::currentNode(); + QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return); + + FileNode *fileNode = currentNode->asFileNode(); + + if (!fileNode) + return; + + const QString rightFileName = currentNode->filePath().toString(); + if (rightFileName.isEmpty()) + return; + + if (!isTextFile(rightFileName)) + return; + + if (auto diffService = ExtensionSystem::PluginManager::getObject()) + diffService->diffFiles(leftFileName, rightFileName); +} + void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath) { const QString oldFilePath = node->filePath().toFileInfo().absoluteFilePath(); diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index f3fa5565b9d..45c78f72ca0 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -266,7 +266,8 @@ FileType Node::fileTypeForMimeType(const Utils::MimeType &mt) FileType Node::fileTypeForFileName(const Utils::FileName &file) { - return fileTypeForMimeType(Utils::mimeTypeForFile(file.toString())); + return fileTypeForMimeType(Utils::mimeTypeForFile(file.toString(), + Utils::MimeMatchMode::MatchExtension)); } /*! @@ -793,7 +794,7 @@ bool FolderNode::isEmpty() const } ContainerNode::ContainerNode(Project *project) - : FolderNode(Utils::FileName(), NodeType::Project), m_project(project) + : FolderNode(project->projectDirectory(), NodeType::Project), m_project(project) {} QString ContainerNode::displayName() const diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index 967c5f58a61..1e97696fb3f 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -116,37 +116,6 @@ private: QHash m_rawListEntries; }; -class PythonProjectFile : public Core::IDocument -{ -public: - PythonProjectFile(PythonProject *parent, const FileName &fileName) : m_project(parent) - { - setId("Generic.ProjectFile"); - setMimeType(PythonMimeType); - setFilePath(fileName); - } - - ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override - { - Q_UNUSED(state) - Q_UNUSED(type) - return BehaviorSilent; - } - - bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override - { - Q_UNUSED(errorString) - Q_UNUSED(flag) - if (type == TypePermissions) - return true; - m_project->refresh(); - return true; - } - -private: - PythonProject *m_project; -}; - class PythonProjectNode : public ProjectNode { public: @@ -406,12 +375,10 @@ private: } }; -PythonProject::PythonProject(const FileName &fileName) +PythonProject::PythonProject(const FileName &fileName) : + Project(Constants::C_PY_MIMETYPE, fileName, [this]() { refresh(); }) { setId(PythonProjectId); - setDocument(new PythonProjectFile(this, fileName)); - DocumentManager::addDocument(document()); - setProjectContext(Context(PythonProjectContext)); setProjectLanguages(Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); } diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 56c326896ea..5e1abd4c3a1 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -28,7 +28,6 @@ #include "qbsbuildconfiguration.h" #include "qbslogsink.h" #include "qbspmlogging.h" -#include "qbsprojectfile.h" #include "qbsprojectparser.h" #include "qbsprojectmanagerconstants.h" #include "qbsnodes.h" @@ -117,6 +116,7 @@ private: // -------------------------------------------------------------------- QbsProject::QbsProject(const FileName &fileName) : + Project(Constants::MIME_TYPE, fileName, [this]() { delayParsing(); }), m_qbsProjectParser(0), m_qbsUpdateFutureInterface(0), m_parsingScheduled(false), @@ -128,8 +128,6 @@ QbsProject::QbsProject(const FileName &fileName) : m_parsingDelay.setInterval(1000); // delay parsing by 1s. setId(Constants::PROJECT_ID); - setDocument(new QbsProjectFile(this, fileName)); - DocumentManager::addDocument(document()); setProjectContext(Context(Constants::PROJECT_ID)); setProjectLanguages(Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); @@ -710,9 +708,9 @@ void QbsProject::updateDocuments(const QSet &files) } QSet toAdd; foreach (const QString &f, filesToAdd) - toAdd.insert(new QbsProjectFile(this, FileName::fromString(f))); + toAdd.insert(new ProjectDocument(Constants::MIME_TYPE, FileName::fromString(f), + [this]() { delayParsing(); })); - DocumentManager::addDocuments(toAdd.toList()); m_qbsDocuments.unite(toAdd); } diff --git a/src/plugins/qbsprojectmanager/qbsprojectfile.cpp b/src/plugins/qbsprojectmanager/qbsprojectfile.cpp deleted file mode 100644 index 59dbff968fc..00000000000 --- a/src/plugins/qbsprojectmanager/qbsprojectfile.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "qbsprojectfile.h" - -#include "qbsproject.h" -#include "qbsprojectmanagerconstants.h" - -namespace QbsProjectManager { -namespace Internal { - -QbsProjectFile::QbsProjectFile(QbsProject *parent, const Utils::FileName &fileName) : Core::IDocument(parent), - m_project(parent) -{ - setId("Qbs.ProjectFile"); - setMimeType(Constants::MIME_TYPE); - setFilePath(fileName); -} - -Core::IDocument::ReloadBehavior QbsProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const -{ - Q_UNUSED(state); - Q_UNUSED(type); - return BehaviorSilent; -} - -bool QbsProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type) -{ - Q_UNUSED(errorString) - Q_UNUSED(flag) - if (type == TypePermissions) - return true; - m_project->delayParsing(); - return true; -} - -} // namespace Internal -} // namespace QbsProjectManager - diff --git a/src/plugins/qbsprojectmanager/qbsprojectfile.h b/src/plugins/qbsprojectmanager/qbsprojectfile.h deleted file mode 100644 index b0879fcee25..00000000000 --- a/src/plugins/qbsprojectmanager/qbsprojectfile.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -namespace QbsProjectManager { -namespace Internal { - -class QbsProject; - -class QbsProjectFile : public Core::IDocument -{ -public: - QbsProjectFile(QbsProject *parent, const Utils::FileName &fileName); - - ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override; - bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; - -private: - QbsProject *m_project; -}; - -} // namespace Internal -} // namespace QbsProjectManager diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro index de973943d69..465bad1d2ca 100644 --- a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro +++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro @@ -34,7 +34,6 @@ HEADERS = \ qbspmlogging.h \ qbsprofilessettingspage.h \ qbsproject.h \ - qbsprojectfile.h \ qbsprojectmanager.h \ qbsprojectmanager_global.h \ qbsprojectmanagerconstants.h \ @@ -59,7 +58,6 @@ SOURCES = \ qbspmlogging.cpp \ qbsprofilessettingspage.cpp \ qbsproject.cpp \ - qbsprojectfile.cpp \ qbsprojectmanager.cpp \ qbsprojectmanagerplugin.cpp \ qbsprojectmanagersettings.cpp \ diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs index 8bbbfaf7662..120a3cae3bd 100644 --- a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs +++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs @@ -94,8 +94,6 @@ QtcPlugin { "qbsprofilessettingswidget.ui", "qbsproject.cpp", "qbsproject.h", - "qbsprojectfile.cpp", - "qbsprojectfile.h", "qbsprojectmanager.cpp", "qbsprojectmanager.h", "qbsprojectmanager.qrc", diff --git a/src/plugins/qmakeprojectmanager/makestep.cpp b/src/plugins/qmakeprojectmanager/makestep.cpp index c2a2315b519..de4666461ba 100644 --- a/src/plugins/qmakeprojectmanager/makestep.cpp +++ b/src/plugins/qmakeprojectmanager/makestep.cpp @@ -32,6 +32,7 @@ #include "qmakebuildconfiguration.h" #include "qmakeprojectmanagerconstants.h" +#include #include #include #include @@ -357,6 +358,8 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep) connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged, this, &MakeStepConfigWidget::updateDetails); connect(m_makeStep->target(), &Target::kitChanged, this, &MakeStepConfigWidget::updateDetails); + + Core::VariableChooser::addSupportForChildWidgets(this, m_makeStep->macroExpander()); } void MakeStepConfigWidget::activeBuildConfigurationChanged() diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp index 5abc263c6da..1611156d6b5 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp @@ -218,15 +218,6 @@ QSet QmakePriFile::files(const FileType &type) const return m_files.value(type); } -bool QmakePriFile::buildsFile(const FileName &fn) const -{ - for (auto it = m_files.constBegin(); it != m_files.constEnd(); ++it) { - if (it.value().contains(fn)) - return true; - } - return false; -} - QmakePriFile::~QmakePriFile() { watchFolders( {} ); diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.h b/src/plugins/qmakeprojectmanager/qmakeparsernodes.h index a1ad876f76a..2cad1340cc8 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.h +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.h @@ -127,7 +127,6 @@ public: void makeEmpty(); QSet files(const ProjectExplorer::FileType &type) const; - bool buildsFile(const Utils::FileName &fn) const; void update(const Internal::QmakePriFileEvalResult &result); diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 0d76e07cdb4..d2ce349211f 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -74,15 +74,6 @@ using namespace Utils; namespace QmakeProjectManager { namespace Internal { -class QmakeProjectFile : public Core::IDocument -{ -public: - explicit QmakeProjectFile(const FileName &fileName); - - ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override; - bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; -}; - /// Watches folders for QmakePriFile nodes /// use one file system watcher to watch all folders /// such minimizing system ressouce usage @@ -156,30 +147,6 @@ QDebug operator<<(QDebug d, const QmakeProjectFiles &f) return d; } -// ----------- QmakeProjectFile - -QmakeProjectFile::QmakeProjectFile(const FileName &fileName) -{ - setId("Qmake.ProFile"); - setMimeType(QmakeProjectManager::Constants::PROFILE_MIMETYPE); - setFilePath(fileName); -} - -Core::IDocument::ReloadBehavior QmakeProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const -{ - Q_UNUSED(state) - Q_UNUSED(type) - return BehaviorSilent; -} - -bool QmakeProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type) -{ - Q_UNUSED(errorString) - Q_UNUSED(flag) - Q_UNUSED(type) - return true; -} - static QList s_projects; } // namespace Internal @@ -191,12 +158,12 @@ static QList s_projects; */ QmakeProject::QmakeProject(const FileName &fileName) : + Project(QmakeProjectManager::Constants::PROFILE_MIMETYPE, fileName), m_qmakeVfs(new QMakeVfs), m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this)) { s_projects.append(this); setId(Constants::QMAKEPROJECT_ID); - setDocument(new QmakeProjectFile(fileName)); setProjectContext(Core::Context(QmakeProjectManager::Constants::PROJECT_ID)); setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); setRequiredKitPredicate(QtSupport::QtKitInformation::qtVersionPredicate()); @@ -1309,7 +1276,7 @@ void QmakeProject::testToolChain(ToolChain *tc, const Utils::FileName &path) con t->kit()->addToEnvironment(env); } - if (env.isSameExecutable(path.toString(), expected.toString())) { + if (!env.isSameExecutable(path.toString(), expected.toString())) { const QPair pair = qMakePair(expected, path); if (!m_toolChainWarnings.contains(pair)) { TaskHub::addTask(Task(Task::Warning, @@ -1345,9 +1312,9 @@ QString QmakeProject::executableFor(const QmakeProFile *file) TargetInformation ti = file->targetInformation(); QString target; - if (tc->targetAbi().os() == Abi::DarwinOS) { - if (file->variableValue(Variable::Config).contains(QLatin1String("app_bundle"))) - target = ti.target + QLatin1String(".app/Contents/MacOS/") + ti.target; + if (tc->targetAbi().os() == Abi::DarwinOS + && file->variableValue(Variable::Config).contains("app_bundle")) { + target = ti.target + ".app/Contents/MacOS/" + ti.target; } else { QString extension = file->singleVariableValue(Variable::TargetExt); target = ti.target + extension; diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 440df96c28a..25c9a34cbcc 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -634,6 +635,9 @@ QMakeStepConfigWidget::QMakeStepConfigWidget(QMakeStep *step) connect(step->target(), &Target::kitChanged, this, &QMakeStepConfigWidget::qtVersionChanged); connect(QtVersionManager::instance(), &QtVersionManager::dumpUpdatedFor, this, &QMakeStepConfigWidget::qtVersionChanged); + auto chooser = new Core::VariableChooser(m_ui->qmakeAdditonalArgumentsLineEdit); + chooser->addMacroExpanderProvider([step] { return step->macroExpander(); }); + chooser->addSupportedWidget(m_ui->qmakeAdditonalArgumentsLineEdit); } QMakeStepConfigWidget::~QMakeStepConfigWidget() diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp index ddc8cefe976..4c58c15dc1f 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp @@ -208,11 +208,8 @@ QString QmlObjectNode::stripedTranslatableText(const PropertyName &name) const if (regularExpressionPatter.exactMatch(modelNode().bindingProperty(name).expression())) return regularExpressionPatter.cap(2); return instanceValue(name).toString(); - } else { - return modelNode().variantProperty(name).value().toString(); } - - return QString(); + return modelNode().variantProperty(name).value().toString(); } QString QmlObjectNode::expression(const PropertyName &name) const diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 3bebbc0b8ff..33056bf9bec 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -199,7 +199,7 @@ void DesignModeWidget::enableWidgets() { if (debug) qDebug() << Q_FUNC_INFO; - hideWarningWidget(); + viewManager().enableWidgets(); m_isDisabled = false; } @@ -221,20 +221,6 @@ void DesignModeWidget::switchTextOrForm() m_centralTabWidget->switchTo(viewManager().widget("TextEditor")); } -void DesignModeWidget::showWarningMessageBox(const QList &warnings) -{ - Q_ASSERT(!warnings.isEmpty()); - warningWidget()->setWarnings(warnings); - warningWidget()->setVisible(true); -} - -bool DesignModeWidget::gotoCodeWasClicked() -{ - if (m_warningWidget) - return warningWidget()->gotoCodeWasClicked(); - return false; -} - static void hideToolButtons(QList &buttons) { foreach (QToolButton *button, buttons) @@ -528,28 +514,6 @@ QWidget *DesignModeWidget::createCrumbleBarFrame() return frame; } -DocumentWarningWidget *DesignModeWidget::warningWidget() -{ - if (m_warningWidget.isNull()) { - m_warningWidget = new DocumentWarningWidget(this); - connect(m_warningWidget.data(), &DocumentWarningWidget::gotoCodeClicked, [=] - (const QString &filePath, int codeLine, int codeColumn) { - Q_UNUSED(filePath); - - if (currentDesignDocument() && currentDesignDocument()->textEditor()) - currentDesignDocument()->textEditor()->gotoLine(codeLine, codeColumn); - Core::ModeManager::activateMode(Core::Constants::MODE_EDIT); - }); - } - return m_warningWidget; -} - -void DesignModeWidget::hideWarningWidget() -{ - if (m_warningWidget) - m_warningWidget->setVisible(false); -} - CrumbleBar *DesignModeWidget::crumbleBar() const { return m_crumbleBar; diff --git a/src/plugins/qmldesigner/designmodewidget.h b/src/plugins/qmldesigner/designmodewidget.h index fd37ad48c8c..50a8fd64611 100644 --- a/src/plugins/qmldesigner/designmodewidget.h +++ b/src/plugins/qmldesigner/designmodewidget.h @@ -78,9 +78,6 @@ public: void disableWidgets(); void switchTextOrForm(); - void showWarningMessageBox(const QList &warnings); - bool gotoCodeWasClicked(); - CrumbleBar* crumbleBar() const; void showInternalTextEditor(); @@ -100,12 +97,9 @@ private: // functions void addNavigatorHistoryEntry(const Utils::FileName &fileName); QWidget *createCenterWidget(); QWidget *createCrumbleBarFrame(); - DocumentWarningWidget *warningWidget(); - void hideWarningWidget(); private: // variables QSplitter *m_mainSplitter = nullptr; - QPointer m_warningWidget; SwitchSplitTabWidget* m_centralTabWidget = nullptr; QScopedPointer m_leftSideBar; diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 366e69bd641..b7eb2ce63e3 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -138,11 +138,6 @@ static bool warningsForQmlFilesInsteadOfUiQmlEnabled() return DesignerSettings::getValue(DesignerSettingsKey::WARNING_FOR_QML_FILES_INSTEAD_OF_UIQML_FILES).toBool(); } -static bool showWarningsForFeaturesInDesigner() -{ - return DesignerSettings::getValue(DesignerSettingsKey::WARNING_FOR_FEATURES_IN_DESIGNER).toBool(); -} - QmlDesignerPlugin::QmlDesignerPlugin() { m_instance = this; @@ -329,13 +324,7 @@ void QmlDesignerPlugin::showDesigner() void QmlDesignerPlugin::hideDesigner() { - if (currentDesignDocument() && currentModel()) { - // the message box handle the cursor jump itself - } - if (d->documentManager.hasCurrentDesignDocument()) { - if (currentModel() && !mainWidget()->gotoCodeWasClicked()) - jumpTextCursorToSelectedModelNode(); deactivateAutoSynchronization(); d->mainWidget->saveSettings(); } @@ -417,8 +406,6 @@ void QmlDesignerPlugin::activateAutoSynchronization() selectModelNodeUnderTextCursor(); d->mainWidget->setupNavigatorHistory(currentDesignDocument()->textEditor()); - if (showWarningsForFeaturesInDesigner() && currentDesignDocument()->hasQmlParseWarnings()) - d->mainWidget->showWarningMessageBox(currentDesignDocument()->qmlParseWarnings()); currentDesignDocument()->updateSubcomponentManager(); } diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 4edfad3ee45..dc08e78b635 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -511,7 +511,6 @@ void QmlProfilerModelManager::processingDone() ++d->numFinishedFinalizers; } - d->notesModel->loadData(); setState(Done); } diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp index c8b9b3ec5f3..22fad39df91 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -108,6 +108,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag case QmlProfilerModelManager::Empty: d->m_modelProxy->setModels(d->m_suspendedModels); d->m_suspendedModels.clear(); + d->m_modelManager->notesModel()->loadData(); break; case QmlProfilerModelManager::ProcessingData: break; diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 43fbe6ab561..601f153582f 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -24,7 +24,6 @@ ****************************************************************************/ #include "qmlproject.h" -#include "qmlprojectfile.h" #include "fileformat/qmlprojectfileformat.h" #include "fileformat/qmlprojectitem.h" #include "qmlprojectrunconfiguration.h" @@ -56,12 +55,10 @@ using namespace ProjectExplorer; namespace QmlProjectManager { QmlProject::QmlProject(const Utils::FileName &fileName) : + Project(QString::fromLatin1(Constants::QMLPROJECT_MIMETYPE), fileName, [this]() { refreshProjectFile(); }), m_defaultImport(UnknownImport) { setId("QmlProjectManager.QmlProject"); - setDocument(new Internal::QmlProjectFile(this, fileName)); - DocumentManager::addDocument(document(), true); - setProjectContext(Context(QmlProjectManager::Constants::PROJECTCONTEXT)); setProjectLanguages(Context(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID)); } diff --git a/src/plugins/qmlprojectmanager/qmlprojectfile.cpp b/src/plugins/qmlprojectmanager/qmlprojectfile.cpp deleted file mode 100644 index 3794f1d11a9..00000000000 --- a/src/plugins/qmlprojectmanager/qmlprojectfile.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "qmlprojectfile.h" -#include "qmlproject.h" -#include "qmlprojectconstants.h" -#include - -namespace QmlProjectManager { -namespace Internal { - -QmlProjectFile::QmlProjectFile(QmlProject *parent, const Utils::FileName &fileName) : - m_project(parent) -{ - QTC_CHECK(m_project); - QTC_CHECK(!fileName.isEmpty()); - setId("Qml.ProjectFile"); - setMimeType(QLatin1String(Constants::QMLPROJECT_MIMETYPE)); - setFilePath(fileName); -} - -Core::IDocument::ReloadBehavior QmlProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const -{ - Q_UNUSED(state) - Q_UNUSED(type) - return BehaviorSilent; -} - -bool QmlProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type) -{ - Q_UNUSED(errorString) - Q_UNUSED(flag) - - if (type == TypeContents) - m_project->refreshProjectFile(); - - return true; -} - -} // namespace Internal -} // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlprojectfile.h b/src/plugins/qmlprojectmanager/qmlprojectfile.h deleted file mode 100644 index 90805fa018f..00000000000 --- a/src/plugins/qmlprojectmanager/qmlprojectfile.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -namespace QmlProjectManager { - -class QmlProject; - -namespace Internal { - -class QmlProjectFile : public Core::IDocument -{ -public: - QmlProjectFile(QmlProject *parent, const Utils::FileName &fileName); - - ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override; - bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; - -private: - QmlProject *m_project; -}; - -} // namespace Internal -} // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.pro b/src/plugins/qmlprojectmanager/qmlprojectmanager.pro index a28281a17d4..2a12d7a6313 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectmanager.pro +++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.pro @@ -9,7 +9,6 @@ HEADERS += qmlproject.h \ qmlprojectplugin.h \ qmlprojectconstants.h \ qmlprojectnodes.h \ - qmlprojectfile.h \ qmlprojectrunconfiguration.h \ qmlprojectrunconfigurationfactory.h \ qmlprojectmanager_global.h \ @@ -20,7 +19,6 @@ SOURCES += qmlproject.cpp \ qmlprojectenvironmentaspect.cpp \ qmlprojectplugin.cpp \ qmlprojectnodes.cpp \ - qmlprojectfile.cpp \ qmlprojectrunconfiguration.cpp \ qmlprojectrunconfigurationfactory.cpp \ qmlprojectrunconfigurationwidget.cpp diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs index a033afb3382..b6dcdcd5f5a 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs +++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs @@ -18,7 +18,6 @@ QtcPlugin { "qmlproject.qrc", "qmlprojectconstants.h", "qmlprojectenvironmentaspect.cpp", "qmlprojectenvironmentaspect.h", - "qmlprojectfile.cpp", "qmlprojectfile.h", "qmlprojectmanager_global.h", "qmlprojectmanagerconstants.h", "qmlprojectnodes.cpp", "qmlprojectnodes.h", diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index a6280978f7b..707d87a97a4 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -291,6 +291,11 @@ QMap TextDocument::openedTextDocumentEncodings() return workingCopy; } +TextDocument *TextDocument::currentTextDocument() +{ + return qobject_cast(EditorManager::currentDocument()); +} + QString TextDocument::plainText() const { return document()->toPlainText(); diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 4bb466382ca..38719dd8486 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -65,6 +65,7 @@ public: static QMap openedTextDocumentContents(); static QMap openedTextDocumentEncodings(); + static TextDocument *currentTextDocument(); virtual QString plainText() const; virtual QString textAt(int pos, int length) const; diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index b7b2f6057bd..7f5cd801f82 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -6152,7 +6152,6 @@ void tst_Dumpers::dumper_data() "Derived d;\n" "Base *b = &d;\n" "unused(&d, &b);\n") - + NoCdbEngine // FIXME + Check("b.@1.a", "a", "21", "int") + Check("b.b", "b", "42", "int"); @@ -6185,8 +6184,6 @@ void tst_Dumpers::dumper_data() "unused(&c);\n" "Base2 *b2 = &d; // This has the right address\n" "unused(&b2);\n") - + NoCdbEngine // FIXME - + Check("c.b2.@1.foo", "42", "int") + Check("c.b2.@2.bar", "43", "int") + Check("c.b2.baz", "84", "int") diff --git a/tests/auto/timeline/timelinerenderer/tst_timelinerenderer.cpp b/tests/auto/timeline/timelinerenderer/tst_timelinerenderer.cpp index f2a88005e09..b657cb0649b 100644 --- a/tests/auto/timeline/timelinerenderer/tst_timelinerenderer.cpp +++ b/tests/auto/timeline/timelinerenderer/tst_timelinerenderer.cpp @@ -137,16 +137,16 @@ void tst_TimelineRenderer::mouseEvents() model.loadData(); testMouseEvents(&renderer, 1, 1); - QCOMPARE(renderer.selectedItem(), 3); + QCOMPARE(renderer.selectedItem(), 2); QCOMPARE(renderer.selectionLocked(), true); model.setExpanded(true); testMouseEvents(&renderer, 1, 1); - QCOMPARE(renderer.selectedItem(), 3); + QCOMPARE(renderer.selectedItem(), 2); QCOMPARE(renderer.selectionLocked(), true); // Don't toggle locked status by clicking same item renderer.setSelectionLocked(false); testMouseEvents(&renderer, 1, 1); - QCOMPARE(renderer.selectedItem(), 3); + QCOMPARE(renderer.selectedItem(), 2); QCOMPARE(renderer.selectionLocked(), false); renderer.setSelectionLocked(true); testMouseEvents(&renderer, 1, 40); @@ -157,7 +157,7 @@ void tst_TimelineRenderer::mouseEvents() QCOMPARE(renderer.selectedItem(), -1); QCOMPARE(renderer.selectionLocked(), false); testMouseEvents(&renderer, 10, 1); - QCOMPARE(renderer.selectedItem(), 19); + QCOMPARE(renderer.selectedItem(), 14); QCOMPARE(renderer.selectionLocked(), false); renderer.setSelectionLocked(true);