From ed907d7c6f4f87e3893ece419bffe83b926e3f5b Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Wed, 25 Dec 2024 04:33:36 -0800 Subject: [PATCH] Support downloading replay folders (#5325) * rename old get replay match method to get enclosing * creat raw getReplayMatch method * implement thing --- cockatrice/src/client/tabs/tab_replays.cpp | 41 +++++++++++-------- cockatrice/src/client/tabs/tab_replays.h | 3 ++ .../remote/remote_replay_list_tree_widget.cpp | 24 ++++++++++- .../remote/remote_replay_list_tree_widget.h | 2 + 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/cockatrice/src/client/tabs/tab_replays.cpp b/cockatrice/src/client/tabs/tab_replays.cpp index fb1375f52..954d9934a 100644 --- a/cockatrice/src/client/tabs/tab_replays.cpp +++ b/cockatrice/src/client/tabs/tab_replays.cpp @@ -239,30 +239,36 @@ void TabReplays::openRemoteReplayFinished(const Response &r) void TabReplays::actDownload() { - QString dirPath; QModelIndex curLeft = localDirView->selectionModel()->currentIndex(); - if (!curLeft.isValid()) - dirPath = localDirModel->rootPath(); - else { - while (!localDirModel->isDir(curLeft)) - curLeft = curLeft.parent(); - dirPath = localDirModel->filePath(curLeft); + while (!localDirModel->isDir(curLeft)) { + curLeft = curLeft.parent(); } - const auto curRights = serverDirView->getSelectedReplays(); - - const auto isNull = [](const auto *replay) { return !replay; }; - if (std::any_of(curRights.begin(), curRights.end(), isNull)) { - QMessageBox::information(this, tr("Downloading Replays"), - tr("Folder download is not yet supported. Please download replays individually.")); - return; + for (const auto curRight : serverDirView->selectionModel()->selectedRows()) { + downloadNodeAtIndex(curLeft, curRight); } +} - for (const auto curRight : curRights) { - const QString filePath = dirPath + QString("/replay_%1.cor").arg(curRight->replay_id()); +void TabReplays::downloadNodeAtIndex(const QModelIndex &curLeft, const QModelIndex &curRight) +{ + if (const auto replayMatch = serverDirView->getReplayMatch(curRight)) { + // node at index is a folder + const QString name = + QString::number(replayMatch->game_id()) + "_" + QString::fromStdString(replayMatch->game_name()); + + const auto newDirIndex = localDirModel->mkdir(curLeft, name); + + int rows = serverDirView->model()->rowCount(curRight); + for (int i = 0; i < rows; i++) { + const auto childIndex = serverDirView->model()->index(i, 0, curRight); + downloadNodeAtIndex(newDirIndex, childIndex); + } + } else if (const auto replay = serverDirView->getReplay(curRight)) { + // node at index is a replay + const QString filePath = localDirModel->filePath(curLeft) + QString("/replay_%1.cor").arg(replay->replay_id()); Command_ReplayDownload cmd; - cmd.set_replay_id(curRight->replay_id()); + cmd.set_replay_id(replay->replay_id()); PendingCommand *pend = client->prepareSessionCommand(cmd); pend->setExtraData(filePath); @@ -270,6 +276,7 @@ void TabReplays::actDownload() SLOT(downloadFinished(Response, CommandContainer, QVariant))); client->sendCommand(pend); } + // node at index was invalid } void TabReplays::downloadFinished(const Response &r, diff --git a/cockatrice/src/client/tabs/tab_replays.h b/cockatrice/src/client/tabs/tab_replays.h index 3f127613b..cf7a76e4f 100644 --- a/cockatrice/src/client/tabs/tab_replays.h +++ b/cockatrice/src/client/tabs/tab_replays.h @@ -27,6 +27,9 @@ private: QAction *aOpenLocalReplay, *aNewLocalFolder, *aDeleteLocalReplay; QAction *aOpenRemoteReplay, *aDownload, *aKeep, *aDeleteRemoteReplay; + + void downloadNodeAtIndex(const QModelIndex &curLeft, const QModelIndex &curRight); + private slots: void actLocalDoubleClick(const QModelIndex &curLeft); void actOpenLocalReplay(); diff --git a/cockatrice/src/server/remote/remote_replay_list_tree_widget.cpp b/cockatrice/src/server/remote/remote_replay_list_tree_widget.cpp index 838524519..88d59a57a 100644 --- a/cockatrice/src/server/remote/remote_replay_list_tree_widget.cpp +++ b/cockatrice/src/server/remote/remote_replay_list_tree_widget.cpp @@ -216,6 +216,18 @@ ServerInfo_Replay const *RemoteReplayList_TreeModel::getReplay(const QModelIndex } ServerInfo_ReplayMatch const *RemoteReplayList_TreeModel::getReplayMatch(const QModelIndex &index) const +{ + if (!index.isValid()) + return nullptr; + + auto *node = dynamic_cast(static_cast(index.internalPointer())); + if (!node) + return nullptr; + + return &node->getMatchInfo(); +} + +ServerInfo_ReplayMatch const *RemoteReplayList_TreeModel::getEnclosingReplayMatch(const QModelIndex &index) const { if (!index.isValid()) return nullptr; @@ -318,6 +330,15 @@ ServerInfo_Replay const *RemoteReplayList_TreeWidget::getReplay(const QModelInde return treeModel->getReplay(proxyModel->mapToSource(ind)); } +/** + * Gets the replay match at the given index + * @return The replay match. Returns nullptr if there is no replay match at the index. + */ +ServerInfo_ReplayMatch const *RemoteReplayList_TreeWidget::getReplayMatch(const QModelIndex &ind) const +{ + return treeModel->getReplayMatch(proxyModel->mapToSource(ind)); +} + /** * Gets all currently selected replays. * Any selection that isn't a replay file (e.g. a folder) will appear as a nullptr in the list. @@ -338,6 +359,7 @@ QList RemoteReplayList_TreeWidget::getSelectedReplays /** * Gets all currently selected replayMatches. + * If a non-folder node is selected, it will return the parent folder of that node. * * @return A Set of pointers to the selected replayMatches. */ @@ -346,7 +368,7 @@ QSet RemoteReplayList_TreeWidget::getSelectedRep const auto selection = selectionModel()->selectedRows(); auto replayMatches = QSet(); for (const auto &row : selection) { - if (const auto replayMatch = treeModel->getReplayMatch(proxyModel->mapToSource(row))) { + if (const auto replayMatch = treeModel->getEnclosingReplayMatch(proxyModel->mapToSource(row))) { replayMatches << replayMatch; } } diff --git a/cockatrice/src/server/remote/remote_replay_list_tree_widget.h b/cockatrice/src/server/remote/remote_replay_list_tree_widget.h index a93e693fa..7822fceda 100644 --- a/cockatrice/src/server/remote/remote_replay_list_tree_widget.h +++ b/cockatrice/src/server/remote/remote_replay_list_tree_widget.h @@ -97,6 +97,7 @@ public: void refreshTree(); ServerInfo_Replay const *getReplay(const QModelIndex &index) const; ServerInfo_ReplayMatch const *getReplayMatch(const QModelIndex &index) const; + ServerInfo_ReplayMatch const *getEnclosingReplayMatch(const QModelIndex &index) const; void addMatchInfo(const ServerInfo_ReplayMatch &matchInfo); void updateMatchInfo(int gameId, const ServerInfo_ReplayMatch &matchInfo); void removeMatchInfo(int gameId); @@ -111,6 +112,7 @@ private: public: RemoteReplayList_TreeWidget(AbstractClient *_client, QWidget *parent = nullptr); ServerInfo_Replay const *getReplay(const QModelIndex &ind) const; + ServerInfo_ReplayMatch const *getReplayMatch(const QModelIndex &ind) const; QList getSelectedReplays() const; QSet getSelectedReplayMatches() const; void refreshTree();