File indexing completed on 2024-04-28 05:35:26

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "clipboardjob.h"
0008 #include "history.h"
0009 #include "historyitem.h"
0010 #include "historystringitem.h"
0011 #include "klipper.h"
0012 
0013 #include "klipper_debug.h"
0014 #include <KIO/PreviewJob>
0015 #include <QIcon>
0016 
0017 #include <Prison/Barcode>
0018 
0019 const static QString s_iconKey = QStringLiteral("icon");
0020 const static QString s_previewKey = QStringLiteral("preview");
0021 const static QString s_previewWidthKey = QStringLiteral("previewWidth");
0022 const static QString s_previewHeightKey = QStringLiteral("previewHeight");
0023 const static QString s_urlKey = QStringLiteral("url");
0024 
0025 ClipboardJob::ClipboardJob(Klipper *klipper, const QString &destination, const QString &operation, const QVariantMap &parameters, QObject *parent)
0026     : Plasma5Support::ServiceJob(destination, operation, parameters, parent)
0027     , m_klipper(klipper)
0028 {
0029 }
0030 
0031 void ClipboardJob::start()
0032 {
0033     const QString operation = operationName();
0034     // first check for operations not needing an item
0035     if (operation == QLatin1String("clearHistory")) {
0036         m_klipper->slotAskClearHistory();
0037         setResult(true);
0038         return;
0039     } else if (operation == QLatin1String("configureKlipper")) {
0040         m_klipper->slotConfigure();
0041         setResult(true);
0042         return;
0043     }
0044 
0045     // other operations need the item
0046     HistoryItemConstPtr item = m_klipper->history()->find(QByteArray::fromBase64(destination().toUtf8()));
0047     if (!item) {
0048         setResult(false);
0049         return;
0050     }
0051     if (operation == QLatin1String("select")) {
0052         m_klipper->history()->slotMoveToTop(item->uuid());
0053         setResult(true);
0054     } else if (operation == QLatin1String("remove")) {
0055         m_klipper->history()->remove(item);
0056         setResult(true);
0057     } else if (operation == QLatin1String("edit")) {
0058         if (parameters().contains(QLatin1String("text"))) {
0059             const QString text = parameters()[QLatin1String("text")].toString();
0060             m_klipper->history()->remove(item);
0061             m_klipper->history()->insert(HistoryItemPtr(new HistoryStringItem(text)));
0062             if (m_klipper->urlGrabber()) {
0063                 m_klipper->urlGrabber()->checkNewData(HistoryItemConstPtr(m_klipper->history()->first()));
0064             }
0065             setResult(true);
0066             return;
0067         }
0068         return;
0069     } else if (operation == QLatin1String("barcode")) {
0070         int pixelWidth = parameters().value(QStringLiteral("width")).toInt();
0071         int pixelHeight = parameters().value(QStringLiteral("height")).toInt();
0072         std::optional<Prison::Barcode> code;
0073         switch (parameters().value(QStringLiteral("barcodeType")).toInt()) {
0074         case 1: {
0075             code = Prison::Barcode::create(Prison::DataMatrix);
0076             const int size = qMin(pixelWidth, pixelHeight);
0077             pixelWidth = size;
0078             pixelHeight = size;
0079             break;
0080         }
0081         case 2: {
0082             code = Prison::Barcode::create(Prison::Code39);
0083             break;
0084         }
0085         case 3: {
0086             code = Prison::Barcode::create(Prison::Code93);
0087             break;
0088         }
0089         case 4: {
0090             code = Prison::Barcode::create(Prison::Aztec);
0091             break;
0092         }
0093         case 0:
0094         default: {
0095             code = Prison::Barcode::create(Prison::QRCode);
0096             const int size = qMin(pixelWidth, pixelHeight);
0097             pixelWidth = size;
0098             pixelHeight = size;
0099             break;
0100         }
0101         }
0102         if (code) {
0103             code->setData(item->text());
0104             setResult(code->toImage(QSizeF(pixelWidth, pixelHeight)));
0105             return;
0106         } else {
0107             setResult(false);
0108         }
0109     } else if (operation == QLatin1String("action")) {
0110         m_klipper->urlGrabber()->invokeAction(item);
0111         setResult(true);
0112 
0113     } else if (operation == s_previewKey) {
0114         const int pixelWidth = parameters().value(s_previewWidthKey).toInt();
0115         const int pixelHeight = parameters().value(s_previewHeightKey).toInt();
0116         QUrl url = parameters().value(s_urlKey).toUrl();
0117         qCDebug(KLIPPER_LOG) << "URL: " << url;
0118         KFileItem item(url);
0119 
0120         if (pixelWidth <= 0 || pixelHeight <= 0) {
0121             qCWarning(KLIPPER_LOG) << "Preview size invalid: " << pixelWidth << "x" << pixelHeight;
0122             iconResult(item);
0123             return;
0124         }
0125 
0126         if (!url.isValid() || !url.isLocalFile()) { // no remote files
0127             qCWarning(KLIPPER_LOG) << "Invalid or non-local url for preview: " << url;
0128             iconResult(item);
0129             return;
0130         }
0131 
0132         KFileItemList urls;
0133         urls << item;
0134 
0135         KIO::PreviewJob *job = KIO::filePreview(urls, QSize(pixelWidth, pixelHeight));
0136         job->setIgnoreMaximumSize(true);
0137         connect(job, &KIO::PreviewJob::gotPreview, this, [this](const KFileItem &item, const QPixmap &preview) {
0138             QVariantMap res;
0139             res.insert(s_urlKey, item.url());
0140             res.insert(s_previewKey, preview);
0141             res.insert(s_iconKey, false);
0142             res.insert(s_previewWidthKey, preview.size().width());
0143             res.insert(s_previewHeightKey, preview.size().height());
0144             setResult(res);
0145         });
0146         connect(job, &KIO::PreviewJob::failed, this, [this](const KFileItem &item) {
0147             iconResult(item);
0148         });
0149 
0150         job->start();
0151 
0152         return;
0153     } else {
0154         setResult(false);
0155     }
0156     emitResult();
0157 }
0158 
0159 void ClipboardJob::iconResult(const KFileItem &item)
0160 {
0161     QVariantMap res;
0162     res.insert(s_urlKey, item.url());
0163     QPixmap pix = QIcon::fromTheme(item.determineMimeType().iconName()).pixmap(128, 128);
0164     res.insert(s_previewKey, pix);
0165     res.insert(s_iconKey, true);
0166     res.insert(QStringLiteral("iconName"), item.currentMimeType().iconName());
0167     res.insert(s_previewWidthKey, pix.size().width());
0168     res.insert(s_previewHeightKey, pix.size().height());
0169     setResult(res);
0170 }