diff options
author | David Schulz <[email protected]> | 2024-04-12 12:53:27 +0200 |
---|---|---|
committer | David Schulz <[email protected]> | 2024-04-15 07:45:15 +0000 |
commit | ee8245d8aaa4e34d2773c572aa05a4ca5866f151 (patch) | |
tree | 629ac912d9e2623b5fdd0bb15dde6fda4464839a | |
parent | 310d3cc041f5617adef10d37605264fda2eda6d3 (diff) |
Core: allow multiple contexts per widget
This makes it possible to allow different sets of actions for a specific
widget depending on the defined contexts for that widget.
Fixes: QTCREATORBUG-30675
Fixes: QTCREATORBUG-30677
Change-Id: I408e0ae445b364d4f450ccdd2fbdfc81ece45015
Reviewed-by: Eike Ziller <[email protected]>
-rw-r--r-- | src/plugins/coreplugin/icore.cpp | 63 | ||||
-rw-r--r-- | src/plugins/coreplugin/icore.h | 4 | ||||
-rw-r--r-- | src/plugins/coreplugin/statusbarmanager.cpp | 10 | ||||
-rw-r--r-- | src/plugins/help/helpplugin.cpp | 30 |
4 files changed, 61 insertions, 46 deletions
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp index 8a727494c2d..85401aa8bc7 100644 --- a/src/plugins/coreplugin/icore.cpp +++ b/src/plugins/coreplugin/icore.cpp @@ -314,7 +314,7 @@ public: QList<IContext *> m_activeContext; - std::unordered_map<QWidget *, IContext *> m_contextWidgets; + std::unordered_map<QWidget *, QList<IContext *>> m_contextWidgets; ShortcutSettings *m_shortcutSettings = nullptr; ToolSettings *m_toolSettings = nullptr; @@ -836,16 +836,18 @@ QString ICore::versionString() } /*! - Returns the top level IContext of the current context, or \c nullptr if + Returns a list IContexts for the current top level context widget, or an empty list if there is none. \sa updateAdditionalContexts() \sa addContextObject() \sa {The Action Manager and Commands} */ -IContext *ICore::currentContextObject() +QList<IContext *> ICore::currentContextObjects() { - return d->m_activeContext.isEmpty() ? nullptr : d->m_activeContext.first(); + if (d->m_activeContext.isEmpty()) + return {}; + return d->m_contextWidgets[d->m_activeContext.first()->widget()]; } /*! @@ -856,8 +858,7 @@ IContext *ICore::currentContextObject() */ QWidget *ICore::currentContextWidget() { - IContext *context = currentContextObject(); - return context ? context->widget() : nullptr; + return d->m_activeContext.isEmpty() ? nullptr : d->m_activeContext.first()->widget(); } /*! @@ -1525,8 +1526,10 @@ void ICore::extensionsInitialized() void ICore::aboutToShutdown() { disconnect(qApp, &QApplication::focusChanged, d, &ICorePrivate::updateFocusWidget); - for (auto contextPair : d->m_contextWidgets) - disconnect(contextPair.second, &QObject::destroyed, d->m_mainwindow, nullptr); + for (auto contextsPair : d->m_contextWidgets) { + for (auto context : contextsPair.second) + disconnect(context, &QObject::destroyed, d->m_mainwindow, nullptr); + } d->m_activeContext.clear(); d->m_mainwindow->hide(); } @@ -2281,13 +2284,14 @@ void ICore::openFileWith() } /*! - Returns the registered IContext instance for the specified \a widget, + Returns all registered IContext instance for the specified \a widget, if any. */ -IContext *ICore::contextObject(QWidget *widget) +QList<IContext *> ICore::contextObjects(QWidget *widget) { - const auto it = d->m_contextWidgets.find(widget); - return it == d->m_contextWidgets.end() ? nullptr : it->second; + if (auto it = d->m_contextWidgets.find(widget); it != d->m_contextWidgets.end()) + return it->second; + return {}; } /*! @@ -2306,11 +2310,7 @@ void ICore::addContextObject(IContext *context) { if (!context) return; - QWidget *widget = context->widget(); - if (d->m_contextWidgets.find(widget) != d->m_contextWidgets.end()) - return; - - d->m_contextWidgets.insert({widget, context}); + d->m_contextWidgets[context->widget()].append(context); connect(context, &QObject::destroyed, m_core, [context] { removeContextObject(context); }); } @@ -2331,15 +2331,19 @@ void ICore::removeContextObject(IContext *context) disconnect(context, &QObject::destroyed, m_core, nullptr); - const auto it = std::find_if(d->m_contextWidgets.cbegin(), - d->m_contextWidgets.cend(), - [context](const std::pair<QWidget *, IContext *> &v) { - return v.second == context; - }); - if (it == d->m_contextWidgets.cend()) + auto it = std::find_if( + d->m_contextWidgets.begin(), + d->m_contextWidgets.end(), + [context](const std::pair<QWidget *, QList<IContext *>> &v) { + return v.second.contains(context); + }); + if (it == d->m_contextWidgets.end()) return; - d->m_contextWidgets.erase(it); + it->second.removeAll(context); + if (it->second.isEmpty()) + d->m_contextWidgets.erase(it); + if (d->m_activeContext.removeAll(context) > 0) d->updateContextObject(d->m_activeContext); } @@ -2355,15 +2359,8 @@ void ICorePrivate::updateFocusWidget(QWidget *old, QWidget *now) return; QList<IContext *> newContext; - if (QWidget *p = QApplication::focusWidget()) { - IContext *context = nullptr; - while (p) { - context = ICore::contextObject(p); - if (context) - newContext.append(context); - p = p->parentWidget(); - } - } + for (QWidget *p = QApplication::focusWidget(); p; p = p->parentWidget()) + newContext.append(ICore::contextObjects(p)); // ignore toplevels that define no context, like popups without parent if (!newContext.isEmpty() || QApplication::focusWidget() == m_mainwindow->focusWidget()) diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h index 8c713e156f4..2c2dbc3c57a 100644 --- a/src/plugins/coreplugin/icore.h +++ b/src/plugins/coreplugin/icore.h @@ -87,9 +87,9 @@ public: static void raiseWindow(QWidget *widget); static void raiseMainWindow(); - static IContext *currentContextObject(); + static QList<IContext *> currentContextObjects(); static QWidget *currentContextWidget(); - static IContext *contextObject(QWidget *widget); + static QList<IContext *> contextObjects(QWidget *widget); static void updateAdditionalContexts(const Context &remove, const Context &add, ContextPriority priority = ContextPriority::Low); static void addAdditionalContext(const Context &context, diff --git a/src/plugins/coreplugin/statusbarmanager.cpp b/src/plugins/coreplugin/statusbarmanager.cpp index c590b3f29ef..e85996b053a 100644 --- a/src/plugins/coreplugin/statusbarmanager.cpp +++ b/src/plugins/coreplugin/statusbarmanager.cpp @@ -156,13 +156,9 @@ StatusBarContext::StatusBarContext(QObject *parent) Context StatusBarContext::context() const { - IMode *currentMode = ModeManager::currentMode(); - QWidget *modeWidget = currentMode ? currentMode->widget() : nullptr; - if (modeWidget) { - if (IContext *context = ICore::contextObject(modeWidget)) - return context->context(); - } - return Context(); + if (IMode *currentMode = ModeManager::currentMode()) + return currentMode->context(); + return {}; } } // Core diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index e9706a3db18..49b4624b269 100644 --- a/src/plugins/help/helpplugin.cpp +++ b/src/plugins/help/helpplugin.cpp @@ -102,6 +102,7 @@ public: void modeChanged(Id mode, Id old); void requestContextHelp(); + void requestContextHelpFor(QList<QPointer<IContext>> contexts); void showContextHelp(const HelpItem &contextHelp); void activateIndex(); void activateContents(); @@ -464,11 +465,32 @@ void HelpPluginPrivate::requestContextHelp() const HelpItem tipHelp = tipHelpValue.canConvert<HelpItem>() ? tipHelpValue.value<HelpItem>() : HelpItem(tipHelpValue.toString()); - IContext *context = ICore::currentContextObject(); - if (tipHelp.isEmpty() && context) - context->contextHelp([this](const HelpItem &item) { showContextHelp(item); }); - else + const QList<IContext *> contexts = ICore::currentContextObjects(); + if (contexts.isEmpty() && !tipHelp.isEmpty()) { showContextHelp(tipHelp); + } else { + requestContextHelpFor(Utils::transform(contexts, [](IContext *context) { + return QPointer<IContext>(context); + })); + } +} + +void HelpPluginPrivate::requestContextHelpFor(QList<QPointer<IContext>> contexts) +{ + if (contexts.isEmpty()) + return; + QPointer<IContext> context = contexts.takeFirst(); + while (!context) { + if (contexts.isEmpty()) + return; + context = contexts.takeFirst(); + } + context->contextHelp([contexts, this](const HelpItem &item) { + if (!item.isEmpty()) + showContextHelp(item); + else + requestContextHelpFor(contexts); + }); } void HelpPluginPrivate::showContextHelp(const HelpItem &contextHelp) |