[education/rkward] /: Keep kate plugin actions active whenever a ktexteditor _or_ the corresponding plugin tool window is active.
Thomas Friedrichsmeier
null at kde.org
Sun Nov 1 07:30:37 GMT 2020
Git commit 1235f217cc8fa94487c015a1b888f73241e61216 by Thomas Friedrichsmeier.
Committed on 01/11/2020 at 07:30.
Pushed by tfry into branch 'master'.
Keep kate plugin actions active whenever a ktexteditor _or_ the corresponding plugin tool window is active.
M +3 -0 ChangeLog
M +28 -21 rkward/rkward.cpp
M +1 -0 rkward/rkward.h
M +3 -2 rkward/windows/detachedwindowcontainer.cpp
M +27 -9 rkward/windows/katepluginintegration.cpp
M +4 -0 rkward/windows/katepluginintegration.h
M +1 -0 rkward/windows/rkcommandeditorwindow.cpp
M +11 -5 rkward/windows/rkmdiwindow.cpp
M +7 -0 rkward/windows/rkmdiwindow.h
M +13 -6 rkward/windows/rkworkplace.cpp
M +3 -1 rkward/windows/rkworkplace.h
https://invent.kde.org/education/rkward/commit/1235f217cc8fa94487c015a1b888f73241e61216
diff --git a/ChangeLog b/ChangeLog
index 0210df6e..542ccc4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+- kate plugin related actions are now active whenever a script window is active (not only the corresponding tool window)
+ - TODO: support kate plugins in detached windows
+
--- Version 0.7.2 - Oct-16-2020
- Script preview keeps vertical scroll position when updating
- Python development scripts have been ported to python3
diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index ec83c94f..7787cea5 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -125,8 +125,9 @@ RKWardMainWindow::RKWardMainWindow () : KParts::MainWindow ((QWidget *)0, (Qt::W
workspace_modified = false;
merge_loads = false;
rkward_mainwin = this;
- katepluginintegration = 0;
- RKGlobals::rinter = 0;
+ katepluginintegration = nullptr;
+ active_ui_buddy = nullptr;
+ RKGlobals::rinter = nullptr;
RKCommonFunctions::getRKWardDataDir(); // call this before any forking, in order to avoid potential race conditions during initialization of data dir
RKSettings::settings_tracker = new RKSettingsTracker (this);
@@ -651,38 +652,44 @@ void updateEmptyMenuIndicator (QAction* indicator, const QMenu *menu) {
indicator->setVisible (true);
}
-void RKWardMainWindow::partChanged (KParts::Part *part) {
+void RKWardMainWindow::partChanged(KParts::Part *part) {
RK_TRACE (APP);
if (gui_rebuild_locked) return;
if (!part) return;
- createGUI (part);
+ createGUI(part);
- if (!guiFactory ()) {
+ if (!guiFactory()) {
RK_ASSERT (false);
return;
}
+ // Check for additional "buddy" that should be loaded
+ RKMDIWindow *w = RKWorkplace::mainWorkplace()->windowForPart(part);
+ KXMLGUIClient* buddy = w->uiBuddy();
+ // NOTE: Even if the buddy stays the same, we have to remove and re-add it to keep the order of menu actions stable
+ if (active_ui_buddy) factory()->removeClient(active_ui_buddy);
+ if (buddy) factory()->addClient(buddy);
+ active_ui_buddy = buddy;
- updateEmptyMenuIndicator (edit_menu_dummy, dynamic_cast<QMenu*>(guiFactory ()->container ("edit", this)));
- updateEmptyMenuIndicator (view_menu_dummy, dynamic_cast<QMenu*>(guiFactory ()->container ("view", this)));
+ updateEmptyMenuIndicator(edit_menu_dummy, dynamic_cast<QMenu*>(guiFactory()->container("edit", this)));
+ updateEmptyMenuIndicator(view_menu_dummy, dynamic_cast<QMenu*>(guiFactory()->container("view", this)));
// plug save file actions into the toolbar collections
- RK_ASSERT (save_any_action);
- for (int i = 0; i < plugged_save_actions.size (); ++i) {
- QAction* a = plugged_save_actions[i].data ();
- if (a) save_any_action->removeAction (a);
+ RK_ASSERT(save_any_action);
+ for (int i = 0; i < plugged_save_actions.size(); ++i) {
+ QAction* a = plugged_save_actions[i].data();
+ if (a) save_any_action->removeAction(a);
}
- plugged_save_actions.clear ();
-
- RKMDIWindow *w = RKWorkplace::mainWorkplace ()->activeWindow (RKMDIWindow::Attached);
- if (w && (w->isType (RKMDIWindow::CommandEditorWindow))) {
- QAction *a = static_cast<RKCommandEditorWindow*>(w)->fileSaveAction ();
- if (a) plugged_save_actions.append (a);
- a = static_cast<RKCommandEditorWindow*>(w)->fileSaveAsAction ();
- if (a) plugged_save_actions.append (a);
+ plugged_save_actions.clear();
+
+ if (w && (w->isType(RKMDIWindow::CommandEditorWindow))) {
+ QAction *a = static_cast<RKCommandEditorWindow*>(w)->fileSaveAction();
+ if (a) plugged_save_actions.append(a);
+ a = static_cast<RKCommandEditorWindow*>(w)->fileSaveAsAction();
+ if (a) plugged_save_actions.append(a);
}
- for (int i = 0; i < plugged_save_actions.size (); ++i) {
- save_any_action->insertAction (save_actions_plug_point, plugged_save_actions[i]);
+ for (int i = 0; i < plugged_save_actions.size(); ++i) {
+ save_any_action->insertAction(save_actions_plug_point, plugged_save_actions[i]);
}
/*
// debug code: prints out all current actions
diff --git a/rkward/rkward.h b/rkward/rkward.h
index 88ebd05e..b851648f 100644
--- a/rkward/rkward.h
+++ b/rkward/rkward.h
@@ -200,6 +200,7 @@ private:
bool merge_loads;
KatePluginIntegrationApp *katepluginintegration;
+ KXMLGUIClient *active_ui_buddy;
};
#endif // RKWARD_H
diff --git a/rkward/windows/detachedwindowcontainer.cpp b/rkward/windows/detachedwindowcontainer.cpp
index ce0966d4..19113a56 100644
--- a/rkward/windows/detachedwindowcontainer.cpp
+++ b/rkward/windows/detachedwindowcontainer.cpp
@@ -2,7 +2,7 @@
detachedwindowcontainer - description
-------------------
begin : Wed Oct 21 2005
- copyright : (C) 2005-2016 by Thomas Friedrichsmeier
+ copyright : (C) 2005-2020 by Thomas Friedrichsmeier
email : thomas.friedrichsmeier at kdemail.net
***************************************************************************/
@@ -76,7 +76,8 @@ DetachedWindowContainer::DetachedWindowContainer (RKMDIWindow *widget_to_capture
widget_to_capture->setParent (this);
setCentralWidget (widget_to_capture);
widget_to_capture->show ();
- createGUI (widget_to_capture->getPart ());
+ createGUI(widget_to_capture->getPart());
+// if (widget_to_capture->uiBuddy()) factory()->addClient(widget_to_capture->uiBuddy());
captured = widget_to_capture;
hideEmptyMenus ();
diff --git a/rkward/windows/katepluginintegration.cpp b/rkward/windows/katepluginintegration.cpp
index 66dc2e8c..c49d6a30 100644
--- a/rkward/windows/katepluginintegration.cpp
+++ b/rkward/windows/katepluginintegration.cpp
@@ -146,8 +146,18 @@ void KatePluginIntegrationApp::loadPlugins(const QStringList& plugins) {
}
if (!changes) return;
- RKWardMainWindow::getMain()->factory()->removeClient(mainWindow());
- RKWardMainWindow::getMain()->factory()->addClient(mainWindow());
+
+ auto w = mainWindow();
+ auto pf = w->persistentGuiClient()->factory();
+ if (pf) {
+ pf->removeClient(w->persistentGuiClient());
+ pf->addClient(w->persistentGuiClient());
+ }
+ auto df = w->dynamicGuiClient()->factory();
+ if (df) {
+ df->removeClient(w->dynamicGuiClient());
+ df->addClient(w->dynamicGuiClient());
+ }
}
void KatePluginIntegrationApp::unloadPlugin(const QString &identifier) {
@@ -176,7 +186,7 @@ void KatePluginIntegrationApp::saveConfigAndUnload() {
RK_TRACE (APP);
for (auto it = known_plugins.constBegin(); it != known_plugins.constEnd(); ++it) {
- unloadPlugin (it.key());
+ unloadPlugin(it.key());
}
known_plugins.clear();
}
@@ -300,18 +310,25 @@ KTextEditor::Plugin *KatePluginIntegrationApp::plugin(const QString &name) {
/// BEGIN KTextEditor::MainWindow interface
-KatePluginIntegrationWindow::KatePluginIntegrationWindow (KatePluginIntegrationApp *parent) : QObject (parent), KXMLGUIClient () {
- RK_TRACE (APP);
+KatePluginIntegrationWindow::KatePluginIntegrationWindow(KatePluginIntegrationApp *parent) : QObject(parent), KXMLGUIClient() {
+ RK_TRACE(APP);
// This one is passed to each created plugin
main = new KTextEditor::MainWindow(this);
// While this one may be accessed from plugins via KTextEditor::Editor::instance()->application()
app = parent;
- active_plugin = 0;
+ active_plugin = nullptr;
+ dynamic_actions_client = new KXMLGUIClient();
connect(RKWorkplace::getHistory(), &RKMDIWindowHistory::activeWindowChanged, this, &KatePluginIntegrationWindow::activeWindowChanged);
}
+KatePluginIntegrationWindow::~KatePluginIntegrationWindow() {
+ RK_TRACE(APP);
+ delete dynamic_actions_client;
+}
+
+
class KatePluginToolWindow : public RKMDIWindow {
Q_OBJECT
public:
@@ -508,13 +525,12 @@ bool KatePluginIntegrationWindow::viewsInSameSplitView(KTextEditor::View* view1,
void KatePluginIntegrationWindow::fixUpPluginUI(const QString &id, const PluginResources &resources) {
RK_TRACE (APP);
- KXMLGUIClient* hacked_parent = this;
// KF6 TODO: In KF6, plugins will probably be limited to one UI client, in the first place.
for (int i = 0; i < resources.clients.size(); ++i) {
KXMLGUIClient* client = resources.clients[i];
RKMDIWindow* window = resources.windows.value(i);
if (window) {
- hacked_parent = window->getPart();;
+ window->addUiBuddy(dynamic_actions_client);
}
factory()->removeClient(client);
@@ -534,10 +550,12 @@ void KatePluginIntegrationWindow::fixUpPluginUI(const QString &id, const PluginR
// TODO: Rename "Search more" to something sensible. These actions should still be accessible, globally.
} else if (i == 0 && id == QStringLiteral("kateprojectplugin")) {
RKCommonFunctions::moveContainer(client, "Menu", "projects", "view", true, false);
+ } else if (i == 0 && id == QStringLiteral("katectagsplugin")) {
+ RKCommonFunctions::moveContainer(client, "Menu", "CTags Menubar", "view", true, false);
}
RKCommonFunctions::moveContainer(client, "Menu", "tools", "edit", true, true);
- hacked_parent->insertChildClient(client);
+ dynamic_actions_client->insertChildClient(client);
}
/* TODO: Ok, I guess we need even more specialization.
diff --git a/rkward/windows/katepluginintegration.h b/rkward/windows/katepluginintegration.h
index c07547ef..98c4b038 100644
--- a/rkward/windows/katepluginintegration.h
+++ b/rkward/windows/katepluginintegration.h
@@ -78,7 +78,10 @@ class KatePluginIntegrationWindow : public QObject, public KXMLGUIClient {
Q_OBJECT
public:
KatePluginIntegrationWindow(KatePluginIntegrationApp *parent);
+ ~KatePluginIntegrationWindow();
KTextEditor::MainWindow *mainWindow() const { return main; };
+ KXMLGUIClient* persistentGuiClient() { return this; }
+ KXMLGUIClient* dynamicGuiClient() const { return dynamic_actions_client; }
private slots:
// These are the implementations of the KTextEditor::MainWindow interface.
// NOTE that they are not technically overrides, but get invoked via QMetaObject::invokeMethod()
@@ -117,6 +120,7 @@ friend class KatePluginIntegrationApp;
QHash<KTextEditor::Plugin*, PluginResources> plugin_resources;
KatePluginIntegrationApp *app;
+ KXMLGUIClient *dynamic_actions_client;
private slots:
void catchXMLGUIClientsHack(KXMLGUIClient* client);
void activeWindowChanged(RKMDIWindow *window);
diff --git a/rkward/windows/rkcommandeditorwindow.cpp b/rkward/windows/rkcommandeditorwindow.cpp
index a682fba5..d99e099b 100644
--- a/rkward/windows/rkcommandeditorwindow.cpp
+++ b/rkward/windows/rkcommandeditorwindow.cpp
@@ -113,6 +113,7 @@ RKCommandEditorWindow::RKCommandEditorWindow (QWidget *parent, const QUrl _url,
m_doc = 0;
preview_dir = 0;
visible_to_kateplugins = flags & RKCommandEditorFlags::VisibleToKTextEditorPlugins;
+ if (visible_to_kateplugins) addUiBuddy(RKWardMainWindow::getMain()->katePluginIntegration()->mainWindow()->dynamicGuiClient());
bool use_r_highlighting = (flags & RKCommandEditorFlags::ForceRHighlighting) || (url.isEmpty() && (flags & RKCommandEditorFlags::DefaultToRHighlighting)) || RKSettingsModuleCommandEditor::matchesScriptFileFilter (url.fileName ());
// Lookup of existing text editor documents: First, if no url is given at all, create a new document, and register an id, in case this window will get split, later
diff --git a/rkward/windows/rkmdiwindow.cpp b/rkward/windows/rkmdiwindow.cpp
index 3d8c95e1..fd54f637 100644
--- a/rkward/windows/rkmdiwindow.cpp
+++ b/rkward/windows/rkmdiwindow.cpp
@@ -65,13 +65,14 @@ RKMDIWindow::RKMDIWindow (QWidget *parent, int type, bool tool_window, const cha
}
RKMDIWindow::type = type;
state = Attached;
- tool_window_bar = 0;
- part = 0;
+ tool_window_bar = nullptr;
+ part = nullptr;
active = false;
no_border_when_active = false;
- standard_client = 0;
- status_popup = 0;
- status_popup_container = 0;
+ standard_client = nullptr;
+ status_popup = nullptr;
+ status_popup_container = nullptr;
+ ui_buddy = nullptr;
if (!(type & KatePluginWindow)) setWindowIcon (RKStandardIcons::iconForWindow (this));
}
@@ -428,4 +429,9 @@ void RKMDIWindow::showWindowSettings () {
RKSettings::configureSettings (settings_page, this);
}
+void RKMDIWindow::addUiBuddy(KXMLGUIClient* buddy) {
+ RK_TRACE(APP);
+ RK_ASSERT(!ui_buddy);
+ ui_buddy = buddy;
+}
diff --git a/rkward/windows/rkmdiwindow.h b/rkward/windows/rkmdiwindow.h
index 051472e1..ec20a0cb 100644
--- a/rkward/windows/rkmdiwindow.h
+++ b/rkward/windows/rkmdiwindow.h
@@ -122,6 +122,11 @@ is simply busy (e.g. when saving the current plot to history). */
KActionCollection *standardActionCollection ();
/** plugin-accessible properties of this object in the global context. Currently used only by RKEditorDataFrame to give information on the currently active data.frame. NOTE: ATM, you cannot set arbitrary properties. Only those supported in RKStandardComponent will have an effect. */
QString globalContextProperty (const QString& property) { return global_context_properties.value (property); };
+
+/** Add an xml client that should be active, whenever this window is active. Noteably the KatePluginIntegrationWindow for kate related windows.
+ * For the time being, only a single buddy is allowed, and it must outlive all mdi windows. */
+ void addUiBuddy(KXMLGUIClient* buddy);
+ KXMLGUIClient* uiBuddy() const { return ui_buddy; };
signals:
/** This signal is emitted, whenever the window caption was changed.
@param RKMDIWindow* a pointer to this window */
@@ -138,6 +143,7 @@ protected:
void initializeActivationSignals ();
void paintEvent (QPaintEvent *e) override;
void changeEvent (QEvent *event) override;
+ void removeUiBuddy(QObject* buddy);
/** reimplemented from QWidget to emulate focus-follows-mouse behavior */
void enterEvent (QEvent *event) override;
@@ -167,6 +173,7 @@ friend class RKToolWindowBar;
QString generic_window_name;
QUrl help_url;
RKSettings::SettingsPage settings_page;
+ KXMLGUIClient* ui_buddy;
};
#endif
diff --git a/rkward/windows/rkworkplace.cpp b/rkward/windows/rkworkplace.cpp
index 46a66535..74f8bccd 100644
--- a/rkward/windows/rkworkplace.cpp
+++ b/rkward/windows/rkworkplace.cpp
@@ -738,20 +738,27 @@ void RKWorkplace::windowRemoved () {
// give up
}
-RKMDIWindow *RKWorkplace::activeWindow (RKMDIWindow::State state) {
+RKMDIWindow *RKWorkplace::activeWindow(RKMDIWindow::State state) const {
RK_TRACE (APP);
- RKMDIWindow *ret = 0;
- for (RKWorkplaceObjectList::const_iterator it = windows.constBegin (); it != windows.constEnd (); ++it) {
+ for (auto it = windows.constBegin (); it != windows.constEnd (); ++it) {
if (!(state & ((*it)->state))) continue;
if ((*it)->isActive ()) {
- ret = *it;
- break;
+ return *it;
}
}
+ return nullptr;
+}
- return (ret);
+RKMDIWindow * RKWorkplace::windowForPart(KParts::Part* part) const {
+ RKMDIWindow *ret = 0;
+ for (auto it = windows.constBegin(); it != windows.constEnd(); ++it) {
+ if ((*it)->getPart() == part) {
+ return *it;
+ }
+ }
+ return nullptr;
}
QUrl checkAdjustRestoredUrl (const QString &_url, const QString old_base) {
diff --git a/rkward/windows/rkworkplace.h b/rkward/windows/rkworkplace.h
index 6eeddce4..c49d5bc3 100644
--- a/rkward/windows/rkworkplace.h
+++ b/rkward/windows/rkworkplace.h
@@ -110,7 +110,9 @@ public:
/** Detouch a window (it is removed from the view (), and placed in a top-level DetachedWindowContainer instead. */
void detachWindow (RKMDIWindow *window, bool was_attached=true);
/** @returns a pointer to the current window. state specifies, which windows should be considered. */
- RKMDIWindow *activeWindow (RKMDIWindow::State state);
+ RKMDIWindow *activeWindow (RKMDIWindow::State state) const;
+/** @returns the RKMDIWindow holding the given part */
+ RKMDIWindow *windowForPart(KParts::Part *part) const;
/** Opens the given url in the appropriate way. */
bool openAnyUrl (const QUrl &url, const QString &known_mimetype = QString (), bool force_external=false);
More information about the rkward-tracker
mailing list