Merge pull request #12080 from AdmiralCurtiss/windark

Add custom dark theme for Windows.
This commit is contained in:
Admiral H. Curtiss 2023-08-12 20:04:03 +02:00 committed by GitHub
commit dfbc0e33d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
86 changed files with 1696 additions and 131 deletions

View File

@ -12,6 +12,7 @@ if (MSVC)
endif()
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Svg)
message(STATUS "Found Qt version ${Qt6_VERSION}")
@ -293,6 +294,8 @@ add_executable(dolphin-emu
QtUtils/ParallelProgressDialog.h
QtUtils/PartiallyClosableTabWidget.cpp
QtUtils/PartiallyClosableTabWidget.h
QtUtils/SetWindowDecorations.cpp
QtUtils/SetWindowDecorations.h
QtUtils/SignalBlocking.h
QtUtils/UTF8CodePointCountValidator.cpp
QtUtils/UTF8CodePointCountValidator.h
@ -362,6 +365,12 @@ add_executable(dolphin-emu
WiiUpdate.h
)
if (WIN32)
target_sources(dolphin-emu PRIVATE
Styles/Dark/dark.qrc
)
endif()
if (NOT WIN32)
target_sources(dolphin-emu PRIVATE
QtUtils/SignalDaemon.cpp
@ -396,6 +405,7 @@ if (WIN32)
PRIVATE
gdi32.lib
shell32.lib
dwmapi.lib # Needed to set window decorations for dark theme
)
endif()

View File

@ -22,6 +22,7 @@
#include "DolphinQt/Config/CheatCodeEditor.h"
#include "DolphinQt/Config/CheatWarningWidget.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "UICommon/GameFile.h"
@ -230,6 +231,7 @@ void ARCodeWidget::OnCodeAddClicked()
CheatCodeEditor ed(this);
ed.SetARCode(&ar);
SetQWidgetWindowDecorations(&ed);
if (ed.exec() == QDialog::Rejected)
return;
@ -253,6 +255,7 @@ void ARCodeWidget::OnCodeEditClicked()
{
ed.SetARCode(&current_ar);
SetQWidgetWindowDecorations(&ed);
if (ed.exec() == QDialog::Rejected)
return;
}
@ -261,6 +264,7 @@ void ARCodeWidget::OnCodeEditClicked()
ActionReplay::ARCode ar = current_ar;
ed.SetARCode(&ar);
SetQWidgetWindowDecorations(&ed);
if (ed.exec() == QDialog::Rejected)
return;

View File

@ -13,6 +13,7 @@
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -59,6 +60,7 @@ void CommonControllersWidget::OnControllerInterfaceConfigure()
ControllerInterfaceWindow* window = new ControllerInterfaceWindow(this);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
}

View File

@ -14,6 +14,7 @@
#include "Common/Config/Config.h"
#include "DolphinQt/Config/ControllerInterface/DualShockUDPClientAddServerDialog.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.h"
DualShockUDPClientWidget::DualShockUDPClientWidget()
@ -111,6 +112,7 @@ void DualShockUDPClientWidget::OnServerAdded()
DualShockUDPClientAddServerDialog add_server_dialog(this);
connect(&add_server_dialog, &DualShockUDPClientAddServerDialog::accepted, this,
&DualShockUDPClientWidget::RefreshServerList);
SetQWidgetWindowDecorations(&add_server_dialog);
add_server_dialog.exec();
}

View File

@ -25,6 +25,7 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "UICommon/UICommon.h"
@ -364,6 +365,7 @@ void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, cons
dialog.Reset();
});
SetQWidgetWindowDecorations(dialog.GetRaw());
dialog.GetRaw()->exec();
future.get();
}

View File

@ -17,6 +17,7 @@
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
FreeLookWidget::FreeLookWidget(QWidget* parent) : QWidget(parent)
@ -97,6 +98,7 @@ void FreeLookWidget::OnFreeLookControllerConfigured()
MappingWindow* window = new MappingWindow(this, MappingWindow::Type::MAPPING_FREELOOK, index);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
}

View File

@ -3,6 +3,11 @@
#include "DolphinQt/Config/GameConfigHighlighter.h"
#include <QBrush>
#include <QColor>
#include "DolphinQt/Settings.h"
struct HighlightingRule
{
QRegularExpression pattern;
@ -13,22 +18,36 @@ GameConfigHighlighter::~GameConfigHighlighter() = default;
GameConfigHighlighter::GameConfigHighlighter(QTextDocument* parent) : QSyntaxHighlighter(parent)
{
const bool is_dark_theme = Settings::Instance().IsThemeDark();
QTextCharFormat equal_format;
equal_format.setForeground(Qt::red);
if (is_dark_theme)
equal_format.setForeground(QBrush{QColor(255, 96, 96)});
else
equal_format.setForeground(Qt::red);
QTextCharFormat section_format;
section_format.setFontWeight(QFont::Bold);
QTextCharFormat comment_format;
comment_format.setForeground(Qt::darkGreen);
if (is_dark_theme)
comment_format.setForeground(QBrush{QColor(0, 220, 0)});
else
comment_format.setForeground(Qt::darkGreen);
comment_format.setFontItalic(true);
QTextCharFormat const_format;
const_format.setFontWeight(QFont::Bold);
const_format.setForeground(Qt::blue);
if (is_dark_theme)
const_format.setForeground(QBrush{QColor(132, 132, 255)});
else
const_format.setForeground(Qt::blue);
QTextCharFormat num_format;
num_format.setForeground(Qt::darkBlue);
if (is_dark_theme)
num_format.setForeground(QBrush{QColor(66, 138, 255)});
else
num_format.setForeground(Qt::darkBlue);
m_rules.emplace_back(HighlightingRule{QRegularExpression(QStringLiteral("=")), equal_format});
m_rules.emplace_back(

View File

@ -24,6 +24,7 @@
#include "DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h"
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -137,8 +138,12 @@ void GamecubeControllersWidget::OnGCPadConfigure(size_t index)
type = MappingWindow::Type::MAPPING_GCPAD;
break;
case SerialInterface::SIDEVICE_WIIU_ADAPTER:
GCPadWiiUConfigDialog(static_cast<int>(index), this).exec();
{
GCPadWiiUConfigDialog dialog(static_cast<int>(index), this);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
case SerialInterface::SIDEVICE_GC_STEERING:
type = MappingWindow::Type::MAPPING_GC_STEERINGWHEEL;
break;
@ -161,6 +166,7 @@ void GamecubeControllersWidget::OnGCPadConfigure(size_t index)
MappingWindow* window = new MappingWindow(this, type, static_cast<int>(index));
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
}

View File

@ -28,6 +28,7 @@
#include "DolphinQt/Config/CheatWarningWidget.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "UICommon/GameFile.h"
@ -201,6 +202,7 @@ void GeckoCodeWidget::AddCode()
CheatCodeEditor ed(this);
ed.SetGeckoCode(&code);
SetQWidgetWindowDecorations(&ed);
if (ed.exec() == QDialog::Rejected)
return;
@ -219,6 +221,7 @@ void GeckoCodeWidget::EditCode()
CheatCodeEditor ed(this);
ed.SetGeckoCode(&m_gecko_codes[index]);
SetQWidgetWindowDecorations(&ed);
if (ed.exec() == QDialog::Rejected)
return;

View File

@ -22,6 +22,7 @@
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
#include "VideoCommon/PostProcessing.h"
@ -570,11 +571,15 @@ void EnhancementsWidget::AddDescriptions()
void EnhancementsWidget::ConfigureColorCorrection()
{
ColorCorrectionConfigWindow(this).exec();
ColorCorrectionConfigWindow dialog(this);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
}
void EnhancementsWidget::ConfigurePostProcessingShader()
{
const std::string shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
PostProcessingConfigWindow(this, shader).exec();
PostProcessingConfigWindow dialog(this, shader);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
}

View File

@ -24,6 +24,7 @@
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipComboBox.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
#include "VideoCommon/VideoBackendBase.h"
@ -164,6 +165,7 @@ void GeneralWidget::SaveSettings()
confirm_sw.setWindowTitle(tr("Confirm backend change"));
confirm_sw.setText(tr(warningMessage->c_str()));
SetQWidgetWindowDecorations(&confirm_sw);
if (confirm_sw.exec() != QMessageBox::Yes)
{
m_backend_combo->setCurrentIndex(m_backend_combo->findData(

View File

@ -11,6 +11,7 @@
#include "Core/FreeLookManager.h"
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/InputConfig.h"
FreeLookRotation::FreeLookRotation(MappingWindow* window) : MappingWidget(window)
@ -33,6 +34,7 @@ void FreeLookRotation::CreateMainLayout()
ControllerInterfaceWindow* window = new ControllerInterfaceWindow(this);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
});
m_main_layout->addLayout(alternate_input_layout, 0, 0, 1, -1);

View File

@ -6,6 +6,8 @@
#include <optional>
#include <thread>
#include <QBrush>
#include <QColor>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QHeaderView>
@ -38,7 +40,6 @@
namespace
{
// TODO: Make sure these functions return colors that will be visible in the current theme.
QTextCharFormat GetSpecialCharFormat()
{
QTextCharFormat format;
@ -49,7 +50,10 @@ QTextCharFormat GetSpecialCharFormat()
QTextCharFormat GetLiteralCharFormat()
{
QTextCharFormat format;
format.setForeground(QBrush{Qt::darkMagenta});
if (Settings::Instance().IsThemeDark())
format.setForeground(QBrush{QColor(171, 132, 219)});
else
format.setForeground(QBrush{Qt::darkMagenta});
return format;
}
@ -57,35 +61,50 @@ QTextCharFormat GetInvalidCharFormat()
{
QTextCharFormat format;
format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
format.setUnderlineColor(Qt::darkRed);
if (Settings::Instance().IsThemeDark())
format.setUnderlineColor(QColor(255, 69, 0));
else
format.setUnderlineColor(Qt::darkRed);
return format;
}
QTextCharFormat GetControlCharFormat()
{
QTextCharFormat format;
format.setForeground(QBrush{Qt::darkGreen});
if (Settings::Instance().IsThemeDark())
format.setForeground(QBrush{QColor(0, 220, 0)});
else
format.setForeground(QBrush{Qt::darkGreen});
return format;
}
QTextCharFormat GetVariableCharFormat()
{
QTextCharFormat format;
format.setForeground(QBrush{Qt::darkYellow});
if (Settings::Instance().IsThemeDark())
format.setForeground(QBrush{QColor(226, 226, 0)});
else
format.setForeground(QBrush{Qt::darkYellow});
return format;
}
QTextCharFormat GetBarewordCharFormat()
{
QTextCharFormat format;
format.setForeground(QBrush{Qt::darkBlue});
if (Settings::Instance().IsThemeDark())
format.setForeground(QBrush{QColor(66, 138, 255)});
else
format.setForeground(QBrush{Qt::darkBlue});
return format;
}
QTextCharFormat GetCommentCharFormat()
{
QTextCharFormat format;
format.setForeground(QBrush{Qt::darkGray});
if (Settings::Instance().IsThemeDark())
format.setForeground(QBrush{QColor(176, 176, 176)});
else
format.setForeground(QBrush{Qt::darkGray});
return format;
}
} // namespace

View File

@ -12,6 +12,7 @@
#include "DolphinQt/Config/Mapping/MappingCommon.h"
#include "DolphinQt/Config/Mapping/MappingWidget.h"
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/ControlReference/ControlReference.h"
#include "InputCommon/ControllerEmu/ControlGroup/Buttons.h"
@ -97,6 +98,7 @@ void MappingButton::AdvancedPressed()
{
IOWindow io(m_parent, m_parent->GetController(), m_reference,
m_reference->IsInput() ? IOWindow::Type::Input : IOWindow::Type::Output);
SetQWidgetWindowDecorations(&io);
io.exec();
ConfigChanged();

View File

@ -16,6 +16,7 @@
#include "DolphinQt/Config/Mapping/MappingIndicator.h"
#include "DolphinQt/Config/Mapping/MappingNumeric.h"
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/ControlReference/ControlReference.h"
#include "InputCommon/ControllerEmu/Control/Control.h"
@ -248,6 +249,7 @@ void MappingWidget::ShowAdvancedControlGroupDialog(ControllerEmu::ControlGroup*
// Enable "Close" button functionality.
connect(button_box, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
}
@ -303,6 +305,7 @@ MappingWidget::CreateSettingAdvancedMappingButton(ControllerEmu::NumericSettingB
setting.SetExpressionFromValue();
IOWindow io(this, GetController(), &setting.GetInputReference(), IOWindow::Type::Input);
SetQWidgetWindowDecorations(&io);
io.exec();
setting.SimplifyIfPossible();

View File

@ -49,6 +49,7 @@
#include "DolphinQt/Config/Mapping/WiimoteEmuMotionControlIMU.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/WindowActivationEventFilter.h"
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
#include "DolphinQt/Settings.h"
@ -255,6 +256,7 @@ void MappingWindow::OnDeleteProfilePressed()
error.setIcon(QMessageBox::Critical);
error.setWindowTitle(tr("Error"));
error.setText(tr("The profile '%1' does not exist").arg(profile_name));
SetQWidgetWindowDecorations(&error);
error.exec();
return;
}
@ -267,6 +269,7 @@ void MappingWindow::OnDeleteProfilePressed()
confirm.setInformativeText(tr("This cannot be undone!"));
confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
SetQWidgetWindowDecorations(&confirm);
if (confirm.exec() != QMessageBox::Yes)
{
return;
@ -294,6 +297,7 @@ void MappingWindow::OnLoadProfilePressed()
error.setIcon(QMessageBox::Critical);
error.setWindowTitle(tr("Error"));
error.setText(tr("The profile '%1' does not exist").arg(m_profiles_combo->currentText()));
SetQWidgetWindowDecorations(&error);
error.exec();
return;
}

View File

@ -14,6 +14,7 @@
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/InputConfig.h"
@ -42,6 +43,7 @@ void WiimoteEmuExtensionMotionInput::CreateNunchukLayout()
ControllerInterfaceWindow* window = new ControllerInterfaceWindow(this);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
});
layout->addLayout(warning_layout, 0, 0, 1, -1);

View File

@ -15,6 +15,7 @@
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/InputConfig.h"
@ -40,6 +41,7 @@ void WiimoteEmuMotionControlIMU::CreateMainLayout()
ControllerInterfaceWindow* window = new ControllerInterfaceWindow(this);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
});

View File

@ -15,6 +15,7 @@
#include "Core/PatchEngine.h"
#include "DolphinQt/Config/NewPatchDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "UICommon/GameFile.h"
@ -74,7 +75,13 @@ void PatchesWidget::OnAdd()
PatchEngine::Patch patch;
patch.user_defined = true;
if (NewPatchDialog(this, patch).exec())
bool new_patch_confirmed = false;
{
NewPatchDialog dialog(this, patch);
SetQWidgetWindowDecorations(&dialog);
new_patch_confirmed = dialog.exec();
}
if (new_patch_confirmed)
{
m_patches.push_back(patch);
SavePatches();
@ -98,7 +105,13 @@ void PatchesWidget::OnEdit()
patch.name = tr("%1 (Copy)").arg(QString::fromStdString(patch.name)).toStdString();
}
if (NewPatchDialog(this, patch).exec())
bool new_patch_confirmed = false;
{
NewPatchDialog dialog(this, patch);
SetQWidgetWindowDecorations(&dialog);
new_patch_confirmed = dialog.exec();
}
if (new_patch_confirmed)
{
if (patch.user_defined)
{

View File

@ -20,6 +20,7 @@
#include "DiscIO/Volume.h"
#include "DiscIO/VolumeVerifier.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
VerifyWidget::VerifyWidget(std::shared_ptr<DiscIO::Volume> volume) : m_volume(std::move(volume))
@ -180,6 +181,7 @@ void VerifyWidget::Verify()
return result;
});
SetQWidgetWindowDecorations(progress.GetRaw());
progress.GetRaw()->exec();
std::optional<DiscIO::VolumeVerifier::Result> result = future.get();

View File

@ -33,6 +33,7 @@
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -261,6 +262,7 @@ void WiimoteControllersWidget::OnWiimoteConfigure(size_t index)
MappingWindow* window = new MappingWindow(this, type, static_cast<int>(index));
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
}

View File

@ -31,6 +31,7 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "UICommon/GameFile.h"
#include "UICommon/UICommon.h"
@ -285,6 +286,7 @@ bool ConvertDialog::ShowAreYouSureDialog(const QString& text)
warning.setInformativeText(text);
warning.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
SetQWidgetWindowDecorations(&warning);
return warning.exec() == QMessageBox::Yes;
}
@ -409,6 +411,7 @@ void ConvertDialog::Convert()
.arg(dst_info.fileName()));
confirm_replace.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
SetQWidgetWindowDecorations(&confirm_replace);
if (confirm_replace.exec() == QMessageBox::No)
continue;
}
@ -519,6 +522,7 @@ void ConvertDialog::Convert()
break;
}
SetQWidgetWindowDecorations(progress_dialog.GetRaw());
progress_dialog.GetRaw()->exec();
if (!success.get())
{

View File

@ -22,6 +22,7 @@
#include "DolphinQt/Debugger/BreakpointDialog.h"
#include "DolphinQt/Debugger/MemoryWidget.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
@ -313,6 +314,7 @@ void BreakpointWidget::OnClear()
void BreakpointWidget::OnNewBreakpoint()
{
BreakpointDialog* dialog = new BreakpointDialog(this);
SetQWidgetWindowDecorations(dialog);
dialog->exec();
}
@ -322,12 +324,14 @@ void BreakpointWidget::OnEditBreakpoint(u32 address, bool is_instruction_bp)
{
auto* dialog =
new BreakpointDialog(this, m_system.GetPowerPC().GetBreakPoints().GetBreakpoint(address));
SetQWidgetWindowDecorations(dialog);
dialog->exec();
}
else
{
auto* dialog =
new BreakpointDialog(this, m_system.GetPowerPC().GetMemChecks().GetMemCheck(address));
SetQWidgetWindowDecorations(dialog);
dialog->exec();
}

View File

@ -37,6 +37,7 @@
#include "Core/System.h"
#include "DolphinQt/Debugger/PatchInstructionDialog.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
@ -306,7 +307,7 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard)
const std::optional<u32> pc =
guard ? std::make_optional(power_pc.GetPPCState().pc) : std::nullopt;
const bool dark_theme = qApp->palette().color(QPalette::Base).valueF() < 0.5;
const bool dark_theme = Settings::Instance().IsThemeDark();
m_branches.clear();
@ -349,7 +350,7 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard)
}
else if (color != 0xFFFFFF)
{
item->setBackground(dark_theme ? QColor(color).darker(240) : QColor(color));
item->setBackground(dark_theme ? QColor(color).darker(400) : QColor(color));
}
}
@ -371,7 +372,7 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard)
description_item->setText(
tr("--> %1").arg(QString::fromStdString(debug_interface.GetDescription(branch_addr))));
param_item->setForeground(Qt::magenta);
param_item->setForeground(dark_theme ? QColor(255, 135, 255) : Qt::magenta);
}
if (ins == "blr")
@ -733,6 +734,7 @@ void CodeViewWidget::AutoStep(CodeTrace::AutoStop option)
.arg(QString::fromStdString(fmt::format("{:#x}", fmt::join(mem_out, ", "))));
msgbox.setInformativeText(msgtext);
SetQWidgetWindowDecorations(&msgbox);
msgbox.exec();
} while (msgbox.clickedButton() == (QAbstractButton*)run_button);
@ -1010,6 +1012,7 @@ void CodeViewWidget::OnReplaceInstruction()
auto& debug_interface = m_system.GetPowerPC().GetDebugInterface();
PatchInstructionDialog dialog(this, addr, debug_interface.ReadInstruction(guard, addr));
SetQWidgetWindowDecorations(&dialog);
if (dialog.exec() == QDialog::Accepted)
{
debug_interface.SetPatch(guard, addr, dialog.GetCode());

View File

@ -28,6 +28,7 @@
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
static const QString BOX_SPLITTER_STYLESHEET = QStringLiteral(
@ -213,6 +214,7 @@ void CodeWidget::OnDiff()
if (!m_diff_dialog)
m_diff_dialog = new CodeDiffDialog(this);
m_diff_dialog->setWindowFlag(Qt::WindowMinimizeButtonHint);
SetQWidgetWindowDecorations(m_diff_dialog);
m_diff_dialog->show();
m_diff_dialog->raise();
m_diff_dialog->activateWindow();

View File

@ -18,6 +18,7 @@
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
RegisterWidget::RegisterWidget(QWidget* parent)
@ -307,6 +308,7 @@ void RegisterWidget::AutoStep(const std::string& reg) const
break;
// Can keep running and try again after a time out.
SetQWidgetWindowDecorations(&msgbox);
msgbox.exec();
if (msgbox.clickedButton() != (QAbstractButton*)run_button)
break;

View File

@ -16,6 +16,7 @@
#include "DolphinQt/DiscordJoinRequestDialog.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
DiscordHandler::DiscordHandler(QWidget* parent) : QObject{parent}, m_parent{parent}
{
@ -60,6 +61,7 @@ void DiscordHandler::ShowNewJoinRequest(const std::string& id, const std::string
std::lock_guard<std::mutex> lock(m_request_dialogs_mutex);
m_request_dialogs.emplace_front(m_parent, id, discord_tag, avatar);
DiscordJoinRequestDialog& request_dialog = m_request_dialogs.front();
SetQWidgetWindowDecorations(&request_dialog);
request_dialog.show();
request_dialog.raise();
request_dialog.activateWindow();

View File

@ -188,6 +188,7 @@
<ClCompile Include="QtUtils\ModalMessageBox.cpp" />
<ClCompile Include="QtUtils\NonDefaultQPushButton.cpp" />
<ClCompile Include="QtUtils\PartiallyClosableTabWidget.cpp" />
<ClCompile Include="QtUtils\SetWindowDecorations.cpp" />
<ClCompile Include="QtUtils\UTF8CodePointCountValidator.cpp" />
<ClCompile Include="QtUtils\WindowActivationEventFilter.cpp" />
<ClCompile Include="QtUtils\WrapInScrollArea.cpp" />
@ -379,6 +380,7 @@
<QtMoc Include="QtUtils\FileOpenEventFilter.h" />
<QtMoc Include="QtUtils\ParallelProgressDialog.h" />
<QtMoc Include="QtUtils\PartiallyClosableTabWidget.h" />
<ClInclude Include="QtUtils\SetWindowDecorations.h" />
<QtMoc Include="QtUtils\UTF8CodePointCountValidator.h" />
<QtMoc Include="QtUtils\WindowActivationEventFilter.h" />
<QtMoc Include="RenderWidget.h" />
@ -415,6 +417,10 @@
<ItemGroup>
<Natvis Include="qt6.natvis" />
</ItemGroup>
<ItemGroup>
<Text Include="Styles\Dark\dark.qss" />
<QtRcc Include="Styles\Dark\dark.qrc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(CoreDir)DolphinLib.vcxproj">
<Project>{D79392F7-06D6-4B4B-A39F-4D587C215D3A}</Project>

View File

@ -29,6 +29,7 @@
#include "Core/System.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/GameCubePane.h"
@ -486,6 +487,7 @@ void GBAWidget::contextMenuEvent(QContextMenuEvent* event)
size_menu->addAction(x4_action);
menu->move(event->globalPos());
SetQWidgetWindowDecorations(menu);
menu->show();
}

View File

@ -42,6 +42,7 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
using namespace ExpansionInterface;
@ -695,6 +696,7 @@ void GCMemcardManager::FixChecksums()
void GCMemcardManager::CreateNewCard(Slot slot)
{
GCMemcardCreateNewDialog dialog(this);
SetQWidgetWindowDecorations(&dialog);
if (dialog.exec() == QDialog::Accepted)
m_slot_file_edit[slot]->setText(QString::fromStdString(dialog.GetMemoryCardPath()));
}

View File

@ -67,6 +67,7 @@
#include "DolphinQt/QtUtils/DoubleClickEventFilter.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/WiiUpdate.h"
@ -546,6 +547,7 @@ void GameList::OpenProperties()
connect(properties, &PropertiesDialog::OpenGraphicsSettings, this,
&GameList::OpenGraphicsSettings);
SetQWidgetWindowDecorations(properties);
properties->show();
}
@ -600,6 +602,7 @@ void GameList::ConvertFile()
return;
ConvertDialog dialog{std::move(games), this};
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
}
@ -617,6 +620,7 @@ void GameList::InstallWAD()
result_dialog.setWindowTitle(success ? tr("Success") : tr("Failure"));
result_dialog.setText(success ? tr("Successfully installed this title to the NAND.") :
tr("Failed to install this title to the NAND."));
SetQWidgetWindowDecorations(&result_dialog);
result_dialog.exec();
}
@ -634,6 +638,7 @@ void GameList::UninstallWAD()
"this title from the NAND without deleting its save data. Continue?"));
warning_dialog.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
SetQWidgetWindowDecorations(&warning_dialog);
if (warning_dialog.exec() == QMessageBox::No)
return;
@ -645,6 +650,7 @@ void GameList::UninstallWAD()
result_dialog.setWindowTitle(success ? tr("Success") : tr("Failure"));
result_dialog.setText(success ? tr("Successfully removed this title from the NAND.") :
tr("Failed to remove this title from the NAND."));
SetQWidgetWindowDecorations(&result_dialog);
result_dialog.exec();
}
@ -818,6 +824,7 @@ void GameList::DeleteFile()
confirm_dialog.setInformativeText(tr("This cannot be undone!"));
confirm_dialog.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
SetQWidgetWindowDecorations(&confirm_dialog);
if (confirm_dialog.exec() == QMessageBox::Yes)
{
for (const auto& game : GetSelectedGames())
@ -843,6 +850,7 @@ void GameList::DeleteFile()
"delete the file or whether it's still in use."));
error_dialog.setStandardButtons(QMessageBox::Retry | QMessageBox::Abort);
SetQWidgetWindowDecorations(&error_dialog);
if (error_dialog.exec() == QMessageBox::Abort)
break;
}

View File

@ -26,6 +26,7 @@
#include "Core/System.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
// Qt is not guaranteed to keep track of file paths using native file pickers, so we use this
@ -149,6 +150,7 @@ void InfinityBaseWindow::LoadFigure(u8 slot)
void InfinityBaseWindow::CreateFigure(u8 slot)
{
CreateFigureDialog create_dlg(this, slot);
SetQWidgetWindowDecorations(&create_dlg);
if (create_dlg.exec() == CreateFigureDialog::Accepted)
{
LoadFigurePath(slot, create_dlg.GetFilePath());

View File

@ -2,11 +2,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef _WIN32
#include <cstdio>
#include <string>
#include <vector>
#include <Windows.h>
#include <cstdio>
#endif
#ifdef __linux__
@ -33,6 +33,7 @@
#include "DolphinQt/MainWindow.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Translation.h"
@ -90,6 +91,7 @@ static bool QtMsgAlertHandler(const char* caption, const char* text, bool yes_no
return QMessageBox::NoIcon;
}());
SetQWidgetWindowDecorations(&message_box);
const int button = message_box.exec();
if (button == QMessageBox::Yes)
return true;
@ -243,8 +245,11 @@ int main(int argc, char* argv[])
{
DolphinAnalytics::Instance().ReportDolphinStart("qt");
MainWindow win{std::move(boot), static_cast<const char*>(options.get("movie"))};
Settings::Instance().InitDefaultPalette();
Settings::Instance().UpdateSystemDark();
Settings::Instance().SetCurrentUserStyle(Settings::Instance().GetCurrentUserStyle());
MainWindow win{std::move(boot), static_cast<const char*>(options.get("movie"))};
win.Show();
#if defined(USE_ANALYTICS) && USE_ANALYTICS
@ -268,6 +273,7 @@ int main(int argc, char* argv[])
"This authorization can be revoked at any time through Dolphin's "
"settings."));
SetQWidgetWindowDecorations(&analytics_prompt);
const int answer = analytics_prompt.exec();
Config::SetBase(Config::MAIN_ANALYTICS_PERMISSION_ASKED, true);

View File

@ -108,6 +108,7 @@
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/WindowActivationEventFilter.h"
#include "DolphinQt/RenderWidget.h"
#include "DolphinQt/ResourcePackManager.h"
@ -1225,6 +1226,7 @@ void MainWindow::ShowControllersWindow()
InstallHotkeyFilter(m_controllers_window);
}
SetQWidgetWindowDecorations(m_controllers_window);
m_controllers_window->show();
m_controllers_window->raise();
m_controllers_window->activateWindow();
@ -1238,6 +1240,7 @@ void MainWindow::ShowFreeLookWindow()
InstallHotkeyFilter(m_freelook_window);
}
SetQWidgetWindowDecorations(m_freelook_window);
m_freelook_window->show();
m_freelook_window->raise();
m_freelook_window->activateWindow();
@ -1251,6 +1254,7 @@ void MainWindow::ShowSettingsWindow()
InstallHotkeyFilter(m_settings_window);
}
SetQWidgetWindowDecorations(m_settings_window);
m_settings_window->show();
m_settings_window->raise();
m_settings_window->activateWindow();
@ -1271,6 +1275,7 @@ void MainWindow::ShowGeneralWindow()
void MainWindow::ShowAboutDialog()
{
AboutDialog about{this};
SetQWidgetWindowDecorations(&about);
about.exec();
}
@ -1282,6 +1287,7 @@ void MainWindow::ShowHotkeyDialog()
InstallHotkeyFilter(m_hotkey_window);
}
SetQWidgetWindowDecorations(m_hotkey_window);
m_hotkey_window->show();
m_hotkey_window->raise();
m_hotkey_window->activateWindow();
@ -1304,6 +1310,7 @@ void MainWindow::ShowGraphicsWindow()
InstallHotkeyFilter(m_graphics_window);
}
SetQWidgetWindowDecorations(m_graphics_window);
m_graphics_window->show();
m_graphics_window->raise();
m_graphics_window->activateWindow();
@ -1311,6 +1318,7 @@ void MainWindow::ShowGraphicsWindow()
void MainWindow::ShowNetPlaySetupDialog()
{
SetQWidgetWindowDecorations(m_netplay_setup_dialog);
m_netplay_setup_dialog->show();
m_netplay_setup_dialog->raise();
m_netplay_setup_dialog->activateWindow();
@ -1321,6 +1329,7 @@ void MainWindow::ShowNetPlayBrowser()
auto* browser = new NetPlayBrowser(this);
browser->setAttribute(Qt::WA_DeleteOnClose, true);
connect(browser, &NetPlayBrowser::Join, this, &MainWindow::NetPlayJoin);
SetQWidgetWindowDecorations(browser);
browser->exec();
}
@ -1333,6 +1342,7 @@ void MainWindow::ShowFIFOPlayer()
[this](const QString& path) { StartGame(path, ScanForSecondDisc::No); });
}
SetQWidgetWindowDecorations(m_fifo_window);
m_fifo_window->show();
m_fifo_window->raise();
m_fifo_window->activateWindow();
@ -1345,6 +1355,7 @@ void MainWindow::ShowSkylanderPortal()
m_skylander_window = new SkylanderPortalWindow();
}
SetQWidgetWindowDecorations(m_skylander_window);
m_skylander_window->show();
m_skylander_window->raise();
m_skylander_window->activateWindow();
@ -1357,6 +1368,7 @@ void MainWindow::ShowInfinityBase()
m_infinity_window = new InfinityBaseWindow();
}
SetQWidgetWindowDecorations(m_infinity_window);
m_infinity_window->show();
m_infinity_window->raise();
m_infinity_window->activateWindow();
@ -1703,6 +1715,36 @@ QSize MainWindow::sizeHint() const
return QSize(800, 600);
}
#ifdef _WIN32
bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr* result)
{
auto* msg = reinterpret_cast<MSG*>(message);
if (msg && msg->message == WM_SETTINGCHANGE && msg->lParam != NULL &&
std::wstring_view(L"ImmersiveColorSet")
.compare(reinterpret_cast<const wchar_t*>(msg->lParam)) == 0)
{
// Windows light/dark theme has changed. Update our flag and refresh the theme.
auto& settings = Settings::Instance();
const bool was_dark_before = settings.IsSystemDark();
settings.UpdateSystemDark();
if (settings.IsSystemDark() != was_dark_before)
{
settings.SetCurrentUserStyle(settings.GetCurrentUserStyle());
// force the colors in the Skylander window to update
if (m_skylander_window)
m_skylander_window->RefreshList();
}
// TODO: When switching from light to dark, the window decorations remain light. Qt seems very
// convinced that it needs to change these in response to this message, so even if we set them
// to dark here, Qt sets them back to light afterwards.
}
return false;
}
#endif
void MainWindow::OnBootGameCubeIPL(DiscIO::Region region)
{
StartGame(std::make_unique<BootParameters>(BootParameters::IPL{region}));
@ -1759,6 +1801,7 @@ void MainWindow::OnImportNANDBackup()
dialog.Reset();
});
SetQWidgetWindowDecorations(dialog.GetRaw());
dialog.GetRaw()->exec();
result.wait();
@ -1866,6 +1909,7 @@ void MainWindow::ShowTASInput()
const auto si_device = Config::Get(Config::GetInfoForSIDevice(i));
if (si_device == SerialInterface::SIDEVICE_GC_GBA_EMULATED)
{
SetQWidgetWindowDecorations(m_gba_tas_input_windows[i]);
m_gba_tas_input_windows[i]->show();
m_gba_tas_input_windows[i]->raise();
m_gba_tas_input_windows[i]->activateWindow();
@ -1873,6 +1917,7 @@ void MainWindow::ShowTASInput()
else if (si_device != SerialInterface::SIDEVICE_NONE &&
si_device != SerialInterface::SIDEVICE_GC_GBA)
{
SetQWidgetWindowDecorations(m_gc_tas_input_windows[i]);
m_gc_tas_input_windows[i]->show();
m_gc_tas_input_windows[i]->raise();
m_gc_tas_input_windows[i]->activateWindow();
@ -1884,6 +1929,7 @@ void MainWindow::ShowTASInput()
if (Config::Get(Config::GetInfoForWiimoteSource(i)) == WiimoteSource::Emulated &&
(!Core::IsRunning() || SConfig::GetInstance().bWii))
{
SetQWidgetWindowDecorations(m_wii_tas_input_windows[i]);
m_wii_tas_input_windows[i]->show();
m_wii_tas_input_windows[i]->raise();
m_wii_tas_input_windows[i]->activateWindow();
@ -1910,6 +1956,7 @@ void MainWindow::ShowAchievementsWindow()
m_achievements_window = new AchievementsWindow(this);
}
SetQWidgetWindowDecorations(m_achievements_window);
m_achievements_window->show();
m_achievements_window->raise();
m_achievements_window->activateWindow();
@ -1920,6 +1967,7 @@ void MainWindow::ShowMemcardManager()
{
GCMemcardManager manager(this);
SetQWidgetWindowDecorations(&manager);
manager.exec();
}
@ -1927,11 +1975,13 @@ void MainWindow::ShowResourcePackManager()
{
ResourcePackManager manager(this);
SetQWidgetWindowDecorations(&manager);
manager.exec();
}
void MainWindow::ShowCheatsManager()
{
SetQWidgetWindowDecorations(m_cheats_manager);
m_cheats_manager->show();
}
@ -1950,6 +2000,7 @@ void MainWindow::ShowRiivolutionBootWidget(const UICommon::GameFile& game)
auto& disc = std::get<BootParameters::Disc>(boot_params->parameters);
RiivolutionBootWidget w(disc.volume->GetGameID(), disc.volume->GetRevision(),
disc.volume->GetDiscNumber(), game.GetFilePath(), this);
SetQWidgetWindowDecorations(&w);
w.exec();
if (!w.ShouldBoot())
return;
@ -1961,7 +2012,10 @@ void MainWindow::ShowRiivolutionBootWidget(const UICommon::GameFile& game)
void MainWindow::Show()
{
if (!Settings::Instance().IsBatchModeEnabled())
{
SetQWidgetWindowDecorations(this);
QWidget::show();
}
// If the booting of a game was requested on start up, do that now
if (m_pending_boot != nullptr)

View File

@ -210,6 +210,11 @@ private:
void dropEvent(QDropEvent* event) override;
QSize sizeHint() const override;
#ifdef _WIN32
// This gets called for each event from the Windows message queue.
bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
#endif
#ifdef HAVE_XRANDR
std::unique_ptr<X11Utils::XRRConfiguration> m_xrr_config;
#endif

View File

@ -59,6 +59,7 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Updater.h"
@ -1178,8 +1179,12 @@ void MenuBar::CheckNAND()
return;
}
if (NANDRepairDialog(result, this).exec() != QDialog::Accepted)
return;
{
NANDRepairDialog dialog(result, this);
SetQWidgetWindowDecorations(&dialog);
if (dialog.exec() != QDialog::Accepted)
return;
}
if (WiiUtils::RepairNAND(ios))
{
@ -1336,6 +1341,7 @@ void MenuBar::GenerateSymbolsFromRSOAuto()
return matches;
});
SetQWidgetWindowDecorations(progress.GetRaw());
progress.GetRaw()->exec();
const auto matches = future.get();

View File

@ -14,14 +14,17 @@
#include "Common/Config/Config.h"
#include "Core/Config/MainSettings.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
bool NKitWarningDialog::ShowUnlessDisabled(QWidget* parent)
{
if (Config::Get(Config::MAIN_SKIP_NKIT_WARNING))
return true;
else
return NKitWarningDialog(parent).exec() == QDialog::Accepted;
NKitWarningDialog dialog(parent);
SetQWidgetWindowDecorations(&dialog);
return dialog.exec() == QDialog::Accepted;
}
NKitWarningDialog::NKitWarningDialog(QWidget* parent) : QDialog(parent)

View File

@ -26,6 +26,7 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
NetPlayBrowser::NetPlayBrowser(QWidget* parent) : QDialog(parent)
@ -303,6 +304,7 @@ void NetPlayBrowser::accept()
dialog->setWindowModality(Qt::WindowModal);
dialog->setTextEchoMode(QLineEdit::Password);
SetQWidgetWindowDecorations(dialog);
if (dialog->exec() != QDialog::Accepted)
return;

View File

@ -51,6 +51,7 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/GameCubePane.h"
@ -213,6 +214,7 @@ void NetPlayDialog::CreateMainLayout()
m_game_digest_menu->addAction(tr("Other game..."), this, [this] {
GameListDialog gld(m_game_list_model, this);
SetQWidgetWindowDecorations(&gld);
if (gld.exec() != QDialog::Accepted)
return;
Settings::Instance().GetNetPlayServer()->ComputeGameDigest(
@ -335,6 +337,7 @@ void NetPlayDialog::ConnectWidgets()
Settings::Instance().GetNetPlayServer()->KickPlayer(id);
});
connect(m_assign_ports_button, &QPushButton::clicked, [this] {
SetQWidgetWindowDecorations(m_pad_mapping);
m_pad_mapping->exec();
Settings::Instance().GetNetPlayServer()->SetPadMapping(m_pad_mapping->GetGCPadArray());
@ -380,6 +383,7 @@ void NetPlayDialog::ConnectWidgets()
connect(m_game_button, &QPushButton::clicked, [this] {
GameListDialog gld(m_game_list_model, this);
SetQWidgetWindowDecorations(&gld);
if (gld.exec() == QDialog::Accepted)
{
Settings& settings = Settings::Instance();

View File

@ -5,6 +5,8 @@
#include <QApplication>
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
ModalMessageBox::ModalMessageBox(QWidget* parent, Qt::WindowModality modality)
: QMessageBox(parent != nullptr ? parent->window() : nullptr)
{
@ -28,6 +30,7 @@ static inline int ExecMessageBox(ModalMessageBox::Icon icon, QWidget* parent, co
msg.setStandardButtons(buttons);
msg.setDefaultButton(default_button);
SetQWidgetWindowDecorations(&msg);
return msg.exec();
}

View File

@ -0,0 +1,25 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include <QWidget>
#include "DolphinQt/Settings.h"
#ifdef _WIN32
#include <dwmapi.h>
#endif
void SetQWidgetWindowDecorations(QWidget* widget)
{
#ifdef _WIN32
if (!Settings::Instance().IsSystemDark())
return;
BOOL use_dark_title_bar = TRUE;
DwmSetWindowAttribute(HWND(widget->winId()),
20 /* DWMWINDOWATTRIBUTE::DWMWA_USE_IMMERSIVE_DARK_MODE */,
&use_dark_title_bar, DWORD(sizeof(use_dark_title_bar)));
#endif
}

View File

@ -0,0 +1,9 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
class QWidget;
// Changes the window decorations (title bar) to dark if the user uses dark mode on Windows.
void SetQWidgetWindowDecorations(QWidget* widget);

View File

@ -14,6 +14,7 @@
#include "Common/FileUtil.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "UICommon/ResourcePack/Manager.h"
ResourcePackManager::ResourcePackManager(QWidget* widget) : QDialog(widget)
@ -241,6 +242,7 @@ void ResourcePackManager::Remove()
box.setIcon(QMessageBox::Warning);
box.setStandardButtons(QMessageBox::Yes | QMessageBox::Abort);
SetQWidgetWindowDecorations(&box);
if (box.exec() != QMessageBox::Yes)
return;

View File

@ -4,21 +4,25 @@
#include "DolphinQt/Settings.h"
#include <atomic>
#include <memory>
#include <QApplication>
#include <QColor>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QFontDatabase>
#include <QPalette>
#include <QRadioButton>
#include <QSize>
#include <QStyle>
#include <QWidget>
#ifdef _WIN32
#include <memory>
#include <fmt/format.h>
#include <winrt/Windows.UI.ViewManagement.h>
#include <QTabBar>
#include <QToolButton>
#endif
@ -47,6 +51,9 @@
#include "VideoCommon/NetPlayChatUI.h"
#include "VideoCommon/NetPlayGolfUI.h"
static bool s_system_dark = false;
static std::unique_ptr<QPalette> s_default_palette;
Settings::Settings()
{
qRegisterMetaType<Core::State>();
@ -125,6 +132,42 @@ QString Settings::GetCurrentUserStyle() const
return QFileInfo(GetQSettings().value(QStringLiteral("userstyle/path")).toString()).fileName();
}
void Settings::InitDefaultPalette()
{
s_default_palette = std::make_unique<QPalette>(qApp->palette());
}
void Settings::UpdateSystemDark()
{
#ifdef _WIN32
// Check if the system is set to dark mode so we can set the default theme and window
// decorations accordingly.
{
using namespace winrt::Windows::UI::ViewManagement;
const UISettings settings;
const auto& color = settings.GetColorValue(UIColorType::Foreground);
const bool is_system_dark = 5 * color.G + 2 * color.R + color.B > 8 * 128;
Settings::Instance().SetSystemDark(is_system_dark);
}
#endif
}
void Settings::SetSystemDark(bool dark)
{
s_system_dark = dark;
}
bool Settings::IsSystemDark()
{
return s_system_dark;
}
bool Settings::IsThemeDark()
{
return qApp->palette().color(QPalette::Base).valueF() < 0.5;
}
// Calling this before the main window has been created breaks the style of some widgets.
void Settings::SetCurrentUserStyle(const QString& stylesheet_name)
{
@ -141,6 +184,44 @@ void Settings::SetCurrentUserStyle(const QString& stylesheet_name)
stylesheet_contents = QString::fromUtf8(stylesheet.readAll().data());
}
#ifdef _WIN32
if (stylesheet_contents.isEmpty())
{
// No theme selected or found. Usually we would just fallthrough and set an empty stylesheet
// which would select Qt's default theme, but unlike other OSes we don't automatically get a
// default dark theme on Windows when the user has selected dark mode in the Windows settings.
// So manually check if the user wants dark mode and, if yes, load our embedded dark theme.
if (IsSystemDark())
{
QFile file(QStringLiteral(":/dolphin_dark_win/dark.qss"));
if (file.open(QFile::ReadOnly))
stylesheet_contents = QString::fromUtf8(file.readAll().data());
QPalette palette = qApp->style()->standardPalette();
palette.setColor(QPalette::Window, QColor(32, 32, 32));
palette.setColor(QPalette::WindowText, QColor(220, 220, 220));
palette.setColor(QPalette::Base, QColor(32, 32, 32));
palette.setColor(QPalette::AlternateBase, QColor(48, 48, 48));
palette.setColor(QPalette::PlaceholderText, QColor(126, 126, 126));
palette.setColor(QPalette::Text, QColor(220, 220, 220));
palette.setColor(QPalette::Button, QColor(48, 48, 48));
palette.setColor(QPalette::ButtonText, QColor(220, 220, 220));
palette.setColor(QPalette::BrightText, QColor(255, 255, 255));
palette.setColor(QPalette::Highlight, QColor(0, 120, 215));
palette.setColor(QPalette::HighlightedText, QColor(255, 255, 255));
palette.setColor(QPalette::Link, QColor(100, 160, 220));
palette.setColor(QPalette::LinkVisited, QColor(100, 160, 220));
qApp->setPalette(palette);
}
else
{
// reset any palette changes that may exist from a previously set dark mode
if (s_default_palette)
qApp->setPalette(*s_default_palette);
}
}
#endif
// Define tooltips style if not already defined
if (!stylesheet_contents.contains(QStringLiteral("QToolTip"), Qt::CaseSensitive))
{

View File

@ -52,6 +52,11 @@ public:
// UI
void SetThemeName(const QString& theme_name);
void InitDefaultPalette();
void UpdateSystemDark();
void SetSystemDark(bool dark);
bool IsSystemDark();
bool IsThemeDark();
void SetCurrentUserStyle(const QString& stylesheet_name);
QString GetCurrentUserStyle() const;

View File

@ -39,6 +39,7 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/BroadbandAdapterSettingsDialog.h"
@ -379,22 +380,32 @@ void GameCubePane::OnConfigPressed(ExpansionInterface::Slot slot)
BrowseAGPRom(slot);
return;
case ExpansionInterface::EXIDeviceType::Microphone:
{
// TODO: convert MappingWindow to use Slot?
MappingWindow(this, MappingWindow::Type::MAPPING_GC_MICROPHONE, static_cast<int>(slot)).exec();
MappingWindow dialog(this, MappingWindow::Type::MAPPING_GC_MICROPHONE, static_cast<int>(slot));
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
case ExpansionInterface::EXIDeviceType::Ethernet:
{
BroadbandAdapterSettingsDialog(this, BroadbandAdapterSettingsDialog::Type::Ethernet).exec();
BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::Ethernet);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
case ExpansionInterface::EXIDeviceType::EthernetXLink:
{
BroadbandAdapterSettingsDialog(this, BroadbandAdapterSettingsDialog::Type::XLinkKai).exec();
BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::XLinkKai);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
case ExpansionInterface::EXIDeviceType::EthernetBuiltIn:
{
BroadbandAdapterSettingsDialog(this, BroadbandAdapterSettingsDialog::Type::BuiltIn).exec();
BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::BuiltIn);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
default:

View File

@ -24,6 +24,7 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -370,6 +371,7 @@ void GeneralPane::GenerateNewIdentity()
message_box.setIcon(QMessageBox::Information);
message_box.setWindowTitle(tr("Identity Generation"));
message_box.setText(tr("New identity generated."));
SetQWidgetWindowDecorations(&message_box);
message_box.exec();
}
#endif

View File

@ -35,6 +35,7 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h"
@ -288,6 +289,7 @@ void WiiPane::CreateSDCard()
progress_dialog.Reset();
return good;
});
SetQWidgetWindowDecorations(progress_dialog.GetRaw());
progress_dialog.GetRaw()->exec();
if (!success.get())
ModalMessageBox::warning(this, tr("Convert Folder to File Now"), tr("Conversion failed."));
@ -312,6 +314,7 @@ void WiiPane::CreateSDCard()
progress_dialog.Reset();
return good;
});
SetQWidgetWindowDecorations(progress_dialog.GetRaw());
progress_dialog.GetRaw()->exec();
if (!success.get())
ModalMessageBox::warning(this, tr("Convert File to Folder Now"), tr("Conversion failed."));
@ -468,6 +471,7 @@ void WiiPane::OnUSBWhitelistAddButton()
USBDeviceAddToWhitelistDialog usb_whitelist_dialog(this);
connect(&usb_whitelist_dialog, &USBDeviceAddToWhitelistDialog::accepted, this,
&WiiPane::PopulateUSBPassthroughListWidget);
SetQWidgetWindowDecorations(&usb_whitelist_dialog);
usb_whitelist_dialog.exec();
}

View File

@ -34,6 +34,7 @@
#include "Core/System.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
@ -560,6 +561,7 @@ void SkylanderPortalWindow::CreateSkylanderAdvanced()
connect(buttons, &QDialogButtonBox::rejected, create_window, &QDialog::reject);
SetQWidgetWindowDecorations(create_window);
create_window->show();
create_window->raise();
}
@ -610,6 +612,8 @@ void SkylanderPortalWindow::UpdateCurrentIDs()
void SkylanderPortalWindow::RefreshList()
{
const bool is_dark_theme = Settings::Instance().IsThemeDark();
const int row = m_skylander_list->currentRow();
m_skylander_list->clear();
if (m_only_show_collection->isChecked())
@ -633,8 +637,16 @@ void SkylanderPortalWindow::RefreshList()
{
const uint qvar = (ids.first << 16) | ids.second;
QListWidgetItem* skylander = new QListWidgetItem(file.baseName());
skylander->setBackground(GetBaseColor(ids));
skylander->setForeground(QBrush(QColor(0, 0, 0, 255)));
if (is_dark_theme)
{
skylander->setBackground(GetBaseColor(ids, true));
skylander->setForeground(QBrush(QColor(220, 220, 220)));
}
else
{
skylander->setBackground(GetBaseColor(ids, false));
skylander->setForeground(QBrush(QColor(0, 0, 0)));
}
skylander->setData(1, qvar);
m_skylander_list->addItem(skylander);
}
@ -650,8 +662,16 @@ void SkylanderPortalWindow::RefreshList()
{
const uint qvar = (entry.first.first << 16) | entry.first.second;
QListWidgetItem* skylander = new QListWidgetItem(tr(entry.second.name));
skylander->setBackground(GetBaseColor(entry.first));
skylander->setForeground(QBrush(QColor(0, 0, 0, 255)));
if (is_dark_theme)
{
skylander->setBackground(GetBaseColor(entry.first, true));
skylander->setForeground(QBrush(QColor(220, 220, 220)));
}
else
{
skylander->setBackground(GetBaseColor(entry.first, false));
skylander->setForeground(QBrush(QColor(0, 0, 0)));
}
skylander->setData(1, qvar);
m_skylander_list->addItem(skylander);
}
@ -895,27 +915,27 @@ int SkylanderPortalWindow::GetElementRadio()
return -1;
}
QBrush SkylanderPortalWindow::GetBaseColor(std::pair<const u16, const u16> ids)
QBrush SkylanderPortalWindow::GetBaseColor(std::pair<const u16, const u16> ids, bool dark_theme)
{
auto skylander = IOS::HLE::USB::list_skylanders.find(ids);
if (skylander == IOS::HLE::USB::list_skylanders.end())
return QBrush(QColor(255, 255, 255, 255));
return QBrush(dark_theme ? QColor(32, 32, 32) : QColor(255, 255, 255));
switch ((*skylander).second.game)
{
case IOS::HLE::USB::Game::SpyrosAdv:
return QBrush(QColor(240, 255, 240, 255));
return QBrush(dark_theme ? QColor(10, 42, 90) : QColor(240, 255, 240));
case IOS::HLE::USB::Game::Giants:
return QBrush(QColor(255, 240, 215, 255));
return QBrush(dark_theme ? QColor(120, 16, 12) : QColor(255, 240, 215));
case IOS::HLE::USB::Game::SwapForce:
return QBrush(QColor(240, 245, 255, 255));
return QBrush(dark_theme ? QColor(28, 45, 12) : QColor(240, 245, 255));
case IOS::HLE::USB::Game::TrapTeam:
return QBrush(QColor(255, 240, 240, 255));
return QBrush(dark_theme ? QColor(0, 56, 76) : QColor(255, 240, 240));
case IOS::HLE::USB::Game::Superchargers:
return QBrush(QColor(247, 228, 215, 255));
return QBrush(dark_theme ? QColor(90, 12, 12) : QColor(247, 228, 215));
default:
return QBrush(QColor(255, 255, 255, 255));
return QBrush(dark_theme ? QColor(32, 32, 32) : QColor(255, 255, 255));
}
}

View File

@ -37,6 +37,8 @@ public:
explicit SkylanderPortalWindow(QWidget* parent = nullptr);
~SkylanderPortalWindow() override;
void RefreshList();
protected:
std::array<QLineEdit*, MAX_SKYLANDERS> m_edit_skylanders;
std::array<std::optional<Skylander>, MAX_SKYLANDERS> m_sky_slots;
@ -60,7 +62,6 @@ private:
// Behind the scenes
void OnEmulationStateChanged(Core::State state);
void OnCollectionPathChanged();
void RefreshList();
void UpdateCurrentIDs();
void CreateSkyfile(const QString& path, bool load_after);
void LoadSkyfilePath(u8 slot, const QString& path);
@ -71,7 +72,7 @@ private:
QString GetFilePath(u16 id, u16 var);
u8 GetCurrentSlot();
int GetElementRadio();
QBrush GetBaseColor(std::pair<const u16, const u16> ids);
QBrush GetBaseColor(std::pair<const u16, const u16> ids, bool dark_theme);
int GetGameID(IOS::HLE::USB::Game game);
int GetElementID(IOS::HLE::USB::Element elem);

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1300" height="1300" viewBox="0 0 1300 1300" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="50" width="1200" height="1200" style="stroke:#7e7e7e;stroke-width:100;fill:#505050;" />
<polyline points="250,700 500,950 1100,350" stroke="#7e7e7e" stroke-width="150" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 336 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1300" height="1300" viewBox="0 0 1300 1300" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="50" width="1200" height="1200" style="stroke:#7e7e7e;stroke-width:100;fill:none;" />
<polyline points="250,700 500,950 1100,350" stroke="#7e7e7e" stroke-width="150" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 333 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1300" height="1300" viewBox="0 0 1300 1300" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="50" width="1200" height="1200" style="stroke:#7e7e7e;stroke-width:100;fill:#505050;" />
</svg>

After

Width:  |  Height:  |  Size: 241 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1300" height="1300" viewBox="0 0 1300 1300" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="50" width="1200" height="1200" style="stroke:#7e7e7e;stroke-width:100;fill:none;" />
</svg>

After

Width:  |  Height:  |  Size: 238 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1300" height="1300" viewBox="0 0 1300 1300" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="50" width="1200" height="1200" style="stroke:#7e7e7e;stroke-width:100;fill:#505050;" />
<rect x="350" y="350" width="600" height="600" style="stroke:#7e7e7e;stroke-width:100;fill:#7e7e7e;" />
</svg>

After

Width:  |  Height:  |  Size: 345 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1300" height="1300" viewBox="0 0 1300 1300" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="50" width="1200" height="1200" style="stroke:#7e7e7e;stroke-width:100;fill:none;" />
<rect x="350" y="350" width="600" height="600" style="stroke:#7e7e7e;stroke-width:100;fill:#7e7e7e;" />
</svg>

After

Width:  |  Height:  |  Size: 342 B

View File

@ -0,0 +1,30 @@
<RCC>
<qresource prefix="/dolphin_dark_win">
<file>dark.qss</file>
<file>checkbox-checked.svg</file>
<file>checkbox-checked-disabled.svg</file>
<file>checkbox-empty.svg</file>
<file>checkbox-empty-disabled.svg</file>
<file>checkbox-half.svg</file>
<file>checkbox-half-disabled.svg</file>
<file>dockwidget-close.svg</file>
<file>dockwidget-undock.svg</file>
<file>down-triangle.svg</file>
<file>down-triangle-spinbox.svg</file>
<file>dropdown-arrow.svg</file>
<file>left-triangle-tabbar.svg</file>
<file>radiobutton-checked.svg</file>
<file>radiobutton-checked-disabled.svg</file>
<file>radiobutton-empty.svg</file>
<file>radiobutton-empty-disabled.svg</file>
<file>right-triangle-tabbar.svg</file>
<file>scrollbar-arrow-down.svg</file>
<file>scrollbar-arrow-left.svg</file>
<file>scrollbar-arrow-right.svg</file>
<file>scrollbar-arrow-up.svg</file>
<file>table-header-sort-arrow-down.svg</file>
<file>table-header-sort-arrow-up.svg</file>
<file>up-triangle.svg</file>
<file>up-triangle-spinbox.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,487 @@
/*
Theme for a look and feel like our default Windows theme, but dark
*/
* {
color: #dcdcdc;
}
*:disabled {
color: #7e7e7e;
}
/*
window title bars apparently can't be styled
would be #000000 for active, #2b2b2b for background
*/
QMenu {
border: 1px solid #7e7e7e;
}
QMenuBar {
background-color: #202020;
color: #dcdcdc;
border: 0px;
}
QMenu {
background-color: #202020;
color: #dcdcdc;
border: 1px solid #7e7e7e;
}
QMenuBar::item {
background-color: #202020;
color: #dcdcdc;
border: 0px;
padding-left: 8px;
padding-right: 8px;
padding-top: 3px;
padding-bottom: 2px;
margin: 0px;
}
QMenuBar {
border-color: #404040;
}
QMenu::item {
background-color: #202020;
color: #dcdcdc;
border: 0px;
padding-left: 8px;
padding-right: 32px;
padding-top: 4px;
padding-bottom: 4px;
margin: 0px;
}
QMenuBar::item:hover, QMenuBar::item:selected, QMenu::item:hover, QMenu::item:selected {
background-color: #404040;
color: #dcdcdc;
}
QMenuBar::item:disabled, QMenu::item:disabled {
color: #7e7e7e;
}
QMenu::separator {
height: 1px;
background-color: #7e7e7e;
margin-left: 2px;
margin-right: 2px;
margin-top: 5px;
margin-bottom: 5px;
}
QWidget {
background-color: #202020;
}
QColumnView, QListView, QTableView, QTableWidget, QTreeView {
background-color: #202020;
alternate-background-color: #303030;
border: 1px solid #7e7e7e;
selection-background-color: #505050; /* #202050; */
gridline-color: #606060;
}
/*
would be consistent with Explorer, but Qt keeps the focus color even if you click away from the item, which is confusing
QColumnView::item:focus, QListView::item:focus, QTableView::item:focus, QTableWidget::item:focus, QTreeView::item:focus {
background-color: #606060;
}
*/
QHeaderView::section {
background-color: #202020;
border: 0px;
border-right: 1px solid #7e7e7e;
padding: 0px;
text-align: right;
/*
this is a hack, Qt is extremely convinced that the sort arrow belongs on the right side
of the header and will reserve space for it there. so this applies that same space to the left
so the text is still centered correctly.
*/
padding-left: 10px;
}
QHeaderView::section:last {
border-right: 0px;
}
QHeaderView::section:hover, QHeaderView::section:checked {
background-color: #404040;
}
QHeaderView::down-arrow {
subcontrol-origin: margin;
subcontrol-position: top center;
image: url(:/dolphin_dark_win/table-header-sort-arrow-down.svg);
width: 10px;
height: 7px;
background: transparent;
}
QHeaderView::up-arrow {
subcontrol-origin: margin;
subcontrol-position: top center;
image: url(:/dolphin_dark_win/table-header-sort-arrow-up.svg);
width: 10px;
height: 7px;
background: transparent;
}
QTabWidget::pane {
border: 1px solid #7e7e7e;
top: -1px; /* move border behind tabs */
}
QTabWidget::tab-bar {
left: 2px; /* leave space on the side of the tabs */
}
QTabBar {
/* The outline on the focused tab has an incorrect position and as far as I can tell there's no way to move it.
So as a hack, remove it and apply an underline to the text instead. */
outline: 0px;
}
QTabBar::tab {
background-color: #303030;
border-left: 1px solid #7e7e7e;
border-right: 1px solid #7e7e7e;
border-top: 1px solid #7e7e7e;
border-bottom: 1px solid #7e7e7e;
padding-top: 2px;
padding-bottom: 2px;
padding-left: 9px;
padding-right: 10px;
margin-right: -1px; /* so adjacent tab borders overlap */
}
QTabBar::tab:only-one {
margin-right: 0px;
}
QTabBar::tab:last {
margin-right: 0px;
}
QTabBar::tab:hover {
background-color: #404040;
}
QTabBar::tab:selected {
border-bottom: 0px;
background-color: #202020;
padding-bottom: 1px;
}
QTabBar::tab:focus {
text-decoration: underline;
}
QTabBar::tab:!selected {
margin-top: 2px;
}
QDockWidget {
background-color: #404040;
titlebar-close-icon: url(:/dolphin_dark_win/dockwidget-close.svg);
titlebar-normal-icon: url(:/dolphin_dark_win/dockwidget-undock.svg);
}
QPushButton, QToolButton {
background-color: #303030;
border: 1px solid #7e7e7e;
padding: 2px;
min-width: 67px;
}
QPushButton:hover, QToolButton:hover {
background-color: #404040;
}
QPushButton:focus, QToolButton:focus {
background-color: #404040;
}
QPushButton:disabled, QToolButton:disabled {
background-color: #505050;
}
/* the dropdownarrow on the right of the button in menu popup mode */
QToolButton[popupMode="1"] {
padding-right: 19px;
}
QToolButton::menu-button {
border: 0px;
border-left: 1px solid #7e7e7e;
width: 18px;
}
QToolButton::menu-arrow {
image: url(:/dolphin_dark_win/down-triangle.svg);
width: 14px;
}
/* the icon bar at the top of the main window */
QToolBar {
border: 0px;
}
QToolBar QToolButton {
border: 0px;
padding: 0px;
padding-left: 3px;
padding-right: 2px;
min-width: 50px;
background-color: #202020;
}
QToolBar QToolButton:hover {
background-color: #404040;
}
QToolBar QToolButton:focus {
background-color: #404040;
}
QToolBar QToolButton:disabled {
background-color: #202020;
}
QToolBar::separator {
min-width: 0px;
width: 1px;
margin-left: 3px;
margin-right: 2px;
background-color: #7e7e7e;
}
QGroupBox {
border: 1px solid #7e7e7e;
margin-top: 9px;
padding-top: 7px;
padding-bottom: 0px;
padding-left: 1px;
padding-right: 1px;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top left;
left: 9px;
padding-top: 1px;
min-width: 0px;
}
QLineEdit, QTextEdit {
border: 1px solid #7e7e7e;
}
QLineEdit:disabled, QTextEdit:disabled {
background-color: #505050;
}
QComboBox {
background-color: #303030;
border: 1px solid #7e7e7e;
margin: 0px;
padding-left: 3px;
padding-right: 3px;
padding-top: 1px;
padding-bottom: 1px;
}
QComboBox:disabled {
background-color: #505050;
}
QComboBox:selected {
background-color: #404040;
}
QComboBox:editable {
background-color: #202020;
}
QComboBox::drop-down {
border: 0px;
}
QComboBox::down-arrow {
image: url(:/dolphin_dark_win/dropdown-arrow.svg);
height: 10px;
width: 15px;
}
QComboBox QAbstractItemView {
background-color: #303030;
selection-background-color: #404040;
border: 1px solid #7e7e7e;
padding: 0px;
margin: 0px;
outline: 0px;
}
QComboBox QAbstractItemView::item:selected {
color: #dcdcdc;
background-color: #404040;
}
QComboBox QAbstractItemView::item:last {
border: 0px;
}
QScrollBar:vertical {
border: 0px;
background: #303030;
width: 15px;
margin: 15px 0px;
}
QScrollBar::handle:vertical { /* the bar in the middle */
border: 0px;
background: #606060;
min-height: 20px;
}
QScrollBar::add-line:vertical { /* the down button at the bottom */
border: 0px;
background: #303030;
height: 15px;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical { /* the up button at the top */
border: 0px;
background: #303030;
height: 15px;
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { /* the area between the bar and the up/down buttons */
border: 0px;
background: none;
}
QScrollBar::up-arrow:vertical {
image: url(:/dolphin_dark_win/scrollbar-arrow-up.svg);
height: 15px;
}
QScrollBar::down-arrow:vertical {
image: url(:/dolphin_dark_win/scrollbar-arrow-down.svg);
height: 15px;
}
QScrollBar:horizontal {
border: 0px;
background: #303030;
height: 15px;
margin: 0px 15px;
}
QScrollBar::handle:horizontal { /* the bar in the middle */
border: 0px;
background: #606060;
min-width: 20px;
}
QScrollBar::add-line:horizontal { /* the right button */
border: 0px;
background: #303030;
width: 15px;
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal { /* the left button */
border: 0px;
background: #303030;
width: 15px;
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { /* the area between the bar and the left/right buttons */
border: 0px;
background: none;
}
QScrollBar::left-arrow:horizontal {
image: url(:/dolphin_dark_win/scrollbar-arrow-left.svg);
width: 15px;
}
QScrollBar::right-arrow:horizontal {
image: url(:/dolphin_dark_win/scrollbar-arrow-right.svg);
width: 15px;
}
QSpinBox, QDateEdit, QDateTimeEdit, QTimeEdit, QDoubleSpinBox {
border: 1px solid #7e7e7e;
padding-right: 15px;
}
QSpinBox:disabled, QDateEdit:disabled, QDateTimeEdit:disabled, QTimeEdit:disabled, QDoubleSpinBox:disabled {
background-color: #505050;
}
QSpinBox::up-button, QDateEdit::up-button, QDateTimeEdit::up-button, QTimeEdit::up-button, QDoubleSpinBox::up-button {
border: 1px transparent;
subcontrol-origin: border;
subcontrol-position: top right;
width: 16px;
}
QSpinBox::down-button, QDateEdit::down-button, QDateTimeEdit::down-button, QTimeEdit::down-button, QDoubleSpinBox::down-button {
border: 1px transparent;
subcontrol-origin: border;
subcontrol-position: bottom right;
width: 16px;
}
QSpinBox::up-arrow, QDateEdit::up-arrow, QDateTimeEdit::up-arrow, QTimeEdit::up-arrow, QDoubleSpinBox::up-arrow {
image: url(:/dolphin_dark_win/up-triangle-spinbox.svg);
width: 14px;
height: 7px;
}
QSpinBox::down-arrow, QDateEdit::down-arrow, QDateTimeEdit::down-arrow, QTimeEdit::down-arrow, QDoubleSpinBox::down-arrow {
image: url(:/dolphin_dark_win/down-triangle-spinbox.svg);
width: 14px;
height: 7px;
}
/*
QSlider ticks break if you try to style the groove.
https://stackoverflow.com/questions/27531542/tick-marks-disappear-on-styled-qslider
https://bugreports.qt.io/browse/QTBUG-3564 (yes that's from 2009 and it's still accurate)
Truly bizarre. I'll just refrain from styling it from now...
*/
QSlider::handle {
background-color: #dcdcdc;
}
QSlider::handle:disabled {
background-color: #7e7e7e;
}
QCheckBox {
padding: 2px 0px;
}
QCheckBox::indicator {
padding: 0px;
margin: 0px;
border: 0px;
width: 13px;
height: 13px;
}
QCheckBox::indicator:unchecked {
image: url(:/dolphin_dark_win/checkbox-empty.svg);
}
QCheckBox::indicator:unchecked:disabled {
image: url(:/dolphin_dark_win/checkbox-empty-disabled.svg);
}
QCheckBox::indicator:checked {
image: url(:/dolphin_dark_win/checkbox-checked.svg);
}
QCheckBox::indicator:checked:disabled {
image: url(:/dolphin_dark_win/checkbox-checked-disabled.svg);
}
QCheckBox::indicator:indeterminate {
image: url(:/dolphin_dark_win/checkbox-half.svg);
}
QCheckBox::indicator:indeterminate:disabled {
image: url(:/dolphin_dark_win/checkbox-half-disabled.svg);
}
QRadioButton {
padding: 2px 0px;
}
QRadioButton::indicator {
padding: 0px;
margin: 0px;
border: 0px;
width: 13px;
height: 13px;
}
QRadioButton::indicator:unchecked {
image: url(:/dolphin_dark_win/radiobutton-empty.svg);
}
QRadioButton::indicator:unchecked:disabled {
image: url(:/dolphin_dark_win/radiobutton-empty-disabled.svg);
}
QRadioButton::indicator:checked {
image: url(:/dolphin_dark_win/radiobutton-checked.svg);
}
QRadioButton::indicator:checked:disabled {
image: url(:/dolphin_dark_win/radiobutton-checked-disabled.svg);
}
QListView::indicator:unchecked {
image: url(:/dolphin_dark_win/checkbox-empty.svg);
}
QListView::indicator:checked {
image: url(:/dolphin_dark_win/checkbox-checked.svg);
}
QListView::indicator:indeterminate {
image: url(:/dolphin_dark_win/checkbox-half.svg);
}
QTabBar QToolButton {
background-color: #202020;
min-width: 0px;
}
QTabBar QToolButton::left-arrow {
image: url(:/dolphin_dark_win/left-triangle-tabbar.svg);
}
QTabBar QToolButton::right-arrow {
image: url(:/dolphin_dark_win/right-triangle-tabbar.svg);
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1300" height="1300" viewBox="0 0 1300 1300" xmlns="http://www.w3.org/2000/svg">
<line x1="100" y1="100" x2="1200" y2="1200" stroke="#7e7e7e" stroke-width="100" />
<line x1="100" y1="1200" x2="1200" y2="100" stroke="#7e7e7e" stroke-width="100" />
</svg>

After

Width:  |  Height:  |  Size: 303 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1300" height="1300" viewBox="0 0 1300 1300" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="350" width="900" height="900" style="stroke:#7e7e7e;stroke-width:100;fill:none;" />
<polyline points="350,350 350,50 1250,50 1250,950 950,950" stroke="#7e7e7e" stroke-width="100" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 347 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="40" viewBox="0 0 100 40" xmlns="http://www.w3.org/2000/svg">
<polyline points="20,5 50,35 80,5" fill="#dcdcdc" />
</svg>

After

Width:  |  Height:  |  Size: 184 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="20,40 50,70 80,40" fill="#dcdcdc" />
</svg>

After

Width:  |  Height:  |  Size: 188 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="20,50 50,80 80,50" stroke="#dcdcdc" stroke-width="15" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="40" height="100" viewBox="0 0 40 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="35,20 5,50 35,80" fill="#dcdcdc" />
</svg>

After

Width:  |  Height:  |  Size: 185 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1000" height="1000" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
<circle cx="500" cy="500" r="450" style="stroke:#7e7e7e;stroke-width:100;fill:#505050;" />
<circle cx="500" cy="500" r="250" style="fill:#7e7e7e;" />
</svg>

After

Width:  |  Height:  |  Size: 287 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1000" height="1000" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
<circle cx="500" cy="500" r="450" style="stroke:#7e7e7e;stroke-width:100;fill:none;" />
<circle cx="500" cy="500" r="250" style="fill:#7e7e7e;" />
</svg>

After

Width:  |  Height:  |  Size: 284 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1000" height="1000" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
<circle cx="500" cy="500" r="450" style="stroke:#7e7e7e;stroke-width:100;fill:#505050;" />
</svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1000" height="1000" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
<circle cx="500" cy="500" r="450" style="stroke:#7e7e7e;stroke-width:100;fill:none;" />
</svg>

After

Width:  |  Height:  |  Size: 225 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="40" height="100" viewBox="0 0 40 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="5,20 35,50 5,80" fill="#dcdcdc" />
</svg>

After

Width:  |  Height:  |  Size: 184 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="25,35 50,60 75,35" stroke="#dcdcdc" stroke-width="15" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="65,25 40,50 65,75" stroke="#dcdcdc" stroke-width="15" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="35,25 60,50 35,75" stroke="#dcdcdc" stroke-width="15" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="25,65 50,40 75,65" stroke="#dcdcdc" stroke-width="15" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="60" height="50" viewBox="0 0 60 50" xmlns="http://www.w3.org/2000/svg">
<polyline points="5,10 30,35 55,10" stroke="#dcdcdc" stroke-width="10" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 215 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="60" height="50" viewBox="0 0 60 50" xmlns="http://www.w3.org/2000/svg">
<polyline points="5,35 30,10 55,35" stroke="#dcdcdc" stroke-width="10" fill="none" />
</svg>

After

Width:  |  Height:  |  Size: 215 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="40" viewBox="0 0 100 40" xmlns="http://www.w3.org/2000/svg">
<polyline points="20,35 50,5 80,35" fill="#dcdcdc" />
</svg>

After

Width:  |  Height:  |  Size: 185 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<polyline points="20,60 50,30 80,60" fill="#dcdcdc" />
</svg>

After

Width:  |  Height:  |  Size: 188 B

View File

@ -28,6 +28,7 @@
#include "DolphinQt/QtUtils/AspectRatioWidget.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/TAS/IRWidget.h"
#include "DolphinQt/TAS/TASCheckBox.h"
#include "DolphinQt/TAS/TASSpinBox.h"
@ -395,15 +396,21 @@ void WiiTASInputWindow::UpdateExt()
if (m_active_extension == WiimoteEmu::ExtensionNumber::NUNCHUK)
{
setWindowTitle(tr("Wii TAS Input %1 - Wii Remote + Nunchuk").arg(m_num + 1));
SetQWidgetWindowDecorations(m_ir_box);
m_ir_box->show();
SetQWidgetWindowDecorations(m_nunchuk_stick_box);
m_nunchuk_stick_box->show();
m_classic_right_stick_box->hide();
m_classic_left_stick_box->hide();
SetQWidgetWindowDecorations(m_remote_accelerometer_box);
m_remote_accelerometer_box->show();
m_remote_gyroscope_box->setVisible(m_is_motion_plus_attached);
SetQWidgetWindowDecorations(m_nunchuk_accelerometer_box);
m_nunchuk_accelerometer_box->show();
m_triggers_box->hide();
SetQWidgetWindowDecorations(m_nunchuk_buttons_box);
m_nunchuk_buttons_box->show();
SetQWidgetWindowDecorations(m_remote_buttons_box);
m_remote_buttons_box->show();
m_classic_buttons_box->hide();
}
@ -412,14 +419,18 @@ void WiiTASInputWindow::UpdateExt()
setWindowTitle(tr("Wii TAS Input %1 - Classic Controller").arg(m_num + 1));
m_ir_box->hide();
m_nunchuk_stick_box->hide();
SetQWidgetWindowDecorations(m_classic_right_stick_box);
m_classic_right_stick_box->show();
SetQWidgetWindowDecorations(m_classic_left_stick_box);
m_classic_left_stick_box->show();
m_remote_accelerometer_box->hide();
m_remote_gyroscope_box->hide();
m_nunchuk_accelerometer_box->hide();
SetQWidgetWindowDecorations(m_triggers_box);
m_triggers_box->show();
m_remote_buttons_box->hide();
m_nunchuk_buttons_box->hide();
SetQWidgetWindowDecorations(m_classic_buttons_box);
m_classic_buttons_box->show();
}
else
@ -429,10 +440,12 @@ void WiiTASInputWindow::UpdateExt()
m_nunchuk_stick_box->hide();
m_classic_right_stick_box->hide();
m_classic_left_stick_box->hide();
SetQWidgetWindowDecorations(m_remote_accelerometer_box);
m_remote_accelerometer_box->show();
m_remote_gyroscope_box->setVisible(m_is_motion_plus_attached);
m_nunchuk_accelerometer_box->hide();
m_triggers_box->hide();
SetQWidgetWindowDecorations(m_remote_buttons_box);
m_remote_buttons_box->show();
m_nunchuk_buttons_box->hide();
m_classic_buttons_box->hide();

View File

@ -17,6 +17,7 @@
#include "Common/Version.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
// Refer to docs/autoupdate_overview.md for a detailed overview of the autoupdate process
@ -100,6 +101,7 @@ void Updater::OnUpdateAvailable(const NewVersionInformation& info)
connect(buttons, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, dialog, &QDialog::reject);
SetQWidgetWindowDecorations(dialog);
return dialog->exec();
});

View File

@ -21,6 +21,7 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
namespace WiiUpdate
{
@ -130,6 +131,7 @@ static WiiUtils::UpdateResult ShowProgress(QWidget* parent, Callable function, A
return res;
});
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return result.get();
}

View File

@ -79,6 +79,8 @@
<AdditionalDependencies>avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!--libcurl needs Crypt32.lib-->
<AdditionalDependencies>Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!--Needed to set window decorations for dark theme-->
<AdditionalDependencies>dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!--See Common/CompatPatches.cpp-->
<ForceSymbolReferences>enableCompatPatches</ForceSymbolReferences>
</Link>

View File

@ -51,9 +51,14 @@
but not the include paths, as passing include paths drastically slows down
moc, and it doesn't appear to actually need them anyway.
-->
<Import Project="qtmoc.props" />
<Import Project="qt_globals.targets"/>
<Import Project="qt_tasks.targets"/>
<ItemDefinitionGroup>
<!--From qtmoc.props-->
<QtMoc>
<ExecutionDescription>moc %(Identity)</ExecutionDescription>
<QTDIR>$(QtHostToolsDir)</QTDIR>
<InputFile>%(FullPath)</InputFile>
<!--
moc task does not properly detect outputs are outdated if Qt version changes
(possibly causing Q_MOC_OUTPUT_REVISION to change). This *might* be because we
@ -62,15 +67,41 @@
to avoid conflicts. (the numeric postfix is the value of Q_MOC_OUTPUT_REVISION)
-->
<OutputFile>$(QtToolOutDir)moc_68\moc_%(Filename).cpp</OutputFile>
<QtMocDir>$(QtToolOutDir)moc_68\</QtMocDir>
<QtMocFileName>moc_%(Filename).cpp</QtMocFileName>
<DynamicSource>output</DynamicSource>
<ParallelProcess>true</ParallelProcess>
<CommandLineTemplate>[AllOptions] [AdditionalOptions]</CommandLineTemplate>
<Outputs>%(OutputFile)</Outputs>
<OverrideClCompile>false</OverrideClCompile>
</QtMoc>
</ItemDefinitionGroup>
<Import Project="qt_globals.targets"/>
<Import Project="qt_tasks.targets"/>
<Import Project="qtmoc.targets" />
<Target Name="QtCheckQtDir" BeforeTargets="QtMocInit" Condition="!$(QtDirValid)">
<Error Text="QTDIR not set or non-existent (pull the submodule?)" />
</Target>
<!--Similar story with rcc-->
<ItemDefinitionGroup>
<!--From qtrcc.props-->
<QtRcc>
<ExecutionDescription>rcc %(Identity)</ExecutionDescription>
<QTDIR>$(QtHostToolsDir)</QTDIR>
<InputFile>%(FullPath)</InputFile>
<OutputFile>$(QtToolOutDir)rcc\qrc_%(Filename).cpp</OutputFile>
<QtRccDir>$(QtToolOutDir)rcc\</QtRccDir>
<QtRccFileName>qrc_%(Filename).cpp</QtRccFileName>
<InitFuncName>%(Filename)</InitFuncName>
<Compression>default</Compression>
<TwoPass>false</TwoPass>
<DynamicSource>output</DynamicSource>
<ParallelProcess>true</ParallelProcess>
<CommandLineTemplate>[AllOptions] [AdditionalOptions]</CommandLineTemplate>
<Outputs>%(OutputFile)</Outputs>
</QtRcc>
</ItemDefinitionGroup>
<Import Project="qtrcc.targets" />
<!--Expose the new targets to VS-->
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml" />

View File

@ -1,83 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt VS Tools.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
-->
<!--
///////////////////////////////////////////////////////////////////////////////////////////////////
// Qt/MSBuild moc property definitions
// -->
<Project>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
// Import pre-requisites
// -->
<Import
Condition="'$(QtMsBuildProps_BeforeMoc)' != ''"
Project="$(QtMsBuildProps_BeforeMoc)"/>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
// QtMoc item template
// -->
<ItemDefinitionGroup>
<QtMoc>
<ExecutionDescription>moc %(Identity)</ExecutionDescription>
<QTDIR Condition="'$(QtVsProjectSettings)' != 'true'"
>$(QtHostToolsDir)</QTDIR>
<QTDIR Condition="'$(QtVsProjectSettings)' == 'true'"
>$(QtInstallDir)</QTDIR>
<InputFile>%(FullPath)</InputFile>
<OutputFile Condition="'$(QtVsProjectSettings)' != 'true'"
>$(ProjectDir)GeneratedFiles\$(Configuration)\moc_%(Filename).cpp</OutputFile>
<QtMocDir Condition="'$(QtVsProjectSettings)' == 'true'"
>$(IntDir)moc\</QtMocDir>
<QtMocFileName Condition="'$(QtVsProjectSettings)' == 'true'"
>moc_%(Filename).cpp</QtMocFileName>
<DynamicSource>output</DynamicSource>
<ParallelProcess>true</ParallelProcess>
<CommandLineTemplate>[AllOptions] [AdditionalOptions]</CommandLineTemplate>
<Outputs>%(OutputFile)</Outputs>
<OverrideClCompile>false</OverrideClCompile>
</QtMoc>
</ItemDefinitionGroup>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
// Import dependants
// -->
<Import
Condition="'$(QtMsBuildProps_AfterMoc)' != ''"
Project="$(QtMsBuildProps_AfterMoc)"/>
</Project>

View File

@ -0,0 +1,580 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/***************************************************************************************************
Copyright (C) 2023 The Qt Company Ltd.
SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
***************************************************************************************************/
-->
<!--
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Definitions specific to rcc
///////////////////////////////////////////////////////////////////////////////////////////////////
// -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
// Import pre-requisites
// -->
<Import
Condition="'$(QtMsBuildTargets_BeforeRcc)' != ''"
Project="$(QtMsBuildTargets_BeforeRcc)"/>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
// Qt/MSBuild global properties
// -->
<PropertyGroup>
<QtBuildTargets>QtRcc;$(QtBuildTargets)</QtBuildTargets>
</PropertyGroup>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
// Setup item type and property page
// -->
<Choose>
<When Condition="'$(QtVsProjectSettings)' == 'true' AND '$(QtVsProjectClProperties)' == 'true'">
<ItemGroup>
<PropertyPageSchema
Include="$(MSBuildThisFileDirectory)qtrcc_v3.xml" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PropertyPageSchema
Include="$(MSBuildThisFileDirectory)qtrcc.xml" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<AvailableItemName Include="QtRcc">
<Targets>Qt;_ClCompile</Targets>
</AvailableItemName>
</ItemGroup>
<PropertyGroup>
<QtRccRuleName>QtRule40_Rcc</QtRccRuleName>
</PropertyGroup>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtRccInit
/////////////////////////////////////////////////////////////////////////////////////////////////
// Initialize default metadata
// -->
<Target Name="QtRccInit">
<!--// Initialize %(OutputFile) -->
<ItemGroup Condition="'$(QtVsProjectSettings)' == 'true' AND '@(QtRcc)' != ''">
<QtRccAux Include="@(QtRcc)">
<OutputFile
>$([System.IO.Path]::Combine('%(QtRcc.QtRccDir)','%(QtRcc.QtRccFileName)'))</OutputFile>
</QtRccAux>
<QtRcc Remove="@(QtRcc)"/>
<QtRcc Include="@(QtRccAux)"/>
<QtRccAux Remove="@(QtRccAux)"/>
</ItemGroup>
</Target>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtRccSetDependencies
/////////////////////////////////////////////////////////////////////////////////////////////////
// Add resource files as dependencies of the QRC file
// -->
<Target Name="QtRccSetDependencies" DependsOnTargets="QtRccInit"
Inputs="%(QtRcc.Identity)" Outputs="@(QtRcc->'####### Don't skip this target #######')">
<ItemGroup>
<selected_files Include="$(SelectedFiles)"/>
</ItemGroup>
<!--// Parse QRC -->
<ListQrc QrcFilePath="%(QtRcc.FullPath)">
<Output TaskParameter="Result" ItemName="res_file"/>
</ListQrc>
<!--// Add dependencies -->
<ItemGroup Condition="'@(QtRcc)' != '' AND '@(res_file)' != ''">
<QtRcc>
<ResourceFiles>@(res_file)</ResourceFiles>
<AdditionalDependencies
>%(QtRcc.AdditionalDependencies);@(res_file->'%(FullPath)')</AdditionalDependencies>
</QtRcc>
</ItemGroup>
<!--// Clean-up -->
<PropertyGroup>
<QtRccExeQuoted/>
<QtRccQuoted/>
<RccListQuoted/>
</PropertyGroup>
<ItemGroup>
<res_file Remove="@(res_file)"/>
</ItemGroup>
</Target>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtRccPrepare
/////////////////////////////////////////////////////////////////////////////////////////////////
// Prepare items for processing
// -->
<Target Name="QtRccPrepare" DependsOnTargets="QtRccSetDependencies"
Inputs="%(QtRcc.Identity)" Outputs="@(QtRcc->'####### Don't skip this target #######')">
<Message Importance="High" Condition="'$(QtDebug)' == 'true'"
Text="## QtRccPrepare @(QtRcc)"/>
<PropertyGroup>
<selected_files>[@(selected_files->'%(Identity)','][')]</selected_files>
<file>[@(QtRcc->'%(Identity)')]</file>
<output_file>@(QtRcc->'%(OutputFile)')</output_file>
<is_selected Condition="$(selected_files.Contains('$(file)'))">true</is_selected>
<is_selected Condition="!$(selected_files.Contains('$(file)'))">false</is_selected>
</PropertyGroup>
<!--// Delete output file to force build of source if it was manually selected to build
// (e.g. by the 'Compile' option in the context menu for the file) -->
<Delete Files="$(output_file)"
Condition="'$(SelectedFiles)' != '' AND '$(is_selected)' == 'true'" />
<!--// If a source was manually selected to build, remove all other sources -->
<ItemGroup Condition="'@(selected_files)' != ''">
<QtRcc Remove="@(QtRcc)"
Condition="'$(SelectedFiles)' != '' AND '$(is_selected)' != 'true'" />
</ItemGroup>
<!--// Remove sources excluded from build -->
<ItemGroup>
<QtRcc Remove="@(QtRcc)"
Condition="'$(SelectedFiles)' == '' AND '%(QtRcc.ExcludedFromBuild)' == 'true'"/>
</ItemGroup>
<!--// Clean-up -->
<PropertyGroup>
<selected_files/>
<file/>
<output_file/>
<is_selected/>
</PropertyGroup>
</Target>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtRccSetModified
/////////////////////////////////////////////////////////////////////////////////////////////////
// Set InputModified flag for modified files (i.e. Inputs newer than Outputs)
// -->
<Target Name="QtRccSetModified" DependsOnTargets="QtRccPrepare"
Condition="'@(QtRcc)' != ''"
Inputs="%(QtRcc.FullPath);%(QtRcc.AdditionalDependencies)" Outputs="@(QtRcc->'%(OutputFile)')">
<Message Importance="High" Condition="'$(QtDebug)' == 'true'"
Text="## QtRccSetModified @(QtRcc)" />
<CreateProperty Value="true">
<!-- // Using ValueSetByTask ensures $(input_changed) is only set to 'true' when the target
// is actually executed and not when MSBuild is figuring out which targets to run -->
<Output TaskParameter="ValueSetByTask" PropertyName="input_changed" />
</CreateProperty>
<ItemGroup>
<QtRcc>
<InputChanged>$(input_changed)</InputChanged>
</QtRcc>
</ItemGroup>
</Target>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtRccOverrideCpp
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// -->
<!--<Import Project="qtrcc_cl.targets"/>-->
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtRcc
/////////////////////////////////////////////////////////////////////////////////////////////////
// Process each QRC file and produce the corresponding QtWork items
// -->
<PropertyGroup>
<QtRccDependsOn>
QtPrepare;
QtRccPrepare;
QtRccSetModified;
$(QtRccDependsOn)
</QtRccDependsOn>
</PropertyGroup>
<Target Name="QtRcc"
DependsOnTargets="$(QtRccDependsOn)"
BeforeTargets="$(QtRccBeforeTargets)" AfterTargets="$(QtRccAfterTargets)"
Condition="'@(QtRcc)' != ''"
Inputs="%(QtRcc.FullPath);%(QtRcc.AdditionalDependencies);$(MSBuildProjectFile)"
Outputs="@(QtRcc->'%(OutputFile)')">
<Message Importance="High" Condition="'$(QtDebug)' == 'true'" Text="## QtRcc @(QtRcc)" />
<CreateProperty Value="true">
<Output TaskParameter="ValueSetByTask" PropertyName="dependencies_changed" />
</CreateProperty>
<PropertyGroup>
<two_pass Condition="'%(QtRcc.TwoPass)' == 'true'">true</two_pass>
</PropertyGroup>
<!--
///////////////////////////////////////////////////////////////////////////////////////////////
// Convert string lists in source item properties to lists of items
// -->
<Flatten Items="@(QtRcc)"
Metadata="InputFile;
OutputFile;
TempFile;
InitFuncName;
Root;
Compression;
NoCompression;
CompressThreshold;
BinaryOutput;
NoZstd;
PassNumber;
NoNamespace;
Verbose;
List;
Project;
FormatVersion">
<Output
TaskParameter="Result" ItemName="LocalOptions" />
</Flatten>
<!--
///////////////////////////////////////////////////////////////////////////////////////////////
// Translate local paths to build host paths
// -->
<HostTranslatePaths
Items="@(LocalOptions)"
Names="InputFile;
OutputFile;
TempFile;
Root">
<Output
TaskParameter="Result" ItemName="options" />
</HostTranslatePaths>
<ItemGroup>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////
// Remove quotes from all paths
// Escape trailing back-slash in paths
// Add quotes to paths containing spaces
// -->
<options>
<Value Condition="'%(Name)' == 'InputFile' OR '%(Name)' == 'OutputFile'
OR '%(Name)' == 'TempFile' OR '%(Name)' == 'Root'"
>$([System.String]::Copy('%(Value)').Replace('&quot;', ''))</Value>
</options>
<options>
<Value Condition="('%(Name)' == 'InputFile' OR '%(Name)' == 'OutputFile'
OR '%(Name)' == 'TempFile' OR '%(Name)' == 'Root')
AND $([System.String]::Copy('%(Value)').Contains(' '))
AND $([System.String]::Copy('%(Value)').EndsWith('\'))"
>%(Value)\</Value>
</options>
<options>
<Value Condition="('%(Name)' == 'InputFile' OR '%(Name)' == 'OutputFile'
OR '%(Name)' == 'TempFile' OR '%(Name)' == 'Root')
AND $([System.String]::Copy('%(Value)').Contains(' '))"
>&quot;%(Value)&quot;</Value>
</options>
<!--
///////////////////////////////////////////////////////////////////////////////////////////////
// Generate tool command line arguments
// -->
<!--// inputs Input files (*.qrc) -->
<options>
<Value Condition="'%(Name)' == 'InputFile'">%(Value)</Value>
</options>
<!--// -o, -output <file> Write output to <file> -->
<options>
<Value Condition="'%(Name)' == 'OutputFile' AND '$(two_pass)' != 'true'">-o %(Value)</Value>
</options>
<options>
<Value Condition="'%(Name)' == 'OutputFile' AND '$(two_pass)' == 'true'"></Value>
</options>
<!--// -t, -temp <file> Use temporary <file> for big resources -->
<options>
<Value Condition="'%(Name)' == 'TempFile'">--temp %(Value)</Value>
</options>
<!--// -name <name> Create an external initialization function with <name> -->
<options>
<Value Condition="'%(Name)' == 'InitFuncName'">--name %(Value)</Value>
</options>
<!--// -root <path> Prefix resource access path with root path -->
<options>
<Value Condition="'%(Name)' == 'Root'">--root %(Value)</Value>
</options>
<!--// -compress <level> Compress input files by <level> -->
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level1'">--compress 1</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level2'">--compress 2</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level3'">--compress 3</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level4'">--compress 4</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level5'">--compress 5</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level6'">--compress 6</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level7'">--compress 7</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level8'">--compress 8</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression' AND '%(Value)' == 'level9'">--compress 9</Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'Compression'
AND !$([System.String]::Copy('%(Value)').StartsWith('--compress'))"></Value>
</options>
<!--// -no-compress Disable all compression -->
<options>
<Value
Condition="'%(Name)' == 'NoCompression' AND '%(Value)' != 'true'"></Value>
</options>
<options>
<Value
Condition="'%(Name)' == 'NoCompression' AND '%(Value)' == 'true'">--no-compress</Value>
</options>
<!--// -threshold <level> Threshold to consider compressing files -->
<options>
<Value Condition="'%(Name)' == 'CompressThreshold'">--threshold %(Value)</Value>
</options>
<!--// -binary Output a binary file for use as a dynamic source -->
<options>
<Value Condition="'%(Name)' == 'BinaryOutput' AND '%(Value)' != 'true'"></Value>
</options>
<options>
<Value Condition="'%(Name)' == 'BinaryOutput' AND '%(Value)' == 'true'">--binary</Value>
</options>
<!--// -no-zstd Disable usage of zstd compression -->
<options>
<Value Condition="'%(Name)' == 'NoZstd' AND '%(Value)' != 'true'"></Value>
</options>
<options>
<Value Condition="'%(Name)' == 'NoZstd' AND '%(Value)' == 'true'">--no-zstd</Value>
</options>
<!--// -pass <number> Pass number for big resources -->
<options>
<Value Condition="'%(Name)' == 'PassNumber'">--pass %(Value)</Value>
</options>
<!--// -namespace Turn off namespace macros -->
<options>
<Value Condition="'%(Name)' == 'NoNamespace' AND '%(Value)' != 'true'"></Value>
</options>
<options>
<Value Condition="'%(Name)' == 'NoNamespace' AND '%(Value)' == 'true'">--namespace</Value>
</options>
<!--// -verbose Enable verbose mode -->
<options>
<Value Condition="'%(Name)' == 'Verbose' AND '%(Value)' != 'true'"></Value>
</options>
<options>
<Value Condition="'%(Name)' == 'Verbose' AND '%(Value)' == 'true'">--verbose</Value>
</options>
<!--// -list Only list .qrc file entries, do not generate code -->
<options>
<Value Condition="'%(Name)' == 'List' AND '%(Value)' != 'true'"></Value>
</options>
<options>
<Value Condition="'%(Name)' == 'List' AND '%(Value)' == 'true'">--list</Value>
</options>
<!--// -project Output a resource file containing all files from the
// current directory -->
<options>
<Value Condition="'%(Name)' == 'Project' AND '%(Value)' != 'true'"></Value>
</options>
<options>
<Value Condition="'%(Name)' == 'Project' AND '%(Value)' == 'true'">--project</Value>
</options>
<!--// -format-version <number> The RCC format version to write -->
<options>
<Value Condition="'%(Name)' == 'FormatVersion'">--format-version %(Value)</Value>
</options>
</ItemGroup>
<PropertyGroup>
<options>@(options->'%(Value)', ' ')</options>
</PropertyGroup>
<!--
///////////////////////////////////////////////////////////////////////////////////////////////
// Aux properties
// -->
<PropertyGroup>
<!--// Force modified flag if source was manually selected to build -->
<input_changed Condition="'$(SelectedFiles)' == ''"
>%(QtRcc.InputChanged)</input_changed>
<input_changed Condition="'$(SelectedFiles)' != ''"
>true</input_changed>
<!--// Run work in parallel processes -->
<run_parallel Condition="'@(QtRcc)' != ''
AND '%(QtRcc.ParallelProcess)' == 'true'
AND '$(SelectedFiles)' == ''"
>true</run_parallel>
<!--// Run work in single process -->
<run_single Condition="'@(QtRcc)' != ''
AND ('%(QtRcc.ParallelProcess)' != 'true'
OR '$(SelectedFiles)' != '')"
>true</run_single>
<!--// Get relative path to output -->
<output_relative
>$([MSBuild]::MakeRelative($(ProjectDir), %(QtRcc.OutputFile)).TrimStart('\'))</output_relative>
</PropertyGroup>
<!--
///////////////////////////////////////////////////////////////////////////////////////////////
// Create work item
// -->
<ItemGroup Condition="'$(run_parallel)' == 'true' OR '$(run_single)' == 'true'">
<QtWork Include="@(QtRcc)">
<WorkType>rcc</WorkType>
<ToolPath Condition="'$(QtVsProjectSettings)' == 'true'">$(QtToolsPath)/rcc</ToolPath>
<ToolPath Condition="'$(QtVsProjectSettings)' != 'true'">%(QtRcc.QTDIR)\bin\rcc.exe</ToolPath>
<Options>$(options)</Options>
<Message>%(QtRcc.ExecutionDescription)</Message>
<DependenciesChanged>$(dependencies_changed)</DependenciesChanged>
<InputChanged>$(input_changed)</InputChanged>
<ParallelBuild Condition="'$(run_parallel)' == 'true'">true</ParallelBuild>
<ParallelBuild Condition="'$(run_single)' == 'true'">false</ParallelBuild>
<!--
///////////////////////////////////////////////////////////////////////////////////////////
// Two-pass ("resources_big"): pass 1 -->
<Message Condition="'%(QtRcc.TwoPass)' == 'true'">%(QtRcc.ExecutionDescription) [pass 1]</Message>
<RccPass Condition="'%(QtRcc.TwoPass)' == 'true'">1</RccPass>
<RccOptions Condition="'%(QtRcc.TwoPass)' == 'true'">$(options)</RccOptions>
<Options Condition="'%(QtRcc.TwoPass)' == 'true'"
>$(options) -pass 1 -o &quot;%(OutputFile)&quot;</Options>
<Optimization Condition="'%(QtRcc.TwoPass)' == 'true'">Disabled</Optimization>
<!--
///////////////////////////////////////////////////////////////////////////////////////////
// C++ dynamic source -->
<ClCompile Condition="'%(QtRcc.DynamicSource)' == 'output'">$(output_relative)</ClCompile>
</QtWork>
</ItemGroup>
<!--
///////////////////////////////////////////////////////////////////////////////////////////////
// Clean-up
// -->
<PropertyGroup>
<options/>
<dependencies_changed/>
<input_changed/>
<run_parallel/>
<run_single/>
<output_relative/>
<two_pass/>
</PropertyGroup>
<ItemGroup>
<LocalOptions Remove="@(LocalOptions)"/>
<options Remove="@(options)"/>
<selected_files Remove="@(selected_files)"/>
</ItemGroup>
</Target>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtRccPass2
/////////////////////////////////////////////////////////////////////////////////////////////////
// Two-pass ("resources_big"): pass 2
// -->
<Target Name="QtRccPass2"
DependsOnTargets="QtRccPass2_GetObjs;QtRccPass2_Exec"/>
<Target Name="QtRccPass2_GetObjs"
DependsOnTargets="ComputeCLOutputs">
<ItemGroup>
<QtRccObj Include="@(Obj->WithMetadataValue('RccPass', '1'))">
<RccPass>2</RccPass>
</QtRccObj>
</ItemGroup>
</Target>
<Target Name="QtRccPass2_Exec"
DependsOnTargets="QtRccPass2_GetObjs"
Condition="'@(QtRccObj)' != ''">
<Move
SourceFiles="%(QtRccObj.Identity)"
DestinationFiles="%(QtRccObj.Identity)_TMP"/>
<Exec
Command="@(QtRccObj->'ECHO %(ExecutionDescription) [pass 2] &amp; %(ToolPath) %(RccOptions) -pass 2 -temp &quot;%(Identity)_TMP&quot; -o &quot;%(Identity)&quot;')"
IgnoreExitCode="true"/>
<ItemGroup>
<Obj Remove="@(QtRccObj->'%(Identity)')"/>
<Obj Include="@(QtRccObj)"/>
<QtRccObj Remove="@(QtRccObj)"/>
</ItemGroup>
</Target>
<Target Name="QtRccPass2_Link"
DependsOnTargets="QtRccPass2"/>
<Target Name="QtRccPass2_Lib"
DependsOnTargets="QtRccPass2"/>
<PropertyGroup>
<ComputeLinkInputsTargets>
$(ComputeLinkInputsTargets);
;QtRccPass2_Link;
</ComputeLinkInputsTargets>
<ComputeLibInputsTargets>
$(ComputeLibInputsTargets);
;QtRccPass2_Lib;
</ComputeLibInputsTargets>
</PropertyGroup>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
// Import dependants
// -->
<Import
Condition="'$(QtMsBuildTargets_AfterRcc)' != ''"
Project="$(QtMsBuildTargets_AfterRcc)"/>
</Project>

5
Source/VSProps/qtrcc.xml Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties">
<ItemType Name="QtRcc" DisplayName="Qt Resource File" />
<ContentType Name="QtRcc" DisplayName="Qt Resource Compiler" />
</ProjectSchemaDefinitions>