1 // Copyright 2017 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include "DolphinQt/NetPlay/MD5Dialog.h"
6 
7 #include <algorithm>
8 #include <functional>
9 
10 #include <QDialogButtonBox>
11 #include <QGroupBox>
12 #include <QLabel>
13 #include <QProgressBar>
14 #include <QPushButton>
15 #include <QVBoxLayout>
16 
17 #include "Core/NetPlayClient.h"
18 #include "Core/NetPlayServer.h"
19 
20 #include "DolphinQt/Settings.h"
21 
GetPlayerNameFromPID(int pid)22 static QString GetPlayerNameFromPID(int pid)
23 {
24   QString player_name = QObject::tr("Invalid Player ID");
25   auto client = Settings::Instance().GetNetPlayClient();
26   if (!client)
27     return player_name;
28 
29   for (const auto* player : client->GetPlayers())
30   {
31     if (player->pid == pid)
32     {
33       player_name = QString::fromStdString(player->name);
34       break;
35     }
36   }
37   return player_name;
38 }
39 
MD5Dialog(QWidget * parent)40 MD5Dialog::MD5Dialog(QWidget* parent) : QDialog(parent)
41 {
42   CreateWidgets();
43   ConnectWidgets();
44   setWindowTitle(tr("MD5 Checksum"));
45   setWindowFlags(Qt::Sheet | Qt::Dialog);
46   setWindowModality(Qt::WindowModal);
47 }
48 
CreateWidgets()49 void MD5Dialog::CreateWidgets()
50 {
51   m_main_layout = new QVBoxLayout;
52   m_progress_box = new QGroupBox;
53   m_progress_layout = new QVBoxLayout;
54   m_button_box = new QDialogButtonBox(QDialogButtonBox::NoButton);
55   m_check_label = new QLabel;
56 
57   m_progress_box->setLayout(m_progress_layout);
58 
59   m_main_layout->addWidget(m_progress_box);
60   m_main_layout->addWidget(m_check_label);
61   m_main_layout->addWidget(m_button_box);
62   setLayout(m_main_layout);
63 }
64 
ConnectWidgets()65 void MD5Dialog::ConnectWidgets()
66 {
67   connect(m_button_box, &QDialogButtonBox::rejected, this, &MD5Dialog::reject);
68 }
69 
show(const QString & title)70 void MD5Dialog::show(const QString& title)
71 {
72   m_progress_box->setTitle(title);
73 
74   for (auto& pair : m_progress_bars)
75   {
76     m_progress_layout->removeWidget(pair.second);
77     pair.second->deleteLater();
78   }
79 
80   for (auto& pair : m_status_labels)
81   {
82     m_progress_layout->removeWidget(pair.second);
83     pair.second->deleteLater();
84   }
85 
86   m_progress_bars.clear();
87   m_status_labels.clear();
88   m_results.clear();
89   m_check_label->setText(QString::fromStdString(""));
90 
91   auto client = Settings::Instance().GetNetPlayClient();
92   if (!client)
93     return;
94 
95   if (Settings::Instance().GetNetPlayServer())
96   {
97     m_button_box->setStandardButtons(QDialogButtonBox::Cancel);
98     QPushButton* cancel_button = m_button_box->button(QDialogButtonBox::Cancel);
99     cancel_button->setAutoDefault(false);
100     cancel_button->setDefault(false);
101   }
102   else
103   {
104     m_button_box->setStandardButtons(QDialogButtonBox::Close);
105     QPushButton* close_button = m_button_box->button(QDialogButtonBox::Close);
106     close_button->setAutoDefault(false);
107     close_button->setDefault(false);
108   }
109 
110   for (const auto* player : client->GetPlayers())
111   {
112     m_progress_bars[player->pid] = new QProgressBar;
113     m_status_labels[player->pid] = new QLabel;
114 
115     m_progress_layout->addWidget(m_progress_bars[player->pid]);
116     m_progress_layout->addWidget(m_status_labels[player->pid]);
117   }
118 
119   QDialog::show();
120 }
121 
SetProgress(int pid,int progress)122 void MD5Dialog::SetProgress(int pid, int progress)
123 {
124   QString player_name = GetPlayerNameFromPID(pid);
125 
126   if (!m_status_labels.count(pid))
127     return;
128 
129   m_status_labels[pid]->setText(
130       tr("%1[%2]: %3 %").arg(player_name, QString::number(pid), QString::number(progress)));
131   m_progress_bars[pid]->setValue(progress);
132 }
133 
SetResult(int pid,const std::string & result)134 void MD5Dialog::SetResult(int pid, const std::string& result)
135 {
136   QString player_name = GetPlayerNameFromPID(pid);
137 
138   if (!m_status_labels.count(pid))
139     return;
140 
141   m_status_labels[pid]->setText(
142       tr("%1[%2]: %3").arg(player_name, QString::number(pid), QString::fromStdString(result)));
143 
144   m_results.push_back(result);
145 
146   auto client = Settings::Instance().GetNetPlayClient();
147   if (client && m_results.size() >= client->GetPlayers().size())
148   {
149     if (std::adjacent_find(m_results.begin(), m_results.end(), std::not_equal_to<>()) ==
150         m_results.end())
151     {
152       m_check_label->setText(tr("The hashes match!"));
153     }
154     else
155     {
156       m_check_label->setText(tr("The hashes do not match!"));
157     }
158 
159     m_button_box->setStandardButtons(QDialogButtonBox::Close);
160     QPushButton* close_button = m_button_box->button(QDialogButtonBox::Close);
161     close_button->setAutoDefault(false);
162     close_button->setDefault(false);
163   }
164 }
165 
reject()166 void MD5Dialog::reject()
167 {
168   auto server = Settings::Instance().GetNetPlayServer();
169 
170   if (server)
171     server->AbortMD5();
172 
173   QDialog::reject();
174 }
175