From b2a2366287f57668710c2f0dc0a993ca62ee377a Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 16 May 2020 20:02:44 +1000 Subject: [PATCH] Qt: Add game properties dialog --- src/duckstation-qt/CMakeLists.txt | 3 + src/duckstation-qt/duckstation-qt.vcxproj | 6 + src/duckstation-qt/gamepropertiesdialog.cpp | 231 ++++++++++++++++++ src/duckstation-qt/gamepropertiesdialog.h | 50 ++++ src/duckstation-qt/gamepropertiesdialog.ui | 225 +++++++++++++++++ src/duckstation-qt/mainwindow.cpp | 4 +- src/duckstation-qt/resources/icons.qrc | 6 + src/duckstation-qt/resources/icons/star-0.png | Bin 0 -> 5534 bytes src/duckstation-qt/resources/icons/star-1.png | Bin 0 -> 6116 bytes src/duckstation-qt/resources/icons/star-2.png | Bin 0 -> 6367 bytes src/duckstation-qt/resources/icons/star-3.png | Bin 0 -> 6526 bytes src/duckstation-qt/resources/icons/star-4.png | Bin 0 -> 6312 bytes src/duckstation-qt/resources/icons/star-5.png | Bin 0 -> 5990 bytes 13 files changed, 524 insertions(+), 1 deletion(-) create mode 100644 src/duckstation-qt/gamepropertiesdialog.cpp create mode 100644 src/duckstation-qt/gamepropertiesdialog.h create mode 100644 src/duckstation-qt/gamepropertiesdialog.ui create mode 100644 src/duckstation-qt/resources/icons/star-0.png create mode 100644 src/duckstation-qt/resources/icons/star-1.png create mode 100644 src/duckstation-qt/resources/icons/star-2.png create mode 100644 src/duckstation-qt/resources/icons/star-3.png create mode 100644 src/duckstation-qt/resources/icons/star-4.png create mode 100644 src/duckstation-qt/resources/icons/star-5.png diff --git a/src/duckstation-qt/CMakeLists.txt b/src/duckstation-qt/CMakeLists.txt index a7879fa1b..5355515c1 100644 --- a/src/duckstation-qt/CMakeLists.txt +++ b/src/duckstation-qt/CMakeLists.txt @@ -18,6 +18,9 @@ add_executable(duckstation-qt gamelistsettingswidget.ui gamelistwidget.cpp gamelistwidget.h + gamepropertiesdialog.cpp + gamepropertiesdialog.h + gamepropertiesdialog.ui generalsettingswidget.cpp generalsettingswidget.h generalsettingswidget.ui diff --git a/src/duckstation-qt/duckstation-qt.vcxproj b/src/duckstation-qt/duckstation-qt.vcxproj index 268a65d82..36fcc5231 100644 --- a/src/duckstation-qt/duckstation-qt.vcxproj +++ b/src/duckstation-qt/duckstation-qt.vcxproj @@ -46,6 +46,7 @@ + @@ -73,6 +74,7 @@ + @@ -128,6 +130,9 @@ Document + + Document + @@ -140,6 +145,7 @@ + diff --git a/src/duckstation-qt/gamepropertiesdialog.cpp b/src/duckstation-qt/gamepropertiesdialog.cpp new file mode 100644 index 000000000..cd33243a2 --- /dev/null +++ b/src/duckstation-qt/gamepropertiesdialog.cpp @@ -0,0 +1,231 @@ +#include "gamepropertiesdialog.h" +#include "common/cd_image.h" +#include "core/game_list.h" +#include "core/settings.h" +#include "qthostinterface.h" +#include "qtutils.h" +#include "scmversion/scmversion.h" +#include + +GamePropertiesDialog::GamePropertiesDialog(QtHostInterface* host_interface, QWidget* parent /* = nullptr */) + : QDialog(parent), m_host_interface(host_interface) +{ + m_ui.setupUi(this); + setupAdditionalUi(); + connectUi(); +} + +GamePropertiesDialog::~GamePropertiesDialog() = default; + +void GamePropertiesDialog::clear() +{ + m_ui.imagePath->clear(); + m_ui.gameCode->clear(); + m_ui.title->clear(); + m_ui.region->setCurrentIndex(0); + + { + QSignalBlocker blocker(m_ui.compatibility); + m_ui.compatibility->setCurrentIndex(0); + } + { + QSignalBlocker blocker(m_ui.upscalingIssues); + m_ui.upscalingIssues->clear(); + } + + { + QSignalBlocker blocker(m_ui.comments); + m_ui.comments->clear(); + } + + m_ui.tracks->clearContents(); +} + +void GamePropertiesDialog::populate(const GameListEntry* ge) +{ + const QString title_qstring(QString::fromStdString(ge->title)); + + setWindowTitle(tr("Game Properties - %1").arg(title_qstring)); + m_ui.imagePath->setText(QString::fromStdString(ge->path)); + m_ui.title->setText(title_qstring); + m_ui.gameCode->setText(QString::fromStdString(ge->code)); + m_ui.region->setCurrentIndex(static_cast(ge->region)); + + if (ge->code.empty()) + { + // can't fill in info without a code + m_ui.compatibility->setDisabled(true); + m_ui.upscalingIssues->setDisabled(true); + m_ui.versionTested->setDisabled(true); + } + else + { + populateCompatibilityInfo(ge->code); + } + + populateTracksInfo(ge->path.c_str()); +} + +void GamePropertiesDialog::populateCompatibilityInfo(const std::string& game_code) +{ + const GameListCompatibilityEntry* entry = m_host_interface->getGameList()->GetCompatibilityEntryForCode(game_code); + + { + QSignalBlocker blocker(m_ui.compatibility); + m_ui.compatibility->setCurrentIndex(entry ? static_cast(entry->compatibility_rating) : 0); + } + + { + QSignalBlocker blocker(m_ui.upscalingIssues); + m_ui.upscalingIssues->setText(entry ? QString::fromStdString(entry->upscaling_issues) : QString()); + } + + { + QSignalBlocker blocker(m_ui.comments); + m_ui.comments->setText(entry ? QString::fromStdString(entry->comments) : QString()); + } +} + +void GamePropertiesDialog::setupAdditionalUi() +{ + for (u8 i = 0; i < static_cast(DiscRegion::Count); i++) + m_ui.region->addItem(tr(Settings::GetDiscRegionDisplayName(static_cast(i)))); + + for (int i = 0; i < static_cast(GameListCompatibilityRating::Count); i++) + { + m_ui.compatibility->addItem( + tr(GameList::GetGameListCompatibilityRatingString(static_cast(i)))); + } + + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); +} + +void GamePropertiesDialog::showForEntry(QtHostInterface* host_interface, const GameListEntry* ge) +{ + GamePropertiesDialog* gpd = new GamePropertiesDialog(host_interface); + gpd->populate(ge); + gpd->show(); + gpd->onResize(); +} + +static QString MSFTotString(const CDImage::Position& position) +{ + return QStringLiteral("%1:%2:%3 (LBA %4)") + .arg(static_cast(position.minute), 2, 10, static_cast('0')) + .arg(static_cast(position.second), 2, 10, static_cast('0')) + .arg(static_cast(position.frame), 2, 10, static_cast('0')) + .arg(static_cast(position.ToLBA())); +} + +void GamePropertiesDialog::populateTracksInfo(const char* image_path) +{ + static constexpr std::array track_mode_strings = { + {"Audio", "Mode 1", "Mode 1/Raw", "Mode 2", "Mode 2/Form 1", "Mode 2/Form 2", "Mode 2/Mix", "Mode 2/Raw"}}; + + m_ui.tracks->clearContents(); + + std::unique_ptr image = CDImage::Open(image_path); + if (!image) + return; + + const u32 num_tracks = image->GetTrackCount(); + for (u32 track = 1; track <= num_tracks; track++) + { + const CDImage::Position position = image->GetTrackStartMSFPosition(static_cast(track)); + const CDImage::Position length = image->GetTrackMSFLength(static_cast(track)); + const CDImage::TrackMode mode = image->GetTrackMode(static_cast(track)); + const int row = static_cast(track - 1u); + m_ui.tracks->insertRow(row); + m_ui.tracks->setItem(row, 0, new QTableWidgetItem(tr("%1").arg(track))); + m_ui.tracks->setItem(row, 1, new QTableWidgetItem(tr(track_mode_strings[static_cast(mode)]))); + m_ui.tracks->setItem(row, 2, new QTableWidgetItem(MSFTotString(position))); + m_ui.tracks->setItem(row, 3, new QTableWidgetItem(MSFTotString(length))); + m_ui.tracks->setItem(row, 4, new QTableWidgetItem(tr(""))); + } +} + +void GamePropertiesDialog::closeEvent(QCloseEvent* ev) +{ + deleteLater(); +} + +void GamePropertiesDialog::resizeEvent(QResizeEvent* ev) +{ + QDialog::resizeEvent(ev); + onResize(); +} + +void GamePropertiesDialog::onResize() +{ + QtUtils::ResizeColumnsForTableView(m_ui.tracks, {20, 85, 125, 125, -1}); +} + +void GamePropertiesDialog::connectUi() +{ + connect(m_ui.compatibility, static_cast(&QComboBox::currentIndexChanged), this, + &GamePropertiesDialog::saveCompatibilityInfo); + connect(m_ui.comments, &QLineEdit::textChanged, this, &GamePropertiesDialog::setCompatibilityInfoChanged); + connect(m_ui.comments, &QLineEdit::editingFinished, this, &GamePropertiesDialog::saveCompatibilityInfoIfChanged); + connect(m_ui.upscalingIssues, &QLineEdit::textChanged, this, &GamePropertiesDialog::setCompatibilityInfoChanged); + connect(m_ui.upscalingIssues, &QLineEdit::editingFinished, this, + &GamePropertiesDialog::saveCompatibilityInfoIfChanged); + connect(m_ui.setToCurrent, &QPushButton::clicked, this, &GamePropertiesDialog::onSetVersionTestedToCurrentClicked); + connect(m_ui.computeHashes, &QPushButton::clicked, this, &GamePropertiesDialog::onComputeHashClicked); + connect(m_ui.verifyDump, &QPushButton::clicked, this, &GamePropertiesDialog::onVerifyDumpClicked); + connect(m_ui.exportCompatibilityInfo, &QPushButton::clicked, this, + &GamePropertiesDialog::onExportCompatibilityInfoClicked); + connect(m_ui.close, &QPushButton::clicked, this, &QDialog::close); +} + +void GamePropertiesDialog::saveCompatibilityInfo() +{ + GameListCompatibilityEntry new_entry; + new_entry.code = m_ui.gameCode->text().toStdString(); + new_entry.title = m_ui.title->text().toStdString(); + new_entry.version_tested = m_ui.versionTested->text().toStdString(); + new_entry.upscaling_issues = m_ui.upscalingIssues->text().toStdString(); + new_entry.comments = m_ui.comments->text().toStdString(); + new_entry.compatibility_rating = static_cast(m_ui.compatibility->currentIndex()); + new_entry.region = static_cast(m_ui.region->currentIndex()); + + if (new_entry.code.empty()) + return; + + m_host_interface->getGameList()->UpdateCompatibilityEntry(std::move(new_entry), true); + emit m_host_interface->gameListRefreshed(); + m_compatibility_info_changed = false; +} + +void GamePropertiesDialog::saveCompatibilityInfoIfChanged() +{ + if (!m_compatibility_info_changed) + return; + + saveCompatibilityInfo(); +} + +void GamePropertiesDialog::setCompatibilityInfoChanged() +{ + m_compatibility_info_changed = true; +} + +void GamePropertiesDialog::onSetVersionTestedToCurrentClicked() +{ + m_ui.versionTested->setText(QString::fromUtf8(g_scm_tag_str)); + saveCompatibilityInfo(); +} + +void GamePropertiesDialog::onComputeHashClicked() +{ + QMessageBox::critical(this, tr("Not yet implemented"), tr("Not yet implemented")); +} + +void GamePropertiesDialog::onVerifyDumpClicked() +{ + QMessageBox::critical(this, tr("Not yet implemented"), tr("Not yet implemented")); +} + +void GamePropertiesDialog::onExportCompatibilityInfoClicked() +{ + QMessageBox::critical(this, tr("Not yet implemented"), tr("Not yet implemented")); +} diff --git a/src/duckstation-qt/gamepropertiesdialog.h b/src/duckstation-qt/gamepropertiesdialog.h new file mode 100644 index 000000000..51325b8b3 --- /dev/null +++ b/src/duckstation-qt/gamepropertiesdialog.h @@ -0,0 +1,50 @@ +#pragma once +#include "ui_gamepropertiesdialog.h" +#include +#include + +struct GameListEntry; + +class QtHostInterface; + +class GamePropertiesDialog final : public QDialog +{ + Q_OBJECT + +public: + GamePropertiesDialog(QtHostInterface* host_interface, QWidget* parent = nullptr); + ~GamePropertiesDialog(); + + static void showForEntry(QtHostInterface* host_interface, const GameListEntry* ge); + +public Q_SLOTS: + void clear(); + void populate(const GameListEntry* ge); + +protected: + void closeEvent(QCloseEvent* ev); + void resizeEvent(QResizeEvent* ev); + +private Q_SLOTS: + void saveCompatibilityInfo(); + void saveCompatibilityInfoIfChanged(); + void setCompatibilityInfoChanged(); + + void onSetVersionTestedToCurrentClicked(); + void onComputeHashClicked(); + void onVerifyDumpClicked(); + void onExportCompatibilityInfoClicked(); + +private: + void setupAdditionalUi(); + void connectUi(); + void populateCompatibilityInfo(const std::string& game_code); + void populateTracksInfo(const char* image_path); + void onResize(); + + Ui::GamePropertiesDialog m_ui; + + QtHostInterface* m_host_interface; + + bool m_compatibility_info_changed = false; +}; diff --git a/src/duckstation-qt/gamepropertiesdialog.ui b/src/duckstation-qt/gamepropertiesdialog.ui new file mode 100644 index 000000000..ce0322847 --- /dev/null +++ b/src/duckstation-qt/gamepropertiesdialog.ui @@ -0,0 +1,225 @@ + + + GamePropertiesDialog + + + + 0 + 0 + 722 + 466 + + + + Dialog + + + + :/icons/duck.png:/icons/duck.png + + + + + + Image Path: + + + + + + + true + + + + + + + Game Code: + + + + + + + true + + + + + + + Title: + + + + + + + true + + + + + + + Region: + + + + + + + false + + + + + + + Compatibility: + + + + + + + + + + Upscaling Issues: + + + + + + + + + + Comments: + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Compute Hashes + + + + + + + Verify Dump + + + + + + + Export Compatibility Info + + + + + + + Close + + + true + + + + + + + + + Tracks: + + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + false + + + + # + + + + + Mode + + + + + Start + + + + + Length + + + + + Hash + + + + + + + + + + + Version Tested: + + + + + + + + + + + + Set to Current + + + + + + + + + + diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 90ec57bf9..65913bf3a 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -5,6 +5,7 @@ #include "core/system.h" #include "gamelistsettingswidget.h" #include "gamelistwidget.h" +#include "gamepropertiesdialog.h" #include "qtdisplaywidget.h" #include "qthostdisplay.h" #include "qthostinterface.h" @@ -347,7 +348,8 @@ void MainWindow::onGameListContextMenuRequested(const QPoint& point, const GameL // Hopefully this pointer doesn't disappear... it shouldn't. if (entry) { - connect(menu.addAction(tr("Properties...")), &QAction::triggered, [this]() { reportError(tr("TODO")); }); + connect(menu.addAction(tr("Properties...")), &QAction::triggered, + [this, entry]() { GamePropertiesDialog::showForEntry(m_host_interface, entry); }); connect(menu.addAction(tr("Open Containing Directory...")), &QAction::triggered, [this, entry]() { const QFileInfo fi(QString::fromStdString(entry->path)); diff --git a/src/duckstation-qt/resources/icons.qrc b/src/duckstation-qt/resources/icons.qrc index 93629c6bd..356d5cc3b 100644 --- a/src/duckstation-qt/resources/icons.qrc +++ b/src/duckstation-qt/resources/icons.qrc @@ -6,6 +6,12 @@ icons/flag-jp.svg icons/flag-us.png icons/flag-us.svg + icons/star-0.png + icons/star-1.png + icons/star-2.png + icons/star-3.png + icons/star-4.png + icons/star-5.png icons/applications-internet.png icons/system-search.png icons/list-add.png diff --git a/src/duckstation-qt/resources/icons/star-0.png b/src/duckstation-qt/resources/icons/star-0.png new file mode 100644 index 0000000000000000000000000000000000000000..e5b56db70af52fbc1629cf6131d3b6d5eebdffc4 GIT binary patch literal 5534 zcmV;P6=CX$P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3&sawIv9M*s5^a|CW6z~gW=n;XpW=fT6JtX#UP zdu*i4loaxCCxLGRGo1hV?;HM$k6N;YDr&8_7Wt^X_B{B;;^*V@HO2b;`+T(bSN#0b z>mhx;Df3d{YkA*r-s=ai%a1o`eP5qHzaDhG_p$dz?=QY?Sp3PEZ{F+dy-~@Z*VFrR z=>v-Qi=R){*?0hJNPU7n@Z!NR65_+qWoJ* z`g85V_qV?k?`wg-)-I0sit=+Q!gm|mFEx5!Px9y5Jr(+?YhT~ypMSA)yz#Fef34l! zcJKM@Zq!DlT6i}V-&;K2aUtcb<#}7%H;RG#`ipW(Z$KR&#% zg}cd9W@CdR&d)8Tq#xKSPoE3dNvz>TUef*EfCcevVKJ%Df!I=!)Kb)(H6>RJ`ZHL0 zE;Ua&kVNuM;nJG|6Es`)XY(FS&$U_d=VhdYMo4Lp#GEcPt5yL&S`7>hDN=)oG*L0> zGFoZ1No!4;Yt+!9RYjYsnsyylteRLeHM4G`=U$L7>8)$%)_Wg=hYoH%c=zCnF=n1+ z)+w`1oi_U%3;3+MWVNNsR$pW1T{iUJZEM)J`yMA9pmgey(~cfH{frCNZn^c!ZC9_| ze#dv$-md=Kwe(Bp{=RGJ?V5M2KG*4wuJN+!*DaFEiFnWGSgwhVt9JlEXYX0GRBQIm zdCy|ckU}zDOXAJh$vZ{|>q%K|`tIG2&i!rQg4F-0Z~0$!E_mzyKROq@b#Lc>@7o`` zw#VZrVK9mC4i7Hy-SWwXgVoOXpxS4B1l0xA5#B>hX!%7fJ;AC*0m z&S6cgC!v9<$Fpi$F4I72H;aWGvuK2FE+8Z0Y~*p*6cAA_eX?bWi5+02GnO-D-Cb)# z+XdQFDVerMv;34{re__E7i8qMM>zYIO*f9wgw&B&&6R3qQ1~u_-wg_-TBR$}acE@k zJME6SqUazgS)dT-L>(gQsj)9NNzc^yvf4k_7_}O_dG#uD%UPxNFbiGvhtJgIu(7eV0MtY!A>xvREGYP>^hA&S|Taa);4_JOB@1?c3Mw-cwmh&H_i{QtiwBZ8rMW_X#q!&)dNFR74TwSaa#oIm@*M?ogSQ z#!x~{9XJM1LU1ziWzZ1q?To@TD5RITcl4&5bk!>B-whjfRwTG#1gX>zAe;sbE9vmo zJ13c(hh9UTw&-ygSX%Kp!0rtK~&qPb;G%t1OdRZkH>y zB1m4p9%78bjmA>J4^|RU?XI)x?iYB*)@hlQ$SR%HTo?tKV6N@~ z=m1AAcW($~OK5~rVx%l=Dndj#qxM~>NjgGZcPS9V+khTV$`3boS#4&h0ps9As`yi; z!S{?V=+QtHKs@Hg)0C$}?Xz1snjc<_1uu}NYzX(ui!}KT;5aS%=~Hb5*5D7WPbKbL zMOcY-T1*Kx?zElvhUj*wdzOlOyWW<*SL_Qaz(I%+(BlHcAXh01c%%%iXTv@h3Wd~c ze+2S*i!H_D7TSMiM)Z=~Rns*lfC%+CFo<=NuZacIY(AF)K^!?Z(CwR8OP~G$HE-zE zg;0RMTPOJ4&2N;kZJe3*Vf2f3@Xd{5ZhGiAybz)i8z}by+L?t;ZFf2VOb8R;?}khR z;v~FxY~#3SQ5a)dlzWf>B&)?ssSRpuWDdO0l7h@9g@{;J1K1TAShl z{|HKYFn7D6sHsqVpV|iDETRimj5aHKFl;hROhT@6G<+Ev_-MxEwnCbrkaC}D?B zh~$Vwy8t;Z3c?@V41X5R-*vMgl#zDL54{zdvtWYD^bw}Fka;gv%gF_fI(-CA$8G

SfiygqJZbx2IknOAC&b(% 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 literal 0 HcmV?d00001 diff --git a/src/duckstation-qt/resources/icons/star-3.png b/src/duckstation-qt/resources/icons/star-3.png new file mode 100644 index 0000000000000000000000000000000000000000..330aefbaca17c6dab21b9e1076e6238eaa269ba3 GIT binary patch literal 6526 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 literal 0 HcmV?d00001 diff --git a/src/duckstation-qt/resources/icons/star-4.png b/src/duckstation-qt/resources/icons/star-4.png new file mode 100644 index 0000000000000000000000000000000000000000..4e9f58dfa3fcc1b8243282b1beb14112b3f64606 GIT binary patch literal 6312 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 eR8!6ClK%mVDD4Shew>d00000laD@ literal 0 HcmV?d00001 diff --git a/src/duckstation-qt/resources/icons/star-5.png b/src/duckstation-qt/resources/icons/star-5.png new file mode 100644 index 0000000000000000000000000000000000000000..aa5707ea750c04a2e1ad86be3e45c34856301def GIT binary patch literal 5990 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