1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2013 Dawit Alemayehu <adawit@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "../utils_p.h"
9#include "clipboardupdater_p.h"
10#include "copyjob.h"
11#include "deletejob.h"
12#include "filecopyjob.h"
13#include "simplejob.h"
14#include <KUrlMimeData>
15
16#include <QClipboard>
17#include <QGuiApplication>
18#include <QMimeData>
19
20using namespace KIO;
21
22static void overwriteUrlsInClipboard(KJob *job)
23{
24 CopyJob *copyJob = qobject_cast<CopyJob *>(object: job);
25 FileCopyJob *fileCopyJob = qobject_cast<FileCopyJob *>(object: job);
26
27 if (!copyJob && !fileCopyJob) {
28 return;
29 }
30
31 QList<QUrl> newUrls;
32
33 if (copyJob) {
34 const auto srcUrls = copyJob->srcUrls();
35 newUrls.reserve(asize: srcUrls.size());
36 for (const QUrl &url : srcUrls) {
37 QUrl dUrl = copyJob->destUrl().adjusted(options: QUrl::StripTrailingSlash);
38 dUrl.setPath(path: Utils::concatPaths(path1: dUrl.path(), path2: url.fileName()));
39 newUrls.append(t: dUrl);
40 }
41 } else if (fileCopyJob) {
42 newUrls << fileCopyJob->destUrl();
43 }
44
45 QMimeData *mime = new QMimeData();
46 mime->setUrls(newUrls);
47 QGuiApplication::clipboard()->setMimeData(data: mime);
48}
49
50static void updateUrlsInClipboard(KJob *job)
51{
52 CopyJob *copyJob = qobject_cast<CopyJob *>(object: job);
53 FileCopyJob *fileCopyJob = qobject_cast<FileCopyJob *>(object: job);
54
55 if (!copyJob && !fileCopyJob) {
56 return;
57 }
58
59 QClipboard *clipboard = QGuiApplication::clipboard();
60 auto mimeData = clipboard->mimeData();
61 if (!mimeData) {
62 return;
63 }
64
65 QList<QUrl> clipboardUrls = KUrlMimeData::urlsFromMimeData(mimeData);
66 bool update = false;
67
68 if (copyJob) {
69 const QList<QUrl> urls = copyJob->srcUrls();
70 for (const QUrl &url : urls) {
71 const int index = clipboardUrls.indexOf(t: url);
72 if (index > -1) {
73 QUrl dUrl = copyJob->destUrl().adjusted(options: QUrl::StripTrailingSlash);
74 dUrl.setPath(path: Utils::concatPaths(path1: dUrl.path(), path2: url.fileName()));
75 clipboardUrls.replace(i: index, t: dUrl);
76 update = true;
77 }
78 }
79 } else if (fileCopyJob) {
80 const int index = clipboardUrls.indexOf(t: fileCopyJob->srcUrl());
81 if (index > -1) {
82 clipboardUrls.replace(i: index, t: fileCopyJob->destUrl());
83 update = true;
84 }
85 }
86
87 if (update) {
88 QMimeData *mime = new QMimeData();
89 mime->setUrls(clipboardUrls);
90 clipboard->setMimeData(data: mime);
91 }
92}
93
94static void removeUrlsFromClipboard(KJob *job)
95{
96 SimpleJob *simpleJob = qobject_cast<SimpleJob *>(object: job);
97 DeleteJob *deleteJob = qobject_cast<DeleteJob *>(object: job);
98
99 if (!simpleJob && !deleteJob) {
100 return;
101 }
102
103 QList<QUrl> deletedUrls;
104 if (simpleJob) {
105 deletedUrls << simpleJob->url();
106 } else if (deleteJob) {
107 deletedUrls << deleteJob->urls();
108 }
109
110 if (deletedUrls.isEmpty()) {
111 return;
112 }
113
114 QClipboard *clipboard = QGuiApplication::clipboard();
115 auto mimeData = clipboard->mimeData();
116 if (!mimeData) {
117 return;
118 }
119
120 QList<QUrl> clipboardUrls = KUrlMimeData::urlsFromMimeData(mimeData);
121 quint32 removedCount = 0;
122
123 for (const QUrl &url : std::as_const(t&: deletedUrls)) {
124 removedCount += clipboardUrls.removeAll(t: url);
125 }
126
127 if (removedCount > 0) {
128 QMimeData *mime = new QMimeData();
129 if (!clipboardUrls.isEmpty()) {
130 mime->setUrls(clipboardUrls);
131 }
132 clipboard->setMimeData(data: mime);
133 }
134}
135
136void ClipboardUpdater::slotResult(KJob *job)
137{
138 if (job->error()) {
139 return;
140 }
141
142 switch (m_mode) {
143 case JobUiDelegateExtension::UpdateContent:
144 updateUrlsInClipboard(job);
145 break;
146 case JobUiDelegateExtension::OverwriteContent:
147 overwriteUrlsInClipboard(job);
148 break;
149 case JobUiDelegateExtension::RemoveContent:
150 removeUrlsFromClipboard(job);
151 break;
152 }
153}
154
155void ClipboardUpdater::setMode(JobUiDelegateExtension::ClipboardUpdaterMode mode)
156{
157 m_mode = mode;
158}
159
160void ClipboardUpdater::update(const QUrl &srcUrl, const QUrl &destUrl)
161{
162 QClipboard *clipboard = QGuiApplication::clipboard();
163 auto mimeData = clipboard->mimeData();
164 if (mimeData && mimeData->hasUrls()) {
165 QList<QUrl> clipboardUrls = KUrlMimeData::urlsFromMimeData(mimeData: clipboard->mimeData());
166 const int index = clipboardUrls.indexOf(t: srcUrl);
167 if (index > -1) {
168 clipboardUrls.replace(i: index, t: destUrl);
169 QMimeData *mime = new QMimeData();
170 mime->setUrls(clipboardUrls);
171 clipboard->setMimeData(data: mime);
172 }
173 }
174}
175
176ClipboardUpdater::ClipboardUpdater(Job *job, JobUiDelegateExtension::ClipboardUpdaterMode mode)
177 : QObject(job)
178 , m_mode(mode)
179{
180 Q_ASSERT(job);
181 connect(sender: job, signal: &KJob::result, context: this, slot: &ClipboardUpdater::slotResult);
182}
183
184#include "moc_clipboardupdater_p.cpp"
185

source code of kio/src/widgets/clipboardupdater.cpp