File indexing completed on 2024-04-28 15:27:17

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2013 Dawit Alemayehu <adawit@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "../utils_p.h"
0009 #include "clipboardupdater_p.h"
0010 #include "copyjob.h"
0011 #include "deletejob.h"
0012 #include "jobclasses.h"
0013 #include <KUrlMimeData>
0014 
0015 #include <QClipboard>
0016 #include <QGuiApplication>
0017 #include <QMimeData>
0018 
0019 using namespace KIO;
0020 
0021 static void overwriteUrlsInClipboard(KJob *job)
0022 {
0023     CopyJob *copyJob = qobject_cast<CopyJob *>(job);
0024     FileCopyJob *fileCopyJob = qobject_cast<FileCopyJob *>(job);
0025 
0026     if (!copyJob && !fileCopyJob) {
0027         return;
0028     }
0029 
0030     QList<QUrl> newUrls;
0031 
0032     if (copyJob) {
0033         const auto srcUrls = copyJob->srcUrls();
0034         newUrls.reserve(srcUrls.size());
0035         for (const QUrl &url : srcUrls) {
0036             QUrl dUrl = copyJob->destUrl().adjusted(QUrl::StripTrailingSlash);
0037             dUrl.setPath(Utils::concatPaths(dUrl.path(), url.fileName()));
0038             newUrls.append(dUrl);
0039         }
0040     } else if (fileCopyJob) {
0041         newUrls << fileCopyJob->destUrl();
0042     }
0043 
0044     QMimeData *mime = new QMimeData();
0045     mime->setUrls(newUrls);
0046     QGuiApplication::clipboard()->setMimeData(mime);
0047 }
0048 
0049 static void updateUrlsInClipboard(KJob *job)
0050 {
0051     CopyJob *copyJob = qobject_cast<CopyJob *>(job);
0052     FileCopyJob *fileCopyJob = qobject_cast<FileCopyJob *>(job);
0053 
0054     if (!copyJob && !fileCopyJob) {
0055         return;
0056     }
0057 
0058     QClipboard *clipboard = QGuiApplication::clipboard();
0059     auto mimeData = clipboard->mimeData();
0060     if (!mimeData) {
0061         return;
0062     }
0063 
0064     QList<QUrl> clipboardUrls = KUrlMimeData::urlsFromMimeData(mimeData);
0065     bool update = false;
0066 
0067     if (copyJob) {
0068         const QList<QUrl> urls = copyJob->srcUrls();
0069         for (const QUrl &url : urls) {
0070             const int index = clipboardUrls.indexOf(url);
0071             if (index > -1) {
0072                 QUrl dUrl = copyJob->destUrl().adjusted(QUrl::StripTrailingSlash);
0073                 dUrl.setPath(Utils::concatPaths(dUrl.path(), url.fileName()));
0074                 clipboardUrls.replace(index, dUrl);
0075                 update = true;
0076             }
0077         }
0078     } else if (fileCopyJob) {
0079         const int index = clipboardUrls.indexOf(fileCopyJob->srcUrl());
0080         if (index > -1) {
0081             clipboardUrls.replace(index, fileCopyJob->destUrl());
0082             update = true;
0083         }
0084     }
0085 
0086     if (update) {
0087         QMimeData *mime = new QMimeData();
0088         mime->setUrls(clipboardUrls);
0089         clipboard->setMimeData(mime);
0090     }
0091 }
0092 
0093 static void removeUrlsFromClipboard(KJob *job)
0094 {
0095     SimpleJob *simpleJob = qobject_cast<SimpleJob *>(job);
0096     DeleteJob *deleteJob = qobject_cast<DeleteJob *>(job);
0097 
0098     if (!simpleJob && !deleteJob) {
0099         return;
0100     }
0101 
0102     QList<QUrl> deletedUrls;
0103     if (simpleJob) {
0104         deletedUrls << simpleJob->url();
0105     } else if (deleteJob) {
0106         deletedUrls << deleteJob->urls();
0107     }
0108 
0109     if (deletedUrls.isEmpty()) {
0110         return;
0111     }
0112 
0113     QClipboard *clipboard = QGuiApplication::clipboard();
0114     auto mimeData = clipboard->mimeData();
0115     if (!mimeData) {
0116         return;
0117     }
0118 
0119     QList<QUrl> clipboardUrls = KUrlMimeData::urlsFromMimeData(mimeData);
0120     quint32 removedCount = 0;
0121 
0122     for (const QUrl &url : std::as_const(deletedUrls)) {
0123         removedCount += clipboardUrls.removeAll(url);
0124     }
0125 
0126     if (removedCount > 0) {
0127         QMimeData *mime = new QMimeData();
0128         if (!clipboardUrls.isEmpty()) {
0129             mime->setUrls(clipboardUrls);
0130         }
0131         clipboard->setMimeData(mime);
0132     }
0133 }
0134 
0135 void ClipboardUpdater::slotResult(KJob *job)
0136 {
0137     if (job->error()) {
0138         return;
0139     }
0140 
0141     switch (m_mode) {
0142     case JobUiDelegateExtension::UpdateContent:
0143         updateUrlsInClipboard(job);
0144         break;
0145     case JobUiDelegateExtension::OverwriteContent:
0146         overwriteUrlsInClipboard(job);
0147         break;
0148     case JobUiDelegateExtension::RemoveContent:
0149         removeUrlsFromClipboard(job);
0150         break;
0151     }
0152 }
0153 
0154 void ClipboardUpdater::setMode(JobUiDelegateExtension::ClipboardUpdaterMode mode)
0155 {
0156     m_mode = mode;
0157 }
0158 
0159 void ClipboardUpdater::update(const QUrl &srcUrl, const QUrl &destUrl)
0160 {
0161     QClipboard *clipboard = QGuiApplication::clipboard();
0162     auto mimeData = clipboard->mimeData();
0163     if (mimeData && mimeData->hasUrls()) {
0164         QList<QUrl> clipboardUrls = KUrlMimeData::urlsFromMimeData(clipboard->mimeData());
0165         const int index = clipboardUrls.indexOf(srcUrl);
0166         if (index > -1) {
0167             clipboardUrls.replace(index, destUrl);
0168             QMimeData *mime = new QMimeData();
0169             mime->setUrls(clipboardUrls);
0170             clipboard->setMimeData(mime);
0171         }
0172     }
0173 }
0174 
0175 ClipboardUpdater::ClipboardUpdater(Job *job, JobUiDelegateExtension::ClipboardUpdaterMode mode)
0176     : QObject(job)
0177     , m_mode(mode)
0178 {
0179     Q_ASSERT(job);
0180     connect(job, &KJob::result, this, &ClipboardUpdater::slotResult);
0181 }
0182 
0183 #include "moc_clipboardupdater_p.cpp"