summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMavridis Philippe <mavridisf@gmail.com>2025-04-09 15:31:05 +0300
committerMavridis Philippe <mavridisf@gmail.com>2025-04-14 19:07:32 +0300
commit77ebecd92cef8d8c368ffb9cee3c856888456546 (patch)
treeaa9598c96c13820a6987d18666a0e24ab915e4b5
parenteea9673d2a3ac7ef6f7cb5f973c502eb7af8419d (diff)
downloadtdegraphics-77ebecd92cef8d8c368ffb9cee3c856888456546.tar.gz
tdegraphics-77ebecd92cef8d8c368ffb9cee3c856888456546.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>
-rw-r--r--kpdf/conf/dlggeneral.ui8
-rw-r--r--kpdf/conf/kpdf.kcfg3
-rw-r--r--kpdf/conf/preferencesdialog.cpp1
-rw-r--r--kpdf/shell/CMakeLists.txt2
-rw-r--r--kpdf/shell/dcop.h27
-rw-r--r--kpdf/shell/main.cpp62
-rw-r--r--kpdf/shell/shell.cpp44
-rw-r--r--kpdf/shell/shell.h11
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 &amp;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..aa44bca6 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 = tdeApp->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(tdeApp->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 f2962be0..f6ba2f18 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 = tdeApp->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: