File indexing completed on 2025-01-05 03:53:32

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-02-04
0007  * Description : a tool to export images to Imgur web service
0008  *
0009  * SPDX-FileCopyrightText: 2010-2012 by Marius Orcsik <marius at habarnam dot ro>
0010  * SPDX-FileCopyrightText: 2013-2020 by Caulier Gilles <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "imgurimageslist.h"
0017 
0018 // C++ includes
0019 
0020 #include <memory>
0021 
0022 // Qt includes
0023 
0024 #include <QLabel>
0025 #include <QPointer>
0026 #include <QDesktopServices>
0027 #include <QApplication>
0028 #include <QClipboard>
0029 #include <QMenu>
0030 
0031 // KDE includes
0032 
0033 #include <klocalizedstring.h>
0034 
0035 // Local includes
0036 
0037 #include "dmetadata.h"
0038 #include "dinfointerface.h"
0039 #include "digikam_debug.h"
0040 
0041 namespace DigikamGenericImgUrPlugin
0042 {
0043 
0044 ImgurImagesList::ImgurImagesList(QWidget* const parent)
0045     : DItemsList(parent)
0046 {
0047     setControlButtonsPlacement(DItemsList::ControlButtonsBelow);
0048     setAllowDuplicate(false);
0049     setAllowRAW(false);
0050 
0051     auto* const list = listView();
0052 
0053     list->setColumnLabel(DItemsListView::Thumbnail, i18n("Thumbnail"));
0054 
0055     list->setColumnLabel(static_cast<DItemsListView::ColumnType>(ImgurImagesList::Title),
0056                          i18n("Submission title"));
0057 
0058     list->setColumnLabel(static_cast<DItemsListView::ColumnType>(ImgurImagesList::Description),
0059                          i18n("Submission description"));
0060 
0061     list->setColumn(static_cast<DItemsListView::ColumnType>(ImgurImagesList::URL),
0062                     i18n("Imgur URL"), true);
0063 
0064     list->setColumn(static_cast<DItemsListView::ColumnType>(ImgurImagesList::DeleteURL),
0065                     i18n("Imgur Delete URL"), true);
0066 
0067     connect(list, &DItemsListView::itemDoubleClicked,
0068             this, &ImgurImagesList::slotDoubleClick);
0069 
0070     connect(list, &DItemsListView::signalContextMenuRequested,
0071             this, &ImgurImagesList::slotContextMenuRequested);
0072 }
0073 
0074 QList<const ImgurImageListViewItem*> ImgurImagesList::getPendingItems()
0075 {
0076     QList<const ImgurImageListViewItem*> ret;
0077 
0078     for (int i = 0 ; i < listView()->topLevelItemCount() ; ++i)
0079     {
0080         auto* const item = dynamic_cast<const ImgurImageListViewItem*>(listView()->topLevelItem(i));
0081 
0082         if (item && item->ImgurUrl().isEmpty())
0083         {
0084             ret << item;
0085         }
0086     }
0087 
0088     return ret;
0089 }
0090 
0091 void ImgurImagesList::slotAddImages(const QList<QUrl>& list)
0092 {
0093     /**
0094      * Replaces the DItemsList::slotAddImages method, so that
0095      * ImgurImageListViewItems can be added instead of ImagesListViewItems
0096      */
0097 
0098     QScopedPointer<DMetadata> meta(new DMetadata);
0099 
0100     for (QList<QUrl>::ConstIterator it = list.constBegin() ; it != list.constEnd() ; ++it)
0101     {
0102         // Already in the list?
0103 
0104         if (listView()->findItem(*it) == nullptr)
0105         {
0106             // Load URLs from meta data, if possible
0107 
0108             if (meta->load((*it).toLocalFile()))
0109             {
0110                 auto* const item = new ImgurImageListViewItem(listView(), *it);
0111                 item->setImgurUrl(meta->getXmpTagString("Xmp.digiKam.ImgurId"));
0112                 item->setImgurDeleteUrl(meta->getXmpTagString("Xmp.digiKam.ImgurDeleteHash"));
0113             }
0114         }
0115     }
0116 
0117     Q_EMIT signalImageListChanged();
0118     Q_EMIT signalAddItems(list);
0119 }
0120 
0121 void ImgurImagesList::slotSuccess(const ImgurTalkerResult& result)
0122 {
0123     QUrl imgurl = QUrl::fromLocalFile(result.action->upload.imgpath);
0124 
0125     processed(imgurl, true);
0126 
0127     QScopedPointer<DMetadata> meta(new DMetadata);
0128 
0129     // Save URLs to meta data, if possible
0130 
0131     if (meta->load(imgurl.toLocalFile()))
0132     {
0133         meta->setXmpTagString("Xmp.digiKam.ImgurId",
0134                              result.image.url);
0135         meta->setXmpTagString("Xmp.digiKam.ImgurDeleteHash",
0136                              ImgurTalker::urlForDeletehash(result.image.deletehash).toString());
0137         meta->setMetadataWritingMode((int)DMetadata::WRITE_TO_FILE_ONLY);
0138         bool saved = meta->applyChanges();
0139 
0140         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Metadata"
0141                                          << (saved ? "Saved" : "Not Saved")
0142                                          << "to" << imgurl;
0143     }
0144 
0145     ImgurImageListViewItem* const currItem = dynamic_cast<ImgurImageListViewItem*>(listView()->findItem(imgurl));
0146 
0147     if (!currItem)
0148     {
0149         return;
0150     }
0151 
0152     if (!result.image.url.isEmpty())
0153     {
0154         currItem->setImgurUrl(result.image.url);
0155     }
0156 
0157     if (!result.image.deletehash.isEmpty())
0158     {
0159         currItem->setImgurDeleteUrl(ImgurTalker::urlForDeletehash(result.image.deletehash).toString());
0160     }
0161 }
0162 
0163 void ImgurImagesList::slotDoubleClick(QTreeWidgetItem* element, int i)
0164 {
0165     if ((i == URL) || (i == DeleteURL))
0166     {
0167         const QUrl url = QUrl(element->text(i));
0168 
0169         // The delete page asks for confirmation, so we don't need to do that here
0170 
0171         QDesktopServices::openUrl(url);
0172     }
0173 }
0174 
0175 void ImgurImagesList::slotContextMenuRequested()
0176 {
0177     if (
0178         listView()->topLevelItemCount()                                    &&
0179         ((listView()->currentIndex().column() == ImgurImagesList::URL)     ||
0180          (listView()->currentIndex().column() == ImgurImagesList::DeleteURL))
0181        )
0182     {
0183         listView()->blockSignals(true);
0184 
0185         QMenu menu(listView());
0186 
0187         QAction* const action = menu.addAction(i18n("Copy"));
0188 
0189         connect(action, SIGNAL(triggered()),
0190                 this , SLOT(slotCopyImurgURL()));
0191 
0192         menu.exec(QCursor::pos());
0193 
0194         listView()->blockSignals(false);
0195     }
0196 }
0197 
0198 void ImgurImagesList::slotCopyImurgURL()
0199 {
0200     QClipboard* const clipboard               = QApplication::clipboard();
0201 
0202     QList<QTreeWidgetItem*> selectedItemsList = listView()->selectedItems();
0203     QList<int> itemsIndex;
0204 
0205     QString copyURLtext;
0206 
0207     for (QList<QTreeWidgetItem*>::const_iterator it = selectedItemsList.constBegin() ;
0208          it != selectedItemsList.constEnd() ; ++it)
0209     {
0210         ImgurImageListViewItem* const item = dynamic_cast<ImgurImageListViewItem*>(*it);
0211 
0212         if (item)
0213         {
0214             if ((listView()->currentIndex().column() == ImgurImagesList::URL) &&
0215                 !item->ImgurUrl().isEmpty())
0216             {
0217                 copyURLtext.append(QString::fromLatin1("%1").arg(item->ImgurUrl()));
0218             }
0219 
0220             if ((listView()->currentIndex().column() == ImgurImagesList::DeleteURL) &&
0221                 !item->ImgurDeleteUrl().isEmpty())
0222             {
0223                copyURLtext.append(QString::fromLatin1("%1").arg(item->ImgurDeleteUrl()));
0224             }
0225         }
0226     }
0227 
0228     clipboard->setText(copyURLtext);
0229 }
0230 
0231 // ------------------------------------------------------------------------------------------------
0232 
0233 ImgurImageListViewItem::ImgurImageListViewItem(DItemsListView* const view, const QUrl& url)
0234     : DItemsListViewItem(view, url)
0235 {
0236     QBrush blue(QColor(50, 50, 255));
0237 
0238     setForeground(ImgurImagesList::URL,       blue);
0239     setForeground(ImgurImagesList::DeleteURL, blue);
0240 }
0241 
0242 void ImgurImageListViewItem::setTitle(const QString& str)
0243 {
0244     setText(ImgurImagesList::Title, str);
0245 }
0246 
0247 QString ImgurImageListViewItem::Title() const
0248 {
0249     return text(ImgurImagesList::Title);
0250 }
0251 
0252 void ImgurImageListViewItem::setDescription(const QString& str)
0253 {
0254     setText(ImgurImagesList::Description, str);
0255 }
0256 
0257 QString ImgurImageListViewItem::Description() const
0258 {
0259     return text(ImgurImagesList::Description);
0260 }
0261 
0262 void ImgurImageListViewItem::setImgurUrl(const QString& str)
0263 {
0264     setText(ImgurImagesList::URL, str);
0265 }
0266 
0267 QString ImgurImageListViewItem::ImgurUrl() const
0268 {
0269     return text(ImgurImagesList::URL);
0270 }
0271 
0272 void ImgurImageListViewItem::setImgurDeleteUrl(const QString& str)
0273 {
0274     setText(ImgurImagesList::DeleteURL, str);
0275 }
0276 
0277 QString ImgurImageListViewItem::ImgurDeleteUrl() const
0278 {
0279     return text(ImgurImagesList::DeleteURL);
0280 }
0281 
0282 } // namespace DigikamGenericImgUrPlugin
0283 
0284 #include "moc_imgurimageslist.cpp"