File indexing completed on 2024-12-01 03:41:11

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