From 6fdb34994c48e6dc5da9f1751b85fd9b2f8a049f Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 8 Mar 2021 13:31:42 +0200 Subject: [PATCH 01/16] QmlDesigner: Ensure item library content is visible Make sure the ScrollView content area is visible after content size changes. Fixes: QDS-3795 Change-Id: I1f7408db9ad318a5c54b5186569dd04235a3d952 Reviewed-by: Mahmoud Badri --- .../qmldesigner/itemLibraryQmlSources/ItemsView.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml index a93bc173a81..2923451de50 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml @@ -87,6 +87,12 @@ ScrollView { itemContextMenu.close() } + onContentHeightChanged: { + var maxPosition = Math.max(contentHeight - height, 0) + if (contentY > maxPosition) + contentY = maxPosition + } + Item { id: styleConstants property int textWidth: 58 From d37f6648f3a7821e15ad22a2e35f901a8b078bdb Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 8 Mar 2021 17:01:40 +0200 Subject: [PATCH 02/16] QmlDesigner: Preserve item library expand state Section and category visibility updates always expanded section or category. Now this forced expansion is only done when searching for items. Fixes: QDS-3811 Change-Id: I006124a92086c4851d54407c4ffba0e9c94a854d Reviewed-by: Mahmoud Badri --- .../components/itemlibrary/itemlibrarycategoriesmodel.cpp | 1 + .../components/itemlibrary/itemlibrarycategory.cpp | 4 ++-- .../components/itemlibrary/itemlibrarycategory.h | 2 +- .../components/itemlibrary/itemlibraryimport.cpp | 4 ++-- .../components/itemlibrary/itemlibraryimport.h | 2 +- .../components/itemlibrary/itemlibrarymodel.cpp | 8 ++++---- .../qmldesigner/components/itemlibrary/itemlibrarymodel.h | 2 +- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp index 1cc032090e2..3176d1ebb70 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp @@ -102,6 +102,7 @@ void ItemLibraryCategoriesModel::expandCategories(bool expand) for (const auto &category : std::as_const(m_categoryList)) { if (category->categoryExpanded() != expand) { category->setExpanded(expand); + ItemLibraryModel::saveExpandedState(expand, category->categoryName()); emit dataChanged(index(i), index(i), {m_roleNames.key("categoryExpanded")}); } ++i; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.cpp index 55ef88a97c6..1c5b8bfcb5f 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.cpp @@ -60,7 +60,7 @@ QObject *ItemLibraryCategory::itemModel() return &m_itemModel; } -bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *changed) +bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *changed, bool expand) { bool hasVisibleItems = false; @@ -81,7 +81,7 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool * } // expand category if it has an item matching search criteria - if (hasVisibleItems && !categoryExpanded()) + if (expand && hasVisibleItems && !categoryExpanded()) setExpanded(true); return hasVisibleItems; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.h index ad3f1579a00..d99d4ea4dc5 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.h @@ -50,7 +50,7 @@ public: void addItem(ItemLibraryItem *item); QObject *itemModel(); - bool updateItemVisibility(const QString &searchText, bool *changed); + bool updateItemVisibility(const QString &searchText, bool *changed, bool expand = false); bool setVisible(bool isVisible); bool isVisible() const; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp index 649d879895d..d0a87013dd8 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp @@ -95,14 +95,14 @@ void ItemLibraryImport::expandCategories(bool expand) m_categoryModel.expandCategories(expand); } -bool ItemLibraryImport::updateCategoryVisibility(const QString &searchText, bool *changed) +bool ItemLibraryImport::updateCategoryVisibility(const QString &searchText, bool *changed, bool expand) { bool hasVisibleCategories = false; *changed = false; for (const auto &category : m_categoryModel.categorySections()) { bool categoryChanged = false; - bool hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged); + bool hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged, expand); categoryChanged |= category->setVisible(hasVisibleItems); *changed |= categoryChanged; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h index 8993dfcb8b6..ed60c1cffe2 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h @@ -67,7 +67,7 @@ public: void addCategory(ItemLibraryCategory *category); QObject *categoryModel(); - bool updateCategoryVisibility(const QString &searchText, bool *changed); + bool updateCategoryVisibility(const QString &searchText, bool *changed, bool expand = false); bool setVisible(bool isVisible); void setImportUsed(bool importUsed); void sortCategorySections(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp index 4def2f46dc3..e7276750386 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp @@ -163,7 +163,7 @@ void ItemLibraryModel::setSearchText(const QString &searchText) m_searchText = lowerSearchText; bool changed = false; - updateVisibility(&changed); + updateVisibility(&changed, !m_searchText.isEmpty()); } } @@ -374,18 +374,18 @@ void ItemLibraryModel::updateUsedImports(const QList &usedImports) } } -void ItemLibraryModel::updateVisibility(bool *changed) +void ItemLibraryModel::updateVisibility(bool *changed, bool expand) { for (ItemLibraryImport *import : std::as_const(m_importList)) { bool categoryChanged = false; - bool hasVisibleItems = import->updateCategoryVisibility(m_searchText, &categoryChanged); + bool hasVisibleItems = import->updateCategoryVisibility(m_searchText, &categoryChanged, expand); *changed |= categoryChanged; if (import->sectionType() == ItemLibraryImport::SectionType::Unimported) *changed |= import->setVisible(!m_searchText.isEmpty()); // expand import if it has an item matching search criteria - if (hasVisibleItems && !import->importExpanded()) + if (expand && hasVisibleItems && !import->importExpanded()) import->setImportExpanded(); } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h index 2412550a3a0..8d592e29cc4 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h @@ -72,7 +72,7 @@ public: Import entryToImport(const ItemLibraryEntry &entry); private: - void updateVisibility(bool *changed); + void updateVisibility(bool *changed, bool expand = false); void addRoleNames(); void sortSections(); void clearSections(); From 89646aadce9037bbd990f752c85b777e488d988e Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Feb 2021 12:38:44 +0100 Subject: [PATCH 03/16] Utils: Don't raise SIGSTOP in the process stub Previously, the starting inferior was sent a SIGSTOP to avoid progress before the debugger could attach. However, these signals are then also visible in the debugger and need to be ignored as part of the startup handling in Creator. The waiting effect can be achieved less intrusively by waiting on a pipe read between fork() and exec(). Task-number: QTCREATORBUG-25073 Task-number: QTCREATORBUG-25082 Task-number: QTCREATORBUG-25227 Change-Id: Ie70b9eb5ea865f85411c26b0dbf377a019fec8d5 Reviewed-by: Eike Ziller Reviewed-by: Christian Stenger --- share/qtcreator/debugger/lldbbridge.py | 11 -------- src/libs/utils/consoleprocess.cpp | 12 +++++++++ src/libs/utils/consoleprocess.h | 1 + src/libs/utils/process_stub_unix.c | 36 +++++++++++++++++++------- src/plugins/debugger/gdb/gdbengine.cpp | 25 +++--------------- src/plugins/debugger/terminal.cpp | 5 ++++ src/plugins/debugger/terminal.h | 1 + 7 files changed, 50 insertions(+), 41 deletions(-) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index e1e0222d02b..c83b349e80a 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -904,14 +904,6 @@ class Dumper(DumperBase): except: # Could have been deleted in the mean time. pass - self.ignoreStops = 0 - if platform.system() == 'Linux': - if self.startMode_ == DebuggerStartMode.AttachCore: - pass - else: - if self.useTerminal_: - self.ignoreStops = 1 - if self.platform_: self.debugger.SetCurrentPlatform(self.platform_) # sysroot has to be set *after* the platform @@ -1450,9 +1442,6 @@ class Dumper(DumperBase): if self.isInterrupting_: self.isInterrupting_ = False self.reportState("inferiorstopok") - elif self.ignoreStops > 0: - self.ignoreStops -= 1 - self.process.Continue() else: self.reportState("stopped") else: diff --git a/src/libs/utils/consoleprocess.cpp b/src/libs/utils/consoleprocess.cpp index bd6f6231b8c..18f6a73e6da 100644 --- a/src/libs/utils/consoleprocess.cpp +++ b/src/libs/utils/consoleprocess.cpp @@ -611,6 +611,18 @@ bool ConsoleProcess::start() return true; } +void Utils::ConsoleProcess::kickoffProcess() +{ +#ifdef Q_OS_WIN + // Not used. +#else + if (d->m_stubSocket && d->m_stubSocket->isWritable()) { + d->m_stubSocket->write("c", 1); + d->m_stubSocket->flush(); + } +#endif +} + void ConsoleProcess::interruptProcess() { #ifdef Q_OS_WIN diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h index ce53e0d87c7..16373fe76e0 100644 --- a/src/libs/utils/consoleprocess.h +++ b/src/libs/utils/consoleprocess.h @@ -90,6 +90,7 @@ public: bool isRunning() const; // This reflects the state of the console+stub qint64 applicationPID() const; + void kickoffProcess(); void interruptProcess(); void killProcess(); void killStub(); diff --git a/src/libs/utils/process_stub_unix.c b/src/libs/utils/process_stub_unix.c index 271404fe3bb..d7a7ff15b09 100644 --- a/src/libs/utils/process_stub_unix.c +++ b/src/libs/utils/process_stub_unix.c @@ -57,6 +57,7 @@ extern char **environ; static int qtcFd; static char *sleepMsg; static int chldPipe[2]; +static int blockingPipe[2]; static int isDebug; static volatile int isDetached; static volatile int chldPid; @@ -236,10 +237,21 @@ int main(int argc, char *argv[]) perror("Cannot create status pipe"); doExit(3); } + /* The debugged program is not supposed to inherit these handles. But we cannot * close the writing end before calling exec(). Just handle both ends the same way ... */ fcntl(chldPipe[0], F_SETFD, FD_CLOEXEC); fcntl(chldPipe[1], F_SETFD, FD_CLOEXEC); + + if (isDebug) { + /* Create execution start notification pipe. The child waits on this until + the parent writes to it, triggered by an 'c' message from Creator */ + if (pipe(blockingPipe)) { + perror("Cannot create blocking pipe"); + doExit(3); + } + } + switch ((chldPid = fork())) { case -1: perror("Cannot fork child process"); @@ -262,9 +274,15 @@ int main(int argc, char *argv[]) #ifdef __linux__ prctl(PR_SET_PTRACER, atoi(argv[ArgPid])); #endif - /* Stop the child to allow the debugger to attach */ - if (isDebug) - kill(chldPid, SIGSTOP); + /* Block to allow the debugger to attach */ + if (isDebug) { + char buf; + int res = read(blockingPipe[0], &buf, 1); + if (res < 0) + perror("Could not read from blocking pipe"); + close(blockingPipe[0]); + close(blockingPipe[1]); + } if (env) environ = env; @@ -296,6 +314,7 @@ int main(int argc, char *argv[]) break; } else { int i; + char c = 'i'; for (i = 0; i < nbytes; ++i) { switch (buffer[i]) { case 'k': @@ -305,13 +324,12 @@ int main(int argc, char *argv[]) kill(chldPid, SIGKILL); } break; - case 'i': - if (chldPid > 0) { - int res = kill(chldPid, SIGINT); - if (res) - perror("Stub could not interrupt inferior"); - } + case 'c': { + int res = write(blockingPipe[1], &c, 1); + if (res < 0) + perror("Could not write to blocking pipe"); break; + } case 'd': isDetached = 1; break; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 42ee110f7e8..3d5c6c07188 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1147,26 +1147,6 @@ void GdbEngine::handleStopResponse(const GdbMi &data) return; } - // Ignore signals from the process stub. - const GdbMi frame = data["frame"]; - if (terminal() - && data["reason"].data() == "signal-received" - && data["signal-name"].data() == "SIGSTOP") - { - const QString from = frame["from"].data(); - const QString func = frame["func"].data(); - if (from.endsWith("/ld-linux.so.2") - || from.endsWith("/ld-linux-x86-64.so.2") - || func == "clone" - || func == "kill") - { - showMessage("INTERNAL CONTINUE AFTER SIGSTOP FROM STUB", LogMisc); - notifyInferiorSpontaneousStop(); - continueInferiorInternal(); - return; - } - } - if (!m_onStop.isEmpty()) { notifyInferiorStopOk(); showMessage("HANDLING QUEUED COMMANDS AFTER TEMPORARY STOP", LogMisc); @@ -1184,6 +1164,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data) QString fullName; QString function; QString language; + const GdbMi frame = data["frame"]; if (frame.isValid()) { const GdbMi lineNumberG = frame["line"]; function = frame["function"].data(); // V4 protocol @@ -4919,7 +4900,9 @@ void GdbEngine::handleStubAttached(const DebuggerResponse &response, qint64 main notifyEngineRunAndInferiorStopOk(); continueInferiorInternal(); } else { - showMessage("INFERIOR ATTACHED AND RUNNING"); + showMessage("INFERIOR ATTACHED"); + QTC_ASSERT(terminal(), return); + terminal()->kickoffProcess(); //notifyEngineRunAndInferiorRunOk(); // Wait for the upcoming *stopped and handle it there. } diff --git a/src/plugins/debugger/terminal.cpp b/src/plugins/debugger/terminal.cpp index c54336c0456..24b1f72f23d 100644 --- a/src/plugins/debugger/terminal.cpp +++ b/src/plugins/debugger/terminal.cpp @@ -183,6 +183,11 @@ TerminalRunner::TerminalRunner(RunControl *runControl, const Runnable &stubRunna this, [this] { reportDone(); }); } +void TerminalRunner::kickoffProcess() +{ + m_stubProc.kickoffProcess(); +} + void TerminalRunner::interruptProcess() { m_stubProc.interruptProcess(); diff --git a/src/plugins/debugger/terminal.h b/src/plugins/debugger/terminal.h index 410d0fb7d91..ceacf3fddd7 100644 --- a/src/plugins/debugger/terminal.h +++ b/src/plugins/debugger/terminal.h @@ -77,6 +77,7 @@ public: qint64 applicationPid() const { return m_applicationPid; } qint64 applicationMainThreadId() const { return m_applicationMainThreadId; } + void kickoffProcess(); void interruptProcess(); void setRunAsRoot(bool on); From 33cafa0dcf5a931482f1da47b4b740ce0350ea2f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 4 Mar 2021 12:52:22 +0100 Subject: [PATCH 04/16] LLDB: Drop secondary lookup of native types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although already tried to lookup a native type with an lldb internal mechanism we still tried to do it "manually" again. This secondary approach was needed at some point when lldb had no integrated way to lookup a type inside all modules. Lookups done manually will not provide a better result than the lldb internal one. The error output generated with this blocks debugging which makes QC unusable at this state. So, remove the secondary lookup completely. Fixes: QTCREATORBUG-25185 Fixes: QTCREATORBUG-25217 Change-Id: Ibd8a125a89633c611bf750e0f1759c639717e1d2 Reviewed-by: Tor Arne Vestbø Reviewed-by: hjk --- share/qtcreator/debugger/lldbbridge.py | 38 +------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index ababe4a362c..022d766fbf8 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -844,39 +844,7 @@ class Dumper(DumperBase): if typeobj is not None: return typeobj - return self.lookupNativeTypeInAllModules(name) - - def lookupNativeTypeInAllModules(self, name): - needle = self.canonicalTypeName(name) - #DumperBase.warn('NEEDLE: %s ' % needle) - DumperBase.warn('Searching for type %s across all target modules, this could be very slow' % name) - for i in range(self.target.GetNumModules()): - module = self.target.GetModuleAtIndex(i) - # SBModule.GetType is new somewhere after early 300.x - # So this may fail. - for t in module.GetTypes(): - n = self.canonicalTypeName(t.GetName()) - #DumperBase.warn('N: %s' % n) - if n == needle: - #DumperBase.warn('FOUND TYPE DIRECT 2: %s ' % t) - self.typeCache[name] = t - return t - if n == needle + '*': - res = t.GetPointeeType() - self.typeCache[name] = res - x = self.fromNativeType(res) # Register under both names - self.registerTypeAlias(x.typeId, name) - #DumperBase.warn('FOUND TYPE BY POINTER: %s ' % res.name) - return res - if n == needle + '&': - res = t.GetDereferencedType().GetUnqualifiedType() - self.typeCache[name] = res - x = self.fromNativeType(res) # Register under both names - self.registerTypeAlias(x.typeId, name) - #DumperBase.warn('FOUND TYPE BY REFERENCE: %s ' % res.name) - return res - #DumperBase.warn('NOT FOUND: %s ' % needle) - return None + return lldb.SBType() def setupInferior(self, args): """ Set up SBTarget instance """ @@ -2086,10 +2054,6 @@ class SummaryDumper(Dumper, LogMixin): def report(self, stuff): return # Don't mess up lldb output - def lookupNativeTypeInAllModules(self, name): - self.warn('Failed to resolve type %s' % name) - return None - def dump_summary(self, valobj, expanded=False): try: from pygdbmi import gdbmiparser From 8e7a3ae4a639449dfc679bd8ca3d2f00493e586f Mon Sep 17 00:00:00 2001 From: Tuomo Pelkonen Date: Wed, 24 Feb 2021 09:02:49 +0200 Subject: [PATCH 05/16] QmlDesigner: draw FormEditorItem bounding rectangle Draw red rectangle around FormEditorItems Optimize drawing using square root based sizes Task-number: QDS-2241 Change-Id: Iedd11b7e50f23e2d8c5a26ad5f7da62756ad426e Reviewed-by: Thomas Hartmann --- .../components/formeditor/formeditoritem.cpp | 173 ++++++++++++------ .../components/formeditor/formeditoritem.h | 7 +- 2 files changed, 120 insertions(+), 60 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp index 055e5cf8a7a..2c388bb6d9c 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -57,8 +58,8 @@ const int blockRadius = 18; const int blockAdjust = 40; const int startItemOffset = 96; -const qreal fontSize = 10; // points -const qreal zoomLevelLabel = 0.5; // Everything lower than that will hide all labels +const qreal labelFontSize = 10; +const qreal labelShowThreshold = 0.25; // Everything lower than that will hide all labels const qreal defaultDpi = 96.0; void drawIcon(QPainter *painter, @@ -627,12 +628,68 @@ void FormEditorFlowItem::updateGeometry() } } +void FormEditorFlowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + FormEditorItem::paint(painter, option, widget); + + if (!painter->isActive()) + return; + + if (!qmlItemNode().isValid()) + return; + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + + QPen pen; + pen.setJoinStyle(Qt::MiterJoin); + + QColor flowColor(0xe71919); + + if (qmlItemNode().rootModelNode().hasAuxiliaryData("areaColor")) + flowColor = qmlItemNode().rootModelNode().auxiliaryData("areaColor").value(); + + if (qmlItemNode().modelNode().hasAuxiliaryData("color")) + flowColor = qmlItemNode().modelNode().auxiliaryData("color").value(); + + pen.setColor(flowColor); + + qreal width = 2; + +// if (qmlItemNode().modelNode().hasAuxiliaryData("width")) +// width = qmlItemNode().modelNode().auxiliaryData("width").toInt(); + + width *= getLineScaleFactor(); + + pen.setWidthF(width); + + + bool dash = false; + + if (qmlItemNode().modelNode().hasAuxiliaryData("dash")) + dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool(); + + if (dash) + pen.setStyle(Qt::DashLine); + else + pen.setStyle(Qt::SolidLine); + + pen.setCosmetic(false); + painter->setPen(pen); + + QColor fillColor = QColor(Qt::transparent); + painter->setBrush(fillColor); + + painter->drawRoundedRect(boundingRect(), blockRadius, blockRadius); + + painter->restore(); +} + QPointF FormEditorFlowItem::instancePosition() const { return qmlItemNode().flowPosition(); } - void FormEditorFlowActionItem::setDataModelPosition(const QPointF &position) { qmlItemNode().setPosition(position); @@ -691,7 +748,6 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi QPen pen; pen.setJoinStyle(Qt::MiterJoin); - pen.setCosmetic(true); QColor flowColor(0xe71919); @@ -706,8 +762,9 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi if (qmlItemNode().modelNode().hasAuxiliaryData("width")) width = qmlItemNode().modelNode().auxiliaryData("width").toInt(); - bool dash = false; + width *= getLineScaleFactor(); + bool dash = false; if (qmlItemNode().modelNode().hasAuxiliaryData("dash")) dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool(); @@ -719,7 +776,7 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi pen.setStyle(Qt::SolidLine); pen.setWidthF(width); - pen.setCosmetic(true); + pen.setCosmetic(false); painter->setPen(pen); QColor fillColor = QColor(Qt::transparent); @@ -867,10 +924,8 @@ class ConnectionConfiguration public: ConnectionConfiguration(const QmlItemNode &node, const ResolveConnection &resolveConnection, - const qreal scaleFactor, bool hitTest = false) : width(2) - , adjustedWidth(width / scaleFactor) , color(QColor(0xe71919)) , lineBrush(QBrush(color)) , penStyle(Qt::SolidLine) @@ -883,9 +938,10 @@ public: , breakOffset(50) , radius(8) , bezier(50) + , fontSize(labelFontSize) , type(ConnectionType::Default) , label() - , labelOffset(14 / scaleFactor) + , labelOffset(14) , labelPosition(50.0) , labelFlags(Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextDontClip) , labelFlipSide(false) @@ -895,12 +951,12 @@ public: { // width if (node.modelNode().hasAuxiliaryData("width")) - width = node.modelNode().auxiliaryData("width").toInt(); + width = node.modelNode().auxiliaryData("width").toFloat(); // adjusted width if (node.modelNode().isSelected()) width += 2; if (hitTest) - width = width * 8 / scaleFactor; + width = width * 8; // color if (resolveConnection.isStartLine) color = QColor("blue"); @@ -966,7 +1022,6 @@ public: } qreal width; - qreal adjustedWidth; QColor color; // TODO private/setter QBrush lineBrush; Qt::PenStyle penStyle; @@ -980,6 +1035,7 @@ public: int breakOffset; int radius; int bezier; + qreal fontSize; ConnectionType type; QString label; qreal labelOffset; @@ -1285,7 +1341,7 @@ public: const bool boolExitRight = fromRect.right() < toRect.center().x(); const bool boolExitBottom = fromRect.bottom() < toRect.center().y(); - const qreal padding = 8; + const int padding = 4 * config.width; if (horizontalFirst) { const qreal startX = boolExitRight ? fromRect.right() + padding : fromRect.x() - padding; @@ -1405,7 +1461,7 @@ void FormEditorTransitionItem::updateGeometry() QPixmap pixmap(640, 480); QPainter localPainter(&pixmap); QFont font = localPainter.font(); - font.setPointSizeF(getFontSize(&localPainter) / getScaleFactor()); + font.setPixelSize(labelFontSize * getTextScaleFactor()); localPainter.setFont(font); const auto fromNodes = resolved.from; @@ -1481,7 +1537,7 @@ void FormEditorTransitionItem::drawSingleLabel(QPainter *painter, const Connecti QPointF position; qreal angle; - const qreal hMargin = 10.0 / getScaleFactor(); + const qreal hMargin = 10.0 * getItemScaleFactor(); QFontMetrics metric(painter->font()); const qreal lineHeight = metric.boundingRect("Xyz").height(); @@ -1506,7 +1562,7 @@ void FormEditorTransitionItem::drawSingleLabel(QPainter *painter, const Connecti labelRect.adjust(-hMargin, 0.0, hMargin, 0.0); if (singleEvent && singleSignal) - labelRect.setHeight(eventRect.height() + signalRect.height() + (6.0 / getScaleFactor())); + labelRect.setHeight(eventRect.height() + signalRect.height() + (6.0 * getTextScaleFactor())); const qreal halfHeight = labelRect.height() * 0.5; @@ -1526,7 +1582,7 @@ void FormEditorTransitionItem::drawSingleLabel(QPainter *painter, const Connecti // Calculate font bounding box without taking into account the cale factor QFont originalFont = painter->font(); - originalFont.setPointSizeF(getFontSize(painter)); + originalFont.setPixelSize(labelFontSize * getTextScaleFactor()); QFontMetrics originalMetric(originalFont); QRectF originalTextRect = originalMetric.boundingRect(events); originalTextRect.adjust(-10.0, 0.0, 10.0, 0.0); @@ -1588,9 +1644,9 @@ void FormEditorTransitionItem::drawSingleLabel(QPainter *painter, const Connecti painter->setPen(Qt::white); if (singleEvent && singleSignal) { eventRect.setWidth(labelRect.width()); - eventRect.moveTopLeft(labelRect.topLeft() + QPointF(0.0, 4.0 / getScaleFactor())); + eventRect.moveTopLeft(labelRect.topLeft() + QPointF(0.0, 4.0 * getItemScaleFactor())); signalRect.setWidth(labelRect.width()); - signalRect.moveBottomLeft(labelRect.bottomLeft() - QPointF(0.0, 4.0 / getScaleFactor())); + signalRect.moveBottomLeft(labelRect.bottomLeft() - QPointF(0.0, 4.0 * getItemScaleFactor())); painter->drawText(eventRect, Qt::AlignCenter, events); painter->drawText(signalRect, Qt::AlignCenter, targetSignal); @@ -1619,9 +1675,8 @@ void FormEditorTransitionItem::drawSelectionLabel(QPainter *painter, const Conne const QStringList events = connection.config.events.split(','); const int eventCount = events.size(); - const qreal scaleFactor = getScaleFactor(); - const qreal radius = 7.0 / scaleFactor; - const qreal hMargin = 10.0 / scaleFactor; + const qreal radius = 7.0 * getItemScaleFactor(); + const qreal hMargin = 10.0 * getItemScaleFactor(); QFontMetrics metric(painter->font()); const qreal lineHeight = metric.boundingRect("Xyz").height(); @@ -1657,7 +1712,7 @@ void FormEditorTransitionItem::drawSelectionLabel(QPainter *painter, const Conne } const int signalCount = signalList.size(); - const qreal offset = 10.0 / scaleFactor; + const qreal offset = 10.0 * getItemScaleFactor(); qreal totalHeight = 0; if (hasEvents) @@ -1730,34 +1785,33 @@ void FormEditorTransitionItem::drawSelectionLabel(QPainter *painter, const Conne static void drawArrow(QPainter *painter, const QPointF &point, const qreal &angle, - const qreal &arrowLength, - const qreal &arrowWidth) + qreal arrowSize, + qreal arrowTipAngle = 90.0) { const QPointF peakP(0, 0); - const QPointF leftP(-arrowLength, -arrowWidth * 0.5); - const QPointF rightP(-arrowLength, arrowWidth * 0.5); + const QPointF endP(-arrowSize, 0); painter->save(); painter->translate(point); - painter->rotate(-angle); - painter->drawLine(leftP, peakP); - painter->drawLine(rightP, peakP); + painter->rotate(-angle - (arrowTipAngle/2.0)); + painter->drawLine(peakP, endP); + painter->rotate(arrowTipAngle); + painter->drawLine(peakP, endP); painter->restore(); } void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connection &connection) { - const qreal arrowLength = 4 * connection.config.adjustedWidth; - const qreal arrowWidth = 8 * connection.config.adjustedWidth; + const int arrowSize = 12 * getLineScaleFactor(); painter->save(); painter->setRenderHint(QPainter::Antialiasing); // Draw path/connection line QPen pen; - pen.setCosmetic(true); + pen.setCosmetic(false); pen.setJoinStyle(Qt::MiterJoin); pen.setCapStyle(Qt::RoundCap); pen.setBrush(connection.config.lineBrush); @@ -1769,12 +1823,12 @@ void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connecti pen.setStyle(connection.config.penStyle); } - pen.setWidthF(connection.config.width); + pen.setWidthF(connection.config.width * getLineScaleFactor()); painter->setPen(pen); painter->drawPath(connection.path); - pen.setWidthF(connection.config.width); + pen.setWidthF(connection.config.width * getLineScaleFactor()); pen.setStyle(Qt::SolidLine); pen.setColor(connection.config.color); painter->setPen(pen); @@ -1791,16 +1845,16 @@ void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connecti } if (connection.config.drawEnd) - drawArrow(painter, connection.end, angle, arrowLength, arrowWidth); + drawArrow(painter, connection.end, angle, arrowSize, 60.0); // Draw start ellipse if (connection.config.drawStart) { painter->setBrush(Qt::white); - painter->drawEllipse(connection.start, arrowLength / 2.0, arrowLength / 2.0); + painter->drawEllipse(connection.start, arrowSize / 5, arrowSize / 5); } // Draw labels - if (viewportTransform().m11() >= zoomLevelLabel) + if (viewportTransform().m11() >= labelShowThreshold) drawLabels(painter, connection); painter->restore(); @@ -1825,11 +1879,11 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi if (!isModelNodeValid(resolved.from)) return; - ConnectionConfiguration config(qmlItemNode(), resolved, viewportTransform().m11(), m_hitTest); + ConnectionConfiguration config(qmlItemNode(), resolved, m_hitTest); - QFont f = painter->font(); - f.setPointSizeF(getFontSize(painter) / getScaleFactor()); - painter->setFont(f); + QFont font = painter->font(); + font.setPixelSize(config.fontSize * getTextScaleFactor()); + painter->setFont(font); const auto fromNodes = resolved.from; const auto toNodes = resolved.to; @@ -1896,7 +1950,7 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi const QString icon = Theme::getIconUnicode(Theme::startNode); QPen pen; - pen.setCosmetic(true); + pen.setCosmetic(false); pen.setColor(config.color); painter->setPen(pen); @@ -1937,18 +1991,19 @@ QTransform FormEditorItem::viewportTransform() const return scene()->views().first()->viewportTransform(); } -qreal FormEditorItem::getFontSize(QPainter *painter) const +qreal FormEditorItem::getItemScaleFactor() const { - const int dpi = std::max(painter->device()->logicalDpiX(), - painter->device()->logicalDpiY()); - - return fontSize * (dpi / defaultDpi); + return 1.0 / viewportTransform().m11(); } -qreal FormEditorItem::getScaleFactor() const +qreal FormEditorItem::getLineScaleFactor() const { - // Cap scaling at 100% zoom - return (viewportTransform().m11() >= 1.0) ? viewportTransform().m11() : 1.0; + return 2 / qSqrt(viewportTransform().m11()); +} + +qreal FormEditorItem::getTextScaleFactor() const +{ + return 2 / qSqrt(viewportTransform().m11()); } void FormEditorFlowDecisionItem::updateGeometry() @@ -1982,7 +2037,7 @@ void FormEditorFlowDecisionItem::updateGeometry() QPixmap pixmap(640, 480); QPainter localPainter(&pixmap); QFont font = localPainter.font(); - font.setPointSizeF(getFontSize(&localPainter) / getScaleFactor()); + font.setPixelSize(labelFontSize * getTextScaleFactor()); localPainter.setFont(font); const qreal margin = blockAdjust * 0.5; @@ -2045,7 +2100,7 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap QPen pen; pen.setJoinStyle(Qt::MiterJoin); - pen.setCosmetic(true); + pen.setCosmetic(false); QColor flowColor(0xe71919); @@ -2055,24 +2110,26 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap if (qmlItemNode().modelNode().hasAuxiliaryData("color")) flowColor = qmlItemNode().modelNode().auxiliaryData("color").value(); + pen.setColor(flowColor); + qreal width = 2; if (qmlItemNode().modelNode().hasAuxiliaryData("width")) width = qmlItemNode().modelNode().auxiliaryData("width").toInt(); + width *= getLineScaleFactor(); + pen.setWidthF(width); + bool dash = false; if (qmlItemNode().modelNode().hasAuxiliaryData("dash")) dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool(); - pen.setColor(flowColor); if (dash) pen.setStyle(Qt::DashLine); else pen.setStyle(Qt::SolidLine); - pen.setWidthF(width); - pen.setCosmetic(true); painter->setPen(pen); QColor fillColor = QColor(Qt::transparent); @@ -2119,7 +2176,7 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap if (qmlItemNode().modelNode().hasAuxiliaryData("showDialogLabel")) showDialogLabel = qmlItemNode().modelNode().auxiliaryData("showDialogLabel").toBool(); - if (showDialogLabel && viewportTransform().m11() >= zoomLevelLabel) { + if (showDialogLabel && viewportTransform().m11() >= labelShowThreshold) { QString dialogTitle; if (qmlItemNode().modelNode().hasVariantProperty("dialogTitle")) dialogTitle = qmlItemNode().modelNode().variantProperty("dialogTitle").value().toString(); @@ -2127,7 +2184,7 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap if (!dialogTitle.isEmpty()) { QFont font = painter->font(); - font.setPointSizeF(getFontSize(painter) / getScaleFactor()); + font.setPixelSize(labelFontSize * getTextScaleFactor()); painter->setFont(font); QRectF textRect(0, 0, 100, 20); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h index 96031baec68..8304f1a36b7 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h @@ -128,8 +128,10 @@ protected: QList offspringFormEditorItemsRecursive(const FormEditorItem *formEditorItem) const; FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene); QTransform viewportTransform() const; - qreal getFontSize(QPainter *painter) const; - qreal getScaleFactor() const; + + qreal getItemScaleFactor() const; + qreal getLineScaleFactor() const; + qreal getTextScaleFactor() const; QRectF m_boundingRect; QRectF m_paintedBoundingRect; @@ -161,6 +163,7 @@ public: void setDataModelPositionInBaseState(const QPointF &position) override; void updateGeometry() override; QPointF instancePosition() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; protected: FormEditorFlowItem(const QmlItemNode &qmlItemNode, FormEditorScene *scene) From 29307b7b1591018ffcbade608b47803d57ed6674 Mon Sep 17 00:00:00 2001 From: Tuomo Pelkonen Date: Tue, 23 Feb 2021 11:47:14 +0200 Subject: [PATCH 06/16] QmlDesigner: Improve in-place Text element text modification When double-clicking Text -element, check if the text is rich text or not. In case of rich text, show a rich-text editor modal dialog In case of plain text, show a in-place LineEdit with correct font Task-number: QDS-2306 Change-Id: I5206c7d6c869e26ad39979106510d72626dbe800 Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/CMakeLists.txt | 1 + .../richtexteditor/richtexteditor.cpp | 6 ++ .../richtexteditor/richtexteditor.h | 3 +- .../components/texttool/textedititem.cpp | 3 + .../components/texttool/texttool.cpp | 22 ++++-- src/plugins/qmldesigner/qmldesignerplugin.pri | 6 +- src/plugins/qmldesigner/qmldesignerplugin.qbs | 2 + .../qmldesigner/richtexteditordialog.cpp | 76 +++++++++++++++++++ .../qmldesigner/richtexteditordialog.h | 56 ++++++++++++++ 9 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 src/plugins/qmldesigner/richtexteditordialog.cpp create mode 100644 src/plugins/qmldesigner/richtexteditordialog.h diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 5681c7f15d7..34ab71154fb 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -30,6 +30,7 @@ add_qtc_plugin(QmlDesigner settingspage.cpp settingspage.h settingspage.ui shortcutmanager.cpp shortcutmanager.h designermcumanager.cpp designermcumanager.h + richtexteditordialog.cpp richtexteditordialog.h EXPLICIT_MOC components/propertyeditor/propertyeditorvalue.h components/connectioneditor/connectionviewwidget.h diff --git a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp index 0732a08ad97..c58bed2995a 100644 --- a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp +++ b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp @@ -132,6 +132,8 @@ RichTextEditor::RichTextEditor(QWidget *parent) this, &RichTextEditor::currentCharFormatChanged); connect(ui->textEdit, &QTextEdit::cursorPositionChanged, this, &RichTextEditor::cursorPositionChanged); + connect(ui->textEdit, &QTextEdit::textChanged, + this, &RichTextEditor::onTextChanged); connect(m_linkDialog, &QDialog::accepted, [this]() { QTextCharFormat oldFormat = ui->textEdit->textCursor().charFormat(); @@ -223,6 +225,10 @@ void RichTextEditor::cursorPositionChanged() tableChanged(ui->textEdit->textCursor()); } +void RichTextEditor::onTextChanged() { + emit textChanged(richText()); +} + void RichTextEditor::mergeFormatOnWordOrSelection(const QTextCharFormat &format) { QTextCursor cursor = ui->textEdit->textCursor(); diff --git a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.h b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.h index a2f44dd0443..39aeb323183 100644 --- a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.h +++ b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.h @@ -69,11 +69,12 @@ public: signals: void insertingImage(QString &filePath); + void textChanged(QString text); private slots: void currentCharFormatChanged(const QTextCharFormat &format); void cursorPositionChanged(); - + void onTextChanged(); private: QIcon getIcon(Theme::Icon icon); void mergeFormatOnWordOrSelection(const QTextCharFormat &format); diff --git a/src/plugins/qmldesigner/components/texttool/textedititem.cpp b/src/plugins/qmldesigner/components/texttool/textedititem.cpp index 1ce3244cbc2..d965c4b7fd5 100644 --- a/src/plugins/qmldesigner/components/texttool/textedititem.cpp +++ b/src/plugins/qmldesigner/components/texttool/textedititem.cpp @@ -76,6 +76,9 @@ void TextEditItem::setFormEditorItem(FormEditorItem *formEditorItem) QSize maximumSize = rect.size().toSize(); activateTextEdit(maximumSize); } else { + auto lineEdit = TextEditItemWidget::lineEdit(); + auto node = m_formEditorItem->qmlItemNode(); + lineEdit->setFont(node.instanceValue("font").value()); activateLineEdit(); } diff --git a/src/plugins/qmldesigner/components/texttool/texttool.cpp b/src/plugins/qmldesigner/components/texttool/texttool.cpp index 76dc414c03f..a8b5ac044ae 100644 --- a/src/plugins/qmldesigner/components/texttool/texttool.cpp +++ b/src/plugins/qmldesigner/components/texttool/texttool.cpp @@ -36,6 +36,7 @@ #include "nodemetainfo.h" #include "qmlitemnode.h" +#include "richtexteditordialog.h" #include #include @@ -207,13 +208,22 @@ void TextTool::selectedItemsChanged(const QList &itemList) } if (!itemList.isEmpty()) { FormEditorItem *formEditorItem = itemList.constFirst(); - m_textItem = new TextEditItem(scene()); - textItem()->setParentItem(scene()->manipulatorLayerItem()); - textItem()->setFormEditorItem(formEditorItem); - connect(textItem(), &TextEditItem::returnPressed, [this] { - textItem()->writeTextToProperty(); + auto text = formEditorItem->qmlItemNode().instanceValue("text").toString(); + auto format = formEditorItem->qmlItemNode().instanceValue("format").value(); + if (format == Qt::RichText || Qt::mightBeRichText(text)) { + RichTextEditorDialog* editorDialog = new RichTextEditorDialog(text); + editorDialog->setFormEditorItem(formEditorItem); + editorDialog->show(); view()->changeToSelectionTool(); - }); + } else { + m_textItem = new TextEditItem(scene()); + textItem()->setParentItem(scene()->manipulatorLayerItem()); + textItem()->setFormEditorItem(formEditorItem); + connect(textItem(), &TextEditItem::returnPressed, [this] { + textItem()->writeTextToProperty(); + view()->changeToSelectionTool(); + }); + } } else { view()->changeToSelectionTool(); } diff --git a/src/plugins/qmldesigner/qmldesignerplugin.pri b/src/plugins/qmldesigner/qmldesignerplugin.pri index b11ff7a53b1..c7d3c1df056 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.pri +++ b/src/plugins/qmldesigner/qmldesignerplugin.pri @@ -10,7 +10,8 @@ HEADERS += $$PWD/qmldesignerconstants.h \ $$PWD/documentwarningwidget.h \ $$PWD/qmldesignericons.h \ $$PWD/openuiqmlfiledialog.h \ - $$PWD/designermcumanager.h + $$PWD/designermcumanager.h \ + $$PWD/richtexteditordialog.h SOURCES += $$PWD/qmldesignerplugin.cpp \ $$PWD/shortcutmanager.cpp \ @@ -22,7 +23,8 @@ SOURCES += $$PWD/qmldesignerplugin.cpp \ $$PWD/documentmanager.cpp \ $$PWD/documentwarningwidget.cpp \ $$PWD/openuiqmlfiledialog.cpp \ - $$PWD/designermcumanager.cpp + $$PWD/designermcumanager.cpp \ + $$PWD/richtexteditordialog.cpp FORMS += $$PWD/settingspage.ui \ $$PWD/openuiqmlfiledialog.ui diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index bd6c94cbb62..816c3d65732 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -984,6 +984,8 @@ Project { "shortcutmanager.h", "designermcumanager.cpp", "designermcumanager.h", + "richtexteditordialog.cpp", + "richtexteditordialog.h", ] } } diff --git a/src/plugins/qmldesigner/richtexteditordialog.cpp b/src/plugins/qmldesigner/richtexteditordialog.cpp new file mode 100644 index 00000000000..d51d063718c --- /dev/null +++ b/src/plugins/qmldesigner/richtexteditordialog.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "richtexteditordialog.h" +#include + +namespace QmlDesigner { + +RichTextEditorDialog::RichTextEditorDialog(QString text) +{ + m_editor = new RichTextEditor(this); + m_editor->setRichText(text); + + auto layout = new QVBoxLayout(this); + layout->addWidget(m_editor); + setLayout(layout); + + connect(m_editor, &RichTextEditor::textChanged, + this, &RichTextEditorDialog::onTextChanged); + + connect(this, &QDialog::finished, + this, &RichTextEditorDialog::onFinished); + + setModal(true); +} + +void RichTextEditorDialog::setFormEditorItem(FormEditorItem* formEditorItem) +{ + m_formEditorItem = formEditorItem; +} + +void RichTextEditorDialog::onTextChanged(QString text) +{ + Q_UNUSED(text); + // TODO: try adding following and make it react faster + // setTextToFormEditorItem(text); +} + +void RichTextEditorDialog::onFinished() +{ + setTextToFormEditorItem(m_editor->richText()); +} + +void RichTextEditorDialog::setTextToFormEditorItem(QString text) +{ + if (m_formEditorItem) { + if (text.isEmpty()) + m_formEditorItem->qmlItemNode().removeProperty("text"); + else + m_formEditorItem->qmlItemNode().setVariantProperty("text", text); + } +} + +} //namespace QmlDesigner diff --git a/src/plugins/qmldesigner/richtexteditordialog.h b/src/plugins/qmldesigner/richtexteditordialog.h new file mode 100644 index 00000000000..126be3b6a4b --- /dev/null +++ b/src/plugins/qmldesigner/richtexteditordialog.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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. +** +****************************************************************************/ + +#ifndef RICHTEXTEDITORDIALOG_H +#define RICHTEXTEDITORDIALOG_H + +#include +#include "richtexteditor/richtexteditor.h" +#include "formeditor/formeditoritem.h" + +namespace QmlDesigner { + + +class RichTextEditorDialog : public QDialog { + Q_OBJECT +public: + explicit RichTextEditorDialog(const QString text); + void setFormEditorItem(FormEditorItem* formEditorItem); + +signals: + void textChanged(QString text); +private: + RichTextEditor* m_editor; + FormEditorItem* m_formEditorItem; + +private slots: + void onTextChanged(QString text); + void onFinished(); + void setTextToFormEditorItem(QString text); +}; + +} // namespace QmlDesigner + +#endif // RICHTEXTEDITORDIALOG_H From dab168fa81b615dc0ac9b60fa76c224660556d81 Mon Sep 17 00:00:00 2001 From: Tuomo Pelkonen Date: Tue, 23 Feb 2021 12:20:22 +0200 Subject: [PATCH 07/16] QmlDesigner: Fix flow editors decision items selection area MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decision item must only be selectable from the item, not the label text. Text can overlap with other items and selection becomes unnatural if it is included in selection bounding rectangle. Task-number: QDS-3747 Change-Id: Ic5697f124cd0210f6af00b3c004ea19d0af2cd91 Reviewed-by: Henning Gründl Reviewed-by: Thomas Hartmann --- .../components/formeditor/formeditoritem.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp index 2c388bb6d9c..ac9fbab89e3 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp @@ -2015,6 +2015,7 @@ void FormEditorFlowDecisionItem::updateGeometry() size = qmlItemNode().modelNode().auxiliaryData("blockSize").toInt(); QRectF boundingRect(0, 0, size, size); + QRectF selectionRect = boundingRect; QTransform transform; if (qmlItemNode().isFlowDecision()) { transform.translate(boundingRect.center().x(), boundingRect.center().y()); @@ -2073,14 +2074,15 @@ void FormEditorFlowDecisionItem::updateGeometry() } } - // Unite the rotate item bounding rect with the label bounding rect. + // bounding rect is combination of label and icon but only icon can be clicked boundingRect = transform.mapRect(boundingRect); + selectionRect = boundingRect; boundingRect = boundingRect.united(labelBoundingRect); } - m_selectionBoundingRect = boundingRect; - m_paintedBoundingRect = m_selectionBoundingRect; - m_boundingRect = m_paintedBoundingRect; + m_selectionBoundingRect = selectionRect; + m_boundingRect = boundingRect; + m_paintedBoundingRect = boundingRect; setTransform(qmlItemNode().instanceTransformWithContentTransform()); const QPointF pos = qmlItemNode().flowPosition(); setTransform(QTransform::fromTranslate(pos.x(), pos.y())); From 20690236d7f30b1d80f7f842374ab106109d54ee Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 18 Feb 2021 17:36:36 +0100 Subject: [PATCH 08/16] Utils: Add iterator constructors to small string Change-Id: I34e15177268f0733200d25c90fd935485c3176ae Reviewed-by: Thomas Hartmann Reviewed-by: Tim Jenssen --- src/libs/sqlite/sqlitebasestatement.cpp | 2 +- src/libs/utils/smallstring.h | 15 +++++++++++---- src/libs/utils/smallstringview.h | 19 ++++++++++++++----- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/libs/sqlite/sqlitebasestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp index cd6e2f0bb21..7412473dad1 100644 --- a/src/libs/sqlite/sqlitebasestatement.cpp +++ b/src/libs/sqlite/sqlitebasestatement.cpp @@ -716,7 +716,7 @@ StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column) break; } - return StringType{"", 0}; + return {}; } } // namespace diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h index 20d4a13e811..b04a2300a37 100644 --- a/src/libs/utils/smallstring.h +++ b/src/libs/utils/smallstring.h @@ -64,8 +64,8 @@ template class BasicSmallString { public: - using iterator = Internal::SmallStringIterator; - using const_iterator = Internal::SmallStringIterator; + using iterator = SmallStringView::iterator; + using const_iterator = SmallStringView::const_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using size_type = std::size_t; @@ -113,8 +113,15 @@ public: BasicSmallString(const char *string, size_type size) : BasicSmallString(string, size, size) - { - } + {} + + explicit BasicSmallString(const_iterator begin, const_iterator end) + : BasicSmallString(SmallStringView{begin, end}) + {} + + explicit BasicSmallString(iterator begin, iterator end) + : BasicSmallString(SmallStringView{begin, end}) + {} template::value>> BasicSmallString(Type characterPointer) diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h index 5559d222322..6d3ea5d35fe 100644 --- a/src/libs/utils/smallstringview.h +++ b/src/libs/utils/smallstringview.h @@ -49,6 +49,7 @@ class SmallStringView { public: using const_iterator = Internal::SmallStringIterator; + using iterator = Internal::SmallStringIterator; using const_reverse_iterator = std::reverse_iterator; using size_type = std::size_t; @@ -62,14 +63,22 @@ public: constexpr SmallStringView(const char *const string, const size_type size) noexcept : m_pointer(string) , m_size(size) - { - } + {} - constexpr SmallStringView(const const_iterator begin, const const_iterator end) noexcept + constexpr SmallStringView(const char *const begin, const char *const end) noexcept + : m_pointer(begin) + , m_size(static_cast(std::distance(begin, end))) + {} + + constexpr SmallStringView(const_iterator begin, const_iterator end) noexcept : m_pointer(begin.data()) , m_size(std::size_t(end - begin)) - { - } + {} + + constexpr SmallStringView(iterator begin, iterator end) noexcept + : m_pointer(begin.data()) + , m_size(std::size_t(end - begin)) + {} template = 0> constexpr SmallStringView(const String &string) noexcept From 00cec8a6888b9d60fca11257cb3f4a1c998e2048 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 25 Feb 2021 09:39:31 +0100 Subject: [PATCH 09/16] QmlProjectManager: Bump up version of the multilanguage database Change-Id: I123171475f6d37241fdbe37c94725df718f5fe9f Reviewed-by: Thomas Hartmann Reviewed-by: Tim Jenssen --- src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp index e2104d7ba9b..b66aec51c28 100644 --- a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp +++ b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp @@ -47,7 +47,7 @@ static Utils::FilePath getMultilanguageDatabaseFilePath(ProjectExplorer::Target { if (target) { auto filePath = target->project()->projectDirectory().pathAppended( - "multilanguage-experimental-v3.db"); + "multilanguage-experimental-v4.db"); if (filePath.exists()) return filePath; } From 5c459be52694545e9e8bd4e5d61ac5e77a5af8a5 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 25 Feb 2021 09:51:55 +0100 Subject: [PATCH 10/16] QmlDesigner: Add Model::bindingPropertiesAboutToBeChanged It is sometime quite useful to know the old value. For example to remove it. We could add add the old values to the bindingPropertiesChanged but this would be a much larger change. Change-Id: I9b4a78602a35766c99092892b61173fc5c439978 Reviewed-by: Thomas Hartmann Reviewed-by: Tim Jenssen --- .../designercore/include/abstractview.h | 1 + .../designercore/model/abstractview.cpp | 2 ++ .../qmldesigner/designercore/model/model.cpp | 17 +++++++++++++++++ .../qmldesigner/designercore/model/model_p.h | 2 ++ 4 files changed, 22 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index 8645da77935..95bf66949f5 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -205,6 +205,7 @@ public: virtual void propertiesAboutToBeRemoved(const QList& propertyList); virtual void propertiesRemoved(const QList& propertyList); virtual void variantPropertiesChanged(const QList& propertyList, PropertyChangeFlags propertyChange); + virtual void bindingPropertiesAboutToBeChanged(const QList &propertyList); virtual void bindingPropertiesChanged(const QList& propertyList, PropertyChangeFlags propertyChange); virtual void signalHandlerPropertiesChanged(const QVector& propertyList, PropertyChangeFlags propertyChange); virtual void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion); diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index b6818d2ee67..665562a44a4 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -329,6 +329,8 @@ void AbstractView::variantPropertiesChanged(const QList& /*prop { } +void AbstractView::bindingPropertiesAboutToBeChanged(const QList &) {} + void AbstractView::bindingPropertiesChanged(const QList& /*propertyList*/, PropertyChangeFlags /*propertyChange*/) { } diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 53a1e563d42..d695be92ef2 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -767,6 +767,21 @@ void ModelPrivate::notifyNodeIdChanged(const InternalNodePointer &node, }); } +void ModelPrivate::notifyBindingPropertiesAboutToBeChanged( + const QList &internalPropertyList) +{ + notifyNodeInstanceViewLast([&](AbstractView *view) { + QList propertyList; + for (const InternalBindingPropertyPointer &bindingProperty : internalPropertyList) { + propertyList.append(BindingProperty(bindingProperty->name(), + bindingProperty->propertyOwner(), + m_model, + view)); + } + view->bindingPropertiesAboutToBeChanged(propertyList); + }); +} + void ModelPrivate::notifyBindingPropertiesChanged( const QList &internalPropertyList, AbstractView::PropertyChangeFlags propertyChange) @@ -1030,6 +1045,7 @@ void ModelPrivate::setBindingProperty(const InternalNodePointer &node, const Pro } InternalBindingPropertyPointer bindingProperty = node->bindingProperty(name); + notifyBindingPropertiesAboutToBeChanged({bindingProperty}); bindingProperty->setExpression(expression); notifyBindingPropertiesChanged({bindingProperty}, propertyChange); } @@ -1087,6 +1103,7 @@ void ModelPrivate::setDynamicBindingProperty(const InternalNodePointer &node, } InternalBindingPropertyPointer bindingProperty = node->bindingProperty(name); + notifyBindingPropertiesAboutToBeChanged({bindingProperty}); bindingProperty->setDynamicExpression(dynamicPropertyType, expression); notifyBindingPropertiesChanged({bindingProperty}, propertyChange); } diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index 7a15b73468b..cc15226265e 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -149,6 +149,8 @@ public: void notifyPropertiesRemoved(const QList &propertyList); void notifyPropertiesAboutToBeRemoved(const QList &internalPropertyList); + void notifyBindingPropertiesAboutToBeChanged( + const QList &internalPropertyList); void notifyBindingPropertiesChanged(const QList &internalPropertyList, AbstractView::PropertyChangeFlags propertyChange); void notifySignalHandlerPropertiesChanged(const QVector &propertyList, AbstractView::PropertyChangeFlags propertyChange); void notifyVariantPropertiesChanged(const InternalNodePointer &node, const PropertyNameList &propertyNameList, AbstractView::PropertyChangeFlags propertyChange); From a6f944e472326a30f6eb94a57ff388de9e9cc516 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Mon, 1 Mar 2021 16:39:53 +0100 Subject: [PATCH 11/16] Sqlite: Use emplace_back instead of push_back It does not only removes code it should be even more optimal. Change-Id: I819a7300ca798c3109b20c1e3bafcd19078faebd Reviewed-by: Tapani Mattila Reviewed-by: Thomas Hartmann Reviewed-by: Tim Jenssen --- src/libs/sqlite/sqlitebasestatement.h | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h index c6baaaf4b92..c6052e20187 100644 --- a/src/libs/sqlite/sqlitebasestatement.h +++ b/src/libs/sqlite/sqlitebasestatement.h @@ -349,7 +349,7 @@ public: bindValues(queryValues...); while (BaseStatement::next()) - pushBackToContainer(container); + emplaceBackValues(container); resetter.reset(); } @@ -448,19 +448,6 @@ private: return callCallable(callable, std::make_integer_sequence{}); } - template - void pushBackToContainer(Container &container, std::integer_sequence) - { - using Type = typename Container::value_type; - container.push_back(Type(ValueGetter(*this, ColumnIndices)...)); - } - - template - void pushBackToContainer(Container &container) - { - pushBackToContainer(container, std::make_integer_sequence{}); - } - template void bindValuesByIndex(int index, const ValueType &value) { From af41cca569d22d6f7255408f484637e03ff12a33 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Fri, 5 Mar 2021 19:47:53 +0200 Subject: [PATCH 12/16] QmlDesigner: Move new item lib qmls to the share folder ...so that theming and hot reloading can be applied. Theming isn't part of this commit. Also used icon font instead of pngs. Change-Id: I7df149fe9c07fb4c2e3deca6bcf3b0346025e3d6 Reviewed-by: Miikka Heikkinen Reviewed-by: Miina Puuronen Reviewed-by: Thomas Hartmann --- .../itemLibraryQmlSources/AddImport.qml | 4 +- .../itemLibraryQmlSources/LibraryHeader.qml | 47 ++++++++++++------ .../components/itemlibrary/images/add.png | Bin 1033 -> 0 bytes .../components/itemlibrary/images/add@2x.png | Bin 1032 -> 0 bytes .../itemlibrary/images/add_unselected.png | Bin 1025 -> 0 bytes .../itemlibrary/images/add_unselected@2x.png | Bin 1032 -> 0 bytes .../components/itemlibrary/images/down.png | Bin 209 -> 0 bytes .../components/itemlibrary/images/down@2x.png | Bin 283 -> 0 bytes .../itemlibrary/images/tab_icon.png | Bin 233 -> 0 bytes .../itemlibrary/images/tab_icon@2x.png | Bin 339 -> 0 bytes .../components/itemlibrary/itemlibrary.qrc | 10 ---- .../itemlibrary/itemlibrarywidget.cpp | 39 ++++++++------- .../itemlibrary/itemlibrarywidget.h | 14 +++--- 13 files changed, 58 insertions(+), 56 deletions(-) rename src/plugins/qmldesigner/components/itemlibrary/qml/addimport.qml => share/qtcreator/qmldesigner/itemLibraryQmlSources/AddImport.qml (97%) rename src/plugins/qmldesigner/components/itemlibrary/qml/libraryheader.qml => share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml (74%) delete mode 100644 src/plugins/qmldesigner/components/itemlibrary/images/add.png delete mode 100644 src/plugins/qmldesigner/components/itemlibrary/images/add@2x.png delete mode 100644 src/plugins/qmldesigner/components/itemlibrary/images/add_unselected.png delete mode 100644 src/plugins/qmldesigner/components/itemlibrary/images/add_unselected@2x.png delete mode 100644 src/plugins/qmldesigner/components/itemlibrary/images/down.png delete mode 100644 src/plugins/qmldesigner/components/itemlibrary/images/down@2x.png delete mode 100644 src/plugins/qmldesigner/components/itemlibrary/images/tab_icon.png delete mode 100644 src/plugins/qmldesigner/components/itemlibrary/images/tab_icon@2x.png diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/addimport.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddImport.qml similarity index 97% rename from src/plugins/qmldesigner/components/itemlibrary/qml/addimport.qml rename to share/qtcreator/qmldesigner/itemLibraryQmlSources/AddImport.qml index e73623bd7ee..53712827700 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/qml/addimport.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddImport.qml @@ -30,8 +30,6 @@ import QtQuickDesignerTheme 1.0 Column { id: root - signal addImport(int index) - Text { id: header text: qsTr("Select a Module to Add") @@ -78,7 +76,7 @@ Column { id: mouseArea anchors.fill: parent hoverEnabled: true - onClicked: addImport(index) + onClicked: rootView.handleAddImport(index) enabled: !isSeparator } } diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/libraryheader.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml similarity index 74% rename from src/plugins/qmldesigner/components/itemlibrary/qml/libraryheader.qml rename to share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml index 18587c07ff4..12052d2a3cb 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/qml/libraryheader.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml @@ -26,17 +26,14 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuickDesignerTheme 1.0 +import StudioControls 1.0 as StudioControls +import StudioTheme 1.0 as StudioTheme Item { id: root width: 200 height: 75 - signal tabChanged(int index) - signal filterChanged(string filterText) - signal addModuleClicked() - signal addAssetClicked() - function setTab(index) { tabBar.setCurrentIndex(index); @@ -86,26 +83,30 @@ Item { anchors.bottom: parent.bottom anchors.rightMargin: 2 anchors.bottomMargin: 2 - width: img.width + 10 - height: img.height + 10 + width: 25 + height: 25 color: mouseArea.containsMouse ? "#353535" : "#262626" ToolTip.delay: 500 ToolTip.text: modelData.addToolTip ToolTip.visible: mouseArea.containsMouse - Image { - id: img - source: tabBar.currentIndex === index ? "../images/add.png" - : "../images/add_unselected.png" + Label { // + sign + text: StudioTheme.Constants.plus + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter anchors.centerIn: parent + color: tabBar.currentIndex === index ? "#0094ce" : "#a8a8a8" } MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true - onClicked: index == 0 ? addModuleClicked() : addAssetClicked() + onClicked: index == 0 ? rootView.handleAddModule() + : rootView.handleAddAsset() } } @@ -117,7 +118,7 @@ Item { } } - onClicked: tabChanged(index) + onClicked: rootView.handleTabChanged(index); } } } @@ -138,16 +139,30 @@ Item { anchors.rightMargin: 5 selectByMouse: true - onTextChanged: filterChanged(text) + onTextChanged: rootView.handleSearchfilterChanged(text) - Image { // clear text button - source: "../images/x.png" + Rectangle { // x button + width: 15 + height: 15 anchors.right: parent.right anchors.rightMargin: 5 anchors.verticalCenter: parent.verticalCenter visible: searchFilterText.text !== "" + color: xMouseArea.containsMouse ? "#353535" : "transparent" + + Label { + text: StudioTheme.Constants.closeCross + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.centerIn: parent + color: "#dadada" + } MouseArea { + id: xMouseArea + hoverEnabled: true anchors.fill: parent onClicked: searchFilterText.text = "" } diff --git a/src/plugins/qmldesigner/components/itemlibrary/images/add.png b/src/plugins/qmldesigner/components/itemlibrary/images/add.png deleted file mode 100644 index 1b9edadee58798488c5c3d80f8695910f8729213..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1033 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QUiyV_#8_n4Fzj zqL7rDo|$K>^nUk#C56lsTcvPQUjyF)=hTc$kE){7;3~h6MhI|Z8xtBTx$ z+|-gpg^Jvqyke^gTP3i$R(Zu%AYpwa1+bEmY+EIWqau6*6rA&mQWebf40MwX3``Zw zE%gk|OiV2ebQFvXj12S*jr0vHbqx)zOwFxKOcbC%$xgwhC?(A*$i)q6S5Zoutx`rw zNr9EVetCJhUb(Seeo?xGK4GRy>*)Z*l#%z~24 z{5%DaiHS-1r6smXN>F1fatnNY;RfdwLjx)~KUcpZu|VHY&pC^bzP$twI7ffN?_`dYcSkaFa=fF7i>0%Hvw@SLg_D7)shJW~ZweNVL-iWs)T?i& zV51L;S)`bT2?e>hftcV#2}+=L3W$`SnwMg$RHS5Y_b^xe3bKB_-^{CjN1pf-b>h$e|Nlc~^-f}7VBjnX@(cbC1q{Ld6+#RQ3=Wg3xpK8epER||CE_q hz2(*0ou>p77?#Ph-JSUR>t#^p^mO%eS?83{1OSKlQDy)D diff --git a/src/plugins/qmldesigner/components/itemlibrary/images/add@2x.png b/src/plugins/qmldesigner/components/itemlibrary/images/add@2x.png deleted file mode 100644 index ba352300c65a368e5c1dc1f4532083412d549af3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1032 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4rT@h2A3sW#~2tGBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFe_(wn^Gtf;oFfdgx zx70HucqbpIn-onpfiKVyje}KTTSPSl>zP+vl9-pA3e%g3&})QOua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6pW1Y3>7rOGxJjN%ZoKZVG9m8E0@%w%(B!Jx1#)9 z1#sY4WnyuFfwQBrg@L(&shfcz$nlOQE|$&)&IV3~7ET7Hre;b|y(w5c4%KUjQ?I_A zf{i{XW|3kVCKTl224aE}B`AT~DIijQYF>)1QjwCq-P5;QH!(0Uhz9tCxH7Ez9ev_Y z+{r)5r~k69`K_?^&;S4bUE5;x85kJYOM?7@|APU8lsB^*0|SG*r;B4q#jT_SWd?~A zYa2RSTRGP=xv{Yw3uJZCNJvXaI2Ll?2nYKb9-cKEa>5~u%zh4Qn3}=_N}gooOj_5F gaBQLLGgb}*hIn@o-sPK$IzV~T)78&qol`;+0IX6+n*aa+ diff --git a/src/plugins/qmldesigner/components/itemlibrary/images/add_unselected.png b/src/plugins/qmldesigner/components/itemlibrary/images/add_unselected.png deleted file mode 100644 index 8e237ce4a12b1fcd36124544e5b40de1dc1f1397..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1025 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QUiyV_#8_n4Fzj zqL7rDo|$K>^nUk#C56lsTcvPQUjyF)=hTc$kE){7;3~h6MhI|Z8xtBTx$ z+|-gpg^Jvqyke^gTP3i$R(Zu%AYpwa1+bEmY+EIWqau6*6rA&mQWebf40MwX3``Zw zE%gk|OiV2ebQFvXj12S*jr0vHbqx)zOwFxKOcbC%$xgwhC?(A*$i)q6S5Zoutx`rw zNr9EVetCJhUb(Seeo?xGK4GRy>*)Z*l#%z~24 z{5%DaiHS-1r6smXN>F1fatnNY;RfdwLjx)~KUcpZu|VHY&pC^bzP$twI7ffN?_`dYcSkaFa=fF7i>0%Hvw@SLg_D7)shJW~ZweNVL-iWs)T?i& zV51L;S)`bT2?e>hftcV#2}+=L3W$`SnwMg$RHS5YcdU|aCj$e6M1W6->&A^6H*MOq za^=cn$BwOAw{FFX6~~Vs|NsAgr0bVu3=9k$B|(0{{~>_kUi02a1_lNjPZ!6Kid#tu z?#w&^vwC@b8>Wi-HZ(R)U{F@hV@wlcV{>y;Q*(1;V-riuVQM+6a7|Xi@AwB983q;! Y2CciSUtcY=dkxBzp00i_>zopr0BsFLt^fc4 diff --git a/src/plugins/qmldesigner/components/itemlibrary/images/add_unselected@2x.png b/src/plugins/qmldesigner/components/itemlibrary/images/add_unselected@2x.png deleted file mode 100644 index 8be6882f3d9e551ca2fffb958740af28d0d365fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1032 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4rT@h2A3sW#~2tGBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFe_(wn^Gtf;oFfdgx zx70HucqbpIn-onpfiKVyjezP+vl9-pA3e%g3(Cds>ua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6pW1Y3>7rOGxJjN%ZoKZVG9m8E0@%w%(B!Jx1#)9 z1#sY4WnyuFfwQBrg@L(&shfcz$nlOQE|$&)&IV3~7ET7Hre;b|y(w5c4%KUjQ?I_A zf{i{XW|3kVCKTl224aE}B`AT~DIijQYF>)1QjwCq-Ql{Htqcqdq5(c3t}9loIDY*2 zi4!MQty*>J)TzyzH~;_t|K7>9HyIch*h_-^g8zd7gOoS38v_G_yQhm|NX4zB1Z4(^ z6>A$hXU^nY&*a9&b}W$9MI#|GA>m-ifg>F3Yj}9paL5UVFf#i&tYK;j6DWC-kuzys hL&C9zuFqIG3>f0wMR-py?f(SIo1U(IF6*2UngDr4OF{qu diff --git a/src/plugins/qmldesigner/components/itemlibrary/images/down.png b/src/plugins/qmldesigner/components/itemlibrary/images/down.png deleted file mode 100644 index d2772546bc88543265a35a4b4f6578330f081347..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmeAS@N?(olHy`uVBq!ia0y~yVBle3VBp|jV_;x7`$X;|0|NtRfk$L90|U1Z2s2)~ zTla^7fuY&c#W6%;YVCxBqD=+@F7{yw!o}NJtQoyGGFv-nHS&F!qpP;>sIQ!o#qu|A z{+#iiHRTek!=-L}BjfXP{SPqDIJ?HW>v$fU8~d^kzil=4*d42$TwL~tG!7Acigu%su4`89;&xGr#Wy=X}JERNj1W8&U>B3 zZbD(7(j|<%pV{7M2|2funIXtHk5W;(ZaRt8V&;3(AK^)j%5f>Hk8q{05;$~c zxjbXcBBSje!j3OyohOo_V!rpi&WAM$%AJ#2lApQ%_Db^g$H-6mAUUtAcXwJ{Yhu*HPeEN*fg1J0lQ+HZqn$feBO@FfXt41E&D{C84 zz;rKq64RP93pdyE>w2=vP2p9##B*~OhklHhiONoGc56r1Nv99G9`q_Z^-w|(qq!x zcp_WZ{9*I9_0N~=VPIUho`qq(;!dx_QrapSwie^$ZLQ44$rjF6*2UngCtLf4l$y diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc index 69ef5b2c1f8..197dd87655b 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.qrc @@ -29,17 +29,7 @@ images/asset_sound_192.png images/asset_sound_256.png images/asset_sound_384.png - images/tab_icon.png - images/tab_icon@2x.png images/x.png images/x@2x.png - images/add.png - images/add@2x.png - images/add_unselected.png - images/add_unselected@2x.png - images/down.png - images/down@2x.png - qml/libraryheader.qml - qml/addimport.qml diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 7ce542de024..8571f7a7d4b 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -141,27 +141,19 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, // create header widget m_headerWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); - m_headerWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate)); Theme::setupTheme(m_headerWidget->engine()); - m_headerWidget->setSource(QUrl("qrc:/ItemLibrary/qml/libraryheader.qml")); - QObject::connect(m_headerWidget->rootObject(), SIGNAL(tabChanged(int)), this, - SLOT(handleTabChanged(int))); - QObject::connect(m_headerWidget->rootObject(), SIGNAL(filterChanged(QString)), this, - SLOT(handleFilterChanged(QString))); - QObject::connect(m_headerWidget->rootObject(), SIGNAL(addModuleClicked()), this, - SLOT(handleAddModule())); - QObject::connect(m_headerWidget->rootObject(), SIGNAL(addAssetClicked()), this, - SLOT(handleAddAsset())); + m_headerWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); + m_headerWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate)); + m_headerWidget->rootContext()->setContextProperty("rootView", QVariant::fromValue(this)); // create add imports widget m_addImportWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); m_addImportWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate)); Theme::setupTheme(m_addImportWidget->engine()); - m_addImportWidget->setSource(QUrl("qrc:/ItemLibrary/qml/addimport.qml")); - m_addImportWidget->rootContext()->setContextProperty( - "addImportModel", QVariant::fromValue(m_itemLibraryAddImportModel.data())); - QObject::connect(m_addImportWidget->rootObject(), SIGNAL(addImport(int)), this, - SLOT(handleAddImport(int))); + m_addImportWidget->rootContext()->setContextProperties({ + {"addImportModel", QVariant::fromValue(m_itemLibraryAddImportModel.data())}, + {"rootView", QVariant::fromValue(this)}, + }); // set up Item Library view and model m_itemViewQuickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); @@ -270,7 +262,7 @@ QList ItemLibraryWidget::createToolBarWidgets() return buttons; } -void ItemLibraryWidget::handleFilterChanged(const QString &filterText) +void ItemLibraryWidget::handleSearchfilterChanged(const QString &filterText) { m_filterText = filterText; @@ -339,11 +331,20 @@ void ItemLibraryWidget::clearSearchFilter() void ItemLibraryWidget::reloadQmlSource() { - QString itemLibraryQmlFilePath = qmlSourcesPath() + QStringLiteral("/ItemsView.qml"); + const QString libraryHeaderQmlPath = qmlSourcesPath() + "/LibraryHeader.qml"; + QTC_ASSERT(QFileInfo::exists(libraryHeaderQmlPath), return); + m_headerWidget->engine()->clearComponentCache(); + m_headerWidget->setSource(QUrl::fromLocalFile(libraryHeaderQmlPath)); - QTC_ASSERT(QFileInfo::exists(itemLibraryQmlFilePath), return); + const QString addImportQmlPath = qmlSourcesPath() + "/AddImport.qml"; + QTC_ASSERT(QFileInfo::exists(addImportQmlPath), return); + m_addImportWidget->engine()->clearComponentCache(); + m_addImportWidget->setSource(QUrl::fromLocalFile(addImportQmlPath)); + + const QString itemLibraryQmlPath = qmlSourcesPath() + "/ItemsView.qml"; + QTC_ASSERT(QFileInfo::exists(itemLibraryQmlPath), return); m_itemViewQuickWidget->engine()->clearComponentCache(); - m_itemViewQuickWidget->setSource(QUrl::fromLocalFile(itemLibraryQmlFilePath)); + m_itemViewQuickWidget->setSource(QUrl::fromLocalFile(itemLibraryQmlPath)); } void ItemLibraryWidget::updateModel() diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index 0b78c485e58..1a34c7e96a1 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -91,6 +91,11 @@ public: Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos); Q_INVOKABLE void removeImport(const QString &importUrl); Q_INVOKABLE void addImportForItem(const QVariant &entry); + Q_INVOKABLE void handleTabChanged(int index); + Q_INVOKABLE void handleAddModule(); + Q_INVOKABLE void handleAddAsset(); + Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText); + Q_INVOKABLE void handleAddImport(int index); signals: void itemActivated(const QString& itemName); @@ -130,13 +135,6 @@ private: bool m_updateRetry = false; QString m_filterText; QPoint m_dragStartPoint; - -private slots: - void handleTabChanged(int index); - void handleFilterChanged(const QString &filterText); - void handleAddModule(); - void handleAddAsset(); - void handleAddImport(int index); }; -} +} // namespace QmlDesigner From 2de66272e87bc71ac0793df9f652fe8ec3211894 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 8 Mar 2021 18:28:26 +0200 Subject: [PATCH 13/16] QmlDesigner: Fix item library header Title text of tab buttons no longer overlaps the plus sign. Fixes: QDS-3842 Change-Id: Iec51ebf00e6f719eac8b7204634ae8dc7696939a Reviewed-by: Mahmoud Badri --- .../itemLibraryQmlSources/LibraryHeader.qml | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml index 12052d2a3cb..da2e18ff873 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/LibraryHeader.qml @@ -66,25 +66,33 @@ Item { {title: qsTr("Assets"), addToolTip: qsTr("Add new assets to project.")}] TabButton { - contentItem: Text { // TabButton text - text: modelData.title - font.pixelSize: 13 - font.bold: true - color: tabBar.currentIndex === index ? "#0094ce" : "#dadada" - anchors.bottomMargin: 2 - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignBottom - elide: Text.ElideRight - } + topPadding: 4 + bottomPadding: 4 + contentItem: Item { + implicitHeight: plusButton.height - background: Item { // TabButton background - Rectangle { // + button - anchors.right: parent.right + Text { // TabButton text + text: modelData.title + font.pixelSize: 13 + font.bold: true + color: tabBar.currentIndex === index ? "#0094ce" : "#dadada" + anchors.left: parent.left + anchors.top: parent.top anchors.bottom: parent.bottom - anchors.rightMargin: 2 + anchors.right: plusButton.left anchors.bottomMargin: 2 - width: 25 - height: 25 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignBottom + elide: Text.ElideRight + } + + Rectangle { // + button + id: plusButton + anchors.right: parent.right + anchors.top: parent.top + anchors.topMargin: 1 + width: 24 + height: 24 color: mouseArea.containsMouse ? "#353535" : "#262626" ToolTip.delay: 500 @@ -109,7 +117,9 @@ Item { : rootView.handleAddAsset() } } + } + background: Item { // TabButton background Rectangle { // bottom strip anchors.bottom: parent.bottom width: parent.width From 675a72e29648844eca625202ee56da9280b6ac22 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 25 Feb 2021 12:53:41 +0100 Subject: [PATCH 14/16] Fix a deadlock when closing Creator while loading a project Replace the call to SynchronousProcess::run() by asynchronous call that invokes a process. This change may be tested by applying the additional patch mentioned in QTCREATORBUG-25385 description. Don't call the SynchronousProcess::run() from the main thread when the Quit event was already scheduled for qApp, since the Quit event will get removed from the awaiting queue by a call to QEventLoop::exec(). Fixes: QTCREATORBUG-25385 Change-Id: I8af39552443bfa9b3af6e31ddce85a01b91bbbd8 Reviewed-by: Eike Ziller --- .../cmakeprojectmanager/cmakebuildsystem.cpp | 87 ++++++++++++------- .../cmakeprojectmanager/cmakebuildsystem.h | 3 + 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index ec843295ebd..73c21babb9e 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ #include #include #include +#include #include #include @@ -207,6 +209,7 @@ CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc) CMakeBuildSystem::~CMakeBuildSystem() { + m_futureSynchronizer.waitForFinished(); if (!m_treeScanner.isFinished()) { auto future = m_treeScanner.future(); future.cancel(); @@ -576,7 +579,7 @@ void CMakeBuildSystem::combineScanAndParse() emitBuildSystemUpdated(); - QTimer::singleShot(0, this, &CMakeBuildSystem::runCTest); + runCTest(); } void CMakeBuildSystem::checkAndReportError(QString &errorMessage) @@ -921,42 +924,62 @@ void CMakeBuildSystem::runCTest() } qCDebug(cmakeBuildSystemLog) << "Requesting ctest run after cmake run"; - BuildDirParameters parameters(cmakeBuildConfiguration()); + const BuildDirParameters parameters(cmakeBuildConfiguration()); QTC_ASSERT(parameters.isValid(), return); - FilePath workingDirectory = workDirectory(parameters); - CommandLine cmd{m_ctestPath, {"-N", "--show-only=json-v1"}}; - SynchronousProcess ctest; - ctest.setTimeoutS(1); - ctest.setEnvironment(cmakeBuildConfiguration()->environment().toStringList()); - ctest.setWorkingDirectory(workingDirectory.toString()); + const CommandLine cmd { m_ctestPath, { "-N", "--show-only=json-v1" } }; + const QString workingDirectory = workDirectory(parameters).toString(); + const QStringList environment = cmakeBuildConfiguration()->environment().toStringList(); - const SynchronousProcessResponse response = ctest.run(cmd); - if (response.result == SynchronousProcessResponse::Finished) { - const QJsonDocument json = QJsonDocument::fromJson(response.allRawOutput()); - if (!json.isEmpty() && json.isObject()) { - const QJsonObject jsonObj = json.object(); - const QJsonObject btGraph = jsonObj.value("backtraceGraph").toObject(); - const QJsonArray cmakelists = btGraph.value("files").toArray(); - const QJsonArray nodes = btGraph.value("nodes").toArray(); - const QJsonArray tests = jsonObj.value("tests").toArray(); - for (const QJsonValue &testVal : tests) { - const QJsonObject test = testVal.toObject(); - QTC_ASSERT(!test.isEmpty(), continue); - const int bt = test.value("backtrace").toInt(-1); - QTC_ASSERT(bt != -1, continue); - const QJsonObject btRef = nodes.at(bt).toObject(); - int file = btRef.value("file").toInt(-1); - int line = btRef.value("line").toInt(-1); - QTC_ASSERT(file != -1 && line != -1, continue); - m_testNames.append({test.value("name").toString(), - FilePath::fromString(cmakelists.at(file).toString()), - line - }); + auto future = Utils::runAsync([cmd, workingDirectory, environment] + (QFutureInterface &futureInterface) { + QProcess process; + process.setEnvironment(environment); + process.setWorkingDirectory(workingDirectory); + process.start(cmd.executable().toString(), cmd.splitArguments(), QIODevice::ReadOnly); + + if (!process.waitForStarted(1000) || !process.waitForFinished(1000)) { + if (process.state() == QProcess::NotRunning) + return; + process.terminate(); + if (process.waitForFinished(1000)) + return; + process.kill(); + process.waitForFinished(1000); + return; + } + if (process.exitCode() || process.exitStatus() != QProcess::NormalExit) + return; + futureInterface.reportResult(process.readAllStandardOutput()); + }); + + Utils::onFinished(future, this, [this](const QFuture &future) { + if (future.resultCount()) { + const QJsonDocument json = QJsonDocument::fromJson(future.result()); + if (!json.isEmpty() && json.isObject()) { + const QJsonObject jsonObj = json.object(); + const QJsonObject btGraph = jsonObj.value("backtraceGraph").toObject(); + const QJsonArray cmakelists = btGraph.value("files").toArray(); + const QJsonArray nodes = btGraph.value("nodes").toArray(); + const QJsonArray tests = jsonObj.value("tests").toArray(); + for (const QJsonValue &testVal : tests) { + const QJsonObject test = testVal.toObject(); + QTC_ASSERT(!test.isEmpty(), continue); + const int bt = test.value("backtrace").toInt(-1); + QTC_ASSERT(bt != -1, continue); + const QJsonObject btRef = nodes.at(bt).toObject(); + int file = btRef.value("file").toInt(-1); + int line = btRef.value("line").toInt(-1); + QTC_ASSERT(file != -1 && line != -1, continue); + m_testNames.append({ test.value("name").toString(), + FilePath::fromString(cmakelists.at(file).toString()), line }); + } } } - } - emit testInformationUpdated(); + emit testInformationUpdated(); + }); + + m_futureSynchronizer.addFuture(future); } CMakeBuildConfiguration *CMakeBuildSystem::cmakeBuildConfiguration() const diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h index 7667b77a772..00740feaa0a 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h @@ -35,6 +35,8 @@ #include #include +#include + namespace ProjectExplorer { class ExtraCompiler; } namespace CppTools { @@ -181,6 +183,7 @@ private: // CTest integration QString m_ctestPath; QList m_testNames; + QFutureSynchronizer m_futureSynchronizer; }; } // namespace Internal From 98ab3af2a8c73e00028d0b97bfc57d90f4bc1c8c Mon Sep 17 00:00:00 2001 From: Michael Winkelmann Date: Tue, 9 Mar 2021 12:06:02 +0100 Subject: [PATCH 15/16] Annotation: isEmpty const Change-Id: I95f1c275c7190f27e0ac2c1a57eb791c9353d4c8 Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/designercore/include/annotation.h | 2 +- src/plugins/qmldesigner/designercore/model/annotation.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/include/annotation.h b/src/plugins/qmldesigner/designercore/include/annotation.h index e00481d57ab..752c817211a 100644 --- a/src/plugins/qmldesigner/designercore/include/annotation.h +++ b/src/plugins/qmldesigner/designercore/include/annotation.h @@ -94,7 +94,7 @@ public: static bool sameContent(const Comment &a, const Comment &b); bool operator==(const Comment &comment) const; //everything is similar. - bool isEmpty(); + bool isEmpty() const; QString toQString() const; diff --git a/src/plugins/qmldesigner/designercore/model/annotation.cpp b/src/plugins/qmldesigner/designercore/model/annotation.cpp index e27cac283c2..f8f2edc0d8a 100644 --- a/src/plugins/qmldesigner/designercore/model/annotation.cpp +++ b/src/plugins/qmldesigner/designercore/model/annotation.cpp @@ -133,7 +133,7 @@ bool Comment::operator==(const Comment &comment) const return (sameContent(comment) && (m_timestamp == comment.timestamp())); } -bool Comment::isEmpty() +bool Comment::isEmpty() const { return sameContent(Comment()); } From 84800e8113c247d2031e01577d3e008d788f37eb Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 9 Mar 2021 11:41:58 +0100 Subject: [PATCH 16/16] QmlDesigner: Forward QT_IM_MODULE=qtvirtualkeyboard to puppet If QT_IM_MODULE=qtvirtualkeyboard is used for the application, when we should also set it for the puppet. Task-number: QDS-3859 Change-Id: Id88132cebbb7aeddb3fbb8ff1e8aa5191cc89d15 Reviewed-by: Tuomo Pelkonen Reviewed-by: Thomas Hartmann --- .../designercore/instances/puppetcreator.cpp | 20 +++++++++++++++++++ .../designercore/instances/puppetcreator.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp index 743d3051d7a..acf3083b3e8 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp @@ -47,6 +47,7 @@ #include +#include #include #include #include @@ -167,6 +168,20 @@ QString PuppetCreator::getStyleConfigFileName() const return QString(); } +bool PuppetCreator::usesVirtualKeyboard() const +{ +#ifndef QMLDESIGNER_TEST + if (m_target) { + auto *qmlbuild = qobject_cast(m_target->buildSystem()); + + const Utils::EnvironmentItem virtualKeyboard("QT_IM_MODULE", "qtvirtualkeyboard"); + return qmlbuild && qmlbuild->environment().indexOf(virtualKeyboard); + } + +#endif + return false; +} + PuppetCreator::PuppetCreator(ProjectExplorer::Target *target, const Model *model) : m_target(target) @@ -494,6 +509,11 @@ QProcessEnvironment PuppetCreator::processEnvironment() const environment.set("QMLDESIGNER_RC_PATHS", m_qrcMapping); } + if (usesVirtualKeyboard()) { + environment.set("QT_IM_MODULE", "qtvirtualkeyboard"); + environment.set("QT_VIRTUALKEYBOARD_DESKTOP_DISABLE", "1"); + } + #ifndef QMLDESIGNER_TEST // set env var if QtQuick3D import exists QmlDesigner::Import import = QmlDesigner::Import::createLibraryImport("QtQuick3D", "1.0"); diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.h b/src/plugins/qmldesigner/designercore/instances/puppetcreator.h index e001b9d0c10..f7b5761762e 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.h +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.h @@ -103,6 +103,7 @@ protected: bool useOnlyFallbackPuppet() const; QString getStyleConfigFileName() const; + bool usesVirtualKeyboard() const; private: mutable QString m_compileLog;