diff options
| author | Mavridis Philippe <mavridisf@gmail.com> | 2025-04-09 15:31:05 +0300 |
|---|---|---|
| committer | Mavridis Philippe <mavridisf@gmail.com> | 2025-04-14 19:14:53 +0300 |
| commit | 1c42c490993492fd52fbbb79ceba7470778c6275 (patch) | |
| tree | dbdf7af2c364943f70bd079bdcf429943db37995 | |
| parent | 8fc0d1697439a9d020a8a7c0deb504b71b20a671 (diff) | |
| download | tdegraphics-1c42c490993492fd52fbbb79ceba7470778c6275.tar.gz tdegraphics-1c42c490993492fd52fbbb79ceba7470778c6275.zip | |
KPDF Shell: Instances can now be reused
This commit adds support for reusing existing KPDF instances to display externally opened documents in new tabs instead of new windows.
The feature depends on whether the corresponding option is checked and on whether KPDF is invoked with any URLs.
This commit adds a DCOP interface which contains tab-related methods.
Also breakoff tabs are now launched in a new instance instead of creating a new Shell widget in the same app, as this causes problems with the KPDFShellDCOPInterface. As a useful bonus, the new "--new-instance" CLI switch is now available to users and scripts.
Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
(cherry picked from commit 77ebecd92cef8d8c368ffb9cee3c856888456546)
| -rw-r--r-- | kpdf/conf/dlggeneral.ui | 8 | ||||
| -rw-r--r-- | kpdf/conf/kpdf.kcfg | 3 | ||||
| -rw-r--r-- | kpdf/conf/preferencesdialog.cpp | 1 | ||||
| -rw-r--r-- | kpdf/shell/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | kpdf/shell/dcop.h | 27 | ||||
| -rw-r--r-- | kpdf/shell/main.cpp | 62 | ||||
| -rw-r--r-- | kpdf/shell/shell.cpp | 44 | ||||
| -rw-r--r-- | kpdf/shell/shell.h | 11 |
8 files changed, 135 insertions, 23 deletions
diff --git a/kpdf/conf/dlggeneral.ui b/kpdf/conf/dlggeneral.ui index 7cde356f..dd8c2bd5 100644 --- a/kpdf/conf/dlggeneral.ui +++ b/kpdf/conf/dlggeneral.ui @@ -78,6 +78,14 @@ </widget> <widget class="TQCheckBox"> <property name="name"> + <cstring>kcfg_OpenInExistingKPDF</cstring> + </property> + <property name="text"> + <string>Open documents in &new tab instead of new window</string> + </property> + </widget> + <widget class="TQCheckBox"> + <property name="name"> <cstring>kcfg_TabsHoverCloseButton</cstring> </property> <property name="text"> diff --git a/kpdf/conf/kpdf.kcfg b/kpdf/conf/kpdf.kcfg index 44587903..5c331ec4 100644 --- a/kpdf/conf/kpdf.kcfg +++ b/kpdf/conf/kpdf.kcfg @@ -53,6 +53,9 @@ <entry key="WatchFile" type="Bool" > <default>true</default> </entry> + <entry key="OpenInExistingKPDF" type="Bool" > + <default>false</default> + </entry> <entry key="TabsHoverCloseButton" type="Bool" > <default>false</default> </entry> diff --git a/kpdf/conf/preferencesdialog.cpp b/kpdf/conf/preferencesdialog.cpp index 814c5301..dbcf56bd 100644 --- a/kpdf/conf/preferencesdialog.cpp +++ b/kpdf/conf/preferencesdialog.cpp @@ -41,4 +41,5 @@ void PreferencesDialog::setShellMode(bool on) { m_shellMode = on; m_general->kcfg_TabsHoverCloseButton->setHidden(!m_shellMode); + m_general->kcfg_OpenInExistingKPDF->setHidden(!m_shellMode); } diff --git a/kpdf/shell/CMakeLists.txt b/kpdf/shell/CMakeLists.txt index 30691f02..99ab138c 100644 --- a/kpdf/shell/CMakeLists.txt +++ b/kpdf/shell/CMakeLists.txt @@ -34,7 +34,7 @@ install( FILES shell.rc DESTINATION ${DATA_INSTALL_DIR}/kpdf ) ##### kpdf (executable) ######################### tde_add_executable( kpdf AUTOMOC - SOURCES main.cpp shell.cpp + SOURCES main.cpp shell.cpp dcop.skel LINK tdeparts-shared DESTINATION ${BIN_INSTALL_DIR} ) diff --git a/kpdf/shell/dcop.h b/kpdf/shell/dcop.h new file mode 100644 index 00000000..8b352c97 --- /dev/null +++ b/kpdf/shell/dcop.h @@ -0,0 +1,27 @@ +/*************************************************************************** + * Copyright (C) 2025 by Philippe Mavridis <mavridisf@gmail.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef KPDF_SHELL_IFACE_H +#define KPDF_SHELL_IFACE_H + +#include <dcopobject.h> +#include <kurl.h> + +class KPDFShellDCOPIface : virtual public DCOPObject +{ + K_DCOP + + k_dcop: + virtual void openURL(const KURL & url) = 0; + virtual void addTab() = 0; + virtual void removeTab() = 0; + virtual const KURL currentTabURL() = 0; +}; + +#endif // KPDF_SHELL_IFACE_H
\ No newline at end of file diff --git a/kpdf/shell/main.cpp b/kpdf/shell/main.cpp index dfe6078c..345b6548 100644 --- a/kpdf/shell/main.cpp +++ b/kpdf/shell/main.cpp @@ -16,7 +16,11 @@ #include <tdeapplication.h> #include <tdeaboutdata.h> #include <tdecmdlineargs.h> +#include <tdeconfig.h> #include <tdelocale.h> +#include <dcopclient.h> +#include <dcopref.h> +#include <kdebug.h> static const char description[] = I18N_NOOP("KPDF, a TDE PDF viewer based on XPDF"); @@ -25,6 +29,7 @@ static const char version[] = "0.5.10"; static TDECmdLineOptions options[] = { + { "new-instance", I18N_NOOP("Don't reuse existing instance"), 0 }, { "+[URL]", I18N_NOOP("Document to open"), 0 }, TDECmdLineLastOption }; @@ -60,12 +65,61 @@ int main(int argc, char** argv) // no session.. just start up normally TDECmdLineArgs* args = TDECmdLineArgs::parsedArgs(); - KPDF::Shell* widget = new KPDF::Shell; - for (int i = 0; i < args->count(); ++i) + DCOPClient *client = kapp->dcopClient(); + if (!client->attach()) { - widget->openURL(args->url(i)); + kdError() << "KPDF::Shell cannot attach DCOP client" << endl; + return 2; + } + + bool reuseKPDF; + + if (args->isSet("new-instance")) + { + reuseKPDF = false; + } + else + { + TDEConfig cfg("kpdfpartrc"); + cfg.setGroup("General"); + reuseKPDF = cfg.readBoolEntry("OpenInExistingKPDF", false); + } + + TQCString kpdfInstance = ""; + TQCString regName = client->registerAs(kapp->name(), true); + + if (reuseKPDF && args->count()) + { + QCStringList allClients = client->registeredApplications(); + for (int c = 0; c < allClients.count(); ++c) + { + if (allClients[c].left(5) == "kpdf-" && allClients[c] != regName) + { + kpdfInstance = allClients[c]; + } + } + } + + if (kpdfInstance.isEmpty()) + { + KPDF::Shell* widget = new KPDF::Shell; + for (int i = 0; i < args->count(); ++i) + { + widget->openURL(args->url(i)); + } + widget->show(); + } + else + { + for (int i = 0; i < args->count(); ++i) + { + DCOPRef ref(kpdfInstance, "KPDFShellDCOPIface"); + ref.call("openURL", args->url(i)); + } + DCOPRef ref(kpdfInstance, "KPDF::Shell"); + ref.call("raise"); + return 1; } - widget->show(); args->clear(); } diff --git a/kpdf/shell/shell.cpp b/kpdf/shell/shell.cpp index c34ca546..ed9f27cb 100644 --- a/kpdf/shell/shell.cpp +++ b/kpdf/shell/shell.cpp @@ -47,7 +47,7 @@ using namespace KPDF; Shell::Shell() - : KParts::MainWindow(0, "KPDF::Shell"), + : DCOPObject("KPDFShellDCOPIface"), KParts::MainWindow(0, "KPDF::Shell"), m_menuBarWasShown(true), m_toolBarWasShown(true), m_tabs(nullptr), @@ -59,7 +59,7 @@ Shell::Shell() } Shell::Shell(const KURL &url) - : KParts::MainWindow(0, "KPDF::Shell"), + : DCOPObject("KPDFShellDCOPIface"), KParts::MainWindow(0, "KPDF::Shell"), m_menuBarWasShown(true), m_toolBarWasShown(true), m_tabs(nullptr), @@ -115,7 +115,7 @@ void Shell::init() } setAutoSaveSettings(); - slotAddTab(); + addTab(); if (m_openUrl.isValid()) { TQTimer::singleShot(0, this, TQ_SLOT(delayedOpen())); @@ -172,6 +172,12 @@ void Shell::openURL( const KURL & url ) } } +const KURL Shell::currentTabURL() +{ + KParts::ReadOnlyPart *part = static_cast<KParts::ReadOnlyPart*>(m_manager->activePart()); + return part->url(); +} + void Shell::readSettings() { m_recent->loadEntries( TDEGlobal::config() ); @@ -208,23 +214,23 @@ void Shell::setupActions() m_fullScreenAction = KStdAction::fullScreen(this, TQ_SLOT(slotUpdateFullScreen()), actionCollection(), this); TDEAction *addTab = new TDEAction(i18n("&New Tab"), SmallIcon("tab_new"), "Ctrl+Shift+N;Ctrl+T", - this, TQ_SLOT(slotAddTab()), actionCollection(), + this, TQ_SLOT(addTab()), actionCollection(), "newtab"); m_addTabButton = new TQToolButton(m_tabs); m_addTabButton->setIconSet(SmallIconSet("tab_new")); m_tabs->setCornerWidget(m_addTabButton, TQt::TopLeft); - connect(m_addTabButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotAddTab())); + connect(m_addTabButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(addTab())); m_addTabButton->show(); TDEAction *removeTab = new TDEAction(i18n("&Close Tab"), SmallIcon("tab_remove"), "Ctrl+W", - this, TQ_SLOT(slotRemoveTab()), actionCollection(), + this, TQ_SLOT(removeTab()), actionCollection(), "removecurrenttab"); m_removeTabButton = new TQToolButton(m_tabs); m_removeTabButton->setIconSet(SmallIconSet("tab_remove")); m_tabs->setCornerWidget(m_removeTabButton, TQt::TopRight); - connect(m_removeTabButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotRemoveTab())); + connect(m_removeTabButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(removeTab())); m_removeTabButton->show(); TDEAction *duplicateTab = new TDEAction(i18n("&Duplicate Tab"), SmallIcon("tab_duplicate"), "Ctrl+Shift+D", @@ -367,12 +373,12 @@ KParts::ReadOnlyPart* Shell::createTab() return part; } -void Shell::slotAddTab() +void Shell::addTab() { createTab(); } -void Shell::slotRemoveTab() +void Shell::removeTab() { if (m_workingTab == -1) { @@ -406,7 +412,7 @@ void Shell::initTabContextMenu() m_tabsContextMenu = new TQPopupMenu(this); m_tabsContextMenu->insertItem(SmallIcon("tab_new"), i18n("&New Tab"), - this, TQ_SLOT(slotAddTab()), + this, TQ_SLOT(addTab()), action("newtab")->shortcut()); m_tabsContextMenu->insertItem(SmallIconSet("tab_duplicate"), i18n("&Duplicate Tab"), @@ -432,7 +438,7 @@ void Shell::initTabContextMenu() m_tabsContextMenu->insertSeparator(); m_tabsContextMenu->insertItem(SmallIconSet("tab_remove"), i18n("&Close Tab"), - this, TQ_SLOT(slotRemoveTab()), + this, TQ_SLOT(removeTab()), action("removecurrenttab")->shortcut(), TabContextMenuItem::TabRemove); m_tabsContextMenu->insertItem(SmallIconSet("tab_remove_other"), @@ -548,10 +554,20 @@ void Shell::slotBreakOffTab() KParts::ReadOnlyPart *currentTab = findPartForTab(m_workingTab); if (currentTab) { - KPDF::Shell* widget = new KPDF::Shell(currentTab->url()); - widget->show(); + TQString e; + TQStringList args; + args << "--new-instance"; + if (currentTab->url().isValid()) + { + args << currentTab->url().url(); + } + int s = kapp->tdeinitExec("kpdf", args, &e, nullptr, "0"); + if (s != 0) + { + kdWarning() << "Unable to start new KPDF instance: " << e << endl; + } } - slotRemoveTab(); + removeTab(); m_workingTab = -1; } diff --git a/kpdf/shell/shell.h b/kpdf/shell/shell.h index e36ddc78..6198aa4c 100644 --- a/kpdf/shell/shell.h +++ b/kpdf/shell/shell.h @@ -21,6 +21,7 @@ #endif #include <tdeparts/mainwindow.h> +#include "dcop.h" class TQToolButton; class TQPopupMenu; @@ -43,11 +44,10 @@ namespace KPDF * @author Wilco Greven <greven@kde.org> * @version 0.1 */ - class Shell : public KParts::MainWindow + class Shell : public KParts::MainWindow, virtual public KPDFShellDCOPIface { TQ_OBJECT - public: /** * Default Constructor @@ -74,6 +74,8 @@ namespace KPDF TabRemoveOther }; + const KURL currentTabURL(); + protected: /** * This method is called when it is time for the app to save its @@ -95,8 +97,9 @@ namespace KPDF void reconfigure(); void openURL(const KURL & url); - void slotAddTab(); - void slotRemoveTab(); + void addTab(); + void removeTab(); + void slotQuit(); private slots: |
