diff --git a/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss b/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss index 96f0b0b004..0847382e6f 100644 --- a/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss +++ b/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss @@ -27,7 +27,7 @@ LauncherWindow QLabel { } LauncherWindow QLabel#label_choose, QLabel#label_options { - color: rgb(255, 255, 255); + color: white; font-size: 10pt; } @@ -37,11 +37,11 @@ LauncherWindow QLabel#clear { LauncherWindow QLabel#version-info { font-size: 10pt; - color: #dfdfdf; + color: rgb(225, 225, 225); } LauncherWindow QComboBox#config { - background: rgb(86, 86, 86); + background: rgb(96, 96, 96); border: 1px solid rgb(225, 225, 225); border-radius: 2px; padding: 1px 18px 1px 3px; @@ -49,7 +49,7 @@ LauncherWindow QComboBox#config { font-size: 10pt; font-family: Segoe UI; font-weight: bold; - color: rgb(255, 255, 255); + color: white; } LauncherWindow QComboBox#config:hover { @@ -61,6 +61,17 @@ LauncherWindow QComboBox#config:disabled { color: rgb(225, 225, 225); } +LauncherWindow QMenu#newprofile { + background: rgb(60, 60, 60); + min-width: 8em; + max-width: 8em; + color: white; +} + +LauncherWindow QMenu#newprofile::item:selected { + background: rgb(110, 110, 110); +} + LauncherWindow QPushButton#start { background: rgb(96, 96, 96); border: 2px solid rgb(225, 225, 225); @@ -69,10 +80,10 @@ LauncherWindow QPushButton#start { font-size: 16pt; font-weight: bold; letter-spacing: 1px; - color: rgb(255, 255, 255); + color: white; } LauncherWindow QPushButton#start:hover { - background: rgb(120, 120, 120); + background: rgb(110, 110, 110); } LauncherWindow QPushButton#start:disabled { background: rgb(60, 60, 60); @@ -81,14 +92,14 @@ LauncherWindow QPushButton#start:disabled { } LauncherWindow QPushButton#small { - background: rgb(86, 86, 86); + background: rgb(90, 90, 90); border: 1px solid rgb(225, 225, 225); border-radius: 2px; border-style: outset; min-height: 1em; font-size: 10pt; font-weight: bold; - color: rgb(255, 255, 255); + color: white; } LauncherWindow QPushButton#small:hover { background: rgb(110, 110, 110); @@ -221,7 +232,7 @@ HorizonsDialog QLabel#thin { } HorizonsDialog QLabel#normal { - color: rgb(0, 0, 0); + color: black; } /* diff --git a/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp b/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp index 2cd8b53aac..092ff5b379 100644 --- a/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp +++ b/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -214,8 +215,8 @@ LauncherWindow::LauncherWindow(bool profileEnabled, const Configuration& globalC _profileBox->setObjectName("config"); _profileBox->setGeometry(geometry::ProfileBox); _profileBox->setAccessibleName("Choose profile"); - _profileBox->populateList(globalConfig.profile); _profileBox->setEnabled(profileEnabled); + _profileBox->populateList(globalConfig.profile); connect( _profileBox, &SplitComboBox::selectionChanged, this, &LauncherWindow::selectProfile @@ -253,6 +254,28 @@ LauncherWindow::LauncherWindow(bool profileEnabled, const Configuration& globalC newProfileButton, &QPushButton::released, this, &LauncherWindow::newProfile ); + + QMenu* menu = new QMenu(this); + menu->setObjectName("newprofile"); + menu->setToolTipsVisible(true); + QAction* newEmpty = new QAction("Empty profile", this); + newEmpty->setToolTip("Creates a new empty profile without any existing content"); + connect( + newEmpty, &QAction::triggered, + this, &LauncherWindow::newProfile + ); + QAction* newFromCurrent = new QAction("Duplicate profile", this); + newFromCurrent->setToolTip( + "Creates a duplicate of the currently selected profile. This duplicate can " + "be edited and saved under a new name, or if it was a user profile be " + "overwritten" + ); + connect( + newFromCurrent, &QAction::triggered, + this, &LauncherWindow::editProfile + ); + menu->addActions({ newEmpty, newFromCurrent }); + newProfileButton->setMenu(menu); } @@ -407,7 +430,19 @@ void LauncherWindow::selectProfile(std::optional selection) { ghoul_assert(selection.has_value(), "No special item in the profiles"); if (selection.has_value()) { // Having the `if` statement here to satisfy the MSVC code analysis - _editProfileButton->setEnabled(std::filesystem::exists(*selection)); + + // Enable the Edit button only for the user profiles + const bool isUser = selection->starts_with(_userProfilePath.string()); + _editProfileButton->setEnabled(isUser); + + if (isUser) { + _editProfileButton->setToolTip(""); + } + else { + _editProfileButton->setToolTip( + "Cannot edit the selected profile as it is one of the built-in profiles" + ); + } } } @@ -423,8 +458,7 @@ void LauncherWindow::selectConfiguration(std::optional selection) { // If the configuration is a default configuration, we don't allow editing _editWindowButton->setEnabled(false); _editWindowButton->setToolTip( - "Cannot edit since the selected configuration is one of the files " - "provided by OpenSpace" + "Cannot edit the selected configuration as it is one of the built-in profiles" ); } else { @@ -614,19 +648,21 @@ void LauncherWindow::openProfileEditor(const std::string& profile, bool isUserPr &ProfileEdit::raiseExitWindow, [&editor, &savePath, &p, &profile]() { const std::string origPath = std::format("{}{}.profile", savePath, profile); - // If this is a new profile we want to prompt the user - if (!std::filesystem::exists(origPath)) { + // If this is a new profile we want to prompt the user, but only if the user + // actually changed something. If it is still an empty profile, there is no + // need to save it + if (!std::filesystem::exists(origPath) && *p != Profile()) { + editor.promptUserOfUnsavedChanges(); + return; + } + // Check if the profile is the same as current existing file + if (std::filesystem::exists(origPath) && *p != Profile(origPath)) { editor.promptUserOfUnsavedChanges(); return; } - // Check if the profile is the same as current existing file - if (*p != Profile(origPath)) { - editor.promptUserOfUnsavedChanges(); - } - else { - editor.closeWithoutSaving(); - } + // If we got this far, we can safely close the dialog without saving anything + editor.closeWithoutSaving(); } ); diff --git a/apps/OpenSpace/ext/launcher/src/splitcombobox.cpp b/apps/OpenSpace/ext/launcher/src/splitcombobox.cpp index ee8ffd0be7..c89e50aaa7 100644 --- a/apps/OpenSpace/ext/launcher/src/splitcombobox.cpp +++ b/apps/OpenSpace/ext/launcher/src/splitcombobox.cpp @@ -42,6 +42,8 @@ SplitComboBox::SplitComboBox(QWidget* parent, std::filesystem::path userPath, , _fileFilter(std::move(fileFilter)) , _createTooltip(std::move(createTooltip)) { + setCursor(Qt::PointingHandCursor); + connect( this, QOverload::of(&QComboBox::currentIndexChanged),