diff --git a/src/dbusinterface.cpp b/src/dbusinterface.cpp index fd2d229a2..abdb3a0fe 100644 --- a/src/dbusinterface.cpp +++ b/src/dbusinterface.cpp @@ -1,73 +1,83 @@ /* * Copyright 2015 Ashish Bansal * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "dbusinterface.h" #include "global.h" #include "dolphin_generalsettings.h" #include #include #include #include #include DBusInterface::DBusInterface() : QObject() { QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/freedesktop/FileManager1"), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors); QDBusConnection::sessionBus().interface()->registerService(QStringLiteral("org.freedesktop.FileManager1"), QDBusConnectionInterface::QueueService); } void DBusInterface::ShowFolders(const QStringList& uriList, const QString& startUpId) { Q_UNUSED(startUpId) const QList urls = Dolphin::validateUris(uriList); if (urls.isEmpty()) { return; } - const auto serviceName = QStringLiteral("org.kde.dolphin-%1").arg(QCoreApplication::applicationPid()); + const auto serviceName = isDaemon() ? QString() : QStringLiteral("org.kde.dolphin-%1").arg(QCoreApplication::applicationPid()); if(!Dolphin::attachToExistingInstance(urls, false, GeneralSettings::splitView(), serviceName)) { Dolphin::openNewWindow(urls); } } void DBusInterface::ShowItems(const QStringList& uriList, const QString& startUpId) { Q_UNUSED(startUpId) const QList urls = Dolphin::validateUris(uriList); if (urls.isEmpty()) { return; } - const auto serviceName = QStringLiteral("org.kde.dolphin-%1").arg(QCoreApplication::applicationPid()); + const auto serviceName = isDaemon() ? QString() : QStringLiteral("org.kde.dolphin-%1").arg(QCoreApplication::applicationPid()); if(!Dolphin::attachToExistingInstance(urls, true, GeneralSettings::splitView(), serviceName)) { Dolphin::openNewWindow(urls, nullptr, Dolphin::OpenNewWindowFlag::Select); }; } void DBusInterface::ShowItemProperties(const QStringList& uriList, const QString& startUpId) { Q_UNUSED(startUpId) const QList urls = Dolphin::validateUris(uriList); if (!urls.isEmpty()) { KPropertiesDialog::showDialog(urls); } } + +void DBusInterface::setAsDaemon() +{ + m_isDaemon = true; +} + +bool DBusInterface::isDaemon() const +{ + return m_isDaemon; +} diff --git a/src/dbusinterface.h b/src/dbusinterface.h index baf804f68..391916d62 100644 --- a/src/dbusinterface.h +++ b/src/dbusinterface.h @@ -1,37 +1,50 @@ /* * Copyright 2015 Ashish Bansal * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DBUSINTERFACE_H #define DBUSINTERFACE_H #include class DBusInterface : QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.freedesktop.FileManager1") public: DBusInterface(); Q_SCRIPTABLE void ShowFolders(const QStringList& uriList, const QString& startUpId); Q_SCRIPTABLE void ShowItems(const QStringList& uriList, const QString& startUpId); Q_SCRIPTABLE void ShowItemProperties(const QStringList& uriList, const QString& startUpId); + + /** + * Set whether this interface has been created by dolphin --deamon. + */ + void setAsDaemon(); + + /** + * @return Whether this interface has been created by dolphin --deamon. + */ + bool isDaemon() const; + +private: + bool m_isDaemon = false; }; #endif // DBUSINTERFACE_H diff --git a/src/global.cpp b/src/global.cpp index 9aff25b26..34ed4e824 100644 --- a/src/global.cpp +++ b/src/global.cpp @@ -1,143 +1,143 @@ /* * Copyright 2015 Ashish Bansal * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "global.h" #include "dolphin_generalsettings.h" #include "dolphindebug.h" #include #include #include #include #include #include QList Dolphin::validateUris(const QStringList& uriList) { const QString currentDir = QDir::currentPath(); QList urls; foreach (const QString& str, uriList) { const QUrl url = QUrl::fromUserInput(str, currentDir, QUrl::AssumeLocalFile); if (url.isValid()) { urls.append(url); } else { qCWarning(DolphinDebug) << "Invalid URL: " << str; } } return urls; } QUrl Dolphin::homeUrl() { return QUrl::fromUserInput(GeneralSettings::homeUrl(), QString(), QUrl::AssumeLocalFile); } void Dolphin::openNewWindow(const QList &urls, QWidget *window, const OpenNewWindowFlags &flags) { QString command = QStringLiteral("dolphin --new-window"); if (flags.testFlag(OpenNewWindowFlag::Select)) { command.append(QLatin1String(" --select")); } if (!urls.isEmpty()) { command.append(QLatin1String(" %U")); } KRun::run( command, urls, window, QApplication::applicationDisplayName(), QApplication::windowIcon().name() ); } bool Dolphin::attachToExistingInstance(const QList& inputUrls, bool openFiles, bool splitView, const QString& preferredService) { // TODO: once Wayland clients can raise or activate themselves remove check from conditional if (KWindowSystem::isPlatformWayland() || inputUrls.isEmpty() || !GeneralSettings::openExternallyCalledFolderInNewTab()) { return false; } QVector, QStringList>> dolphinInterfaces; if (!preferredService.isEmpty()) { QSharedPointer preferredInterface( new QDBusInterface(preferredService, QStringLiteral("/dolphin/Dolphin_1"), - QString()) // #414402: use empty interface name to prevent QtDBus from caching the interface. + QStringLiteral("org.kde.dolphin.MainWindow")) ); if (preferredInterface->isValid() && !preferredInterface->lastError().isValid()) { dolphinInterfaces.append(qMakePair(preferredInterface, QStringList())); } } // Look for dolphin instances among all available dbus services. const QStringList dbusServices = QDBusConnection::sessionBus().interface()->registeredServiceNames().value(); // Don't match the service without trailing "-" (unique instance) const QString pattern = QStringLiteral("org.kde.dolphin-"); // Don't match the pid without leading "-" const QString myPid = QLatin1Char('-') + QString::number(QCoreApplication::applicationPid()); for (const QString& service : dbusServices) { if (service.startsWith(pattern) && !service.endsWith(myPid)) { // Check if instance can handle our URLs QSharedPointer interface( new QDBusInterface(service, QStringLiteral("/dolphin/Dolphin_1"), QStringLiteral("org.kde.dolphin.MainWindow")) ); if (interface->isValid() && !interface->lastError().isValid()) { dolphinInterfaces.append(qMakePair(interface, QStringList())); } } } if (dolphinInterfaces.isEmpty()) { return false; } QStringList newUrls; // check to see if any instances already have any of the given URLs open const auto urls = QUrl::toStringList(inputUrls); for (const QString& url : urls) { bool urlFound = false; for (auto& interface: dolphinInterfaces) { QDBusReply isUrlOpenReply = interface.first->call(QStringLiteral("isUrlOpen"), url); if (isUrlOpenReply.isValid() && isUrlOpenReply.value()) { interface.second.append(url); urlFound = true; break; } } if (!urlFound) { newUrls.append(url); } } dolphinInterfaces.front().second << newUrls; for (const auto& interface: dolphinInterfaces) { if (!interface.second.isEmpty()) { interface.first->call(openFiles ? QStringLiteral("openFiles") : QStringLiteral("openDirectories"), interface.second, splitView); interface.first->call(QStringLiteral("activateWindow")); } } return true; } diff --git a/src/global.h b/src/global.h index f203615f1..7ee564581 100644 --- a/src/global.h +++ b/src/global.h @@ -1,59 +1,61 @@ /* * Copyright 2015 Ashish Bansal * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GLOBAL_H #define GLOBAL_H #include #include #include namespace Dolphin { QList validateUris(const QStringList& uriList); /** * Returns the home url which is defined in General Settings */ QUrl homeUrl(); enum class OpenNewWindowFlag { None = 0, Select = 1<<1 }; Q_DECLARE_FLAGS(OpenNewWindowFlags, OpenNewWindowFlag) /** * Opens a new Dolphin window */ void openNewWindow(const QList &urls = {}, QWidget *window = nullptr, const OpenNewWindowFlags &flags = OpenNewWindowFlag::None); /** * Attaches URLs to an existing Dolphin instance if possible. - * Returns true if URLs were successfully attached + * If @p preferredService is a valid dbus service, it will be tried first. + * @p preferredService needs to support the org.kde.dolphin.MainWindow dbus interface with the /dolphin/Dolphin_1 path. + * Returns true if the URLs were successfully attached. */ bool attachToExistingInstance(const QList& inputUrls, bool openFiles, bool splitView, const QString& preferredService = QString()); /** * TODO: Move this somewhere global to all KDE apps, not just Dolphin */ const int VERTICAL_SPACER_HEIGHT = 18; const int LAYOUT_SPACING_SMALL = 2; } #endif //GLOBAL_H diff --git a/src/main.cpp b/src/main.cpp index 2b2674f9d..5932df5ce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,189 +1,190 @@ /*************************************************************************** * Copyright (C) 2006 by Peter Penz * * Copyright (C) 2006 by Stefan Monov * * Copyright (C) 2015 by Mathieu Tarral * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ #include "dbusinterface.h" #include "dolphin_generalsettings.h" #include "dolphin_version.h" #include "dolphindebug.h" #include "dolphinmainwindow.h" #include "global.h" #include #include #include #include #include #include #include #include #include #include #include #ifndef Q_OS_WIN #include #endif #include extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv) { #ifndef Q_OS_WIN // Prohibit using sudo or kdesu (but allow using the root user directly) if (getuid() == 0) { if (!qEnvironmentVariableIsEmpty("SUDO_USER")) { std::cout << "Executing Dolphin with sudo is not possible due to unfixable security vulnerabilities." << std::endl; return EXIT_FAILURE; } else if (!qEnvironmentVariableIsEmpty("KDESU_USER")) { std::cout << "Executing Dolphin with kdesu is not possible due to unfixable security vulnerabilities." << std::endl; return EXIT_FAILURE; } } #endif /** * enable high dpi support */ QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); QApplication app(argc, argv); app.setWindowIcon(QIcon::fromTheme(QStringLiteral("system-file-manager"), app.windowIcon())); KCrash::initialize(); Kdelibs4ConfigMigrator migrate(QStringLiteral("dolphin")); migrate.setConfigFiles(QStringList() << QStringLiteral("dolphinrc")); migrate.setUiFiles(QStringList() << QStringLiteral("dolphinpart.rc") << QStringLiteral("dolphinui.rc")); migrate.migrate(); KLocalizedString::setApplicationDomain("dolphin"); KAboutData aboutData(QStringLiteral("dolphin"), i18n("Dolphin"), QStringLiteral(DOLPHIN_VERSION_STRING), i18nc("@title", "File Manager"), KAboutLicense::GPL, i18nc("@info:credit", "(C) 2006-2018 Peter Penz, Frank Reininghaus, Emmanuel Pescosta and Elvis Angelaccio")); aboutData.setHomepage(QStringLiteral("https://kde.org/applications/system/org.kde.dolphin")); aboutData.addAuthor(i18nc("@info:credit", "Elvis Angelaccio"), i18nc("@info:credit", "Maintainer (since 2018) and developer"), QStringLiteral("elvis.angelaccio@kde.org")); aboutData.addAuthor(i18nc("@info:credit", "Emmanuel Pescosta"), i18nc("@info:credit", "Maintainer (2014-2018) and developer"), QStringLiteral("emmanuelpescosta099@gmail.com")); aboutData.addAuthor(i18nc("@info:credit", "Frank Reininghaus"), i18nc("@info:credit", "Maintainer (2012-2014) and developer"), QStringLiteral("frank78ac@googlemail.com")); aboutData.addAuthor(i18nc("@info:credit", "Peter Penz"), i18nc("@info:credit", "Maintainer and developer (2006-2012)"), QStringLiteral("peter.penz19@gmail.com")); aboutData.addAuthor(i18nc("@info:credit", "Sebastian Trüg"), i18nc("@info:credit", "Developer"), QStringLiteral("trueg@kde.org")); aboutData.addAuthor(i18nc("@info:credit", "David Faure"), i18nc("@info:credit", "Developer"), QStringLiteral("faure@kde.org")); aboutData.addAuthor(i18nc("@info:credit", "Aaron J. Seigo"), i18nc("@info:credit", "Developer"), QStringLiteral("aseigo@kde.org")); aboutData.addAuthor(i18nc("@info:credit", "Rafael Fernández López"), i18nc("@info:credit", "Developer"), QStringLiteral("ereslibre@kde.org")); aboutData.addAuthor(i18nc("@info:credit", "Kevin Ottens"), i18nc("@info:credit", "Developer"), QStringLiteral("ervin@kde.org")); aboutData.addAuthor(i18nc("@info:credit", "Holger Freyther"), i18nc("@info:credit", "Developer"), QStringLiteral("freyther@gmx.net")); aboutData.addAuthor(i18nc("@info:credit", "Max Blazejak"), i18nc("@info:credit", "Developer"), QStringLiteral("m43ksrocks@gmail.com")); aboutData.addAuthor(i18nc("@info:credit", "Michael Austin"), i18nc("@info:credit", "Documentation"), QStringLiteral("tuxedup@users.sourceforge.net")); KAboutData::setApplicationData(aboutData); QCommandLineParser parser; aboutData.setupCommandLine(&parser); // command line options parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("select"), i18nc("@info:shell", "The files and folders passed as arguments " "will be selected."))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("split"), i18nc("@info:shell", "Dolphin will get started with a split view."))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("new-window"), i18nc("@info:shell", "Dolphin will explicitly open in a new window."))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("daemon"), i18nc("@info:shell", "Start Dolphin Daemon (only required for DBus Interface)"))); parser.addPositionalArgument(QStringLiteral("+[Url]"), i18nc("@info:shell", "Document to open")); parser.process(app); aboutData.processCommandLine(&parser); const bool splitView = parser.isSet(QStringLiteral("split")) || GeneralSettings::splitView(); const bool openFiles = parser.isSet(QStringLiteral("select")); const QStringList args = parser.positionalArguments(); QList urls = Dolphin::validateUris(args); if (parser.isSet(QStringLiteral("daemon"))) { KDBusService dolphinDBusService; DBusInterface interface; + interface.setAsDaemon(); return app.exec(); } if (!parser.isSet(QStringLiteral("new-window"))) { if (Dolphin::attachToExistingInstance(urls, openFiles, splitView)) { // Successfully attached to existing instance of Dolphin return 0; } } if (urls.isEmpty()) { // We need at least one URL to open Dolphin urls.append(Dolphin::homeUrl()); } if (splitView && urls.size() < 2) { // Split view does only make sense if we have at least 2 URLs urls.append(urls.last()); } DolphinMainWindow* mainWindow = new DolphinMainWindow(); if (openFiles) { mainWindow->openFiles(urls, splitView); } else { mainWindow->openDirectories(urls, splitView); } mainWindow->show(); if (app.isSessionRestored()) { const QString className = KXmlGuiWindow::classNameOfToplevel(1); if (className == QLatin1String("DolphinMainWindow")) { mainWindow->restore(1); } else { qCWarning(DolphinDebug) << "Unknown class " << className << " in session saved data!"; } } KDBusService dolphinDBusService; DBusInterface interface; return app.exec(); // krazy:exclude=crash; }