File indexing completed on 2024-04-21 05:45:44

0001 /*
0002  * SPDX-FileCopyrightText: 2015 Ashish Bansal <bansal.ashish096@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "global.h"
0008 
0009 #include "dolphin_generalsettings.h"
0010 #include "dolphindebug.h"
0011 #include "dolphinmainwindowinterface.h"
0012 #include "views/viewproperties.h"
0013 
0014 #include <KConfigWatcher>
0015 #include <KDialogJobUiDelegate>
0016 #include <KIO/ApplicationLauncherJob>
0017 #include <KService>
0018 #include <KWindowSystem>
0019 
0020 #include <QApplication>
0021 
0022 QList<QUrl> Dolphin::validateUris(const QStringList &uriList)
0023 {
0024     const QString currentDir = QDir::currentPath();
0025     QList<QUrl> urls;
0026     for (const QString &str : uriList) {
0027         const QUrl url = QUrl::fromUserInput(str, currentDir, QUrl::AssumeLocalFile);
0028         if (url.isValid()) {
0029             urls.append(url);
0030         } else {
0031             qCWarning(DolphinDebug) << "Invalid URL: " << str;
0032         }
0033     }
0034     return urls;
0035 }
0036 
0037 QUrl Dolphin::homeUrl()
0038 {
0039     return QUrl::fromUserInput(GeneralSettings::homeUrl(), QString(), QUrl::AssumeLocalFile);
0040 }
0041 
0042 void Dolphin::openNewWindow(const QList<QUrl> &urls, QWidget *window, const OpenNewWindowFlags &flags)
0043 {
0044     QString command = QStringLiteral("dolphin --new-window");
0045 
0046     if (flags.testFlag(OpenNewWindowFlag::Select)) {
0047         command.append(QLatin1String(" --select"));
0048     }
0049 
0050     if (!urls.isEmpty()) {
0051         command.append(QLatin1String(" %U"));
0052     }
0053     KService::Ptr service(new KService(QApplication::applicationDisplayName(), command, QApplication::windowIcon().name()));
0054     auto *job = new KIO::ApplicationLauncherJob(service, window);
0055     job->setUrls(urls);
0056     job->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, window));
0057     job->start();
0058 }
0059 
0060 bool Dolphin::attachToExistingInstance(const QList<QUrl> &inputUrls,
0061                                        bool openFiles,
0062                                        bool splitView,
0063                                        const QString &preferredService,
0064                                        const QString &activationToken)
0065 {
0066     bool attached = false;
0067 
0068     if (inputUrls.isEmpty()) {
0069         return false;
0070     }
0071 
0072     auto dolphinInterfaces = dolphinGuiInstances(preferredService);
0073     if (dolphinInterfaces.isEmpty()) {
0074         return false;
0075     }
0076 
0077     int activeWindowIndex = -1;
0078     for (const auto &interface : std::as_const(dolphinInterfaces)) {
0079         ++activeWindowIndex;
0080 
0081         auto isActiveWindowReply = interface.first->isActiveWindow();
0082         isActiveWindowReply.waitForFinished();
0083         if (!isActiveWindowReply.isError() && isActiveWindowReply.value()) {
0084             break;
0085         }
0086     }
0087 
0088     // check to see if any instances already have any of the given URLs or their parents open
0089     QList<QUrl> newWindowURLs;
0090     for (const QUrl &url : inputUrls) {
0091         bool urlFound = false;
0092         const QString urlString = url.toString();
0093 
0094         // looping through the windows starting from the active one
0095         int i = activeWindowIndex;
0096         do {
0097             auto &interface = dolphinInterfaces[i];
0098 
0099             auto isUrlOpenReply = openFiles ? interface.first->isItemVisibleInAnyView(urlString) : interface.first->isUrlOpen(urlString);
0100             isUrlOpenReply.waitForFinished();
0101             if (!isUrlOpenReply.isError() && isUrlOpenReply.value()) {
0102                 interface.second.append(urlString);
0103                 urlFound = true;
0104                 break;
0105             }
0106 
0107             i = (i + 1) % dolphinInterfaces.size();
0108         } while (i != activeWindowIndex);
0109 
0110         if (!urlFound) {
0111             if (GeneralSettings::openExternallyCalledFolderInNewTab()) {
0112                 dolphinInterfaces[activeWindowIndex].second.append(urlString);
0113             } else {
0114                 newWindowURLs.append(url);
0115             }
0116         }
0117     }
0118 
0119     for (const auto &interface : std::as_const(dolphinInterfaces)) {
0120         if (interface.second.isEmpty()) {
0121             continue;
0122         }
0123         auto reply = openFiles ? interface.first->openFiles(interface.second, splitView) : interface.first->openDirectories(interface.second, splitView);
0124         reply.waitForFinished();
0125         if (!reply.isError()) {
0126             interface.first->activateWindow(activationToken);
0127             attached = true;
0128         }
0129     }
0130     if (attached && !newWindowURLs.isEmpty()) {
0131         if (openFiles) {
0132             openNewWindow(newWindowURLs, nullptr, Dolphin::OpenNewWindowFlag::Select);
0133         } else {
0134             openNewWindow(newWindowURLs);
0135         }
0136     }
0137 
0138     return attached;
0139 }
0140 
0141 QVector<QPair<QSharedPointer<OrgKdeDolphinMainWindowInterface>, QStringList>> Dolphin::dolphinGuiInstances(const QString &preferredService)
0142 {
0143     QVector<QPair<QSharedPointer<OrgKdeDolphinMainWindowInterface>, QStringList>> dolphinInterfaces;
0144     if (!preferredService.isEmpty()) {
0145         QSharedPointer<OrgKdeDolphinMainWindowInterface> preferredInterface(
0146             new OrgKdeDolphinMainWindowInterface(preferredService, QStringLiteral("/dolphin/Dolphin_1"), QDBusConnection::sessionBus()));
0147         if (preferredInterface->isValid() && !preferredInterface->lastError().isValid()) {
0148             dolphinInterfaces.append(qMakePair(preferredInterface, QStringList()));
0149         }
0150     }
0151 
0152     // Look for dolphin instances among all available dbus services.
0153     QDBusConnectionInterface *sessionInterface = QDBusConnection::sessionBus().interface();
0154     const QStringList dbusServices = sessionInterface ? sessionInterface->registeredServiceNames().value() : QStringList();
0155     // Don't match the service without trailing "-" (unique instance)
0156     const QString pattern = QStringLiteral("org.kde.dolphin-");
0157     // Don't match the pid without leading "-"
0158     const QString myPid = QLatin1Char('-') + QString::number(QCoreApplication::applicationPid());
0159     for (const QString &service : dbusServices) {
0160         if (service.startsWith(pattern) && !service.endsWith(myPid)) {
0161             // Check if instance can handle our URLs
0162             QSharedPointer<OrgKdeDolphinMainWindowInterface> interface(
0163                 new OrgKdeDolphinMainWindowInterface(service, QStringLiteral("/dolphin/Dolphin_1"), QDBusConnection::sessionBus()));
0164             if (interface->isValid() && !interface->lastError().isValid()) {
0165                 dolphinInterfaces.append(qMakePair(interface, QStringList()));
0166             }
0167         }
0168     }
0169 
0170     return dolphinInterfaces;
0171 }
0172 
0173 QPair<QString, Qt::SortOrder> Dolphin::sortOrderForUrl(QUrl &url)
0174 {
0175     ViewProperties globalProps(url);
0176     return QPair<QString, Qt::SortOrder>(globalProps.sortRole(), globalProps.sortOrder());
0177 }
0178 
0179 double GlobalConfig::animationDurationFactor()
0180 {
0181     if (s_animationDurationFactor >= 0.0) {
0182         return s_animationDurationFactor;
0183     }
0184     // This is the first time this method is called.
0185     auto kdeGlobalsConfig = KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("KDE"));
0186     updateAnimationDurationFactor(kdeGlobalsConfig, {"AnimationDurationFactor"});
0187 
0188     KConfigWatcher::Ptr configWatcher = KConfigWatcher::create(KSharedConfig::openConfig());
0189     connect(configWatcher.data(), &KConfigWatcher::configChanged, &GlobalConfig::updateAnimationDurationFactor);
0190     return s_animationDurationFactor;
0191 }
0192 
0193 void GlobalConfig::updateAnimationDurationFactor(const KConfigGroup &group, const QByteArrayList &names)
0194 {
0195     if (group.name() == QLatin1String("KDE") && names.contains(QByteArrayLiteral("AnimationDurationFactor"))) {
0196         s_animationDurationFactor = std::max(0.0, group.readEntry("AnimationDurationFactor", 1.0));
0197     }
0198 }
0199 
0200 double GlobalConfig::s_animationDurationFactor = -1.0;
0201 
0202 #include "moc_global.cpp"