1 // Copyright 2018 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include "DolphinQt/Updater.h"
6 
7 #include <QCheckBox>
8 #include <QDialog>
9 #include <QDialogButtonBox>
10 #include <QLabel>
11 #include <QPushButton>
12 #include <QTextBrowser>
13 #include <QVBoxLayout>
14 
15 #include "Common/Version.h"
16 
17 #include "DolphinQt/QtUtils/RunOnObject.h"
18 #include "DolphinQt/Settings.h"
19 
Updater(QWidget * parent)20 Updater::Updater(QWidget* parent) : m_parent(parent)
21 {
22   connect(this, &QThread::finished, this, &QObject::deleteLater);
23 }
24 
run()25 void Updater::run()
26 {
27   AutoUpdateChecker::CheckForUpdate();
28 }
29 
CheckForUpdate()30 bool Updater::CheckForUpdate()
31 {
32   m_update_available = false;
33   AutoUpdateChecker::CheckForUpdate();
34 
35   return m_update_available;
36 }
37 
OnUpdateAvailable(const NewVersionInformation & info)38 void Updater::OnUpdateAvailable(const NewVersionInformation& info)
39 {
40   bool later = false;
41   m_update_available = true;
42 
43   std::optional<int> choice = RunOnObject(m_parent, [&] {
44     QDialog* dialog = new QDialog(m_parent);
45     dialog->setWindowTitle(tr("Update available"));
46     dialog->setWindowFlags(dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);
47 
48     auto* label = new QLabel(
49         tr("<h2>A new version of Dolphin is available!</h2>Dolphin %1 is available for "
50            "download. "
51            "You are running %2.<br> Would you like to update?<br><h4>Release Notes:</h4>")
52             .arg(QString::fromStdString(info.new_shortrev))
53             .arg(QString::fromStdString(Common::scm_desc_str)));
54     label->setTextFormat(Qt::RichText);
55 
56     auto* changelog = new QTextBrowser;
57 
58     changelog->setHtml(QString::fromStdString(info.changelog_html));
59     changelog->setOpenExternalLinks(true);
60     changelog->setMinimumWidth(400);
61 
62     auto* update_later_check = new QCheckBox(tr("Update after closing Dolphin"));
63 
64     connect(update_later_check, &QCheckBox::toggled, [&](bool checked) { later = checked; });
65 
66     auto* buttons = new QDialogButtonBox;
67 
68     auto* never_btn =
69         buttons->addButton(tr("Never Auto-Update"), QDialogButtonBox::DestructiveRole);
70     buttons->addButton(tr("Remind Me Later"), QDialogButtonBox::RejectRole);
71     buttons->addButton(tr("Install Update"), QDialogButtonBox::AcceptRole);
72 
73     auto* layout = new QVBoxLayout;
74     dialog->setLayout(layout);
75 
76     layout->addWidget(label);
77     layout->addWidget(changelog);
78     layout->addWidget(update_later_check);
79     layout->addWidget(buttons);
80 
81     connect(never_btn, &QPushButton::clicked, [dialog] {
82       Settings::Instance().SetAutoUpdateTrack(QString{});
83       dialog->reject();
84     });
85 
86     connect(buttons, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
87     connect(buttons, &QDialogButtonBox::rejected, dialog, &QDialog::reject);
88 
89     return dialog->exec();
90   });
91 
92   if (choice && *choice == QDialog::Accepted)
93   {
94     TriggerUpdate(info, later ? AutoUpdateChecker::RestartMode::NO_RESTART_AFTER_UPDATE :
95                                 AutoUpdateChecker::RestartMode::RESTART_AFTER_UPDATE);
96 
97     if (!later)
98     {
99       RunOnObject(m_parent, [this] {
100         m_parent->close();
101         return 0;
102       });
103     }
104   }
105 }
106