1 #include "tab_replays.h"
2 
3 #include "abstractclient.h"
4 #include "pb/command_replay_delete_match.pb.h"
5 #include "pb/command_replay_download.pb.h"
6 #include "pb/command_replay_modify_match.pb.h"
7 #include "pb/event_replay_added.pb.h"
8 #include "pb/game_replay.pb.h"
9 #include "pb/response.pb.h"
10 #include "pb/response_replay_download.pb.h"
11 #include "pending_command.h"
12 #include "remotereplaylist_treewidget.h"
13 #include "settingscache.h"
14 #include "tab_game.h"
15 
16 #include <QAction>
17 #include <QApplication>
18 #include <QFileSystemModel>
19 #include <QGroupBox>
20 #include <QHBoxLayout>
21 #include <QHeaderView>
22 #include <QInputDialog>
23 #include <QMessageBox>
24 #include <QToolBar>
25 #include <QTreeView>
26 #include <QVBoxLayout>
27 
TabReplays(TabSupervisor * _tabSupervisor,AbstractClient * _client)28 TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client) : Tab(_tabSupervisor), client(_client)
29 {
30     localDirModel = new QFileSystemModel(this);
31     localDirModel->setRootPath(SettingsCache::instance().getReplaysPath());
32     localDirModel->sort(0, Qt::AscendingOrder);
33 
34     localDirView = new QTreeView;
35     localDirView->setModel(localDirModel);
36     localDirView->setColumnHidden(1, true);
37     localDirView->setRootIndex(localDirModel->index(localDirModel->rootPath(), 0));
38     localDirView->setSortingEnabled(true);
39     localDirView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
40     localDirView->header()->setSortIndicator(0, Qt::AscendingOrder);
41 
42     leftToolBar = new QToolBar;
43     leftToolBar->setOrientation(Qt::Horizontal);
44     leftToolBar->setIconSize(QSize(32, 32));
45     QHBoxLayout *leftToolBarLayout = new QHBoxLayout;
46     leftToolBarLayout->addStretch();
47     leftToolBarLayout->addWidget(leftToolBar);
48     leftToolBarLayout->addStretch();
49 
50     QVBoxLayout *leftVbox = new QVBoxLayout;
51     leftVbox->addWidget(localDirView);
52     leftVbox->addLayout(leftToolBarLayout);
53     leftGroupBox = new QGroupBox;
54     leftGroupBox->setLayout(leftVbox);
55 
56     rightToolBar = new QToolBar;
57     rightToolBar->setOrientation(Qt::Horizontal);
58     rightToolBar->setIconSize(QSize(32, 32));
59     QHBoxLayout *rightToolBarLayout = new QHBoxLayout;
60     rightToolBarLayout->addStretch();
61     rightToolBarLayout->addWidget(rightToolBar);
62     rightToolBarLayout->addStretch();
63 
64     serverDirView = new RemoteReplayList_TreeWidget(client);
65 
66     QVBoxLayout *rightVbox = new QVBoxLayout;
67     rightVbox->addWidget(serverDirView);
68     rightVbox->addLayout(rightToolBarLayout);
69     rightGroupBox = new QGroupBox;
70     rightGroupBox->setLayout(rightVbox);
71 
72     QHBoxLayout *hbox = new QHBoxLayout;
73     hbox->addWidget(leftGroupBox);
74     hbox->addWidget(rightGroupBox);
75 
76     aOpenLocalReplay = new QAction(this);
77     aOpenLocalReplay->setIcon(QPixmap("theme:icons/view"));
78     connect(aOpenLocalReplay, SIGNAL(triggered()), this, SLOT(actOpenLocalReplay()));
79     connect(localDirView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actOpenLocalReplay()));
80     aDeleteLocalReplay = new QAction(this);
81     aDeleteLocalReplay->setIcon(QPixmap("theme:icons/remove_row"));
82     connect(aDeleteLocalReplay, SIGNAL(triggered()), this, SLOT(actDeleteLocalReplay()));
83     aOpenRemoteReplay = new QAction(this);
84     aOpenRemoteReplay->setIcon(QPixmap("theme:icons/view"));
85     connect(aOpenRemoteReplay, SIGNAL(triggered()), this, SLOT(actOpenRemoteReplay()));
86     connect(serverDirView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actOpenRemoteReplay()));
87     aDownload = new QAction(this);
88     aDownload->setIcon(QPixmap("theme:icons/arrow_left_green"));
89     connect(aDownload, SIGNAL(triggered()), this, SLOT(actDownload()));
90     aKeep = new QAction(this);
91     aKeep->setIcon(QPixmap("theme:icons/lock"));
92     connect(aKeep, SIGNAL(triggered()), this, SLOT(actKeepRemoteReplay()));
93     aDeleteRemoteReplay = new QAction(this);
94     aDeleteRemoteReplay->setIcon(QPixmap("theme:icons/remove_row"));
95     connect(aDeleteRemoteReplay, SIGNAL(triggered()), this, SLOT(actDeleteRemoteReplay()));
96 
97     leftToolBar->addAction(aOpenLocalReplay);
98     leftToolBar->addAction(aDeleteLocalReplay);
99     rightToolBar->addAction(aOpenRemoteReplay);
100     rightToolBar->addAction(aDownload);
101     rightToolBar->addAction(aKeep);
102     rightToolBar->addAction(aDeleteRemoteReplay);
103 
104     retranslateUi();
105 
106     QWidget *mainWidget = new QWidget(this);
107     mainWidget->setLayout(hbox);
108     setCentralWidget(mainWidget);
109 
110     connect(client, SIGNAL(replayAddedEventReceived(const Event_ReplayAdded &)), this,
111             SLOT(replayAddedEventReceived(const Event_ReplayAdded &)));
112 }
113 
retranslateUi()114 void TabReplays::retranslateUi()
115 {
116     leftGroupBox->setTitle(tr("Local file system"));
117     rightGroupBox->setTitle(tr("Server replay storage"));
118 
119     aOpenLocalReplay->setText(tr("Watch replay"));
120     aDeleteLocalReplay->setText(tr("Delete"));
121     aOpenRemoteReplay->setText(tr("Watch replay"));
122     aDownload->setText(tr("Download replay"));
123     aKeep->setText(tr("Toggle expiration lock"));
124     aDeleteRemoteReplay->setText(tr("Delete"));
125 }
126 
actOpenLocalReplay()127 void TabReplays::actOpenLocalReplay()
128 {
129     QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
130     if (localDirModel->isDir(curLeft))
131         return;
132     QString filePath = localDirModel->filePath(curLeft);
133 
134     QFile f(filePath);
135     if (!f.open(QIODevice::ReadOnly))
136         return;
137     QByteArray data = f.readAll();
138     f.close();
139 
140     GameReplay *replay = new GameReplay;
141     replay->ParseFromArray(data.data(), data.size());
142 
143     emit openReplay(replay);
144 }
145 
actDeleteLocalReplay()146 void TabReplays::actDeleteLocalReplay()
147 {
148     QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
149     if (QMessageBox::warning(this, tr("Delete local file"),
150                              tr("Are you sure you want to delete \"%1\"?").arg(localDirModel->fileName(curLeft)),
151                              QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
152         return;
153 
154     localDirModel->remove(curLeft);
155 }
156 
actOpenRemoteReplay()157 void TabReplays::actOpenRemoteReplay()
158 {
159     ServerInfo_Replay const *curRight = serverDirView->getCurrentReplay();
160     if (!curRight)
161         return;
162 
163     Command_ReplayDownload cmd;
164     cmd.set_replay_id(curRight->replay_id());
165 
166     PendingCommand *pend = client->prepareSessionCommand(cmd);
167     connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
168             SLOT(openRemoteReplayFinished(const Response &)));
169     client->sendCommand(pend);
170 }
171 
openRemoteReplayFinished(const Response & r)172 void TabReplays::openRemoteReplayFinished(const Response &r)
173 {
174     if (r.response_code() != Response::RespOk)
175         return;
176 
177     const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext);
178     GameReplay *replay = new GameReplay;
179     replay->ParseFromString(resp.replay_data());
180 
181     emit openReplay(replay);
182 }
183 
actDownload()184 void TabReplays::actDownload()
185 {
186     QString filePath;
187     QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
188     if (!curLeft.isValid())
189         filePath = localDirModel->rootPath();
190     else {
191         while (!localDirModel->isDir(curLeft))
192             curLeft = curLeft.parent();
193         filePath = localDirModel->filePath(curLeft);
194     }
195 
196     ServerInfo_Replay const *curRight = serverDirView->getCurrentReplay();
197 
198     if (!curRight) {
199         QMessageBox::information(this, tr("Downloading Replays"),
200                                  tr("You cannot download replay folders at this time"));
201         return;
202     }
203 
204     filePath += QString("/replay_%1.cor").arg(curRight->replay_id());
205 
206     Command_ReplayDownload cmd;
207     cmd.set_replay_id(curRight->replay_id());
208 
209     PendingCommand *pend = client->prepareSessionCommand(cmd);
210     pend->setExtraData(filePath);
211     connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
212             SLOT(downloadFinished(Response, CommandContainer, QVariant)));
213     client->sendCommand(pend);
214 }
215 
downloadFinished(const Response & r,const CommandContainer &,const QVariant & extraData)216 void TabReplays::downloadFinished(const Response &r,
217                                   const CommandContainer & /* commandContainer */,
218                                   const QVariant &extraData)
219 {
220     if (r.response_code() != Response::RespOk)
221         return;
222 
223     const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext);
224     QString filePath = extraData.toString();
225 
226     const std::string &data = resp.replay_data();
227     QFile f(filePath);
228     f.open(QIODevice::WriteOnly);
229     f.write((const char *)data.data(), data.size());
230     f.close();
231 }
232 
actKeepRemoteReplay()233 void TabReplays::actKeepRemoteReplay()
234 {
235     ServerInfo_ReplayMatch const *curRight = serverDirView->getCurrentReplayMatch();
236     if (!curRight)
237         return;
238 
239     Command_ReplayModifyMatch cmd;
240     cmd.set_game_id(curRight->game_id());
241     cmd.set_do_not_hide(!curRight->do_not_hide());
242 
243     PendingCommand *pend = client->prepareSessionCommand(cmd);
244     connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
245             SLOT(keepRemoteReplayFinished(Response, CommandContainer)));
246     client->sendCommand(pend);
247 }
248 
keepRemoteReplayFinished(const Response & r,const CommandContainer & commandContainer)249 void TabReplays::keepRemoteReplayFinished(const Response &r, const CommandContainer &commandContainer)
250 {
251     if (r.response_code() != Response::RespOk)
252         return;
253 
254     const Command_ReplayModifyMatch &cmd =
255         commandContainer.session_command(0).GetExtension(Command_ReplayModifyMatch::ext);
256 
257     ServerInfo_ReplayMatch temp;
258     temp.set_do_not_hide(cmd.do_not_hide());
259 
260     serverDirView->updateMatchInfo(cmd.game_id(), temp);
261 }
262 
actDeleteRemoteReplay()263 void TabReplays::actDeleteRemoteReplay()
264 {
265     ServerInfo_ReplayMatch const *curRight = serverDirView->getCurrentReplayMatch();
266     if (!curRight)
267         return;
268     if (QMessageBox::warning(this, tr("Delete remote replay"),
269                              tr("Are you sure you want to delete the replay of game %1?").arg(curRight->game_id()),
270                              QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
271         return;
272 
273     Command_ReplayDeleteMatch cmd;
274     cmd.set_game_id(curRight->game_id());
275 
276     PendingCommand *pend = client->prepareSessionCommand(cmd);
277     connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
278             SLOT(deleteRemoteReplayFinished(Response, CommandContainer)));
279     client->sendCommand(pend);
280 }
281 
deleteRemoteReplayFinished(const Response & r,const CommandContainer & commandContainer)282 void TabReplays::deleteRemoteReplayFinished(const Response &r, const CommandContainer &commandContainer)
283 {
284     if (r.response_code() != Response::RespOk)
285         return;
286 
287     const Command_ReplayDeleteMatch &cmd =
288         commandContainer.session_command(0).GetExtension(Command_ReplayDeleteMatch::ext);
289     serverDirView->removeMatchInfo(cmd.game_id());
290 }
291 
replayAddedEventReceived(const Event_ReplayAdded & event)292 void TabReplays::replayAddedEventReceived(const Event_ReplayAdded &event)
293 {
294     serverDirView->addMatchInfo(event.match_info());
295 }
296