2 * SPDX-FileCopyrightText: 2015 Ashish Bansal <bansal.ashish096@gmail.com>
4 * SPDX-License-Identifier: GPL-2.0-or-later
9 #include "dolphin_generalsettings.h"
10 #include "dolphindebug.h"
11 #include "dolphinmainwindowinterface.h"
12 #include "views/viewproperties.h"
14 #include <KConfigWatcher>
15 #include <KDialogJobUiDelegate>
16 #include <KIO/ApplicationLauncherJob>
18 #include <KWindowSystem>
19 #ifdef HAVE_KACTIVITIES
20 #include <KActivities/Consumer>
23 #include <QApplication>
25 QList
<QUrl
> Dolphin::validateUris(const QStringList
&uriList
)
27 const QString currentDir
= QDir::currentPath();
29 for (const QString
&str
: uriList
) {
30 const QUrl url
= QUrl::fromUserInput(str
, currentDir
, QUrl::AssumeLocalFile
);
34 qCWarning(DolphinDebug
) << "Invalid URL: " << str
;
40 QUrl
Dolphin::homeUrl()
42 return QUrl::fromUserInput(GeneralSettings::homeUrl(), QString(), QUrl::AssumeLocalFile
);
45 void Dolphin::openNewWindow(const QList
<QUrl
> &urls
, QWidget
*window
, const OpenNewWindowFlags
&flags
)
47 QString command
= QStringLiteral("dolphin --new-window");
49 if (flags
.testFlag(OpenNewWindowFlag::Select
)) {
50 command
.append(QLatin1String(" --select"));
53 if (!urls
.isEmpty()) {
54 command
.append(QLatin1String(" %U"));
56 KService::Ptr
service(new KService(QApplication::applicationDisplayName(), command
, QApplication::windowIcon().name()));
57 auto *job
= new KIO::ApplicationLauncherJob(service
, window
);
59 job
->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled
, window
));
63 bool Dolphin::attachToExistingInstance(const QList
<QUrl
> &inputUrls
,
66 const QString
&preferredService
,
67 const QString
&activationToken
)
69 bool attached
= false;
71 if (inputUrls
.isEmpty()) {
75 auto dolphinInterfaces
= dolphinGuiInstances(preferredService
);
76 if (dolphinInterfaces
.isEmpty()) {
80 int activeWindowIndex
= -1;
81 for (const auto &interface
: qAsConst(dolphinInterfaces
)) {
84 auto isActiveWindowReply
= interface
.first
->isActiveWindow();
85 isActiveWindowReply
.waitForFinished();
86 if (!isActiveWindowReply
.isError() && isActiveWindowReply
.value()) {
91 // check to see if any instances already have any of the given URLs or their parents open
92 QList
<QUrl
> newWindowURLs
;
93 for (const QUrl
&url
: inputUrls
) {
94 bool urlFound
= false;
95 const QString urlString
= url
.toString();
97 // looping through the windows starting from the active one
98 int i
= activeWindowIndex
;
100 auto &interface
= dolphinInterfaces
[i
];
102 auto isUrlOpenReply
= openFiles
? interface
.first
->isItemVisibleInAnyView(urlString
) : interface
.first
->isUrlOpen(urlString
);
103 isUrlOpenReply
.waitForFinished();
104 if (!isUrlOpenReply
.isError() && isUrlOpenReply
.value()) {
105 interface
.second
.append(urlString
);
110 i
= (i
+ 1) % dolphinInterfaces
.size();
111 } while (i
!= activeWindowIndex
);
114 if (GeneralSettings::openExternallyCalledFolderInNewTab()) {
115 dolphinInterfaces
[activeWindowIndex
].second
.append(urlString
);
117 newWindowURLs
.append(url
);
122 for (const auto &interface
: qAsConst(dolphinInterfaces
)) {
123 if (interface
.second
.isEmpty()) {
126 auto reply
= openFiles
? interface
.first
->openFiles(interface
.second
, splitView
) : interface
.first
->openDirectories(interface
.second
, splitView
);
127 reply
.waitForFinished();
128 if (!reply
.isError()) {
129 interface
.first
->activateWindow(activationToken
);
133 if (attached
&& !newWindowURLs
.isEmpty()) {
135 openNewWindow(newWindowURLs
, nullptr, Dolphin::OpenNewWindowFlag::Select
);
137 openNewWindow(newWindowURLs
);
144 QVector
<QPair
<QSharedPointer
<OrgKdeDolphinMainWindowInterface
>, QStringList
>> Dolphin::dolphinGuiInstances(const QString
&preferredService
)
146 #ifdef HAVE_KACTIVITIES
147 static std::once_flag one_consumer
;
148 static KActivities::Consumer
*consumer
;
149 std::call_once(one_consumer
, []() {
150 consumer
= new KActivities::Consumer();
151 // ensures the consumer is ready for query
153 QObject::connect(consumer
, &KActivities::Consumer::serviceStatusChanged
, &loop
, &QEventLoop::quit
);
158 QVector
<QPair
<QSharedPointer
<OrgKdeDolphinMainWindowInterface
>, QStringList
>> dolphinInterfaces
;
159 const auto tryAppendInterface
= [&dolphinInterfaces
](const QString
&service
) {
160 // Check if instance can handle our URLs
161 QSharedPointer
<OrgKdeDolphinMainWindowInterface
> interface(
162 new OrgKdeDolphinMainWindowInterface(service
, QStringLiteral("/dolphin/Dolphin_1"), QDBusConnection::sessionBus()));
163 if (interface
->isValid() && !interface
->lastError().isValid()) {
164 #ifdef HAVE_KACTIVITIES
165 const auto currentActivity
= consumer
->currentActivity();
166 if (currentActivity
.isEmpty() || currentActivity
== QStringLiteral("00000000-0000-0000-0000-000000000000")
167 || interface
->isOnActivity(consumer
->currentActivity()))
169 if (interface
->isOnCurrentDesktop()) {
170 dolphinInterfaces
.append(qMakePair(interface
, QStringList()));
175 if (!preferredService
.isEmpty()) {
176 tryAppendInterface(preferredService
);
179 // Look for dolphin instances among all available dbus services.
180 QDBusConnectionInterface
*sessionInterface
= QDBusConnection::sessionBus().interface();
181 const QStringList dbusServices
= sessionInterface
? sessionInterface
->registeredServiceNames().value() : QStringList();
182 // Don't match the service without trailing "-" (unique instance)
183 const QString pattern
= QStringLiteral("org.kde.dolphin-");
184 // Don't match the pid without leading "-"
185 const QString myPid
= QLatin1Char('-') + QString::number(QCoreApplication::applicationPid());
186 for (const QString
&service
: dbusServices
) {
187 if (service
.startsWith(pattern
) && !service
.endsWith(myPid
)) {
188 tryAppendInterface(service
);
192 return dolphinInterfaces
;
195 QPair
<QString
, Qt::SortOrder
> Dolphin::sortOrderForUrl(QUrl
&url
)
197 ViewProperties
globalProps(url
);
198 return QPair
<QString
, Qt::SortOrder
>(globalProps
.sortRole(), globalProps
.sortOrder());
201 double GlobalConfig::animationDurationFactor()
203 if (s_animationDurationFactor
>= 0.0) {
204 return s_animationDurationFactor
;
206 // This is the first time this method is called.
207 auto kdeGlobalsConfig
= KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("KDE"));
208 updateAnimationDurationFactor(kdeGlobalsConfig
, {"AnimationDurationFactor"});
210 KConfigWatcher::Ptr configWatcher
= KConfigWatcher::create(KSharedConfig::openConfig());
211 connect(configWatcher
.data(), &KConfigWatcher::configChanged
, &GlobalConfig::updateAnimationDurationFactor
);
212 return s_animationDurationFactor
;
215 void GlobalConfig::updateAnimationDurationFactor(const KConfigGroup
&group
, const QByteArrayList
&names
)
217 if (group
.name() == QLatin1String("KDE") && names
.contains(QByteArrayLiteral("AnimationDurationFactor"))) {
218 s_animationDurationFactor
= std::max(0.0, group
.readEntry("AnimationDurationFactor", 1.0));
222 double GlobalConfig::s_animationDurationFactor
= -1.0;