File indexing completed on 2024-04-28 16:54:22
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 <QFutureWatcher> 0016 #include <QIcon> 0017 #include <QtConcurrent> 0018 0019 #include <Prison/Prison> 0020 0021 const static QString s_iconKey = QStringLiteral("icon"); 0022 const static QString s_previewKey = QStringLiteral("preview"); 0023 const static QString s_previewWidthKey = QStringLiteral("previewWidth"); 0024 const static QString s_previewHeightKey = QStringLiteral("previewHeight"); 0025 const static QString s_urlKey = QStringLiteral("url"); 0026 0027 ClipboardJob::ClipboardJob(Klipper *klipper, const QString &destination, const QString &operation, const QVariantMap ¶meters, QObject *parent) 0028 : Plasma::ServiceJob(destination, operation, parameters, parent) 0029 , m_klipper(klipper) 0030 { 0031 } 0032 0033 void ClipboardJob::start() 0034 { 0035 const QString operation = operationName(); 0036 // first check for operations not needing an item 0037 if (operation == QLatin1String("clearHistory")) { 0038 m_klipper->slotAskClearHistory(); 0039 setResult(true); 0040 return; 0041 } else if (operation == QLatin1String("configureKlipper")) { 0042 m_klipper->slotConfigure(); 0043 setResult(true); 0044 return; 0045 } 0046 0047 // other operations need the item 0048 HistoryItemConstPtr item = m_klipper->history()->find(QByteArray::fromBase64(destination().toUtf8())); 0049 if (item.isNull()) { 0050 setResult(false); 0051 return; 0052 } 0053 if (operation == QLatin1String("select")) { 0054 m_klipper->history()->slotMoveToTop(item->uuid()); 0055 setResult(true); 0056 } else if (operation == QLatin1String("remove")) { 0057 m_klipper->history()->remove(item); 0058 setResult(true); 0059 } else if (operation == QLatin1String("edit")) { 0060 if (parameters().contains(QLatin1String("text"))) { 0061 const QString text = parameters()[QLatin1String("text")].toString(); 0062 if (item) { 0063 m_klipper->history()->remove(item); 0064 } 0065 m_klipper->history()->insert(HistoryItemPtr(new HistoryStringItem(text))); 0066 if (m_klipper->urlGrabber()) { 0067 m_klipper->urlGrabber()->checkNewData(HistoryItemConstPtr(m_klipper->history()->first())); 0068 } 0069 setResult(true); 0070 return; 0071 } 0072 connect(m_klipper, &Klipper::editFinished, this, [this, item](HistoryItemConstPtr editedItem, int result) { 0073 if (item != editedItem) { 0074 // not our item 0075 return; 0076 } 0077 setResult(result); 0078 }); 0079 m_klipper->editData(item); 0080 return; 0081 } else if (operation == QLatin1String("barcode")) { 0082 int pixelWidth = parameters().value(QStringLiteral("width")).toInt(); 0083 int pixelHeight = parameters().value(QStringLiteral("height")).toInt(); 0084 Prison::AbstractBarcode *code = nullptr; 0085 switch (parameters().value(QStringLiteral("barcodeType")).toInt()) { 0086 case 1: { 0087 code = Prison::createBarcode(Prison::DataMatrix); 0088 const int size = qMin(pixelWidth, pixelHeight); 0089 pixelWidth = size; 0090 pixelHeight = size; 0091 break; 0092 } 0093 case 2: { 0094 code = Prison::createBarcode(Prison::Code39); 0095 break; 0096 } 0097 case 3: { 0098 code = Prison::createBarcode(Prison::Code93); 0099 break; 0100 } 0101 case 4: { 0102 code = Prison::createBarcode(Prison::Aztec); 0103 break; 0104 } 0105 case 0: 0106 default: { 0107 code = Prison::createBarcode(Prison::QRCode); 0108 const int size = qMin(pixelWidth, pixelHeight); 0109 pixelWidth = size; 0110 pixelHeight = size; 0111 break; 0112 } 0113 } 0114 if (code) { 0115 code->setData(item->text()); 0116 QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this); 0117 connect(watcher, &QFutureWatcher<QImage>::finished, this, [this, watcher, code] { 0118 setResult(watcher->result()); 0119 watcher->deleteLater(); 0120 delete code; 0121 }); 0122 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0123 auto future = QtConcurrent::run(code, &Prison::AbstractBarcode::toImage, QSizeF(pixelWidth, pixelHeight)); 0124 #else 0125 auto future = QtConcurrent::run(&Prison::AbstractBarcode::toImage, code, QSizeF(pixelWidth, pixelHeight)); 0126 #endif 0127 watcher->setFuture(future); 0128 return; 0129 } else { 0130 setResult(false); 0131 } 0132 } else if (operation == QLatin1String("action")) { 0133 m_klipper->urlGrabber()->invokeAction(item); 0134 setResult(true); 0135 0136 } else if (operation == s_previewKey) { 0137 const int pixelWidth = parameters().value(s_previewWidthKey).toInt(); 0138 const int pixelHeight = parameters().value(s_previewHeightKey).toInt(); 0139 QUrl url = parameters().value(s_urlKey).toUrl(); 0140 qCDebug(KLIPPER_LOG) << "URL: " << url; 0141 KFileItem item(url); 0142 0143 if (pixelWidth <= 0 || pixelHeight <= 0) { 0144 qCWarning(KLIPPER_LOG) << "Preview size invalid: " << pixelWidth << "x" << pixelHeight; 0145 iconResult(item); 0146 return; 0147 } 0148 0149 if (!url.isValid() || !url.isLocalFile()) { // no remote files 0150 qCWarning(KLIPPER_LOG) << "Invalid or non-local url for preview: " << url; 0151 iconResult(item); 0152 return; 0153 } 0154 0155 KFileItemList urls; 0156 urls << item; 0157 0158 KIO::PreviewJob *job = KIO::filePreview(urls, QSize(pixelWidth, pixelHeight)); 0159 job->setIgnoreMaximumSize(true); 0160 connect(job, &KIO::PreviewJob::gotPreview, this, [this](const KFileItem &item, const QPixmap &preview) { 0161 QVariantMap res; 0162 res.insert(s_urlKey, item.url()); 0163 res.insert(s_previewKey, preview); 0164 res.insert(s_iconKey, false); 0165 res.insert(s_previewWidthKey, preview.size().width()); 0166 res.insert(s_previewHeightKey, preview.size().height()); 0167 setResult(res); 0168 }); 0169 connect(job, &KIO::PreviewJob::failed, this, [this](const KFileItem &item) { 0170 iconResult(item); 0171 }); 0172 0173 job->start(); 0174 0175 return; 0176 } else { 0177 setResult(false); 0178 } 0179 emitResult(); 0180 } 0181 0182 void ClipboardJob::iconResult(const KFileItem &item) 0183 { 0184 QVariantMap res; 0185 res.insert(s_urlKey, item.url()); 0186 QPixmap pix = QIcon::fromTheme(item.determineMimeType().iconName()).pixmap(128, 128); 0187 res.insert(s_previewKey, pix); 0188 res.insert(s_iconKey, true); 0189 res.insert(QStringLiteral("iconName"), item.currentMimeType().iconName()); 0190 res.insert(s_previewWidthKey, pix.size().width()); 0191 res.insert(s_previewHeightKey, pix.size().height()); 0192 setResult(res); 0193 }