diff --git a/.travis/linux-frozen/build.sh b/.travis/linux-frozen/build.sh index 25c6555161..25fa0259e3 100755 --- a/.travis/linux-frozen/build.sh +++ b/.travis/linux-frozen/build.sh @@ -1,4 +1,4 @@ #!/bin/bash -ex docker pull ubuntu:16.04 -docker run -v $(pwd):/citra ubuntu:16.04 /bin/bash -ex /citra/.travis/linux-frozen/docker.sh +docker run -e ENABLE_COMPATIBILITY_REPORTING -v $(pwd):/citra ubuntu:16.04 /bin/bash -ex /citra/.travis/linux-frozen/docker.sh diff --git a/.travis/linux-frozen/docker.sh b/.travis/linux-frozen/docker.sh index edca9a7a15..f5cb1b0c0e 100755 --- a/.travis/linux-frozen/docker.sh +++ b/.travis/linux-frozen/docker.sh @@ -21,7 +21,7 @@ echo y | sh cmake-3.9.0-Linux-x86_64.sh --prefix=cmake export PATH=/citra/cmake/cmake-3.9.0-Linux-x86_64/bin:$PATH mkdir build && cd build -cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_BUILD_TYPE=Release +cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_BUILD_TYPE=Release -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} make -j4 ctest -VV -C Release diff --git a/.travis/linux/build.sh b/.travis/linux/build.sh index 14deaf31c2..3e7b212f41 100755 --- a/.travis/linux/build.sh +++ b/.travis/linux/build.sh @@ -1,3 +1,3 @@ #!/bin/bash -ex -docker run -v $(pwd):/citra ubuntu:16.04 /bin/bash -ex /citra/.travis/linux/docker.sh +docker run -e ENABLE_COMPATIBILITY_REPORTING -v $(pwd):/citra ubuntu:16.04 /bin/bash -ex /citra/.travis/linux/docker.sh diff --git a/.travis/linux/docker.sh b/.travis/linux/docker.sh index ac8940719b..1a51975556 100755 --- a/.travis/linux/docker.sh +++ b/.travis/linux/docker.sh @@ -11,7 +11,7 @@ echo y | sh cmake-3.9.0-Linux-x86_64.sh --prefix=cmake export PATH=/citra/cmake/cmake-3.9.0-Linux-x86_64/bin:$PATH mkdir build && cd build -cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON +cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} make -j4 ctest -VV -C Release diff --git a/.travis/macos/build.sh b/.travis/macos/build.sh index 37e84f6e87..25a4d4d5bd 100755 --- a/.travis/macos/build.sh +++ b/.travis/macos/build.sh @@ -6,7 +6,7 @@ export MACOSX_DEPLOYMENT_TARGET=10.9 export Qt5_DIR=$(brew --prefix)/opt/qt5 mkdir build && cd build -cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON +cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} make -j4 ctest -VV -C Release diff --git a/CMakeLists.txt b/CMakeLists.txt index 734ff08b5a..6b00aa770e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -243,6 +243,9 @@ endif() if (ENABLE_WEB_SERVICE) add_definitions(-DENABLE_WEB_SERVICE) endif() +if (CITRA_ENABLE_COMPATIBILITY_REPORTING) + add_definitions(-DCITRA_ENABLE_COMPATIBILITY_REPORTING) +endif() # Platform-specific library requirements # ====================================== diff --git a/appveyor.yml b/appveyor.yml index 58038b8b56..df98040d90 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,11 +41,12 @@ before_build: - mkdir %BUILD_TYPE%_build - cd %BUILD_TYPE%_build - ps: | + $COMPAT = if ($env:ENABLE_COMPATIBILITY_REPORTING -eq $null) {0} else {$env:ENABLE_COMPATIBILITY_REPORTING} if ($env:BUILD_TYPE -eq 'msvc') { # redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning - cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DCITRA_USE_BUNDLED_QT=1 -DCITRA_USE_BUNDLED_SDL2=1 -DCMAKE_USE_OPENSSL=0 .. 2>&1 && exit 0' + cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DCITRA_USE_BUNDLED_QT=1 -DCITRA_USE_BUNDLED_SDL2=1 -DCMAKE_USE_OPENSSL=0 -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} .. 2>&1 && exit 0' } else { - C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DUSE_SYSTEM_CURL=1 -DCITRA_USE_BUNDLED_CURL=1 -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON .. 2>&1" + C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DUSE_SYSTEM_CURL=1 -DCITRA_USE_BUNDLED_CURL=1 -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} .. 2>&1" } - cd .. diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index ac472ad5ce..b0fc1acca0 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -65,6 +65,8 @@ add_executable(citra-qt util/spinbox.h util/util.cpp util/util.h + compatdb.cpp + compatdb.h ) set(UIS @@ -80,6 +82,7 @@ set(UIS aboutdialog.ui hotkeys.ui main.ui + compatdb.ui ) file(GLOB_RECURSE ICONS ${CMAKE_SOURCE_DIR}/dist/icons/*) diff --git a/src/citra_qt/compatdb.cpp b/src/citra_qt/compatdb.cpp new file mode 100644 index 0000000000..f2ad7927dd --- /dev/null +++ b/src/citra_qt/compatdb.cpp @@ -0,0 +1,58 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <QMessageBox> +#include <QPushButton> +#include "citra_qt/compatdb.h" +#include "common/telemetry.h" +#include "core/core.h" +#include "ui_compatdb.h" + +CompatDB::CompatDB(QWidget* parent) + : QWizard(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), + ui{std::make_unique<Ui::CompatDB>()} { + ui->setupUi(this); + connect(ui->radioButton_Perfect, &QRadioButton::clicked, this, &CompatDB::EnableNext); + connect(ui->radioButton_Great, &QRadioButton::clicked, this, &CompatDB::EnableNext); + connect(ui->radioButton_Okay, &QRadioButton::clicked, this, &CompatDB::EnableNext); + connect(ui->radioButton_Bad, &QRadioButton::clicked, this, &CompatDB::EnableNext); + connect(ui->radioButton_IntroMenu, &QRadioButton::clicked, this, &CompatDB::EnableNext); + connect(ui->radioButton_WontBoot, &QRadioButton::clicked, this, &CompatDB::EnableNext); + connect(button(NextButton), &QPushButton::clicked, this, &CompatDB::Submit); +} + +CompatDB::~CompatDB() = default; + +enum class CompatDBPage { Intro = 0, Selection = 1, Final = 2 }; + +void CompatDB::Submit() { + QButtonGroup* compatibility = new QButtonGroup(this); + compatibility->addButton(ui->radioButton_Perfect, 0); + compatibility->addButton(ui->radioButton_Great, 1); + compatibility->addButton(ui->radioButton_Okay, 2); + compatibility->addButton(ui->radioButton_Bad, 3); + compatibility->addButton(ui->radioButton_IntroMenu, 4); + compatibility->addButton(ui->radioButton_WontBoot, 5); + switch ((static_cast<CompatDBPage>(currentId()))) { + case CompatDBPage::Selection: + if (compatibility->checkedId() == -1) { + button(NextButton)->setEnabled(false); + } + break; + case CompatDBPage::Final: + LOG_DEBUG(Frontend, "Compatibility Rating: %d", compatibility->checkedId()); + Core::Telemetry().AddField(Telemetry::FieldType::UserFeedback, "Compatibility", + compatibility->checkedId()); + // older versions of QT don't support the "NoCancelButtonOnLastPage" option, this is a + // workaround + button(QWizard::CancelButton)->setVisible(false); + break; + default: + LOG_ERROR(Frontend, "Unexpected page: %d", currentId()); + } +} + +void CompatDB::EnableNext() { + button(NextButton)->setEnabled(true); +} diff --git a/src/citra_qt/compatdb.h b/src/citra_qt/compatdb.h new file mode 100644 index 0000000000..0a0f27cca5 --- /dev/null +++ b/src/citra_qt/compatdb.h @@ -0,0 +1,27 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <QWizard> + +namespace Ui { +class CompatDB; +} + +class CompatDB : public QWizard { + Q_OBJECT + +public: + explicit CompatDB(QWidget* parent = nullptr); + ~CompatDB(); + +private: + std::unique_ptr<Ui::CompatDB> ui; + +private slots: + void Submit(); + void EnableNext(); +}; diff --git a/src/citra_qt/compatdb.ui b/src/citra_qt/compatdb.ui new file mode 100644 index 0000000000..2e00550f28 --- /dev/null +++ b/src/citra_qt/compatdb.ui @@ -0,0 +1,215 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>CompatDB</class> + <widget class="QWizard" name="CompatDB"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>482</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>500</width> + <height>410</height> + </size> + </property> + <property name="windowTitle"> + <string>Report Compatibility</string> + </property> + <property name="options"> + <set>QWizard::DisabledBackButtonOnLastPage|QWizard::HelpButtonOnRight|QWizard::NoBackButtonOnStartPage</set> + </property> + <widget class="QWizardPage" name="wizard_Info"> + <property name="title"> + <string>Report Game Compatibility</string> + </property> + <attribute name="pageId"> + <string notr="true">0</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="lbl_Spiel"> + <property name="text"> + <string><html><head/><body><p><span style=" font-size:10pt;">Should you choose to submit a test case to the </span><a href="https://citra-emu.org/game/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Citra Compatibility List</span></a><span style=" font-size:10pt;">, The following information will be collected and displayed on the site:</span></p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Hardware Information (CPU / GPU / Operating System)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Which version of Citra you are running</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The connected Citra account</li></ul></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QWizardPage" name="wizard_Report"> + <property name="title"> + <string>Report Game Compatibility</string> + </property> + <attribute name="pageId"> + <string notr="true">1</string> + </attribute> + <layout class="QFormLayout" name="formLayout"> + <item row="2" column="0"> + <widget class="QRadioButton" name="radioButton_Perfect"> + <property name="text"> + <string>Perfect</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="lbl_Perfect"> + <property name="text"> + <string><html><head/><body><p>Game functions flawlessly with no audio or graphical glitches.</p></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QRadioButton" name="radioButton_Great"> + <property name="text"> + <string>Great </string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="lbl_Great"> + <property name="text"> + <string><html><head/><body><p>Game functions with minor graphical or audio glitches and is playable from start to finish. May require some workarounds.</p></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QRadioButton" name="radioButton_Okay"> + <property name="text"> + <string>Okay</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="lbl_Okay"> + <property name="text"> + <string><html><head/><body><p>Game functions with major graphical or audio glitches, but game is playable from start to finish with workarounds.</p></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QRadioButton" name="radioButton_Bad"> + <property name="text"> + <string>Bad</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLabel" name="lbl_Bad"> + <property name="text"> + <string><html><head/><body><p>Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches even with workarounds.</p></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QRadioButton" name="radioButton_IntroMenu"> + <property name="text"> + <string>Intro/Menu</string> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QLabel" name="lbl_IntroMenu"> + <property name="text"> + <string><html><head/><body><p>Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start Screen.</p></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="8" column="0"> + <widget class="QRadioButton" name="radioButton_WontBoot"> + <property name="text"> + <string>Won't Boot</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="8" column="1"> + <widget class="QLabel" name="lbl_WontBoot"> + <property name="text"> + <string><html><head/><body><p>The game crashes when attempting to startup.</p></body></html></string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QLabel" name="lbl_Independent"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string><html><head/><body><p>Independent of speed or performance, how well does this game play from start to finish on this version of Citra?</p></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QWizardPage" name="wizard_ThankYou"> + <property name="title"> + <string>Thank you for your submission!</string> + </property> + <attribute name="pageId"> + <string notr="true">2</string> + </attribute> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index b92564db0c..cb25502d7c 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -17,6 +17,7 @@ #include <QtWidgets> #include "citra_qt/aboutdialog.h" #include "citra_qt/bootmanager.h" +#include "citra_qt/compatdb.h" #include "citra_qt/configuration/config.h" #include "citra_qt/configuration/configure_dialog.h" #include "citra_qt/debugger/graphics/graphics.h" @@ -146,6 +147,9 @@ GMainWindow::~GMainWindow() { } void GMainWindow::InitializeWidgets() { +#ifdef CITRA_ENABLE_COMPATIBILITY_REPORTING + ui.action_Report_Compatibility->setVisible(true); +#endif render_window = new GRenderWindow(this, emu_thread.get()); render_window->hide(); @@ -380,6 +384,8 @@ void GMainWindow::ConnectMenuEvents() { connect(ui.action_Start, &QAction::triggered, this, &GMainWindow::OnStartGame); connect(ui.action_Pause, &QAction::triggered, this, &GMainWindow::OnPauseGame); connect(ui.action_Stop, &QAction::triggered, this, &GMainWindow::OnStopGame); + connect(ui.action_Report_Compatibility, &QAction::triggered, this, + &GMainWindow::OnMenuReportCompatibility); connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); // View @@ -635,6 +641,7 @@ void GMainWindow::ShutdownGame() { ui.action_Start->setText(tr("Start")); ui.action_Pause->setEnabled(false); ui.action_Stop->setEnabled(false); + ui.action_Report_Compatibility->setEnabled(false); render_window->hide(); game_list->show(); game_list->setFilterFocus(); @@ -816,6 +823,7 @@ void GMainWindow::OnStartGame() { ui.action_Pause->setEnabled(true); ui.action_Stop->setEnabled(true); + ui.action_Report_Compatibility->setEnabled(true); } void GMainWindow::OnPauseGame() { @@ -830,6 +838,19 @@ void GMainWindow::OnStopGame() { ShutdownGame(); } +void GMainWindow::OnMenuReportCompatibility() { + if (!Settings::values.citra_token.empty() && !Settings::values.citra_username.empty()) { + CompatDB compatdb{this}; + compatdb.exec(); + } else { + QMessageBox::critical( + this, tr("Missing Citra Account"), + tr("In order to submit a game compatibility test case, you must link your Citra " + "account.<br><br/>To link your Citra account, go to Emulation \> Configuration \> " + "Web.")); + } +} + void GMainWindow::ToggleFullscreen() { if (!emulation_running) { return; diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index b0bceaac5f..fa36546d46 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -127,6 +127,7 @@ private slots: void OnStartGame(); void OnPauseGame(); void OnStopGame(); + void OnMenuReportCompatibility(); /// Called whenever a user selects a game in the game list widget. void OnGameListLoadFile(QString game_path); void OnGameListOpenSaveFolder(u64 program_id); diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui index 1bc0717760..bbc82f9e70 100644 --- a/src/citra_qt/main.ui +++ b/src/citra_qt/main.ui @@ -45,7 +45,7 @@ <x>0</x> <y>0</y> <width>1081</width> - <height>21</height> + <height>26</height> </rect> </property> <widget class="QMenu" name="menu_File"> @@ -100,6 +100,8 @@ <addaction name="action_Check_For_Updates"/> <addaction name="action_Open_Maintenance_Tool"/> <addaction name="separator"/> + <addaction name="action_Report_Compatibility"/> + <addaction name="separator"/> <addaction name="action_FAQ"/> <addaction name="action_About"/> </widget> @@ -233,6 +235,18 @@ <string>Check for Updates</string> </property> </action> + <action name="action_Report_Compatibility"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Report Compatibility</string> + </property> + <property name="visible"> + <bool>false</bool> + </property> + </action> </widget> <resources/> + <connections/> </ui>