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        : 2016-06-06
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: 2016      by Fabian Vogt <fabian at ritter dash vogt dot de>
0011  * SPDX-FileCopyrightText: 2013-2020 by Caulier Gilles <caulier dot gilles at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "imgurwindow.h"
0018 
0019 // Qt includes
0020 
0021 #include <QDesktopServices>
0022 #include <QInputDialog>
0023 #include <QCloseEvent>
0024 #include <QMessageBox>
0025 #include <QBoxLayout>
0026 #include <QWindow>
0027 
0028 // KDE includes
0029 
0030 #include <klocalizedstring.h>
0031 #include <ksharedconfig.h>
0032 #include <kconfiggroup.h>
0033 
0034 // Local includes
0035 
0036 #include "digikam_debug.h"
0037 #include "digikam_version.h"
0038 
0039 namespace DigikamGenericImgUrPlugin
0040 {
0041 
0042 class Q_DECL_HIDDEN ImgurWindow::Private
0043 {
0044 public:
0045 
0046     explicit Private()
0047       : list             (nullptr),
0048         api              (nullptr),
0049         forgetButton     (nullptr),
0050         uploadAnonButton (nullptr),
0051         userLabel        (nullptr)
0052     {
0053     }
0054 
0055     ImgurImagesList* list;
0056     ImgurTalker*     api;
0057     QPushButton*     forgetButton;
0058     QPushButton*     uploadAnonButton;
0059     QLabel*          userLabel;
0060 
0061     /// Contains the imgur username if API authorized, else is null.
0062     QString          username;
0063 };
0064 
0065 ImgurWindow::ImgurWindow(DInfoInterface* const iface, QWidget* const /*parent*/)
0066     : WSToolDialog(nullptr, QLatin1String("Imgur Dialog")),
0067       d           (new Private)
0068 {
0069     d->api = new ImgurTalker(this);
0070 
0071     // Connect API signals
0072 
0073     connect(d->api, &ImgurTalker::signalAuthorized,
0074             this, &ImgurWindow::slotApiAuthorized);
0075 
0076     connect(d->api, &ImgurTalker::signalAuthError,
0077             this, &ImgurWindow::slotApiAuthError);
0078 
0079     connect(d->api, &ImgurTalker::signalProgress,
0080             this, &ImgurWindow::slotApiProgress);
0081 
0082     connect(d->api, &ImgurTalker::signalRequestPin,
0083             this, &ImgurWindow::slotApiRequestPin);
0084 
0085     connect(d->api, &ImgurTalker::signalSuccess,
0086             this, &ImgurWindow::slotApiSuccess);
0087 
0088     connect(d->api, &ImgurTalker::signalError,
0089             this, &ImgurWindow::slotApiError);
0090 
0091     connect(d->api, &ImgurTalker::signalBusy,
0092             this, &ImgurWindow::slotApiBusy);
0093 
0094     // | List | Auth |
0095 
0096     auto* const mainLayout = new QHBoxLayout;
0097     auto* const mainWidget = new QWidget(this);
0098     mainWidget->setLayout(mainLayout);
0099     this->setMainWidget(mainWidget);
0100 
0101     d->list                = new ImgurImagesList;
0102     d->list->setIface(iface);
0103     d->list->loadImagesFromCurrentSelection();
0104     mainLayout->addWidget(d->list);
0105 
0106     /*
0107      * |  Logged in as:  |
0108      * | <Not logged in> |
0109      * |     Forget      |
0110      */
0111     auto* const userLabelLabel = new QLabel(i18n("Logged in as:"));
0112     userLabelLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
0113     userLabelLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
0114 
0115     // Label set in readSettings().
0116 
0117     d->userLabel               = new QLabel;
0118     d->userLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
0119     d->userLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
0120 
0121     d->forgetButton            = new QPushButton(i18n("Forget"));
0122 
0123     auto* const authLayout = new QVBoxLayout;
0124     mainLayout->addLayout(authLayout);
0125     authLayout->addWidget(userLabelLabel);
0126     authLayout->addWidget(d->userLabel);
0127     authLayout->addWidget(d->forgetButton);
0128     authLayout->insertStretch(-1, 1);
0129 
0130     // Add anonymous upload button
0131 
0132     d->uploadAnonButton    = new QPushButton(i18n("Upload Anonymously"));
0133     addButton(d->uploadAnonButton, QDialogButtonBox::ApplyRole);
0134 
0135     // Connect UI signals
0136 
0137     connect(d->forgetButton, &QPushButton::clicked,
0138             this, &ImgurWindow::slotForgetButtonClicked);
0139 
0140     connect(startButton(), &QPushButton::clicked,
0141             this, &ImgurWindow::slotUpload);
0142 
0143     connect(d->uploadAnonButton, &QPushButton::clicked,
0144             this, &ImgurWindow::slotAnonUpload);
0145 
0146     connect(this, &ImgurWindow::finished,
0147             this, &ImgurWindow::slotFinished);
0148 
0149     connect(this, &ImgurWindow::cancelClicked,
0150             this, &ImgurWindow::slotCancel);
0151 
0152     setWindowTitle(i18nc("@title:window", "Export to imgur.com"));
0153     setModal(false);
0154 
0155     startButton()->setText(i18nc("@action:button", "Upload"));
0156     startButton()->setToolTip(i18nc("@info:tooltip, button", "Start upload to Imgur"));
0157     startButton()->setEnabled(true);
0158 
0159     // Only used if not overwritten by readSettings()
0160 
0161     resize(650, 320);
0162     readSettings();
0163 }
0164 
0165 ImgurWindow::~ImgurWindow()
0166 {
0167     saveSettings();
0168     delete d;
0169 }
0170 
0171 void ImgurWindow::setItemsList(const QList<QUrl>& urls)
0172 {
0173     d->list->slotAddImages(urls);
0174 }
0175 
0176 void ImgurWindow::reactivate()
0177 {
0178     d->list->loadImagesFromCurrentSelection();
0179     show();
0180 }
0181 
0182 void ImgurWindow::slotForgetButtonClicked()
0183 {
0184     d->api->getAuth().unlink();
0185 
0186     slotApiAuthorized(false, {});
0187 }
0188 
0189 void ImgurWindow::slotUpload()
0190 {
0191     QList<const ImgurImageListViewItem*> pending = d->list->getPendingItems();
0192 
0193     for (const auto& item : qAsConst(pending))
0194     {
0195         ImgurTalkerAction action;
0196         action.type               = ImgurTalkerActionType::IMG_UPLOAD;
0197         action.upload.imgpath     = item->url().toLocalFile();
0198         action.upload.title       = item->Title();
0199         action.upload.description = item->Description();
0200 
0201         d->api->queueWork(action);
0202     }
0203 }
0204 
0205 void ImgurWindow::slotAnonUpload()
0206 {
0207     QList<const ImgurImageListViewItem*> pending = d->list->getPendingItems();
0208 
0209     for (const auto& item : qAsConst(pending))
0210     {
0211         ImgurTalkerAction action;
0212         action.type               = ImgurTalkerActionType::ANON_IMG_UPLOAD;
0213         action.upload.imgpath     = item->url().toLocalFile();
0214         action.upload.title       = item->Title();
0215         action.upload.description = item->Description();
0216 
0217         d->api->queueWork(action);
0218     }
0219 }
0220 
0221 void ImgurWindow::slotFinished()
0222 {
0223     saveSettings();
0224 }
0225 
0226 void ImgurWindow::slotCancel()
0227 {
0228     d->api->cancelAllWork();
0229 }
0230 
0231 void ImgurWindow::slotApiAuthorized(bool success, const QString& username)
0232 {
0233     if (success)
0234     {
0235         d->username = username;
0236         d->userLabel->setText(d->username);
0237         d->forgetButton->setEnabled(true);
0238         return;
0239     }
0240 
0241     d->username = QString();
0242     d->userLabel->setText(i18n("<i>Not logged in</i>"));
0243     d->forgetButton->setEnabled(false);
0244 }
0245 
0246 void ImgurWindow::slotApiAuthError(const QString& msg)
0247 {
0248     QMessageBox::critical(this,
0249                           i18nc("@title:window", "Authorization Failed"),
0250                           i18n("Failed to log into Imgur: %1\n", msg));
0251 }
0252 
0253 void ImgurWindow::slotApiProgress(unsigned int /*percent*/, const ImgurTalkerAction& action)
0254 {
0255     d->list->processing(QUrl::fromLocalFile(action.upload.imgpath));
0256 }
0257 
0258 void ImgurWindow::slotApiRequestPin(const QUrl& url)
0259 {
0260     QDesktopServices::openUrl(url);
0261 }
0262 
0263 void ImgurWindow::slotApiSuccess(const ImgurTalkerResult& result)
0264 {
0265     d->list->slotSuccess(result);
0266 }
0267 
0268 void ImgurWindow::slotApiError(const QString& msg, const ImgurTalkerAction& action)
0269 {
0270     d->list->processed(QUrl::fromLocalFile(action.upload.imgpath), false);
0271 
0272     // 1 here because the current item is still in the queue.
0273 
0274     if (d->api->workQueueLength() <= 1)
0275     {
0276         QMessageBox::critical(this,
0277                               i18nc("@title:window", "Uploading Failed"),
0278                               i18n("Failed to upload photo to Imgur: %1\n", msg));
0279         return;
0280     }
0281 
0282     QMessageBox::StandardButton cont =
0283             QMessageBox::question(this,
0284                                   i18nc("@title:window", "Uploading Failed"),
0285                                   i18n("Failed to upload photo to Imgur: %1\n"
0286                                        "Do you want to continue?", msg));
0287 
0288     if (cont != QMessageBox::Yes)
0289     {
0290         d->api->cancelAllWork();
0291     }
0292 }
0293 
0294 void ImgurWindow::slotApiBusy(bool busy)
0295 {
0296     setCursor(busy ? Qt::WaitCursor : Qt::ArrowCursor);
0297     startButton()->setEnabled(!busy);
0298 }
0299 
0300 void ImgurWindow::closeEvent(QCloseEvent* e)
0301 {
0302     if (!e)
0303     {
0304         return;
0305     }
0306 
0307     slotFinished();
0308     e->accept();
0309 }
0310 
0311 void ImgurWindow::readSettings()
0312 {
0313     KSharedConfigPtr config = KSharedConfig::openConfig();
0314     KConfigGroup groupAuth  = config->group(QLatin1String("Imgur Auth"));
0315     d->username             = groupAuth.readEntry("username", QString());
0316     slotApiAuthorized(!d->username.isEmpty(), d->username);
0317 }
0318 
0319 void ImgurWindow::saveSettings()
0320 {
0321     KSharedConfigPtr config = KSharedConfig::openConfig();
0322     KConfigGroup groupAuth  = config->group(QLatin1String("Imgur Auth"));
0323     groupAuth.writeEntry("username", d->username);
0324 }
0325 
0326 } // namespace DigikamGenericImgUrPlugin
0327 
0328 #include "moc_imgurwindow.cpp"