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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-02-15
0007  * Description : a tool to export items to Google web services
0008  *
0009  * SPDX-FileCopyrightText: 2010      by Jens Mueller <tschenser at gmx dot de>
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 "gsreplacedlg.h"
0017 
0018 // Qt includes
0019 
0020 #include <QIcon>
0021 #include <QTimer>
0022 #include <QFrame>
0023 #include <QLabel>
0024 #include <QLayout>
0025 #include <QPainter>
0026 #include <QPushButton>
0027 #include <QMimeDatabase>
0028 #include <QDialogButtonBox>
0029 #include <QNetworkAccessManager>
0030 
0031 // KDE includes
0032 
0033 #include <klocalizedstring.h>
0034 
0035 // Local includes
0036 
0037 #include "dworkingpixmap.h"
0038 #include "wstoolutils.h"
0039 
0040 namespace DigikamGenericGoogleServicesPlugin
0041 {
0042 
0043 class Q_DECL_HIDDEN ReplaceDialog::Private
0044 {
0045 public:
0046 
0047     explicit Private()
0048       : bAdd            (nullptr),
0049         bAddAll         (nullptr),
0050         bReplace        (nullptr),
0051         bReplaceAll     (nullptr),
0052         iface           (nullptr),
0053         lbSrc           (nullptr),
0054         lbDest          (nullptr),
0055         netMngr         (nullptr),
0056         progressPix     (nullptr),
0057         thumbLoadThread (ThumbnailLoadThread::defaultThread()),
0058         progressCount   (0),
0059         progressTimer   (nullptr),
0060         result          (-1)
0061     {
0062     }
0063 
0064     QPushButton*           bAdd;
0065     QPushButton*           bAddAll;
0066     QPushButton*           bReplace;
0067     QPushButton*           bReplaceAll;
0068     QUrl                   src;
0069     QUrl                   dest;
0070     DInfoInterface*        iface;
0071     QLabel*                lbSrc;
0072     QLabel*                lbDest;
0073     QNetworkAccessManager* netMngr;
0074     QPixmap                mimePix;
0075     DWorkingPixmap*        progressPix;
0076     ThumbnailLoadThread*   thumbLoadThread;
0077     int                    progressCount;
0078     QTimer*                progressTimer;
0079     int                    result;
0080 };
0081 
0082 ReplaceDialog::ReplaceDialog(QWidget* const parent,
0083                              const QString& _caption,
0084                              DInfoInterface* const iface,
0085                              const QUrl& src,
0086                              const QUrl& dest)
0087     : QDialog(parent),
0088       d      (new Private)
0089 {
0090     setObjectName(QLatin1String("ReplaceDialog"));
0091 
0092     d->src         = src;
0093     d->dest        = dest;
0094     d->iface       = iface;
0095     d->progressPix = new DWorkingPixmap(this);
0096 
0097     setWindowTitle(_caption);
0098 
0099     QDialogButtonBox* const buttonBox = new QDialogButtonBox();
0100     buttonBox->addButton(QDialogButtonBox::Cancel);
0101 
0102     connect(buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()),
0103             this, SLOT(cancelPressed()));
0104 
0105     d->bAdd = new QPushButton(buttonBox);
0106     d->bAdd->setText(i18n("Add As New"));
0107     d->bAdd->setToolTip(i18n("Item will be added alongside the linked version."));
0108 
0109     connect(d->bAdd, SIGNAL(clicked()),
0110             this, SLOT(addPressed()));
0111 
0112     d->bAddAll = new QPushButton(buttonBox);
0113     d->bAddAll->setText(i18n("Add All"));
0114     d->bAddAll->setToolTip(i18n("Items will be added alongside the linked version. You will not be prompted again."));
0115 
0116     connect(d->bAddAll, SIGNAL(clicked()),
0117             this, SLOT(addAllPressed()));
0118 
0119     d->bReplace = new QPushButton(buttonBox);
0120     d->bReplace->setText(i18n("Replace"));
0121     d->bReplace->setToolTip(i18n("Item will be replacing the linked version."));
0122 
0123     connect(d->bReplace, SIGNAL(clicked()),
0124             this, SLOT(replacePressed()));
0125 
0126     d->bReplaceAll = new QPushButton(buttonBox);
0127     d->bReplaceAll->setText(i18n("Replace All"));
0128     d->bReplaceAll->setToolTip(i18n("Items will be replacing the linked version. You will not be prompted again."));
0129 
0130     connect(d->bReplaceAll, SIGNAL(clicked()),
0131             this, SLOT(replaceAllPressed()));
0132 
0133     buttonBox->addButton(d->bAdd,        QDialogButtonBox::AcceptRole);
0134     buttonBox->addButton(d->bAddAll,     QDialogButtonBox::AcceptRole);
0135     buttonBox->addButton(d->bReplace,    QDialogButtonBox::AcceptRole);
0136     buttonBox->addButton(d->bReplaceAll, QDialogButtonBox::AcceptRole);
0137 
0138     connect(buttonBox, SIGNAL(accepted()),
0139             this, SLOT(accept()));
0140 
0141     connect(buttonBox, SIGNAL(rejected()),
0142             this, SLOT(reject()));
0143 
0144     QVBoxLayout* const pLayout    = new QVBoxLayout(this);
0145     pLayout->addStrut(360);                          // makes dlg at least that wide
0146 
0147     QGridLayout* const gridLayout = new QGridLayout();
0148     pLayout->addLayout(gridLayout);
0149 
0150     QLabel* const lb1             = new QLabel(this);
0151     lb1->setText(i18n("A linked item already exists."));
0152     lb1->setAlignment(Qt::AlignHCenter);
0153     gridLayout->addWidget(lb1, 0, 0, 1, 3);
0154 
0155     QMimeDatabase db;
0156     QString icon = db.mimeTypeForUrl(d->dest).iconName();
0157     d->mimePix = QIcon::fromTheme(icon).pixmap(48);
0158 
0159     d->lbDest  = new QLabel(this);
0160     d->lbDest->setPixmap(d->mimePix);
0161     d->lbDest->setAlignment(Qt::AlignCenter);
0162     gridLayout->addWidget(d->lbDest, 1, 0, 1, 1);
0163 
0164     d->lbSrc   = new QLabel(this);
0165     icon = db.mimeTypeForUrl(d->src).iconName();
0166     d->lbSrc->setPixmap(QIcon::fromTheme(icon).pixmap(48));
0167     d->lbSrc->setAlignment(Qt::AlignCenter);
0168     gridLayout->addWidget(d->lbSrc, 1, 2, 1, 1);
0169 
0170     QLabel* const lb2 = new QLabel(this);
0171     lb2->setText(i18n("Destination"));
0172     lb2->setAlignment(Qt::AlignHCenter);
0173     gridLayout->addWidget(lb2, 2, 0, 1, 1);
0174 
0175     QLabel* const lb3 = new QLabel(this);
0176     lb3->setText(i18nc("@label: source file", "Source"));
0177     lb3->setAlignment(Qt::AlignHCenter);
0178     gridLayout->addWidget(lb3, 2, 2, 1, 1);
0179 
0180     QHBoxLayout* const layout2 = new QHBoxLayout();
0181     pLayout->addLayout(layout2);
0182 
0183     QFrame* const hline = new QFrame(this);
0184     hline->setLineWidth(1);
0185     hline->setMidLineWidth(0);
0186     hline->setFrameShape(QFrame::HLine);
0187     hline->setFrameShadow(QFrame::Sunken);
0188     hline->setMinimumSize(0, 2);
0189     hline->updateGeometry();
0190     pLayout->addWidget(hline);
0191 
0192     QHBoxLayout* const layout = new QHBoxLayout();
0193     pLayout->addLayout(layout);
0194 
0195     layout->addStretch(1);
0196     layout->addWidget(buttonBox);
0197 
0198     d->progressTimer = new QTimer(this);
0199 
0200     connect(d->progressTimer, SIGNAL(timeout()),
0201             this, SLOT(slotProgressTimerDone()));
0202 
0203     d->progressTimer->start(300);
0204 
0205     // get source thumbnail
0206 
0207     if (d->src.isValid())
0208     {
0209         connect(d->thumbLoadThread, SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)),
0210             this, SLOT(slotThumbnail(LoadingDescription,QPixmap)));
0211 
0212         d->thumbLoadThread->find(ThumbnailIdentifier(d->src.toLocalFile()));
0213     }
0214 
0215     // get dest thumbnail
0216 
0217     if (d->dest.isValid())
0218     {
0219         d->netMngr = new QNetworkAccessManager(this);
0220 
0221         connect(d->netMngr, SIGNAL(finished(QNetworkReply*)),
0222                 this, SLOT(slotFinished(QNetworkReply*)));
0223 
0224         QNetworkRequest netRequest(d->dest);
0225         netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
0226                              QLatin1String("application/x-www-form-urlencoded"));
0227 
0228         d->netMngr->get(netRequest);
0229     }
0230 
0231     resize(sizeHint());
0232 }
0233 
0234 void ReplaceDialog::slotFinished(QNetworkReply* reply)
0235 {
0236     d->progressTimer->stop();
0237 
0238     if (reply->error() != QNetworkReply::NoError)
0239     {
0240         reply->deleteLater();
0241         return;
0242     }
0243 
0244     QByteArray buffer = reply->readAll();
0245 
0246     if (!buffer.isEmpty())
0247     {
0248         QPixmap pxm;
0249         pxm.loadFromData(buffer);
0250         d->lbDest->setPixmap(pxm.scaled(200, 200, Qt::KeepAspectRatio, Qt::FastTransformation));
0251     }
0252 
0253     reply->deleteLater();
0254 }
0255 
0256 void ReplaceDialog::slotThumbnail(const LoadingDescription& desc, const QPixmap& pix)
0257 {
0258     if (QUrl::fromLocalFile(desc.filePath) == d->src)
0259     {
0260         d->lbSrc->setPixmap(pix.scaled(200, 200, Qt::KeepAspectRatio, Qt::FastTransformation));
0261     }
0262 }
0263 
0264 ReplaceDialog::~ReplaceDialog()
0265 {
0266     delete d;
0267 }
0268 
0269 void ReplaceDialog::cancelPressed()
0270 {
0271     close();
0272     d->result = PWR_CANCEL;
0273 }
0274 
0275 void ReplaceDialog::addPressed()
0276 {
0277     close();
0278     d->result = PWR_ADD;
0279 }
0280 
0281 void ReplaceDialog::addAllPressed()
0282 {
0283     close();
0284     d->result = PWR_ADD_ALL;
0285 }
0286 
0287 void ReplaceDialog::replacePressed()
0288 {
0289     close();
0290     d->result = PWR_REPLACE;
0291 }
0292 
0293 void ReplaceDialog::replaceAllPressed()
0294 {
0295     close();
0296     d->result = PWR_REPLACE_ALL;
0297 }
0298 
0299 QPixmap ReplaceDialog::setProgressAnimation(const QPixmap& thumb, const QPixmap& pix)
0300 {
0301     QPixmap overlay = thumb;
0302     QPixmap mask(overlay.size());
0303     mask.fill(QColor(128, 128, 128, 192));
0304     QPainter p(&overlay);
0305     p.drawPixmap(0, 0, mask);
0306     p.drawPixmap((overlay.width()/2) - (pix.width()/2), (overlay.height()/2) - (pix.height()/2), pix);
0307 
0308     return overlay;
0309 }
0310 
0311 void ReplaceDialog::slotProgressTimerDone()
0312 {
0313     d->lbDest->setPixmap(setProgressAnimation(d->mimePix, d->progressPix->frameAt(d->progressCount)));
0314     d->progressCount++;
0315 
0316     if (d->progressCount == 8)
0317     {
0318         d->progressCount = 0;
0319     }
0320 
0321     d->progressTimer->start(300);
0322 }
0323 
0324 int ReplaceDialog::getResult()
0325 {
0326     return d->result;
0327 }
0328 
0329 } // namespace DigikamGenericGoogleServicesPlugin
0330 
0331 #include "moc_gsreplacedlg.cpp"