From 7c6071dfe1d8d5986ae762a0262e4fb1707ef12c Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 11 Jan 2023 20:21:27 +1000 Subject: [PATCH] Qt: Add option to reset played time --- src/duckstation-qt/mainwindow.cpp | 17 ++++++++++++ src/duckstation-qt/mainwindow.h | 1 + src/frontend-common/fullscreen_ui.cpp | 4 +++ src/frontend-common/game_list.cpp | 35 +++++++++++++++++++----- src/frontend-common/game_list.h | 1 + src/frontend-common/imgui_fullscreen.cpp | 2 +- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 0059636a2..54876c14f 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -1408,6 +1408,9 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point) connect(menu.addAction(tr("Exclude From List")), &QAction::triggered, [this, entry]() { getSettingsDialog()->getGameListSettingsWidget()->addExcludedPath(entry->path); }); + connect(menu.addAction(tr("Reset Play Time")), &QAction::triggered, + [this, entry]() { clearGameListEntryPlayTime(entry); }); + connect(menu.addAction(tr("Add Search Directory...")), &QAction::triggered, [this]() { getSettingsDialog()->getGameListSettingsWidget()->addSearchDirectory(this); }); @@ -1451,6 +1454,20 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry) m_game_list_widget->refreshGridCovers(); } +void MainWindow::clearGameListEntryPlayTime(const GameList::Entry* entry) +{ + if (QMessageBox::question( + this, tr("Confirm Reset"), + tr("Are you sure you want to reset the play time for '%1'?\n\nThis action cannot be undone.") + .arg(QString::fromStdString(entry->title))) != QMessageBox::Yes) + { + return; + } + + GameList::ClearPlayedTimeForSerial(entry->serial); + m_game_list_widget->refresh(false); +} + void MainWindow::setupAdditionalUi() { const bool status_bar_visible = Host::GetBaseBoolSettingValue("UI", "ShowStatusBar", true); diff --git a/src/duckstation-qt/mainwindow.h b/src/duckstation-qt/mainwindow.h index ca9fec85f..42fee11a6 100644 --- a/src/duckstation-qt/mainwindow.h +++ b/src/duckstation-qt/mainwindow.h @@ -226,6 +226,7 @@ private: void updateMenuSelectedTheme(); std::string getDeviceDiscPath(const QString& title); void setGameListEntryCoverImage(const GameList::Entry* entry); + void clearGameListEntryPlayTime(const GameList::Entry* entry); void setTheme(const QString& theme); void recreate(); diff --git a/src/frontend-common/fullscreen_ui.cpp b/src/frontend-common/fullscreen_ui.cpp index 6ef7cb4d2..d62a0b2b0 100644 --- a/src/frontend-common/fullscreen_ui.cpp +++ b/src/frontend-common/fullscreen_ui.cpp @@ -5834,6 +5834,7 @@ void FullscreenUI::HandleGameListOptions(const GameList::Entry* entry) {ICON_FA_WRENCH " Game Properties", false}, {ICON_FA_PLAY " Resume Game", false}, {ICON_FA_UNDO " Load State", false}, {ICON_FA_COMPACT_DISC " Default Boot", false}, {ICON_FA_LIGHTBULB " Fast Boot", false}, {ICON_FA_MAGIC " Slow Boot", false}, + {ICON_FA_FOLDER_MINUS " Reset Play Time", false}, {ICON_FA_WINDOW_CLOSE " Close Menu", false}, }; @@ -5860,6 +5861,9 @@ void FullscreenUI::HandleGameListOptions(const GameList::Entry* entry) case 5: // Slow Boot DoStartPath(entry_path, {}, false); break; + case 6: // Reset Play Time + GameList::ClearPlayedTimeForSerial(entry_serial); + break; default: break; } diff --git a/src/frontend-common/game_list.cpp b/src/frontend-common/game_list.cpp index c5d01768b..9def6ad0e 100644 --- a/src/frontend-common/game_list.cpp +++ b/src/frontend-common/game_list.cpp @@ -862,8 +862,8 @@ GameList::PlayedTimeEntry GameList::UpdatePlayedTimeFile(const std::string& path continue; // found it! - line_entry.last_played_time = last_time; - line_entry.total_played_time += add_time; + line_entry.last_played_time = (last_time != 0) ? last_time : 0; + line_entry.total_played_time = (last_time != 0) ? (line_entry.total_played_time + add_time) : 0; std::string new_line(MakePlayedTimeLine(serial, line_entry)); if (FileSystem::FSeek64(fp.get(), line_pos, SEEK_SET) != 0 || @@ -875,12 +875,15 @@ GameList::PlayedTimeEntry GameList::UpdatePlayedTimeFile(const std::string& path return line_entry; } - // new entry. - std::string new_line(MakePlayedTimeLine(serial, new_entry)); - if (FileSystem::FSeek64(fp.get(), 0, SEEK_END) != 0 || - std::fwrite(new_line.data(), new_line.length(), 1, fp.get()) != 1) + if (last_time != 0) { - Log_ErrorPrintf("Failed to write '%s'.", path.c_str()); + // new entry. + std::string new_line(MakePlayedTimeLine(serial, new_entry)); + if (FileSystem::FSeek64(fp.get(), 0, SEEK_END) != 0 || + std::fwrite(new_line.data(), new_line.length(), 1, fp.get()) != 1) + { + Log_ErrorPrintf("Failed to write '%s'.", path.c_str()); + } } return new_entry; @@ -906,6 +909,24 @@ void GameList::AddPlayedTimeForSerial(const std::string& serial, std::time_t las } } +void GameList::ClearPlayedTimeForSerial(const std::string& serial) +{ + if (serial.empty()) + return; + + UpdatePlayedTimeFile(GetPlayedTimeFile(), serial, 0, 0); + + std::unique_lock lock(s_mutex); + for (GameList::Entry& entry : s_entries) + { + if (entry.serial != serial) + continue; + + entry.last_played_time = 0; + entry.total_played_time = 0; + } +} + std::time_t GameList::GetCachedPlayedTimeForSerial(const std::string& serial) { if (serial.empty()) diff --git a/src/frontend-common/game_list.h b/src/frontend-common/game_list.h index 87707539f..e075d174a 100644 --- a/src/frontend-common/game_list.h +++ b/src/frontend-common/game_list.h @@ -81,6 +81,7 @@ void Refresh(bool invalidate_cache, bool only_cache = false, ProgressCallback* p /// Add played time for the specified serial. void AddPlayedTimeForSerial(const std::string& serial, std::time_t last_time, std::time_t add_time); +void ClearPlayedTimeForSerial(const std::string& serial); /// Returns the total time played for a game. Requires the game to be scanned in the list. std::time_t GetCachedPlayedTimeForSerial(const std::string& serial); diff --git a/src/frontend-common/imgui_fullscreen.cpp b/src/frontend-common/imgui_fullscreen.cpp index 0d86a2f50..3bab3d4e5 100644 --- a/src/frontend-common/imgui_fullscreen.cpp +++ b/src/frontend-common/imgui_fullscreen.cpp @@ -1857,7 +1857,7 @@ void ImGuiFullscreen::DrawChoiceDialog() const float title_height = g_large_font->FontSize + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f; const float height = - std::min(LayoutScale(400.0f), + std::min(LayoutScale(450.0f), title_height + LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY + (LAYOUT_MENU_BUTTON_Y_PADDING * 2.0f)) * static_cast(s_choice_dialog_options.size())); ImGui::SetNextWindowSize(ImVec2(width, height));