File indexing completed on 2025-01-05 03:56:35

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2020-12-31
0007  * Description : Online version dialog.
0008  *
0009  * SPDX-FileCopyrightText: 2020-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "onlineversiondlg.h"
0016 
0017 // Qt includes
0018 
0019 #include <QUrl>
0020 #include <QTimer>
0021 #include <QAction>
0022 #include <QList>
0023 #include <QFile>
0024 #include <QFont>
0025 #include <QFontMetrics>
0026 #include <QFontDatabase>
0027 #include <QFileDevice>
0028 #include <QStyle>
0029 #include <QIcon>
0030 #include <QLabel>
0031 #include <QImage>
0032 #include <QGridLayout>
0033 #include <QVBoxLayout>
0034 #include <QApplication>
0035 #include <QPushButton>
0036 #include <QProgressBar>
0037 #include <QLocale>
0038 #include <QProcess>
0039 #include <QDialogButtonBox>
0040 #include <QMessageBox>
0041 #include <QTextBrowser>
0042 #include <QMargins>
0043 #include <QGroupBox>
0044 #include <QTextDocument>
0045 
0046 // KDE includes
0047 
0048 #include <klocalizedstring.h>
0049 
0050 // Local includes
0051 
0052 #include "digikam_debug.h"
0053 #include "digikam_globals.h"
0054 #include "onlineversionchecker.h"
0055 #include "onlineversiondwnl.h"
0056 #include "dfileoperations.h"
0057 #include "itempropertiestab.h"
0058 
0059 namespace Digikam
0060 {
0061 
0062 class Q_DECL_HIDDEN OnlineVersionDlg::Private
0063 {
0064 public:
0065 
0066     explicit Private()
0067       : preRelease     (false),
0068         updateWithDebug(false),
0069         bar            (nullptr),
0070         label          (nullptr),
0071         stats          (nullptr),
0072         received       (nullptr),
0073         total          (nullptr),
0074         rate           (nullptr),
0075         remain         (nullptr),
0076         logo           (nullptr),
0077         buttons        (nullptr),
0078         speedTimer     (nullptr),
0079         checker        (nullptr),
0080         dwnloader      (nullptr)
0081     {
0082     }
0083 
0084     bool                   preRelease;
0085     bool                   updateWithDebug;
0086 
0087     QString                curVersion;
0088     QDateTime              curBuildDt;
0089     QDateTime              onlineDt;         ///< Build date for pre-release only.
0090     QString                newVersion;       ///< For stable => version IDs ; for pre-release => build ISO date.
0091     QProgressBar*          bar;
0092     QLabel*                label;
0093     QWidget*               stats;
0094     QLabel*                received;
0095     QLabel*                total;
0096     QLabel*                rate;
0097     QLabel*                remain;
0098     QLabel*                logo;
0099     QDialogButtonBox*      buttons;
0100     QTimer*                speedTimer;
0101     QDateTime              dwnlStart;
0102 
0103     OnlineVersionChecker*  checker;
0104     OnlineVersionDwnl*     dwnloader;
0105 };
0106 
0107 OnlineVersionDlg::OnlineVersionDlg(QWidget* const parent,
0108                                    const QString& version,
0109                                    const QDateTime& buildDt,
0110                                    bool checkPreRelease,
0111                                    bool updateWithDebug)
0112     : QDialog(parent),
0113       d      (new Private)
0114 {
0115     setModal(true);
0116 
0117     d->curVersion      = version;
0118     d->curBuildDt      = buildDt;
0119     d->preRelease      = checkPreRelease;
0120     d->updateWithDebug = updateWithDebug;
0121     d->checker         = new OnlineVersionChecker(this, d->preRelease);
0122     d->checker->setCurrentVersion(d->curVersion);
0123     d->checker->setCurrentBuildDate(d->curBuildDt);
0124     d->dwnloader       = new OnlineVersionDwnl(this, d->preRelease, d->updateWithDebug);
0125 
0126     connect(d->checker, SIGNAL(signalNewVersionAvailable(QString)),
0127             this, SLOT(slotNewVersionAvailable(QString)));
0128 
0129     connect(d->checker, SIGNAL(signalNewVersionCheckError(QString)),
0130             this, SLOT(slotNewVersionCheckError(QString)));
0131 
0132     connect(d->dwnloader, SIGNAL(signalDownloadError(QString)),
0133             this, SLOT(slotDownloadError(QString)));
0134 
0135     connect(d->dwnloader, SIGNAL(signalDownloadProgress(qint64,qint64)),
0136             this, SLOT(slotDownloadProgress(qint64,qint64)));
0137 
0138     connect(d->dwnloader, SIGNAL(signalComputeChecksum()),
0139             this, SLOT(slotComputeChecksum()));
0140 
0141     d->speedTimer            = new QTimer(this);
0142 
0143     connect(d->speedTimer, SIGNAL(timeout()),
0144             this, SLOT(slotUpdateStats()));
0145 
0146     QWidget* const page      = new QWidget(this);
0147     QGridLayout* const grid  = new QGridLayout(page);
0148     d->label                 = new QLabel(page);
0149     d->label->setOpenExternalLinks(true);
0150 
0151     d->stats                 = new QWidget(page);
0152     d->stats->setVisible(false);
0153 
0154     QFont sfnt               = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont);
0155     sfnt.setItalic(true);
0156     sfnt.setStyleHint(QFont::Monospace);
0157     d->stats->setFont(sfnt);
0158     QFontMetrics fontMt(sfnt);
0159     QRect fontRect           = fontMt.boundingRect(0, 0, width(), height(), 0, QLatin1String("XXXXXXXXXX"));
0160 
0161     d->received              = new QLabel(d->stats);
0162     d->received->setAlignment(Qt::AlignRight);
0163     d->total                 = new QLabel(d->stats);
0164     d->total->setAlignment(Qt::AlignRight);
0165     d->rate                  = new QLabel(d->stats);
0166     d->rate->setAlignment(Qt::AlignRight);
0167     d->remain                = new QLabel(d->stats);
0168     d->remain->setAlignment(Qt::AlignRight);
0169 
0170     QGridLayout* const grid2 = new QGridLayout(d->stats);
0171     grid2->addWidget(new QLabel(i18nc("@info: download status", "Received:")),  0, 0, 1, 1);
0172     grid2->addWidget(new QLabel(i18nc("@info: download status", "Total:")),     1, 0, 1, 1);
0173     grid2->addWidget(new QLabel(i18nc("@info: download status", "Rate:")),      2, 0, 1, 1);
0174     grid2->addWidget(new QLabel(i18nc("@info: download status", "ETA:")),       3, 0, 1, 1);
0175     grid2->addWidget(d->received,                                               0, 2, 1, 1);
0176     grid2->addWidget(d->total,                                                  1, 2, 1, 1);
0177     grid2->addWidget(d->rate,                                                   2, 2, 1, 1);
0178     grid2->addWidget(d->remain,                                                 3, 2, 1, 1);
0179     grid2->setContentsMargins(QMargins());
0180     grid2->setSpacing(0);
0181     grid2->setColumnMinimumWidth(2, fontRect.width());
0182 
0183     if (d->preRelease)
0184     {
0185         setWindowTitle(i18nc("@title:window", "Online Version Checker - Pre-Release"));
0186         d->label->setText(i18n("Check for new pre-release version available, please wait..."));
0187     }
0188     else
0189     {
0190         setWindowTitle(i18nc("@title:window", "Online Version Checker - Stable Version"));
0191         d->label->setText(i18n("Check for new stable version available, please wait..."));
0192     }
0193 
0194     d->logo                = new QLabel(page);
0195 
0196     if (QApplication::applicationName() == QLatin1String("digikam"))
0197     {
0198         d->logo->setPixmap(QIcon::fromTheme(QLatin1String("digikam")).pixmap(QSize(48, 48)));
0199     }
0200     else
0201     {
0202         d->logo->setPixmap(QIcon::fromTheme(QLatin1String("showfoto")).pixmap(QSize(48, 48)));
0203     }
0204 
0205     d->bar                 = new QProgressBar(page);
0206     d->bar->setMaximum(1);
0207     d->bar->setMinimum(0);
0208     d->bar->setValue(0);
0209 
0210     d->buttons             = new QDialogButtonBox(QDialogButtonBox::Help  |
0211                                                   QDialogButtonBox::Apply |         // Download button
0212                                                   QDialogButtonBox::Reset |         // Configure button
0213                                                   QDialogButtonBox::Cancel,
0214                                                   page);
0215     d->buttons->button(QDialogButtonBox::Cancel)->setDefault(true);
0216 
0217     grid->addWidget(d->logo,     0, 0, 1, 1);
0218     grid->addWidget(d->label,    0, 1, 1, 2);
0219     grid->addWidget(d->stats,    0, 3, 1, 1);
0220     grid->addWidget(d->bar,      1, 0, 1, 4);
0221     grid->setSpacing(qMin(style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0222                           style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)));
0223     grid->setContentsMargins(QMargins());
0224     grid->setColumnStretch(2, 10);
0225     grid->setRowStretch(2, 10);
0226 
0227     QVBoxLayout* const vbx = new QVBoxLayout(this);
0228     vbx->addWidget(page);
0229     vbx->addWidget(d->buttons);
0230     setLayout(vbx);
0231 
0232     connect(d->buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()),
0233             this, SLOT(close()));
0234 
0235     connect(d->buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()),
0236             this, SLOT(slotHelp()));
0237 
0238     adjustSize();
0239 
0240     d->buttons->button(QDialogButtonBox::Apply)->setVisible(false);
0241     d->buttons->button(QDialogButtonBox::Apply)->setEnabled(false);
0242     d->buttons->button(QDialogButtonBox::Reset)->setVisible(true);
0243     d->buttons->button(QDialogButtonBox::Reset)->setEnabled(true);
0244     d->buttons->button(QDialogButtonBox::Reset)->setText(i18n("Configure..."));
0245     d->buttons->button(QDialogButtonBox::Reset)->setToolTip(i18n("Open setup dialog page to configure updates."));
0246     d->buttons->button(QDialogButtonBox::Reset)->setIcon(QIcon::fromTheme(QLatin1String("configure")));
0247 
0248     disconnect(d->buttons->button(QDialogButtonBox::Reset), SIGNAL(clicked()), 0, 0);
0249 
0250     connect(d->buttons->button(QDialogButtonBox::Reset), SIGNAL(clicked()),
0251             this, SLOT(slotSetupUpdate()));
0252 
0253     d->checker->checkForNewVersion();
0254 }
0255 
0256 OnlineVersionDlg::~OnlineVersionDlg()
0257 {
0258     d->checker->cancelCheck();
0259     d->dwnloader->cancelDownload();
0260 
0261     delete d;
0262 }
0263 
0264 void OnlineVersionDlg::slotNewVersionAvailable(const QString& version)
0265 {
0266     d->newVersion = version;
0267     d->bar->hide();
0268     d->stats->hide();
0269     d->speedTimer->stop();
0270 
0271     d->buttons->button(QDialogButtonBox::Apply)->setVisible(true);
0272     d->buttons->button(QDialogButtonBox::Apply)->setEnabled(true);
0273     d->buttons->button(QDialogButtonBox::Apply)->setText(i18n("Download"));
0274     d->buttons->button(QDialogButtonBox::Apply)->setIcon(QIcon::fromTheme(QLatin1String("download")));
0275     d->buttons->button(QDialogButtonBox::Reset)->setVisible(true);
0276 
0277     disconnect(d->buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()), 0, 0);
0278 
0279     connect(d->buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()),
0280             this, SLOT(slotDownloadInstaller()));
0281 
0282     if (d->preRelease)
0283     {
0284         d->onlineDt = QDateTime::fromString(d->newVersion, QLatin1String("yyyyMMddTHHmmss"));
0285         d->onlineDt.setTimeSpec(Qt::UTC);
0286 
0287         d->label->setText(i18n("<p>Current <b>%1</b> pre-release date is <i>%2</i>.</p>"
0288                                "<p>New pre-release built on <i>%3</i> is available on this <a href='%4'>repository</a>.</p>"
0289                                "<p>Press <b>Download</b> to get the file...</p>"
0290                                "<p>Note: from Setup/Misc panel, you can switch to check for stable release only.<br/>"
0291                                "Stable versions are safe to use in production.</p>"
0292                                "<p>Press <b>Configure</b> if you want to customize update options from setup dialog.</p>",
0293                                qApp->applicationName(),
0294                                QLocale().toString(d->curBuildDt, QLocale::ShortFormat),
0295                                QLocale().toString(d->onlineDt, QLocale::ShortFormat),
0296                                d->dwnloader->downloadUrl()));
0297     }
0298     else
0299     {
0300         d->label->setText(i18n("<p>Current <b>%1</b> stable version is <i>%2</i></p>"
0301                                "<p>New stable version <i>%3</i> is available on this <a href='%4'>repository</a>.</p>"
0302                                "<p>Press <b>Download</b> to get the file...</p>"
0303                                "<p>Note: from Setup/Misc panel, you can switch to check for weekly pre-release.<br/>"
0304                                "Pre-release versions are dedicated to test quickly new features.<br/>"
0305                                "It's not recommended to use pre-releases in production as bugs can remain,<br/>"
0306                                "unless you know what you are doing.</p>"
0307                                "<p>Press <b>Configure</b> if you want to customize update options from setup dialog.</p>",
0308                                qApp->applicationName(),
0309                                d->curVersion,
0310                                version,
0311                                d->dwnloader->downloadUrl()));
0312     }
0313 }
0314 
0315 void OnlineVersionDlg::slotNewVersionCheckError(const QString& error)
0316 {
0317     d->bar->hide();
0318     d->stats->hide();
0319     d->speedTimer->stop();
0320     d->buttons->button(QDialogButtonBox::Apply)->setVisible(false);
0321     d->buttons->button(QDialogButtonBox::Cancel)->setText(i18n("Close"));
0322     d->buttons->button(QDialogButtonBox::Cancel)->setIcon(QIcon::fromTheme(QLatin1String("close")));
0323 
0324     if (error.isEmpty())
0325     {
0326         if (d->preRelease)
0327         {
0328             d->label->setText(i18n("Your software is up-to-date.\n"
0329                                    "%1 pre-release built on %2 is the most recent version available.",
0330                                    qApp->applicationName(),
0331                                    QLocale().toString(d->curBuildDt, QLocale::ShortFormat)));
0332         }
0333         else
0334         {
0335             d->label->setText(i18n("Your software is up-to-date.\n"
0336                                    "%1 stable version %2 is the most recent version available.",
0337                                    qApp->applicationName(),
0338                                    QString::fromLatin1(digikam_version_short)));
0339         }
0340     }
0341     else
0342     {
0343         d->label->setText(i18n("Error while trying to check for new %1 version:\n\"%2\"",
0344                                qApp->applicationName(),
0345                                error));
0346     }
0347 }
0348 
0349 void OnlineVersionDlg::slotDownloadInstaller()
0350 {
0351     if (d->preRelease)
0352     {
0353         QString version = d->updateWithDebug ? i18n("built on %1 with debug symbols", QLocale().toString(d->onlineDt, QLocale::ShortFormat))
0354                                              : i18n("built on %1", QLocale().toString(d->onlineDt, QLocale::ShortFormat));
0355 
0356         d->label->setText(i18n("Downloading new %1\n%2\nin progress, please wait...",
0357                                qApp->applicationName(),
0358                                version));
0359     }
0360     else
0361     {
0362         QString version = d->updateWithDebug ? i18n("version %1 with debug symbols", d->newVersion)
0363                                              : i18n("version %1", d->newVersion);
0364 
0365         d->label->setText(i18n("Downloading new %1\nversion %2\nin progress, please wait...",
0366                                qApp->applicationName(),
0367                                version));
0368     }
0369 
0370     d->buttons->button(QDialogButtonBox::Apply)->setEnabled(false);
0371     d->buttons->button(QDialogButtonBox::Reset)->setEnabled(false);
0372 
0373     d->bar->setMaximum(1);
0374     d->bar->setMinimum(0);
0375     d->bar->setValue(0);
0376     d->bar->show();
0377     d->stats->show();
0378     d->speedTimer->start(1000);
0379     d->dwnlStart = QDateTime::currentDateTime();
0380 
0381     if (d->preRelease)
0382     {
0383         d->dwnloader->startDownload(d->checker->preReleaseFileName());
0384     }
0385     else
0386     {
0387         d->dwnloader->startDownload(d->newVersion);
0388     }
0389 }
0390 
0391 void OnlineVersionDlg::slotComputeChecksum()
0392 {
0393     if (d->preRelease)
0394     {
0395         QString version = d->updateWithDebug ? i18n("built on %1 with debug symbols", QLocale().toString(d->onlineDt, QLocale::ShortFormat))
0396                                              : i18n("built on %1", QLocale().toString(d->onlineDt, QLocale::ShortFormat));
0397 
0398         d->label->setText(i18n("Verify Checksum for new %1\n%2\nin progress, please wait...",
0399                                qApp->applicationName(),
0400                                version));
0401     }
0402     else
0403     {
0404         QString version = d->updateWithDebug ? i18n("version %1 with debug symbols", d->newVersion)
0405                                              : i18n("version %1", d->newVersion);
0406 
0407         d->label->setText(i18n("Verify checksum for %1\nversion %2\nin progress, please wait...",
0408                                qApp->applicationName(),
0409                                version));
0410     }
0411 
0412     d->buttons->button(QDialogButtonBox::Apply)->setEnabled(false);
0413     d->buttons->button(QDialogButtonBox::Reset)->setEnabled(false);
0414 
0415     d->bar->setMaximum(0);
0416     d->bar->setMinimum(0);
0417     d->bar->setValue(0);
0418     d->bar->show();
0419     d->stats->hide();
0420     d->speedTimer->stop();
0421 }
0422 
0423 void OnlineVersionDlg::slotDownloadError(const QString& error)
0424 {
0425     d->bar->hide();
0426     d->stats->hide();
0427     d->speedTimer->stop();
0428 
0429     if (error.isEmpty())        // empty error want mean a complete download.
0430     {
0431 
0432 #ifdef Q_OS_LINUX
0433 
0434         d->buttons->button(QDialogButtonBox::Apply)->setText(i18nc("@action: open bundle file", "Open..."));
0435         d->buttons->button(QDialogButtonBox::Apply)->setIcon(QIcon::fromTheme(QLatin1String("system-file-manager")));
0436         d->buttons->button(QDialogButtonBox::Apply)->setEnabled(true);
0437 
0438         disconnect(d->buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()), 0, 0);
0439 
0440         connect(d->buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()),
0441                 this, SLOT(slotOpenInFileManager()));
0442 
0443         if (d->preRelease)
0444         {
0445             d->label->setText(i18n("The new %1\npre-release built on %2\nhave been downloaded at:\n\n"
0446                                    "%3\n\n"
0447                                    "Press \"Open\" to show the bundle in file-manager...",
0448                                    qApp->applicationName(),
0449                                    QLocale().toString(d->onlineDt, QLocale::ShortFormat),
0450                                    d->dwnloader->downloadedPath()));
0451         }
0452         else
0453         {
0454             d->label->setText(i18n("The new %1\nstable version %2\nhave been downloaded at:\n\n"
0455                                    "%3\n\n"
0456                                    "Press \"Open\" to show the bundle in file-manager...",
0457                                    qApp->applicationName(),
0458                                    d->newVersion,
0459                                    d->dwnloader->downloadedPath()));
0460         }
0461 
0462 #else // Windows and macOS
0463 
0464         d->buttons->button(QDialogButtonBox::Apply)->setEnabled(true);
0465         d->buttons->button(QDialogButtonBox::Apply)->setText(i18n("Install..."));
0466         d->buttons->button(QDialogButtonBox::Apply)->setIcon(QIcon::fromTheme(QLatin1String("run-install")));
0467 
0468         if (d->preRelease)
0469         {
0470             d->label->setText(i18n("The new pre-release %1\nbuilt on %2\nhave been downloaded at:\n\n"
0471                                    "%3\n\n"
0472                                    "Press \"Install\" to close current session and upgrade...",
0473                                    qApp->applicationName(),
0474                                    QLocale().toString(d->onlineDt, QLocale::ShortFormat),
0475                                    d->dwnloader->downloadedPath()));
0476         }
0477         else
0478         {
0479             d->label->setText(i18n("The new %1\nstable version %2\nhave been downloaded at:\n\n"
0480                                    "%3\n\n"
0481                                    "Press \"Install\" to close current session and upgrade...",
0482                                    qApp->applicationName(),
0483                                    d->newVersion,
0484                                    d->dwnloader->downloadedPath()));
0485         }
0486 
0487         disconnect(d->buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()), 0, 0);
0488 
0489         connect(d->buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()),
0490                 this, SLOT(slotRunInstaller()));
0491 
0492 #endif
0493 
0494     }
0495     else
0496     {
0497         d->buttons->button(QDialogButtonBox::Apply)->setVisible(false);
0498         d->buttons->button(QDialogButtonBox::Cancel)->setText(i18n("Close"));
0499         d->buttons->button(QDialogButtonBox::Cancel)->setIcon(QIcon::fromTheme(QLatin1String("close")));
0500 
0501         if (d->preRelease)
0502         {
0503             d->label->setText(i18n("Error while trying to download %1\npre-release built on %2:\n\n\"%3\"",
0504                                    qApp->applicationName(),
0505                                    QLocale().toString(d->onlineDt, QLocale::ShortFormat),
0506                                    error));
0507         }
0508         else
0509         {
0510             d->label->setText(i18n("Error while trying to download %1\nstable version %2:\n\n\"%3\"",
0511                                    qApp->applicationName(),
0512                                    d->newVersion,
0513                                    error));
0514         }
0515     }
0516 }
0517 
0518 void OnlineVersionDlg::slotDownloadProgress(qint64 recv, qint64 total)
0519 {
0520     if (total == 0)
0521     {
0522         return;
0523     }
0524 
0525     d->bar->setMaximum(total);
0526     d->bar->setMinimum(0);
0527     d->bar->setValue(recv);
0528 }
0529 
0530 void OnlineVersionDlg::slotUpdateStats()
0531 {
0532     QDateTime now = QDateTime::currentDateTime();
0533     qint64 diff   = d->dwnlStart.secsTo(now);
0534     qint64 rate   = 0;
0535     qint64 remain = 0;
0536 
0537     if (diff)
0538     {
0539         rate = d->bar->value() / diff;
0540 
0541         if (rate)
0542         {
0543             remain = (d->bar->maximum() - d->bar->value()) / rate;
0544         }
0545     }
0546 
0547     QString durationString = QString::fromUtf8("%1s").arg(remain);
0548 
0549     if (remain)
0550     {
0551         unsigned int r, d, h, m, s;
0552         r = qAbs(remain * 1000);
0553         d = r / 86400000;
0554         r = r % 86400000;
0555         h = r / 3600000;
0556         r = r % 3600000;
0557         m = r / 60000;
0558         r = r % 60000;
0559         s = r / 1000;
0560 
0561         durationString = QString().asprintf("%d.%02d:%02d:%02d", d, h, m, s);
0562     }
0563 
0564     d->received->setText(ItemPropertiesTab::humanReadableBytesCount(d->bar->value()));
0565     d->total->setText(ItemPropertiesTab::humanReadableBytesCount(d->bar->maximum()));
0566     d->rate->setText(QString::fromUtf8("%1/s").arg(ItemPropertiesTab::humanReadableBytesCount(rate)));
0567     d->remain->setText(durationString);
0568 }
0569 
0570 void OnlineVersionDlg::slotRunInstaller()
0571 {
0572 
0573 #ifndef Q_OS_LINUX
0574 
0575     bool started = false;
0576     QString path = d->dwnloader->downloadedPath();
0577     qCDebug(DIGIKAM_GENERAL_LOG) << "Run installer:" << path;
0578 
0579 #   ifdef Q_OS_WIN
0580 
0581     started = QProcess::startDetached(path, QStringList());
0582 
0583 #   elif defined Q_OS_MACOS
0584 
0585     QStringList args;
0586     args << QLatin1String("-e");
0587     args << QLatin1String("tell application \"Finder\"");
0588     args << QLatin1String("-e");
0589     args << QString::fromUtf8("open POSIX file \"%1\"").arg(path);
0590     args << QLatin1String("-e");
0591     args << QLatin1String("end tell");
0592     args << QLatin1String("-e");
0593     args << QLatin1String("return");
0594 
0595     started = QProcess::startDetached(QLatin1String("/usr/bin/osascript"), args);
0596 
0597 #   endif
0598 
0599     if (!started)
0600     {
0601         QMessageBox::critical(this, qApp->applicationName(),
0602                               i18n("Cannot start installer:\n%1", path));
0603         return;
0604     }
0605 
0606     // Close this dialog
0607 
0608     close();
0609 
0610     // Now close main window application after 3 secondes to wait Installer to start in background.
0611     // See bug #437813.
0612 
0613     qCDebug(DIGIKAM_GENERAL_LOG) << "Call to close all main windows";
0614 
0615     QTimer::singleShot(3000, qApp, SLOT(closeAllWindows()));
0616 
0617 #endif
0618 
0619 }
0620 
0621 void OnlineVersionDlg::slotOpenInFileManager()
0622 {
0623     QList<QUrl> lst = QList<QUrl>() << QUrl::fromLocalFile(d->dwnloader->downloadedPath());
0624     DFileOperations::openInFileManager(lst);
0625     close();
0626 }
0627 
0628 void OnlineVersionDlg::slotHelp()
0629 {
0630     openOnlineDocumentation(QLatin1String("setup_application"), QLatin1String("miscs_settings"), QLatin1String("updates-settings"));
0631 }
0632 
0633 void OnlineVersionDlg::slotSetupUpdate()
0634 {
0635     close();
0636     Q_EMIT signalSetupUpdate();
0637 }
0638 
0639 } // namespace Digikam
0640 
0641 #include "moc_onlineversiondlg.cpp"