Add Start at Login Option (Windows and Linux implemented, MacOS stubbed)

This merge request adds the following:

1. A new class AutoStart, designed to add login startup entries for Linux (FreeDesktop autostart) and Windows (Shortcut File).
1. CLI options to enable, disable and check for autostart. (--autostart-enable, --autostart-disable and --autostart-check). e.g. OpenRGB.exe --autostart-enable "--startminimized --server --profile Blue" --nodetect --noautoconnect
1. UI options to enable "Start At Login" with several other options (see screenshots in Comments)

Tested on KDE Neon and Windows 10 x64 (x64 build).

Commits squashed and amended for code style by Adam Honse <calcprogrammer1@gmail.com>
This commit is contained in:
Tom Greenwood
2021-06-26 06:01:25 +00:00
committed by Adam Honse
parent 30d70035fb
commit 7624a70b67
13 changed files with 1318 additions and 23 deletions

View File

@@ -0,0 +1,212 @@
#include "AutoStart-Linux.h"
#include "LogManager.h"
#include "filesystem.h"
#include <fstream>
#include <iostream>
#include <unistd.h>
#include <linux/limits.h>
/*-----------------------------------------------------*\
| Linux AutoStart Implementation |
| Public Methods |
\*-----------------------------------------------------*/
AutoStart::AutoStart(std::string name)
{
InitAutoStart(name);
}
bool AutoStart::DisableAutoStart()
{
std::error_code autostart_file_remove_errcode;
bool success = false;
/*-------------------------------------------------*\
| Check if the filename is valid |
\*-------------------------------------------------*/
if(autostart_file != "")
{
/*---------------------------------------------*\
| If file doesn't exist, disable is successful |
\*---------------------------------------------*/
if(!filesystem::exists(autostart_file))
{
success = true;
}
/*---------------------------------------------*\
| Otherwise, delete the file |
\*---------------------------------------------*/
else
{
success = filesystem::remove(autostart_file, autostart_file_remove_errcode);
if(!success)
{
LOG_ERROR("[AutoStart] An error occurred removing the auto start file.");
}
}
}
else
{
LOG_ERROR("Could not establish correct autostart file path.");
}
return(success);
}
bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info)
{
bool success = false;
/*-------------------------------------------------*\
| Check if the filename is valid |
\*-------------------------------------------------*/
if(autostart_file != "")
{
std::string desktop_file = GenerateDesktopFile(autostart_info);
std::ofstream autostart_file_stream(autostart_file, std::ios::out | std::ios::trunc);
/*---------------------------------------------*\
| Error out if the file could not be opened |
\*---------------------------------------------*/
if(!autostart_file_stream)
{
LOG_ERROR("Could not open %s for writing.", autostart_file.c_str());
success = false;
}
/*---------------------------------------------*\
| Otherwise, write the file |
\*---------------------------------------------*/
else
{
autostart_file_stream << desktop_file;
autostart_file_stream.close();
success = !autostart_file_stream.fail();
if (!success)
{
LOG_ERROR("An error occurred writing the auto start file.");
}
}
}
else
{
LOG_ERROR("Could not establish correct autostart file path.");
}
return(success);
}
bool AutoStart::IsAutoStartEnabled()
{
/*-------------------------------------------------*\
| Check if the filename is valid |
\*-------------------------------------------------*/
if(autostart_file != "")
{
return(filesystem::exists(autostart_file));
}
else
{
return(false);
}
}
std::string AutoStart::GetExePath()
{
/*-------------------------------------------------*\
| Create the OpenRGB executable path |
\*-------------------------------------------------*/
char exepath[ PATH_MAX ];
ssize_t count = readlink("/proc/self/exe", exepath, PATH_MAX);
return(std::string(exepath, (count > 0) ? count : 0));
}
/*-----------------------------------------------------*\
| Linux AutoStart Implementation |
| Private Methods |
\*-----------------------------------------------------*/
std::string AutoStart::GenerateDesktopFile(AutoStartInfo autostart_info)
{
/*-------------------------------------------------*\
| Generate a .desktop file from the AutoStart |
| parameters |
\*-------------------------------------------------*/
std::stringstream fileContents;
fileContents << "[Desktop Entry]" << std::endl;
fileContents << "Categories=" << autostart_info.category << std::endl;
fileContents << "Comment=" << autostart_info.desc << std::endl;
fileContents << "Icon=" << autostart_info.icon << std::endl;
fileContents << "Name=" << GetAutoStartName() << std::endl;
fileContents << "StartupNotify=true" << std::endl;
fileContents << "Terminal=false" << std::endl;
fileContents << "Type=Application" << std::endl;
/*-------------------------------------------------*\
| Add the executable path and arguments |
\*-------------------------------------------------*/
fileContents << "Exec=" << autostart_info.path;
if (autostart_info.args != "")
{
fileContents << " " << autostart_info.args;
}
fileContents << std::endl;
return(fileContents.str());
}
void AutoStart::InitAutoStart(std::string name)
{
std::string autostart_dir;
autostart_name = name;
/*-------------------------------------------------*\
| Get home and config paths |
\*-------------------------------------------------*/
const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
const char *home = getenv("HOME");
/*-------------------------------------------------*\
| Determine where the autostart .desktop files are |
| kept |
\*-------------------------------------------------*/
if(xdg_config_home != NULL)
{
autostart_dir = xdg_config_home;
autostart_dir = autostart_dir + "/autostart/";
}
else if(home != NULL)
{
autostart_dir = home;
autostart_dir = autostart_dir + "/.config/autostart/";
}
/*-------------------------------------------------*\
| Check if the filename is valid |
\*-------------------------------------------------*/
if(autostart_dir != "")
{
std::error_code ec;
bool success = true;
if(!filesystem::exists(autostart_dir))
{
success = filesystem::create_directories(autostart_dir, ec);
}
if(success)
{
autostart_file = autostart_dir + autostart_name + ".desktop";
}
}
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include <string>
#include "AutoStart.h"
class AutoStart: public AutoStartInterface
{
public:
AutoStart(std::string name);
bool DisableAutoStart();
bool EnableAutoStart(AutoStartInfo autostart_info);
bool IsAutoStartEnabled();
std::string GetExePath();
private:
void InitAutoStart(std::string name);
std::string GenerateDesktopFile(AutoStartInfo autostart_info);
};

View File

@@ -0,0 +1,181 @@
#include "AutoStart-MacOS.h"
#include "LogManager.h"
#include "filesystem.h"
#include <fstream>
#include <iostream>
#include <unistd.h>
/*-----------------------------------------------------*\
| MacOS AutoStart Implementation |
| Public Methods |
\*-----------------------------------------------------*/
AutoStart::AutoStart(std::string name)
{
InitAutoStart(name);
}
bool AutoStart::DisableAutoStart()
{
std::error_code autostart_file_remove_errcode;
bool success = false;
// /*-------------------------------------------------*\
// | Check if the filename is valid |
// \*-------------------------------------------------*/
// if(autostart_file != "")
// {
// /*---------------------------------------------*\
// | If file doesn't exist, disable is successful |
// \*---------------------------------------------*/
// if(!filesystem::exists(autostart_file))
// {
// success = true;
// }
// /*---------------------------------------------*\
// | Otherwise, delete the file |
// \*---------------------------------------------*/
// else
// {
// success = filesystem::remove(autostart_file, autostart_file_remove_errcode);
// if(!success)
// {
// LOG_ERROR("[AutoStart] An error occurred removing the auto start file.");
// }
// }
// }
// else
// {
// LOG_ERROR("Could not establish correct autostart file path.");
// }
return(success);
}
bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info)
{
bool success = false;
// /*-------------------------------------------------*\
// | Check if the filename is valid |
// \*-------------------------------------------------*/
// if(autostart_file != "")
// {
// std::string desktop_file = GenerateDesktopFile(autostart_info);
// std::ofstream autostart_file_stream(autostart_file, std::ios::out | std::ios::trunc);
// /*---------------------------------------------*\
// | Error out if the file could not be opened |
// \*---------------------------------------------*/
// if(!autostart_file_stream)
// {
// LOG_ERROR("Could not open %s for writing.", autostart_file.c_str());
// success = false;
// }
// /*---------------------------------------------*\
// | Otherwise, write the file |
// \*---------------------------------------------*/
// else
// {
// autostart_file_stream << desktop_file;
// autostart_file_stream.close();
// success = !autostart_file_stream.fail();
// if (!success)
// {
// LOG_ERROR("An error occurred writing the auto start file.");
// }
// }
// }
// else
// {
// LOG_ERROR("Could not establish correct autostart file path.");
// }
return(success);
}
bool AutoStart::IsAutoStartEnabled()
{
/*-------------------------------------------------*\
| Check if the filename is valid |
\*-------------------------------------------------*/
if(autostart_file != "")
{
return(filesystem::exists(autostart_file));
}
else
{
return(false);
}
}
std::string AutoStart::GetExePath()
{
/*-------------------------------------------------*\
| Create the OpenRGB executable path |
\*-------------------------------------------------*/
// char exepath[ PATH_MAX ];
// ssize_t count = readlink("/proc/self/exe", exepath, PATH_MAX);
// return(std::string(exepath, (count > 0) ? count : 0));
return("");
}
/*-----------------------------------------------------*\
| MacOS AutoStart Implementation |
| Private Methods |
\*-----------------------------------------------------*/
void AutoStart::InitAutoStart(std::string name)
{
std::string autostart_dir;
autostart_name = name;
// /*-------------------------------------------------*\
// | Get home and config paths |
// \*-------------------------------------------------*/
// const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
// const char *home = getenv("HOME");
// /*-------------------------------------------------*\
// | Determine where the autostart .desktop files are |
// | kept |
// \*-------------------------------------------------*/
// if(xdg_config_home != NULL)
// {
// autostart_dir = xdg_config_home;
// autostart_dir = autostart_dir + "/autostart/";
// }
// else if(home != NULL)
// {
// autostart_dir = home;
// autostart_dir = autostart_dir + "/.config/autostart/";
// }
// /*-------------------------------------------------*\
// | Check if the filename is valid |
// \*-------------------------------------------------*/
// if(autostart_dir != "")
// {
// std::error_code ec;
// bool success = true;
// if(!filesystem::exists(autostart_dir))
// {
// success = filesystem::create_directories(autostart_dir, ec);
// }
// if(success)
// {
// autostart_file = autostart_dir + autostart_name + ".desktop";
// }
// }
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include <string>
#include "AutoStart.h"
class AutoStart: public AutoStartInterface
{
public:
AutoStart(std::string name);
bool DisableAutoStart();
bool EnableAutoStart(AutoStartInfo autostart_info);
bool IsAutoStartEnabled();
std::string GetExePath();
private:
void InitAutoStart(std::string name);
};

View File

@@ -0,0 +1,204 @@
#include "AutoStart-Windows.h"
#include "LogManager.h"
#include "filesystem.h"
#include <fstream>
#include <iostream>
#include "windows.h"
#include <shlobj.h>
/*-----------------------------------------------------*\
| Windows AutoStart Implementation |
| Public Methods |
\*-----------------------------------------------------*/
AutoStart::AutoStart(std::string name)
{
InitAutoStart(name);
}
bool AutoStart::DisableAutoStart()
{
std::error_code autostart_file_remove_errcode;
bool success = false;
/*-------------------------------------------------*\
| Check if the filename is valid |
\*-------------------------------------------------*/
if(autostart_file != "")
{
/*---------------------------------------------*\
| If file doesn't exist, disable is successful |
\*---------------------------------------------*/
if(!filesystem::exists(autostart_file))
{
success = true;
}
/*---------------------------------------------*\
| Otherwise, delete the file |
\*---------------------------------------------*/
else
{
success = filesystem::remove(autostart_file, autostart_file_remove_errcode);
if(!success)
{
LOG_ERROR("An error occurred removing the auto start file.");
}
}
}
else
{
LOG_ERROR("Could not establish correct autostart file path.");
}
return(success);
}
bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info)
{
bool success = false;
/*-------------------------------------------------*\
| Check if the filename is valid |
\*-------------------------------------------------*/
if(autostart_file != "")
{
bool weInitialised = false;
HRESULT result;
IShellLinkW* shellLink = NULL;
std::wstring exepathw = utf8_decode(autostart_info.path);
std::wstring argumentsw = utf8_decode(autostart_info.args);
std::wstring startupfilepathw = utf8_decode(autostart_file);
std::wstring descriptionw = utf8_decode(autostart_info.desc);
std::wstring iconw = utf8_decode(autostart_info.path);
result = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&shellLink);
/*---------------------------------------------*\
| If not initialized, initialize |
\*---------------------------------------------*/
if(result == CO_E_NOTINITIALIZED)
{
weInitialised = true;
CoInitializeEx(NULL, 2u);
result = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&shellLink);
}
/*---------------------------------------------*\
| If successfully initialized, save a shortcut |
| from the AutoStart parameters |
\*---------------------------------------------*/
if(SUCCEEDED(result))
{
shellLink->SetPath(exepathw.c_str());
shellLink->SetArguments(argumentsw.c_str());
shellLink->SetDescription(descriptionw.c_str());
shellLink->SetIconLocation(iconw.c_str(), 0);
IPersistFile* persistFile;
result = shellLink->QueryInterface(IID_IPersistFile, (void**)&persistFile);
if(SUCCEEDED(result))
{
result = persistFile->Save(startupfilepathw.c_str(), TRUE);
success = SUCCEEDED(result);
persistFile->Release();
}
shellLink->Release();
}
/*---------------------------------------------*\
| Uninitialize when done |
\*---------------------------------------------*/
if(weInitialised)
{
CoUninitialize();
}
}
else
{
LOG_ERROR("Could not establish correct autostart file path.");
}
return success;
}
bool AutoStart::IsAutoStartEnabled()
{
/*-------------------------------------------------*\
| Check if the filename is valid |
\*-------------------------------------------------*/
if(autostart_file != "")
{
return(filesystem::exists(autostart_file));
}
else
{
return(false);
}
}
std::string AutoStart::GetExePath()
{
/*-------------------------------------------------*\
| Create the OpenRGB executable path |
\*-------------------------------------------------*/
char exepath[MAX_PATH] = "";
DWORD count = GetModuleFileNameA(NULL, exepath, MAX_PATH);
return(std::string(exepath, (count > 0) ? count : 0));
}
/*-----------------------------------------------------*\
| Windows AutoStart Implementation |
| Private Methods |
\*-----------------------------------------------------*/
void AutoStart::InitAutoStart(std::string name)
{
char startMenuPath[MAX_PATH];
autostart_name = name;
/*-------------------------------------------------*\
| Get startup applications path |
\*-------------------------------------------------*/
HRESULT result = SHGetFolderPathA(NULL, CSIDL_PROGRAMS, NULL, 0, startMenuPath);
if(SUCCEEDED(result))
{
autostart_file = std::string(startMenuPath);
autostart_file += "\\Startup\\" + autostart_name + ".lnk";
}
else
{
autostart_file.clear();
}
}
/*-----------------------------------------------------*\
| Convert an UTF8 string to a wide Unicode String |
| (from wmi.cpp) |
\*-----------------------------------------------------*/
std::wstring AutoStart::utf8_decode(const std::string& str)
{
if(str.empty())
{
return std::wstring();
}
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int) str.size(), nullptr, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int) str.size(), &wstrTo[0], size_needed);
return(wstrTo);
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include <string>
#include "AutoStart.h"
class AutoStart: public AutoStartInterface
{
public:
AutoStart(std::string name);
bool DisableAutoStart();
bool EnableAutoStart(AutoStartInfo autostart_info);
bool IsAutoStartEnabled();
std::string GetExePath();
private:
void InitAutoStart(std::string name);
std::wstring utf8_decode(const std::string& str);
};

16
AutoStart/AutoStart.cpp Normal file
View File

@@ -0,0 +1,16 @@
#include "AutoStart.h"
/*-----------------------------------------------------*\
| Common AutoStart Implementation |
| Public Methods |
\*-----------------------------------------------------*/
std::string AutoStartInterface::GetAutoStartFile()
{
return(autostart_file);
}
std::string AutoStartInterface::GetAutoStartName()
{
return(autostart_name);
}

40
AutoStart/AutoStart.h Normal file
View File

@@ -0,0 +1,40 @@
#pragma once
#include <string>
struct AutoStartInfo
{
std::string path;
std::string args;
std::string desc;
std::string icon;
std::string category;
};
class AutoStartInterface
{
public:
virtual bool DisableAutoStart() = 0;
virtual bool EnableAutoStart(AutoStartInfo autostart_info) = 0;
virtual bool IsAutoStartEnabled() = 0;
virtual std::string GetExePath() = 0;
std::string GetAutoStartFile();
std::string GetAutoStartName();
protected:
std::string autostart_file;
std::string autostart_name;
};
#ifdef _WIN32
#include "AutoStart-Windows.h"
#endif
#ifdef __linux__
#include "AutoStart-Linux.h"
#endif
#ifdef __APPLE__
#include "AutoStart-MacOS.h"
#endif

View File

@@ -60,6 +60,7 @@ INCLUDEPATH +=
pci_ids/ \
serial_port/ \
super_io/ \
AutoStart/ \
Controllers/AMDWraithPrismController/ \
Controllers/ASRockPolychromeSMBusController/ \
Controllers/ASRockPolychromeUSBController/ \
@@ -170,6 +171,7 @@ HEADERS +=
serial_port/find_usb_serial_port.h \
serial_port/serial_port.h \
super_io/super_io.h \
AutoStart/AutoStart.h \
Controllers/AMDWraithPrismController/AMDWraithPrismController.h \
Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.h \
Controllers/AnnePro2Controller/AnnePro2Controller.h \
@@ -458,6 +460,7 @@ SOURCES +=
qt/hsv.cpp \
serial_port/serial_port.cpp \
super_io/super_io.cpp \
AutoStart/AutoStart.cpp \
Controllers/AMDWraithPrismController/AMDWraithPrismController.cpp \
Controllers/AMDWraithPrismController/AMDWraithPrismControllerDetect.cpp \
Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.cpp \
@@ -875,6 +878,7 @@ win32:SOURCES +=
serial_port/find_usb_serial_port_win.cpp \
wmi/wmi.cpp \
wmi/acpiwmi.cpp \
AutoStart/AutoStart-Windows.cpp \
Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp \
Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp \
Controllers/OpenRazerController/OpenRazerWindowsDetect.cpp \
@@ -892,6 +896,7 @@ win32:HEADERS +=
i2c_smbus/i2c_smbus_piix4.h \
wmi/wmi.h \
wmi/acpiwmi.h \
AutoStart/AutoStart-Windows.h \
Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h \
Controllers/OpenRazerController/RGBController_OpenRazerWindows.h \
@@ -980,6 +985,7 @@ unix:!macx {
HEADERS += \
i2c_smbus/i2c_smbus_linux.h \
AutoStart/AutoStart-Linux.h \
Controllers/FaustusController/RGBController_Faustus.h \
Controllers/LinuxLEDController/LinuxLEDController.h \
Controllers/LinuxLEDController/RGBController_LinuxLED.h \
@@ -1019,6 +1025,7 @@ unix:!macx {
dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp \
i2c_smbus/i2c_smbus_linux.cpp \
serial_port/find_usb_serial_port_linux.cpp \
AutoStart/AutoStart-Linux.cpp \
Controllers/FaustusController/RGBController_Faustus.cpp \
Controllers/LinuxLEDController/LinuxLEDController.cpp \
Controllers/LinuxLEDController/LinuxLEDControllerDetect.cpp \
@@ -1065,9 +1072,13 @@ macx {
DEFINES += \
USE_HID_USAGE \
HEADERS += \
AutoStart/AutoStart-MacOS.h \
SOURCES += \
dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp \
serial_port/find_usb_serial_port_linux.cpp \
AutoStart/AutoStart-MacOS.cpp \
LIBS += \
-lusb-1.0 \

85
cli.cpp
View File

@@ -4,6 +4,7 @@
#include <tuple>
#include <iostream>
#include "OpenRGB.h"
#include "AutoStart.h"
#include "ProfileManager.h"
#include "ResourceManager.h"
#include "RGBController.h"
@@ -402,6 +403,9 @@ void OptionHelp()
help_text += "--print-source Print the source code file and line number for each log entry.\n";
help_text += "-v, --verbose Print log messages to stdout.\n";
help_text += "-vv, --very-verbose Print debug messages and log messages to stdout.\n";
help_text += "--autostart-check Check if OpenRGB starting at login is enabled.\n";
help_text += "--autostart-disable Disable OpenRGB starting at login.\n";
help_text += "--autostart-enable arguments Enable OpenRGB to start at login. Requires arguments to give to OpenRGB at login.\n";
std::cout << help_text << std::endl;
}
@@ -833,7 +837,9 @@ int ProcessOptions(int argc, char *argv[], Options *options, std::vector<RGBCont
||(option == "--verbose" || option == "-v")
||(option == "--very-verbose" || option == "-vv")
||(option == "--help" || option == "-h")
||(option == "--version" || option == "-V"))
||(option == "--version" || option == "-V")
||(option == "--autostart-check")
||(option == "--autostart-disable"))
{
/*-------------------------------------------------*\
| Do nothing, these are pre-detection arguments |
@@ -842,7 +848,8 @@ int ProcessOptions(int argc, char *argv[], Options *options, std::vector<RGBCont
}
else if((option == "--server-port")
||(option == "--loglevel")
||(option == "--config"))
||(option == "--config")
||(option == "--autostart-enable"))
{
/*-------------------------------------------------*\
| Increment index for pre-detection arguments with |
@@ -1198,6 +1205,80 @@ unsigned int cli_pre_detection(int argc, char *argv[])
arg_index++;
}
/*---------------------------------------------------------*\
| --autostart-check (no arguments) |
\*---------------------------------------------------------*/
else if(option == "--autostart-check")
{
AutoStart auto_start("OpenRGB");
if(auto_start.IsAutoStartEnabled())
{
std::cout << "Autostart is enabled." << std::endl;
}
else
{
std::cout << "Autostart is disabled." << std::endl;
}
}
/*---------------------------------------------------------*\
| --autostart-disable (no arguments) |
\*---------------------------------------------------------*/
else if(option == "--autostart-disable")
{
AutoStart auto_start("OpenRGB");
if(auto_start.DisableAutoStart())
{
std::cout << "Autostart disabled." << std::endl;
}
else
{
std::cout << "Autostart failed to disable." << std::endl;
}
}
/*---------------------------------------------------------*\
| --autostart-enable |
\*---------------------------------------------------------*/
else if(option == "--autostart-enable")
{
if (argument != "")
{
std::string desc = "OpenRGB ";
desc += VERSION_STRING;
desc += ", for controlling RGB lighting.";
AutoStart auto_start("OpenRGB");
AutoStartInfo auto_start_interface;
auto_start_interface.args = argument;
auto_start_interface.category = "Utility;";
auto_start_interface.desc = desc;
auto_start_interface.icon = "OpenRGB";
auto_start_interface.path = auto_start.GetExePath();
if(auto_start.EnableAutoStart(auto_start_interface))
{
std::cout << "Autostart enabled." << std::endl;
}
else
{
std::cout << "Autostart failed to enable." << std::endl;
}
}
else
{
std::cout << "Error: Missing argument for --autostart-enable" << std::endl;
print_help = true;
break;
}
cfg_args++;
arg_index++;
}
/*---------------------------------------------------------*\
| --gui (no arguments) |
\*---------------------------------------------------------*/

View File

@@ -1,3 +1,4 @@
#include "AutoStart.h"
#include "OpenRGBSettingsPage.h"
#include "ui_OpenRGBSettingsPage.h"
#include "ResourceManager.h"
@@ -35,7 +36,7 @@ OpenRGBSettingsPage::OpenRGBSettingsPage(QWidget *parent) :
#endif
/*---------------------------------------------------------*\
| Load user interface settings (Windows only) |
| Load user interface settings |
\*---------------------------------------------------------*/
json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface");
@@ -56,6 +57,68 @@ OpenRGBSettingsPage::OpenRGBSettingsPage(QWidget *parent) :
ui->CheckboxSaveGeometry->setChecked(ui_settings["geometry"]["save_on_exit"]);
}
}
/*---------------------------------------------------------*\
| Load AutoStart settings |
\*---------------------------------------------------------*/
ProfileManager* profile_manager = ResourceManager::get()->GetProfileManager();
/*---------------------------------------------------------*\
| Load profiles into combo box |
\*---------------------------------------------------------*/
if(profile_manager != NULL)
{
ui->ComboBoxAutoStartProfile->clear();
for(std::size_t profile_index = 0; profile_index < profile_manager->profile_list.size(); profile_index++)
{
ui->ComboBoxAutoStartProfile->addItem(profile_manager->profile_list[profile_index].c_str());
}
}
/*---------------------------------------------------------*\
| Make sure autostart settings exist |
\*---------------------------------------------------------*/
CreateAutoStartSettings();
/*---------------------------------------------------------*\
| Initialise UI to current settings or defaults |
\*---------------------------------------------------------*/
json autostart_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("AutoStart");
RemediateAutoStartProfile(autostart_settings);
/*---------------------------------------------------------*\
| Text boxes |
\*---------------------------------------------------------*/
ui->TextServerPort->setText(QString::fromStdString(autostart_settings["port"]));
ui->TextServerPort->setEnabled(autostart_settings["setserverport"]);
ui->TextClientHost->setText(QString::fromStdString(autostart_settings["client"]));
ui->TextClientHost->setEnabled(autostart_settings["setclient"]);
ui->TextCustomArgs->setText(QString::fromStdString(autostart_settings["custom"]));
ui->TextCustomArgs->setEnabled(autostart_settings["setcustom"]);
/*---------------------------------------------------------*\
| Checkboxes |
\*---------------------------------------------------------*/
ui->CheckboxAutoStart->setChecked(autostart_settings["enabled"]);
SetAutoStartVisibility(autostart_settings["enabled"]);
ui->CheckboxAutoStartMinimized->setChecked(autostart_settings["setminimized"]);
ui->CheckboxAutoStartClient->setChecked(autostart_settings["setclient"]);
ui->CheckboxAutoStartServer->setChecked(autostart_settings["setserver"]);
ui->CheckboxAutoStartSetServerPort->setChecked(autostart_settings["setserverport"]);
ui->CheckboxAutoStartCustom->setChecked(autostart_settings["setcustom"]);
ui->AutoStartStatusLabel->hide();
autostart_initialized = true;
#ifdef __APPLE__
SetAutoStartVisibility(false);
ui->CheckboxAutoStart->hide();
#endif
}
OpenRGBSettingsPage::~OpenRGBSettingsPage()
@@ -98,6 +161,329 @@ void Ui::OpenRGBSettingsPage::on_CheckboxSaveGeometry_clicked()
SaveSettings();
}
void Ui::OpenRGBSettingsPage::on_CheckboxAutoStart_clicked()
{
if(autostart_initialized)
{
json autostart_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("AutoStart");
autostart_settings["enabled"] = ui->CheckboxAutoStart->isChecked();
if(autostart_settings["enabled"])
{
RemediateAutoStartProfile(autostart_settings);
}
ResourceManager::get()->GetSettingsManager()->SetSettings("AutoStart", autostart_settings);
SaveSettings();
SetAutoStartVisibility(autostart_settings["enabled"]);
ConfigureAutoStart();
}
}
void Ui::OpenRGBSettingsPage::on_CheckboxAutoStartMinimized_clicked()
{
SaveAutoStartSetting("setminimized", ui->CheckboxAutoStartMinimized->isChecked());
}
void Ui::OpenRGBSettingsPage::on_CheckboxAutoStartServer_clicked()
{
SaveAutoStartSetting("setserver", ui->CheckboxAutoStartServer->isChecked());
}
void Ui::OpenRGBSettingsPage::on_CheckboxAutoStartSetServerPort_clicked()
{
SaveAutoStartSetting("setserverport", ui->CheckboxAutoStartSetServerPort->isChecked());
ui->TextServerPort->setEnabled(ui->CheckboxAutoStartSetServerPort->isChecked());
}
void Ui::OpenRGBSettingsPage::on_CheckboxAutoStartClient_clicked()
{
SaveAutoStartSetting("setclient", ui->CheckboxAutoStartClient->isChecked());
ui->TextClientHost->setEnabled(ui->CheckboxAutoStartClient->isChecked());
}
void Ui::OpenRGBSettingsPage::on_CheckboxAutoStartProfile_clicked()
{
SaveAutoStartSetting("setprofile", ui->CheckboxAutoStartProfile->isChecked());
ui->ComboBoxAutoStartProfile->setEnabled(ui->CheckboxAutoStartProfile->isChecked());
}
void Ui::OpenRGBSettingsPage::on_CheckboxAutoStartCustom_clicked()
{
SaveAutoStartSetting("setcustom", ui->CheckboxAutoStartCustom->isChecked());
ui->TextCustomArgs->setEnabled(ui->CheckboxAutoStartCustom->isChecked());
}
void Ui::OpenRGBSettingsPage::on_TextServerPort_textChanged(QString port)
{
SaveAutoStartSetting("port", port);
}
void Ui::OpenRGBSettingsPage::on_TextClientHost_textChanged(QString client)
{
SaveAutoStartSetting("client", client);
}
void Ui::OpenRGBSettingsPage::on_TextCustomArgs_textChanged(QString custom)
{
SaveAutoStartSetting("custom", custom);
}
void Ui::OpenRGBSettingsPage::on_ComboBoxAutoStartProfile_currentTextChanged(const QString profile)
{
SaveAutoStartSetting("profile", profile);
}
void OpenRGBSettingsPage::SaveAutoStartSetting(std::string name, QString value)
{
if(autostart_initialized)
{
json autostart_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("AutoStart");
autostart_settings[name] = value.toStdString();
ResourceManager::get()->GetSettingsManager()->SetSettings("AutoStart", autostart_settings);
SaveSettings();
ConfigureAutoStart();
}
}
void OpenRGBSettingsPage::SaveAutoStartSetting(std::string name, bool value)
{
if(autostart_initialized)
{
json autostart_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("AutoStart");
autostart_settings[name] = value;
ResourceManager::get()->GetSettingsManager()->SetSettings("AutoStart", autostart_settings);
SaveSettings();
ConfigureAutoStart();
}
}
void OpenRGBSettingsPage::SetAutoStartVisibility(bool visible)
{
if (!visible)
{
ui->ComboBoxAutoStartProfile->hide();
ui->CheckboxAutoStartClient->hide();
ui->CheckboxAutoStartCustom->hide();
ui->CheckboxAutoStartMinimized->hide();
ui->CheckboxAutoStartProfile->hide();
ui->CheckboxAutoStartServer->hide();
ui->CheckboxAutoStartSetServerPort->hide();
ui->TextCustomArgs->hide();
ui->TextClientHost->hide();
ui->TextServerPort->hide();
ui->AutoStartLabel->hide();
ui->AutoStartStatusLabel->hide();
}
else
{
ui->ComboBoxAutoStartProfile->show();
ui->CheckboxAutoStartClient->show();
ui->CheckboxAutoStartCustom->show();
ui->CheckboxAutoStartMinimized->show();
ui->CheckboxAutoStartProfile->show();
ui->CheckboxAutoStartServer->show();
ui->CheckboxAutoStartSetServerPort->show();
ui->TextCustomArgs->show();
ui->TextClientHost->show();
ui->TextServerPort->show();
ui->AutoStartLabel->show();
ui->AutoStartStatusLabel->show();
}
}
void OpenRGBSettingsPage::ConfigureAutoStart()
{
std::map<std::string, std::tuple<std::string, std::string, bool>> autostart_map = {
{"setminimized", {"--startminimized","",false}},
{"setserver", {"--server","",false}},
{"setserverport", {"--server-port","port",false}},
{"setclient", {"--client","client",false}},
{"setprofile", {"--profile","profile",true}},
{"setcustom", {"","custom",false}},
};
json autostart_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("AutoStart");
AutoStart auto_start("OpenRGB");
if (!autostart_settings["enabled"])
{
if (!auto_start.DisableAutoStart())
{
ui->AutoStartStatusLabel->setText("A problem occurred disabling Start At Login.");
ui->AutoStartStatusLabel->show();
SetAutoStartVisibility(true);
}
else
{
ui->AutoStartStatusLabel->hide();
}
}
else
{
std::string desc = "OpenRGB ";
desc += VERSION_STRING;
desc += ", for controlling RGB lighting.";
std::string arguments = "";
for(std::pair<const std::string, std::tuple<std::string, std::string, bool>>& x: autostart_map)
{
std::string argumentsetting = x.first;
std::string argument = std::get<0>(x.second);
std::string argumentvaluename = std::get<1>(x.second);
bool argumentquoted = std::get<2>(x.second);
if (autostart_settings[x.first])
{
if (argument != "")
{
if (arguments != "")
{
arguments += " ";
}
arguments += argument;
}
if (argumentvaluename != "")
{
std::string argumentvalue = autostart_settings[argumentvaluename];
if (argumentvalue != "")
{
if (arguments != "")
{
arguments += " ";
}
if (argumentquoted)
{
arguments += "\"" + argumentvalue + "\"";
}
else
{
arguments += argumentvalue;
}
}
}
}
}
AutoStartInfo auto_start_info;
auto_start_info.args = arguments;
auto_start_info.category = "Utility;";
auto_start_info.desc = desc;
auto_start_info.icon = "OpenRGB";
auto_start_info.path = auto_start.GetExePath();
if (!auto_start.EnableAutoStart(auto_start_info))
{
ui->AutoStartStatusLabel->setText("A problem occurred enabling Start At Login.");
ui->AutoStartStatusLabel->show();
SetAutoStartVisibility(true);
}
else
{
ui->AutoStartStatusLabel->hide();
}
}
}
void OpenRGBSettingsPage::CreateAutoStartSettings()
{
std::map<std::string, std::string> autostart_default_map_string = {
{"custom", ""},
{"port", "6742"},
{"client","localhost:6742"},
{"profile",ui->ComboBoxAutoStartProfile->count() > 0 ? ui->ComboBoxAutoStartProfile->itemText(0).toStdString(): ""}
};
std::map<std::string, bool> autostart_default_map_bool = {
{"enabled", false},
{"setminimized", false},
{"setclient", false},
{"setserver", false},
{"setserverport", false},
{"setcustom", false},
{"setprofile", false},
};
json autostart_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("AutoStart");
for(std::pair<const std::string, bool>& x: autostart_default_map_bool)
{
if(!autostart_settings.contains(x.first))
{
autostart_settings[x.first] = x.second;
}
}
for(std::pair<const std::string, std::string>& x: autostart_default_map_string)
{
if(!autostart_settings.contains(x.first))
{
autostart_settings[x.first] = x.second;
}
}
ResourceManager::get()->GetSettingsManager()->SetSettings("AutoStart", autostart_settings);
}
void OpenRGBSettingsPage::RemediateAutoStartProfile(json &autostart_settings)
{
/*---------------------------------------------------------*\
| If there are no profiles then we disable the UI for |
| profiles and if AutoStart is enabled then we force |
| disable setprofile |
\*---------------------------------------------------------*/
if(ui->ComboBoxAutoStartProfile->count() == 0)
{
ui->CheckboxAutoStartProfile->setEnabled(false);
ui->ComboBoxAutoStartProfile->setEnabled(false);
autostart_settings["profile"] = "";
if(autostart_settings["enabled"])
{
autostart_settings["setprofile"] = false;
ResourceManager::get()->GetSettingsManager()->SetSettings("AutoStart", autostart_settings);
ConfigureAutoStart();
SaveSettings();
}
}
/*---------------------------------------------------------*\
| Else If the profile we want doesn't exist then we force |
| it to a profile which exists and if AutoStart is enabled |
| then we force disable setprofile |
\*---------------------------------------------------------*/
else if(autostart_settings["profile"] == "" ||
(autostart_settings["profile"] != "" &&
ui->ComboBoxAutoStartProfile->findText(QString::fromStdString(autostart_settings["profile"])) == -1))
{
autostart_settings["profile"] = ui->ComboBoxAutoStartProfile->itemText(0).toStdString();
if(autostart_settings["enabled"])
{
autostart_settings["setprofile"] = false;
ResourceManager::get()->GetSettingsManager()->SetSettings("AutoStart", autostart_settings);
ConfigureAutoStart();
SaveSettings();
}
}
ui->ComboBoxAutoStartProfile->setCurrentText(QString::fromStdString(autostart_settings["profile"]));
ui->ComboBoxAutoStartProfile->setEnabled(autostart_settings["setprofile"]);
ui->CheckboxAutoStartProfile->setChecked(autostart_settings["setprofile"]);
}
void OpenRGBSettingsPage::SaveSettings()
{
ResourceManager::get()->GetSettingsManager()->SaveSettings();

View File

@@ -3,6 +3,7 @@
#include "ui_OpenRGBSettingsPage.h"
#include <QWidget>
#include "ResourceManager.h"
namespace Ui {
class OpenRGBSettingsPage;
@@ -20,13 +21,32 @@ private:
Ui::OpenRGBSettingsPageUi *ui;
void SaveSettings();
void CreateAutoStartSettings();
void ConfigureAutoStart();
void RemediateAutoStartProfile(json &autostart_settings);
void SetAutoStartVisibility(bool visible);
void SaveAutoStartSetting(std::string name, QString value);
void SaveAutoStartSetting(std::string name, bool value);
bool theme_initialized = false;
bool autostart_initialized = false;
private slots:
void on_ComboBoxTheme_currentTextChanged(const QString);
void on_CheckboxMinimizeOnClose_clicked();
void on_CheckboxLoadGeometry_clicked();
void on_CheckboxSaveGeometry_clicked();
void on_CheckboxAutoStart_clicked();
void on_CheckboxAutoStartMinimized_clicked();
void on_CheckboxAutoStartServer_clicked();
void on_CheckboxAutoStartClient_clicked();
void on_CheckboxAutoStartProfile_clicked();
void on_TextServerPort_textChanged(const QString);
void on_TextClientHost_textChanged(const QString);
void on_TextCustomArgs_textChanged(const QString);
void on_ComboBoxAutoStartProfile_currentTextChanged(const QString);
void on_CheckboxAutoStartSetServerPort_clicked();
void on_CheckboxAutoStartCustom_clicked();
};
#endif // OPENRGBSETTINGSPAGE_H

View File

@@ -7,18 +7,28 @@
<x>0</x>
<y>0</y>
<width>432</width>
<height>144</height>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="7" column="0">
<item row="11" column="1">
<widget class="QCheckBox" name="CheckboxAutoStartSetServerPort">
<property name="text">
<string>Set Server Port</string>
</property>
</widget>
</item>
<item row="18" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
@@ -27,37 +37,115 @@
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="CheckboxLoadGeometry">
<property name="text">
<string>Load Window Geometry</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="ComboBoxTheme"/>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="CheckboxMinimizeOnClose">
<property name="text">
<string>Minimize On Close</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="ThemeLabel">
<property name="text">
<string>Theme</string>
</property>
</widget>
</item>
<item row="6" column="0">
<item row="15" column="6">
<widget class="QComboBox" name="ComboBoxAutoStartProfile"/>
</item>
<item row="0" column="6">
<widget class="QComboBox" name="ComboBoxTheme"/>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="CheckboxMinimizeOnClose">
<property name="text">
<string>Minimize On Close</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QCheckBox" name="CheckboxAutoStartServer">
<property name="text">
<string>Start Server</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="CheckboxAutoStart">
<property name="text">
<string>Start At Login</string>
</property>
</widget>
</item>
<item row="11" column="6">
<widget class="QLineEdit" name="TextServerPort">
<property name="inputMask">
<string>90000</string>
</property>
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QCheckBox" name="CheckboxAutoStartProfile">
<property name="text">
<string>Load Profile</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QCheckBox" name="CheckboxAutoStartClient">
<property name="text">
<string>Start Client</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="CheckboxAutoStartMinimized">
<property name="text">
<string>Start Minimized</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="CheckboxSaveGeometry">
<property name="text">
<string>Save Geometry On Close</string>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QLabel" name="AutoStartStatusLabel">
<property name="text">
<string>Start at Login Status</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="AutoStartLabel">
<property name="text">
<string>Start At Login Settings:</string>
</property>
</widget>
</item>
<item row="13" column="6">
<widget class="QLineEdit" name="TextClientHost"/>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="CheckboxLoadGeometry">
<property name="text">
<string>Load Window Geometry</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QCheckBox" name="CheckboxAutoStartCustom">
<property name="text">
<string>Custom Arguments</string>
</property>
</widget>
</item>
<item row="14" column="6">
<widget class="QLineEdit" name="TextCustomArgs"/>
</item>
</layout>
</widget>
<resources/>