diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml
new file mode 100644
index 0000000..72827af
--- /dev/null
+++ b/.github/workflows/build-and-release.yml
@@ -0,0 +1,157 @@
+name: Build and Release
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+ build-windows:
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Qt
+ uses: jurplel/install-qt-action@v4
+ with:
+ version: "6.7.2"
+ add-tools-to-path: true
+
+ - name: Setup MSVC
+ uses: ilammy/msvc-dev-cmd@v1
+
+ - name: Build
+ run: |
+ mkdir build
+ cd build
+ qmake ../
+ nmake
+
+ - name: Remove source and object files
+ shell: pwsh
+ run: |
+ $buildDir = "build/release"
+ if (Test-Path $buildDir) {
+ Get-ChildItem -Path $buildDir -Include *.cpp, *.h, *.obj, *.res -Recurse | Remove-Item -Force
+ } else {
+ Write-Host "Directory not found: $buildDir"
+ }
+
+ - name: Deploy Qt
+ shell: pwsh
+ run: |
+ cd build
+ $windeployqtPath = "D:\a\HeadsetControl-GUI\Qt\6.7.2\msvc2019_64\bin\windeployqt6.exe"
+ if (Test-Path $windeployqtPath) {
+ & $windeployqtPath `
+ --exclude-plugins qsvgicon,qsvg,qico,qjpeg,qgif,qnetworklistmanager,qtuiotouchplugin `
+ --no-opengl-sw `
+ --no-system-dxc-compiler `
+ --no-compiler-runtime `
+ --no-translations `
+ --no-system-d3d-compiler `
+ D:\a\HeadsetControl-GUI\HeadsetControl-GUI\build\release\HeadsetControl-GUI.exe
+ } else {
+ Write-Error "windeploygui not found at the expected path!"
+ exit 1
+ }
+ - name: Download ZIP from other repo
+ shell: pwsh
+ run: |
+ Invoke-WebRequest -Uri "https://github.com/Sapd/HeadsetControl/releases/latest/download/headsetcontrol-windows.zip" -OutFile headsetcontrol-windows.zip
+ Expand-Archive -Path headsetcontrol-windows.zip -DestinationPath build/release/
+
+ - name: Zip binaries folder
+ run: |
+ $zipFile = "HeadsetControl-GUI_windows_64.zip"
+ $folder = "build/release/"
+ Compress-Archive -Path $folder -DestinationPath $zipFile
+ shell: pwsh
+
+ - name: Upload Windows artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: HeadsetControl-GUI_windows_64
+ path: HeadsetControl-GUI_windows_64.zip
+
+ build-linux:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Qt
+ uses: jurplel/install-qt-action@v4
+ with:
+ version: "6.7.2"
+ host: "linux"
+ add-tools-to-path: true
+
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y build-essential libgl1-mesa-dev
+
+ - name: Build with qmake
+ run: |
+ mkdir build
+ cd build
+ qmake ../HeadsetControl-GUI.pro CONFIG+=release
+ make -j$(nproc)
+
+ - name: Zip binaries folder
+ run: |
+ zip build/HeadsetControl-GUI_linux_64.zip build/HeadsetControl-GUI
+
+ - name: Upload Artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: HeadsetControl-GUI_linux_64
+ path: build/HeadsetControl-GUI_linux_64.zip
+
+ create-release:
+ needs: [build-linux, build-windows]
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Download Linux artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: HeadsetControl-GUI_linux_64
+
+ - name: Download Windows artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: HeadsetControl-GUI_windows_64
+
+ - name: Create Release
+ id: create_release
+ uses: actions/create-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.ref }}
+ release_name: Release v${{ github.ref }}
+ draft: false
+ prerelease: false
+
+ - name: Upload Linux Release Asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ asset_path: ./HeadsetControl-GUI_linux_64.zip
+ asset_name: HeadsetControl-GUI_linux_64.zip
+ asset_content_type: application/octet-stream
+
+ - name: Upload Windows Release Asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ asset_path: ./HeadsetControl-GUI_windows_64.zip
+ asset_name: HeadsetControl-GUI_windows_64.zip
+ asset_content_type: application/octet-stream
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
new file mode 100644
index 0000000..26b281c
--- /dev/null
+++ b/.github/workflows/build.yaml
@@ -0,0 +1,58 @@
+name: Build
+
+on:
+ push:
+ branches: [main]
+ paths-ignore:
+ - '.src/**'
+ - 'HeadsetControl-GUI.pro'
+ pull_request:
+ branches: [main]
+
+jobs:
+ build-windows:
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Qt
+ uses: jurplel/install-qt-action@v4
+ with:
+ version: "6.7.2"
+ add-tools-to-path: true
+
+ - name: Setup MSVC
+ uses: ilammy/msvc-dev-cmd@v1
+
+ - name: Build
+ run: |
+ mkdir build
+ cd build
+ qmake ../
+ nmake
+
+ build-linux:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Qt
+ uses: jurplel/install-qt-action@v4
+ with:
+ version: "6.7.2"
+ host: "linux"
+ add-tools-to-path: true
+
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y build-essential libgl1-mesa-dev
+
+ - name: Build with qmake
+ run: |
+ mkdir build
+ cd build
+ qmake ../HeadsetControl-GUI.pro CONFIG+=release
+ make -j$(nproc)
diff --git a/.gitignore b/.gitignore
index 259148f..bf96c2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,9 @@
*.exe
*.out
*.app
+
+# Folders
+build/*
+
+# User files
+HeadsetControl-GUI.pro.user
diff --git a/HeadsetControl-GUI.pro b/HeadsetControl-GUI.pro
index 3c39a7e..d4a5a40 100644
--- a/HeadsetControl-GUI.pro
+++ b/HeadsetControl-GUI.pro
@@ -1,30 +1,52 @@
-QT += core gui
+QT += core gui network
+greaterThan(QT_MAJOR_VERSION, 5): QT += widgets
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+CONFIG += c++17
-CONFIG += c++11
-
-# You can make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+INCLUDEPATH += \
+ src/DataTypes \
+ src/UI \
+ src/Utils
SOURCES += \
- main.cpp \
- mainwindow.cpp
+ src/UI/settingswindow.cpp \
+ src/main.cpp \
+ src/DataTypes/device.cpp \
+ src/DataTypes/settings.cpp \
+ src/UI/dialoginfo.cpp \
+ src/UI/loaddevicewindow.cpp \
+ src/UI/mainwindow.cpp \
+ src/Utils/utils.cpp
HEADERS += \
- mainwindow.h
+ src/DataTypes/device.h \
+ src/DataTypes/settings.h \
+ src/UI/dialoginfo.h \
+ src/UI/loaddevicewindow.h \
+ src/UI/mainwindow.h \
+ src/UI/settingswindow.h \
+ src/Utils/utils.h
FORMS += \
- mainwindow.ui
+ src/UI/dialoginfo.ui \
+ src/UI/loaddevicewindow.ui \
+ src/UI/mainwindow.ui \
+ src/UI/settingswindow.ui
TRANSLATIONS += \
- HeadsetControl-GUI_en_US.ts
+ src/Resources/tr/HeadsetControl_GUI_en_US.ts \
+ src/Resources/tr/HeadsetControl_GUI_it_IT.ts
+
+RESOURCES += \
+ src/Resources/icons.qrc \
+ src/Resources/translations.qrc
+
+RC_FILE = src/Resources/appicon.rc
+
+DISTFILES += \
+ .gitignore
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
-
-RESOURCES += \
- icons.qrc
diff --git a/HeadsetControl-GUI_en_US.ts b/HeadsetControl-GUI_en_US.ts
deleted file mode 100644
index edd0d34..0000000
--- a/HeadsetControl-GUI_en_US.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/README.md b/README.md
index 6c54379..c9d7dac 100644
--- a/README.md
+++ b/README.md
@@ -1,62 +1,61 @@
-# HeadsetControl-GUI
-This is a GUI for [Sapds great HeadsetControl](https://github.com/Sapd/HeadsetControl/). It's just a frontend to graphically interact with the original HeadsetControl and has no functionality by itself.
+A simply remake of [HeadsetControl-GUI](https://github.com/LeoKlaus/HeadsetControl-GUI) by @LeoKlaus
+# HeadsetControl-GUI [![Github All Releases](https://img.shields.io/github/downloads/nicola02nb/headsetcontrol-gui/total.svg)]() [![license](https://img.shields.io/github/license/nicola02nb/HeadsetControl-GUI)]()
+This is a GUI for [Sapds great HeadsetControl](https://github.com/Sapd/HeadsetControl/).
+It's just a frontend to graphically interact with the original HeadsetControl and has no functionality by itself.
-I have to give a huge thank you to Sapd for doing all the heavy lifting and developing the command line tool HeadsetControl without which this project wouldn't be possible.
-**Disclaimer**:
-This program is in no way affiliated with Sapd or HeadsetControl.
-All issues regarding the functionality of HeadsetControl (like compatiblity with devices) are beyond the scope of this project.
+## Platforms
+
+OS | Compiled | Tested
+:------------ | :-------------| :-------------
+Windows | ✅ | ✅
+Linux | ✅ | ❌
+MacOS | ❌ | ❌
+
+If you are on Linux or Mac and try to build the app and test it, I'd be happy to hear if it did or didn't work.
-## Installation (Windows only for now)
-Download the [latest release](https://github.com/LeoKlaus/HeadsetControl-GUI/releases/latest/) of HeadsetControl-GUI from the [releases section](https://github.com/LeoKlaus/HeadsetControl-GUI/releases) of this page.
-Download the corresponding version of [Sapds HeadsetControl from their GitHub page](https://github.com/Sapd/HeadsetControl/releases/).
+## Installation (Windows)
+1. Download the [latest release](https://github.com/nicola02nb/HeadsetControl-GUI/releases/latest/) of HeadsetControl-GUI from the [releases section](https://github.com/nicola02nb/HeadsetControl-GUI/releases) of this page.
+2. Extract HeadsetControl-GUI to any folder.
-Extract HeadsetControl-GUI to any folder of your choice and drop HeadsetControl into the same folder.
The finished folder should look something like this:
-![Screenshot of the folder structure](https://i.imgur.com/bbymxL6.jpg "Screenshot of the folder structure")
+![image](https://github.com/user-attachments/assets/0145ca37-6e59-4170-ba26-804e8856dbc8)
-You HAVE to download a version of the [original headsetcontrol](https://github.com/Sapd/HeadsetControl/releases/) and put it in the same folder.
-The executable of headsetcontrol has to be called "HeadsetControl".
-Only if both these requirements are met, the GUI can work.
+### Usage
+Start HeadsetControl-GUI by double-clicking "HeadsetControl-GUI.exe", and if your headset is supported and everything was set up correctly, you will be greeted by the following screen HeadsetControl-GUI has..
-## Usage
-Start HeadsetControl-GUI by double-clicking "HeadsetControl-GUI.exe".
-If your headset is supported and everything was set up correctly, you will be greeted by the only screen HeadsetControl-GUI has.
+If you don't find some features in you ui, probably it's not supported by your headset or it has not been implemented by [HeadsetControl](https://github.com/Sapd/HeadsetControl/).
-![Screenshot of the GUI with a Corsair Void Pro Wireless](https://i.imgur.com/xALkNjr.jpg)
+![image](https://github.com/nicola02nb/HeadsetControl-GUI/assets/61830443/ce6a9628-4705-4a79-a262-8c43db2c92b0)
Here you can adjust all settings supported by your headset.
-In my experience, these changes persist even after rebooting the system or turning the headset off.
-If you have a wired headset and are finished changing settings, you can close the GUI and call it day. Yay!
+Changes may or may not persist even after rebooting the system or turning the headset off(It depends on how headsets stores their own settings).
If you have a wireless headset with support for battery levels, you can also minimize HeadsetControl-GUI to the system tray.
-![HeadsetControl-GUI in the system tray](https://i.imgur.com/83Apn66.jpg)
+![image](https://github.com/nicola02nb/HeadsetControl-GUI/assets/61830443/ea327c0a-e39a-4035-aa99-bc6325724571)
-That way, you will be able to see the battery status at a glance and get a reminder when the batteries of your headset run low (below 30%).
+That way, you will be able to see the battery status at a glance and get a reminder when the batteries of your headset run low (below 15%).
Hovering over the tray icon will show you the current battery percentage. You can also right-click the tray icon to bring up a context menu with quick access to the light control. You can also open or completely close the GUI through the context menu.
-![The tray icon context menu](https://i.imgur.com/2IWhbfa.jpg)
+![image](https://github.com/nicola02nb/HeadsetControl-GUI/assets/61830443/0213a37c-806c-44d5-b8d7-5cc6b5d69407)
-## Performance
+### Performance
While the concept of calling another app for every single interaction has some inherit overhead, HeadsetControl-GUI is very light on ressources.
-Being open in the background, HeadsetControl-GUI consists of a single process that uses virtually no CPU time and less than 8MB of system memory.
-
-![Screenshot of the background task in task manager](https://i.imgur.com/3PaxKF6.jpg)
+Being open in the background, HeadsetControl-GUI consists of a single process that uses virtually no CPU time and about 8-10MB of system memory.
+![image](https://github.com/user-attachments/assets/3171e62d-8a0c-49b6-88bd-e5b03393c7fe)
## Building from source
-To build HeadsetControl-GUI from source, you have to have a proper QT-ready development environment.
-I developed, built and tested the program with Qt 6.0.3, though there's no apparent reason why it wouldn't work with older or newer versions of Qt.
-Clone the source code, import the project into Qt creator or your favourite IDE and build it.
-
-## Support for other platforms
-I haven't used any platform-specific code, so generally, you should be able to build and run this app on Linux or MacOS just fine.
-I haven't taken the time to build and test on neither Linux nor MacOS (yet), so I can't make any definitive claims on what is supported and what isn't.
-If you are on Linux or Mac and try to build the app, I'd be happy to hear if it did or didn't work.
+To build HeadsetControl-GUI from source, you have to have a proper QT-ready development environment.
+I developed, built and tested the program with Qt 6.7.0 and [Qt Creator](https://www.qt.io/product/development-tools) as IDE.
+Clone the source code, import the project into [Qt Creator](https://www.qt.io/product/development-tools) or your favourite IDE and build it.
## Additional information
-This was written in a day and I'm aware the code is pretty ugly. I plan to fix this and add some additional functionality like persistent settings later down the road.
+This software comes with no warranty whatsoever.
+It's not properly tested for memory leakage and may or may not work with configurations other than those I've tested.
-This software comes with no warranty whatsoever. It's not properly tested for memory leakage and may or may not work with configurations other than those I've tested.
+**Disclaimer**:
+This program is in no way affiliated with Sapd or HeadsetControl.
+All issues regarding the functionality of HeadsetControl (like compatiblity with devices) are beyond the scope of this project.
diff --git a/main.cpp b/main.cpp
deleted file mode 100644
index fd2c98e..0000000
--- a/main.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "mainwindow.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-int main(int argc, char *argv[])
-{
- QApplication a(argc, argv);
- MainWindow w;
- w.resize(10, 10);
- w.show();
-
- return a.exec();
-}
diff --git a/mainwindow.cpp b/mainwindow.cpp
deleted file mode 100644
index 63c8394..0000000
--- a/mainwindow.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-#include "mainwindow.h"
-#include "ui_mainwindow.h"
-#include
-#include
-#include
-#include
-
-MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::MainWindow)
-{
- ui->setupUi(this);
-
- tray->setIcon(QIcon(":/icons/headphones-inv.png"));
- tray->show();
- tray->setToolTip("HeadsetControl");
-
- QMenu *menu = new QMenu(nullptr);
- menu->addAction("Show", this, SLOT(show()));
- menu->addAction("Turn Lights On", this, SLOT(on_onButton_clicked()));
- menu->addAction("Turn Lights Off", this, SLOT(on_offButton_clicked()));
- menu->addAction("Exit", this, SLOT(close()));
-
- tray->setContextMenu(menu);
-
- connect(tray, SIGNAL(DoubleClick), this, SLOT(show()));
-
- tray->connect(tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this,
- SLOT(RestoreWindowTrigger(QSystemTrayIcon::ActivationReason)));
-
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList() << QString("-c?"));
-
- proc->waitForFinished();
- QByteArray strdata = proc->readAllStandardOutput();
- QString supportedParams = strdata;
- //supportedParams = "sbnlimvr"; //Uncomment this to enable all "modules"
-
- if (supportedParams == "") {
- ui->notSupportedFrame->setHidden(false);
- ui->sidetoneFrame->setHidden(true);
- ui->batteryFrame->setHidden(true);
- ui->lightFrame->setHidden(true);
- ui->inactivityFrame->setHidden(true);
- ui->voicepromptFrame->setHidden(true);
- ui->rotateFrame->setHidden(true);
- }
- else {
- ui->notSupportedFrame->setHidden(true);
-
- if (supportedParams.contains("s")){
- ui->sidetoneFrame->setHidden(false);
- qDebug() << "Sidetone supported";
- }
- else ui->sidetoneFrame->setHidden(true);
-
- if (supportedParams.contains("b")){
- ui->batteryFrame->setHidden(false);
-
- QTimer *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(setBatteryStatus()));
- timer->start(300000);
- this->setBatteryStatus();
- qDebug() << "Battery percentage supported";
- }
- else ui->batteryFrame->setHidden(true);
-
- if (supportedParams.contains("l")){
- ui->lightFrame->setHidden(false);
- qDebug() << "Light control supported";
- }
- else ui->lightFrame->setHidden(true);
- if (supportedParams.contains("i")){
- ui->inactivityFrame->setHidden(false);
- qDebug() << "Inactivity timer supported";
- }
- else ui->inactivityFrame->setHidden(true);
- if (supportedParams.contains("v")){
- ui->voicepromptFrame->setHidden(false);
- qDebug() << "Voice prompt control supported";
- }
- else ui->voicepromptFrame->setHidden(true);
- if (supportedParams.contains("r")){
- ui->rotateFrame->setHidden(false);
- qDebug() << "Rotate to mute supported";
- }
- else ui->rotateFrame->setHidden(true);
- }
-}
-
-MainWindow::~MainWindow()
-{
- delete ui;
-}
-
-void MainWindow::on_onButton_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 1")
- << QString("-cl 1")
- );
- proc->waitForFinished();
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_offButton_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 0")
- << QString("-cl 0")
- );
- proc->waitForFinished();
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_voiceOnButton_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 1")
- << QString("-cv 1")
- );
- proc->waitForFinished();
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_voiceOffButton_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 0")
- << QString("-cv 0")
- );
- proc->waitForFinished();
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_sideToneApply_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 1")
- << QString("-s" + QString::number(ui->sidetoneSlider->sliderPosition()))
- );
- proc->waitForFinished();
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_sideToneOff_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 0")
- << QString("-s 0")
- );
- proc->waitForFinished();
- ui->sidetoneSlider->setValue(0);
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_inactivityOffButton_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 0")
- << QString("-i 0")
- );
- proc->waitForFinished();
- ui->sidetoneSlider->setValue(0);
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_inactivityApplyButton_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 1")
- << QString("-i" + QString::number(ui->inactivitySlider->sliderPosition()))
- );
- proc->waitForFinished();
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_rotateOn_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 1")
- << QString("-r 1")
- );
- proc->waitForFinished();
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::on_rotateOff_clicked()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-n 0")
- << QString("-r 0")
- );
- proc->waitForFinished();
- //qDebug() << proc->readAllStandardError();
-}
-
-void MainWindow::setBatteryStatus()
-{
- QProcess *proc = new QProcess();
- proc->start("headsetcontrol", QStringList()
- << QString("-cb")
- );
- proc->waitForFinished();
- QString batteryStatus = proc->readAllStandardOutput();
- //qDebug() << proc->readAllStandardError();
-
- if (batteryStatus == "-2"){
- ui->batteryPercentage->setText("Headset Off");
- tray->setToolTip("HeadsetControl \r\nHeadset Off");
- }
- else if (batteryStatus == "-1") {
- ui->batteryPercentage->setText("Headset Charging");
- tray->setToolTip("HeadsetControl \r\nBattery Charging");
- tray->setIcon(QIcon(":/icons/battery-charging-inv.png"));
- }
- else {
- ui->batteryPercentage->setText(batteryStatus);
- tray->setToolTip("HeadsetControl \r\nBattery: " + batteryStatus + "%");
- if (batteryStatus.toInt() >= 70){
- tray->setIcon(QIcon(":/icons/battery-level-full-inv.png"));
- notified = false;
- }
- else if (batteryStatus.toInt() >= 30) {
- tray->setIcon(QIcon(":/icons/battery-medium-inv.png"));
- notified = false;
- }
- else {
- tray->setIcon(QIcon(":/icons/battery-low-inv.png"));
- if (!notified){
- tray->showMessage("Battery Alert!", "The battery of your headset is running low", QIcon(":/icons/battery-low-inv.png"));
- notified = true;
- }
- }
- }
-}
-
-void MainWindow::changeEvent(QEvent* e)
-{
- switch (e->type())
- {
- case QEvent::LanguageChange:
- this->ui->retranslateUi(this);
- break;
- case QEvent::WindowStateChange:
- {
- if (this->windowState() & Qt::WindowMinimized)
- {
- QTimer::singleShot(0, this, SLOT(hide()));
- }
-
- break;
- }
- default:
- break;
- }
-
- QMainWindow::changeEvent(e);
-}
-
-void MainWindow::RestoreWindowTrigger(QSystemTrayIcon::ActivationReason RW)
-{
- if(RW == QSystemTrayIcon::DoubleClick)
- {
- show();
- activateWindow();
- raise();
- }
-}
diff --git a/mainwindow.h b/mainwindow.h
deleted file mode 100644
index 8570f53..0000000
--- a/mainwindow.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class MainWindow; }
-QT_END_NAMESPACE
-
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
-
-public:
- MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
-
- bool notified = false;
- QSystemTrayIcon *tray = new QSystemTrayIcon(this);
-
-private slots:
- void changeEvent(QEvent *e);
-
- void RestoreWindowTrigger(QSystemTrayIcon::ActivationReason RW);
-
- void on_onButton_clicked();
-
- void on_offButton_clicked();
-
- void on_voiceOnButton_clicked();
-
- void on_voiceOffButton_clicked();
-
- void on_sideToneApply_clicked();
-
- void on_sideToneOff_clicked();
-
- void on_inactivityOffButton_clicked();
-
- void on_inactivityApplyButton_clicked();
-
- void on_rotateOn_clicked();
-
- void on_rotateOff_clicked();
-
- void setBatteryStatus();
-
-private:
- Ui::MainWindow *ui;
-};
-#endif // MAINWINDOW_H
diff --git a/mainwindow.ui b/mainwindow.ui
deleted file mode 100644
index 2224440..0000000
--- a/mainwindow.ui
+++ /dev/null
@@ -1,689 +0,0 @@
-
-
- MainWindow
-
-
-
- 0
- 0
- 510
- 647
-
-
-
-
- 0
- 0
-
-
-
- HeadsetControl - GUI
-
-
-
- :/icons/headphones.png:/icons/headphones.png
-
-
- background-color: rgb(44, 44, 44);
-color: rgb(208, 208, 208);
-font: 87 10pt "Segoe UI Black";
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
- QLabel {
- min-width: 120px;
- max-width: 120px;
-}
-
-QPushButton {
- border-width: 1px;
- border-color: rgb(200, 200, 200);
- border-style: inset;
- border-radius: 5px;
-}
-.QFrame {
- border-radius: 5px;
- border-width: 1px;
- border-style: solid;
- border-color: rgb(200, 200, 200);
-}
-
-
- -
-
-
-
- 0
- 0
-
-
-
- QLabel {
-min-width: 400px;
-max-width: 400px;
-}
-
-
-
-
-
-
-
- 400
- 0
-
-
-
-
- 400
- 16777215
-
-
-
- HeadsetControl couldn't find any compatible headsets. :(
-
-
- Qt::AlignCenter
-
-
-
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
-
-
-
-
- 6
-
-
- 9
-
-
- 9
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 120
- 0
-
-
-
-
- 120
- 16777215
-
-
-
- Battery:
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
-
- 200
- 16777215
-
-
-
- QLabel {
-min-width: 200px;
-max-width: 200px;
-}
-
-
- No compatible Device found!
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
- 120
- 0
-
-
-
-
- 120
- 16777215
-
-
-
- Lights:
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
-
- -
-
-
-
- 120
- 0
-
-
-
- RGB ON
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 120
- 0
-
-
-
- RGB OFF
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
- 120
- 0
-
-
-
- Sidetone Level:
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
-
- -
-
-
- QLayout::SetDefaultConstraint
-
-
-
-
-
- false
-
-
- Drag to adjust Sidetone Level
-
-
- 128
-
-
- 16
-
-
- Qt::Horizontal
-
-
- QSlider::TicksBelow
-
-
- 16
-
-
-
- -
-
-
-
-
-
- Quiet
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Qt::LeftToRight
-
-
- Loud
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
-
- -
-
-
-
-
-
-
- 120
- 0
-
-
-
- Off
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 120
- 0
-
-
-
- Apply
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
-
-
-
- 120
- 10
-
-
-
-
- 120
- 16777215
-
-
-
- Voice Prompts:
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
-
- -
-
-
-
-
-
-
- 120
- 0
-
-
-
- Voice On
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 120
- 0
-
-
-
- Voice Off
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
- 120
- 0
-
-
-
- Inactivity Timer:
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
-
- -
-
-
-
-
-
- 1
-
-
- 90
-
-
- Qt::Horizontal
-
-
- QSlider::TicksBelow
-
-
- 10
-
-
-
- -
-
-
-
-
-
- 1 Minute
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- 90 Minutes
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
-
- -
-
-
-
-
-
-
- 120
- 0
-
-
-
- Off
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 120
- 0
-
-
-
- Apply
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
-
- Rotate to mute:
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
-
- -
-
-
- Rotate-to-Mute On
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Rotate-to-Mute Off
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/DataTypes/device.cpp b/src/DataTypes/device.cpp
new file mode 100644
index 0000000..68449f8
--- /dev/null
+++ b/src/DataTypes/device.cpp
@@ -0,0 +1,305 @@
+#include "device.h"
+#include
+#include
+#include
+#include
+#include
+
+Battery::Battery(){
+
+}
+
+Battery::Battery(QString stat, int lev){
+ status=stat;
+ level=lev;
+}
+
+Equalizer::Equalizer(){
+
+}
+
+Equalizer::Equalizer(int bands, int baseline, double step, int min, int max){
+ bands_number=bands;
+ band_baseline=baseline;
+ band_min=min;
+ band_step=step;
+ band_max=max;
+}
+
+Device::Device(){
+
+}
+
+Device::Device(const QJsonObject& jsonObj, QString jsonData){
+ connected=jsonObj["status"].toString()=="success";
+
+ device=jsonObj["device"].toString();
+ vendor=jsonObj["vendor"].toString();
+ product=jsonObj["product"].toString();
+ id_vendor=jsonObj["id_vendor"].toString();
+ id_product=jsonObj["id_product"].toString();
+
+ QJsonArray caps=jsonObj["capabilities"].toArray();
+ for (const QJsonValue &value : caps) {
+ capabilities.insert(value.toString());
+ }
+ if (capabilities.contains("CAP_BATTERY_STATUS")){
+ QJsonObject jEq=jsonObj["battery"].toObject();
+ battery=Battery(jEq["status"].toString(), jEq["level"].toInt());
+ }
+ if (capabilities.contains("CAP_CHATMIX_STATUS")){
+ chatmix=jsonObj["chatmix"].toInt();
+ }
+
+ if (capabilities.contains("CAP_EQUALIZER_PRESET")){
+ if (jsonObj.contains("equalizer_presets") && jsonObj["equalizer_presets"].isObject()) {
+ QJsonObject equalizerPresets = jsonObj["equalizer_presets"].toObject();
+
+ // Parse the original JSON string to find the order of keys
+ QRegularExpression re("\"(\\w+)\":\\s*\\[");
+ QRegularExpressionMatchIterator i = re.globalMatch(jsonData);
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+ QString presetName = match.captured(1);
+ if (equalizerPresets.contains(presetName)) {
+ EqualizerPreset preset;
+ preset.name = presetName;
+
+ QJsonArray valuesArray = equalizerPresets[presetName].toArray();
+ for (const QJsonValue& value : valuesArray) {
+ preset.values.append(value.toDouble());
+ }
+
+ presets_list.append(preset);
+ }
+ }
+ }
+ }
+ if (capabilities.contains("CAP_EQUALIZER")){
+ QJsonObject jEq=jsonObj["equalizer"].toObject();
+ if(!jEq.isEmpty()){
+ equalizer=Equalizer(jEq["bands"].toInt(), jEq["baseline"].toInt(), jEq["step"].toDouble(), jEq["min"].toInt(), jEq["max"].toInt());
+ equalizer_curve=QVector(equalizer.bands_number, equalizer.band_baseline);
+ }
+ }
+}
+
+//Helper functions
+bool Device::operator!=(const Device &d) const {
+ return this->id_vendor!=d.id_vendor || this->id_product!=d.id_product;
+}
+
+bool Device::operator==(const Device &d) const {
+ return this->id_vendor==d.id_vendor && this->id_product==d.id_product;
+}
+
+bool Device::operator==(const Device* d) const {
+ return this->id_vendor==d->id_vendor && this->id_product==d->id_product;
+}
+
+void Device::updateDevice(const Device* new_device){
+ this->battery=new_device->battery;
+ this->chatmix=new_device->chatmix;
+}
+
+void Device::updateDevice(const QList& new_device_list){
+ for (int i = 0; i < new_device_list.length(); ++i) {
+ if(this!=new_device_list.at(i)){
+ this->battery=new_device_list.at(i)->battery;
+ this->chatmix=new_device_list.at(i)->chatmix;
+ break;
+ }
+ }
+}
+
+QJsonObject Device::toJson() const {
+ QJsonObject json;
+ json["device"] = device;
+ json["vendor"] = vendor;
+ json["product"] = product;
+ json["id_vendor"] = id_vendor;
+ json["id_product"] = id_product;
+
+ json["lights"] = lights;
+ json["sidetone"] = sidetone;
+ json["voice_prompts"] = voice_prompts;
+ json["inactive_time"] = inactive_time;
+ json["equalizer_preset"] = equalizer_preset;
+ json["equalizer_curve"] = QJsonArray::fromVariantList(QVariantList(equalizer_curve.begin(), equalizer_curve.end()));
+ json["volume_limiter"] = volume_limiter;
+ json["rotate_to_mute"] = rotate_to_mute;
+ json["mic_mute_led_brightness"] = mic_mute_led_brightness;
+ json["mic_volume"] = mic_volume;
+ json["bt_when_powered_on"] = bt_when_powered_on;
+ json["bt_call_volume"] = bt_call_volume;
+
+ return json;
+}
+
+Device Device::fromJson(const QJsonObject& json) {
+ Device device;
+ device.device = json["device"].toString();
+ device.vendor = json["vendor"].toString();
+ device.product = json["product"].toString();
+ device.id_vendor = json["id_vendor"].toString();
+ device.id_product = json["id_product"].toString();
+
+ device.lights = json["lights"].toInt();
+ device.sidetone = json["sidetone"].toInt();
+ device.voice_prompts = json["voice_prompts"].toInt();
+ device.inactive_time = json["inactive_time"].toInt();
+ device.equalizer_preset = json["equalizer_preset"].toInt();
+
+ QJsonArray curveArray = json["equalizer_curve"].toArray();
+ for (const auto& value : curveArray) {
+ device.equalizer_curve.append(value.toInt());
+ }
+
+ device.volume_limiter = json["volume_limiter"].toInt();
+ device.rotate_to_mute = json["rotate_to_mute"].toInt();
+ device.mic_mute_led_brightness = json["mic_mute_led_brightness"].toInt();
+ device.mic_volume = json["mic_volume"].toInt();
+ device.bt_when_powered_on = json["bt_when_powered_on"].toInt();
+ device.bt_call_volume = json["bt_call_volume"].toInt();
+
+ return device;
+}
+
+//HC rleated functions
+QString sendCommand(const QStringList& args_list){
+ QProcess *proc = new QProcess();
+ QStringList args = QStringList() << QString("--output") << QString("JSON");
+ //args << QString("--test-device"); //Uncomment this to enable all "modules"
+ args << args_list;
+
+ proc->start("headsetcontrol", args);
+ proc->waitForFinished();
+ QString output=proc->readAllStandardOutput();
+ //qDebug() << args;
+ //qDebug() << output;
+ return output;
+}
+
+Action sendAction(const QStringList& args_list){
+ QString output=sendCommand(args_list);
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(output.toUtf8());
+ QJsonObject jsonInfo = jsonDoc.object();
+ QJsonArray actions = jsonInfo["actions"].toArray();
+ Action action;
+ if(!actions.isEmpty()){
+ QJsonObject jaction = actions[0].toObject();
+
+ action.device=jaction["device"].toString();
+ action.capability=jaction["capability"].toString();
+ action.status=jaction["status"].toString();
+ action.error_message=jaction["error_message"].toString();
+ }
+
+ return action;
+}
+
+QVersionNumber getHCVersion(){
+ QStringList args=QStringList() << QString("--output") << QString("JSON");
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(sendCommand(args).toUtf8());
+ QJsonObject jsonInfo=jsonDoc.object();
+ return QVersionNumber::fromString(jsonInfo["version"].toString());
+}
+
+QList getDevices(){
+ QList devices;
+
+ return devices;
+}
+
+QList mergeDevices(QList connectedDevices, const QList& savedDevices) {
+ for (Device* savedDevice : savedDevices)
+ {
+ bool deviceFound = false;
+ for (Device* connectedDevice : connectedDevices)
+ {
+ if (connectedDevice->id_vendor==savedDevice->id_vendor && connectedDevice->id_product==savedDevice->id_product)
+ {
+ // Update the connected device with saved device's information
+ connectedDevice->lights = savedDevice->lights;
+ connectedDevice->sidetone = savedDevice->sidetone;
+ connectedDevice->voice_prompts = savedDevice->voice_prompts;
+ connectedDevice->inactive_time = savedDevice->inactive_time;
+
+ connectedDevice->equalizer_preset = savedDevice->equalizer_preset;
+ connectedDevice->equalizer_curve = savedDevice->equalizer_curve;
+ connectedDevice->volume_limiter = savedDevice->volume_limiter;
+
+ connectedDevice->rotate_to_mute = savedDevice->rotate_to_mute;
+ connectedDevice->mic_mute_led_brightness = savedDevice->mic_mute_led_brightness;
+ connectedDevice->mic_volume = savedDevice->mic_volume;
+
+ connectedDevice->bt_when_powered_on = savedDevice->bt_when_powered_on;
+ connectedDevice->bt_call_volume = savedDevice->bt_call_volume;
+
+ deviceFound = true;
+ break;
+ }
+ }
+
+ if (!deviceFound)
+ {
+ // If the device wasn't found in saved devices, add it
+ connectedDevices.append(new Device(*savedDevice));
+ }
+ }
+ return connectedDevices;
+}
+
+QList getSavedDevices(const QString& file_name){
+ return deserializeDevices(file_name);
+}
+
+QList getConnectedDevices(){
+ QStringList args=QStringList() << QString("--output") << QString("JSON");
+ QString output = sendCommand(args);
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(output.toUtf8());
+ QJsonObject jsonInfo = jsonDoc.object();
+
+ int device_number = jsonInfo["device_count"].toInt();
+ QList devices;
+ QJsonArray jsonDevices = jsonInfo["devices"].toArray();
+ if(!jsonDoc.isNull()){
+ for (int i = 0; i < device_number; ++i) {
+ devices.append(new Device(jsonDevices[i].toObject(), output));
+ }
+ }
+
+ return devices;
+}
+
+void serializeDevices(const QList& devices, const QString& filename) {
+ QJsonArray jsonArray;
+ for (const auto* device : devices) {
+ jsonArray.append(device->toJson());
+ }
+
+ QJsonDocument doc(jsonArray);
+ QFile file(filename);
+ if (file.open(QIODevice::WriteOnly)) {
+ file.write(doc.toJson());
+ file.close();
+ }
+}
+
+QList deserializeDevices(const QString& filename) {
+ QList devices;
+ QFile file(filename);
+ if (file.open(QIODevice::ReadOnly)) {
+ QByteArray data = file.readAll();
+ QJsonDocument doc = QJsonDocument::fromJson(data);
+ QJsonArray jsonArray = doc.array();
+
+ for (const auto& value : jsonArray) {
+ Device* device = new Device(Device::fromJson(value.toObject()));
+ devices.append(device);
+ }
+
+ file.close();
+ }
+ return devices;
+}
diff --git a/src/DataTypes/device.h b/src/DataTypes/device.h
new file mode 100644
index 0000000..bb00a61
--- /dev/null
+++ b/src/DataTypes/device.h
@@ -0,0 +1,104 @@
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include
+#include
+#include
+
+class Action{
+public:
+ QString capability;
+ QString device;
+ QString status;
+ QString error_message;
+};
+
+class Battery{
+public:
+ Battery();
+ Battery(QString stat, int lev);
+ QString status = "BATTERY_UNAVAILABLE";
+ int level = 0;
+};
+
+class EqualizerPreset{
+public:
+ QString name;
+ QList values;
+};
+
+class Equalizer{
+public:
+ Equalizer();
+ Equalizer(int bands, int baseline, double step, int min, int max);
+
+ int bands_number = 0;
+ int band_baseline = 0;
+ double band_step = 0;
+ int band_min = 0;
+ int band_max = 0;
+};
+
+class Device
+{
+public:
+ Device();
+ Device(const QJsonObject& jsonObj, QString jsonData);
+
+ //Status
+ bool connected = false;
+
+ //Basic info
+ QString device;
+ QString vendor;
+ QString product;
+ QString id_vendor;
+ QString id_product;
+ QSet capabilities;
+
+ //Info to get from json and display
+ Battery battery;
+ int chatmix = 65;
+ QList presets_list;
+ Equalizer equalizer;
+ bool notification_sound=false;
+
+ //Info to set with gui and to save
+ int lights=-1;
+ int sidetone=-1;
+ int voice_prompts=-1;
+ int inactive_time=-1;
+ int equalizer_preset=-1;
+ QList equalizer_curve;
+ int volume_limiter=-1;
+ int rotate_to_mute=-1;
+ int mic_mute_led_brightness=-1;
+ int mic_volume=-1;
+ int bt_when_powered_on=-1;
+ int bt_call_volume=-1;
+
+ bool operator!=(const Device& d) const;
+ bool operator==(const Device &d) const;
+ bool operator==(const Device* d) const;
+
+ void updateDevice(const Device* new_device);
+ void updateDevice(const QList& new_device_list);
+
+ QJsonObject toJson() const;
+ static Device fromJson(const QJsonObject& json);
+};
+
+QString sendCommand(const QStringList& args_list);
+Action sendAction(const QStringList& args_list);
+
+QVersionNumber getHCVersion();
+
+QList getDevices();
+QList mergeDevices(QList connectedDevices, const QList& savedDevices);
+QList getSavedDevices(const QString& file_name);
+QList getConnectedDevices();
+
+void serializeDevices(const QList& devices, const QString& filename);
+QList deserializeDevices(const QString& filename);
+
+#endif // DEVICE_H
diff --git a/src/DataTypes/settings.cpp b/src/DataTypes/settings.cpp
new file mode 100644
index 0000000..871af4e
--- /dev/null
+++ b/src/DataTypes/settings.cpp
@@ -0,0 +1,52 @@
+#include "settings.h"
+#include
+#include
+#include
+
+Settings::Settings() {}
+
+Settings loadSettingsFromFile(const QString& filename){
+ Settings s;
+
+ QFile file(filename);
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning("Couldn't open save file.");
+ return s;
+ }
+
+ QByteArray saveData = file.readAll();
+ file.close();
+
+ QJsonDocument doc(QJsonDocument::fromJson(saveData));
+ QJsonObject json = doc.object();
+
+ if (json.contains("runOnStartup")) {
+ s.runOnstartup = json["runOnStartup"].toBool();
+ }
+ if (json.contains("batteryLowThreshold")) {
+ s.batteryLowThreshold = json["batteryLowThreshold"].toInt();
+ }
+ if (json.contains("msecUpdateIntervalTime")) {
+ s.msecUpdateIntervalTime = json["msecUpdateIntervalTime"].toInt();
+ }
+
+ return s;
+}
+
+void saveSettingstoFile(const Settings& settings, const QString& filename){
+ QJsonObject json;
+ json["runOnStartup"] = settings.runOnstartup;
+ json["batteryLowThreshold"] = settings.batteryLowThreshold;
+ json["msecUpdateIntervalTime"] = settings.msecUpdateIntervalTime;
+
+ QJsonDocument doc(json);
+ QFile file(filename);
+
+ if (!file.open(QIODevice::WriteOnly)) {
+ qWarning("Couldn't open save file.");
+ }
+
+ file.write(doc.toJson());
+ file.close();
+}
diff --git a/src/DataTypes/settings.h b/src/DataTypes/settings.h
new file mode 100644
index 0000000..5554512
--- /dev/null
+++ b/src/DataTypes/settings.h
@@ -0,0 +1,19 @@
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include
+
+class Settings
+{
+public:
+ Settings();
+
+ bool runOnstartup=false;
+ int batteryLowThreshold=15;
+ int msecUpdateIntervalTime=30000;
+};
+
+Settings loadSettingsFromFile(const QString& filename);
+void saveSettingstoFile(const Settings& settings, const QString& filename);
+
+#endif // SETTINGS_H
diff --git a/src/Resources/appicon.rc b/src/Resources/appicon.rc
new file mode 100644
index 0000000..d2559c1
--- /dev/null
+++ b/src/Resources/appicon.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "headphones-exe.ico"
diff --git a/src/Resources/headphones-exe.ico b/src/Resources/headphones-exe.ico
new file mode 100644
index 0000000..1b7b622
Binary files /dev/null and b/src/Resources/headphones-exe.ico differ
diff --git a/icons.qrc b/src/Resources/icons.qrc
similarity index 100%
rename from icons.qrc
rename to src/Resources/icons.qrc
diff --git a/icons/battery-charging-inv.png b/src/Resources/icons/battery-charging-inv.png
similarity index 100%
rename from icons/battery-charging-inv.png
rename to src/Resources/icons/battery-charging-inv.png
diff --git a/icons/battery-charging.png b/src/Resources/icons/battery-charging.png
similarity index 100%
rename from icons/battery-charging.png
rename to src/Resources/icons/battery-charging.png
diff --git a/icons/battery-level-full-inv.png b/src/Resources/icons/battery-level-full-inv.png
similarity index 100%
rename from icons/battery-level-full-inv.png
rename to src/Resources/icons/battery-level-full-inv.png
diff --git a/icons/battery-level-full.png b/src/Resources/icons/battery-level-full.png
similarity index 100%
rename from icons/battery-level-full.png
rename to src/Resources/icons/battery-level-full.png
diff --git a/icons/battery-low-inv.png b/src/Resources/icons/battery-low-inv.png
similarity index 100%
rename from icons/battery-low-inv.png
rename to src/Resources/icons/battery-low-inv.png
diff --git a/icons/battery-low.png b/src/Resources/icons/battery-low.png
similarity index 100%
rename from icons/battery-low.png
rename to src/Resources/icons/battery-low.png
diff --git a/icons/battery-medium-inv.png b/src/Resources/icons/battery-medium-inv.png
similarity index 100%
rename from icons/battery-medium-inv.png
rename to src/Resources/icons/battery-medium-inv.png
diff --git a/icons/battery-medium.png b/src/Resources/icons/battery-medium.png
similarity index 100%
rename from icons/battery-medium.png
rename to src/Resources/icons/battery-medium.png
diff --git a/icons/headphones-inv.png b/src/Resources/icons/headphones-inv.png
similarity index 100%
rename from icons/headphones-inv.png
rename to src/Resources/icons/headphones-inv.png
diff --git a/icons/headphones.png b/src/Resources/icons/headphones.png
similarity index 100%
rename from icons/headphones.png
rename to src/Resources/icons/headphones.png
diff --git a/src/Resources/tr/HeadsetControl_GUI_en_US.qm b/src/Resources/tr/HeadsetControl_GUI_en_US.qm
new file mode 100644
index 0000000..da379f7
Binary files /dev/null and b/src/Resources/tr/HeadsetControl_GUI_en_US.qm differ
diff --git a/src/Resources/tr/HeadsetControl_GUI_en_US.ts b/src/Resources/tr/HeadsetControl_GUI_en_US.ts
new file mode 100644
index 0000000..87a833a
--- /dev/null
+++ b/src/Resources/tr/HeadsetControl_GUI_en_US.ts
@@ -0,0 +1,453 @@
+
+
+
+
+ MainWindow
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ dialogInfo
+
+
+
+
+
+
+
+ loaddevicewindow
+
+
+
+
+
+
+
+
+
+
+
+
+ settingswindow
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Battery low treshold:
+
+
+
+
+
+
+
+
diff --git a/src/Resources/tr/HeadsetControl_GUI_it_IT.qm b/src/Resources/tr/HeadsetControl_GUI_it_IT.qm
new file mode 100644
index 0000000..a9cf69f
Binary files /dev/null and b/src/Resources/tr/HeadsetControl_GUI_it_IT.qm differ
diff --git a/src/Resources/tr/HeadsetControl_GUI_it_IT.ts b/src/Resources/tr/HeadsetControl_GUI_it_IT.ts
new file mode 100644
index 0000000..40c9ce5
--- /dev/null
+++ b/src/Resources/tr/HeadsetControl_GUI_it_IT.ts
@@ -0,0 +1,456 @@
+
+
+
+
+ MainWindow
+
+
+
+
+
+
+
+
+ HeadsetControl non è riuscito a trovare delle cuffie funizionanti o compatibili. :(
+
+
+
+
+ <html><head/><body><p>Dispositivo:<br/>Distributore:<br/>Modello:</p></body></html>
+
+
+
+
+ Nessuna informazione sul dipositivo
+
+
+
+
+ Batteria:
+
+
+
+
+ Nessun dispositivo compatibile è stato trovato!
+
+
+
+
+ Altro
+
+
+
+
+ Luci:
+
+
+
+
+ RGB OFF
+
+
+
+
+ RGB ON
+
+
+
+
+ Tono Laterale:
+
+
+
+
+ Trascina per regolare il Tono Laterale
+
+
+
+
+ Silenzioso (Spento)
+
+
+
+
+
+ Forte
+
+
+
+
+ Istruzioni Vocali:
+
+
+
+
+ Voce Accesa
+
+
+
+
+ Voce Spenta
+
+
+
+
+ Suono di Notifica:
+
+
+
+
+ Prova 0
+
+
+
+
+ Prova 1
+
+
+
+
+ Tempo di Inattività:
+
+
+
+
+ 0 Minuti (Spento)
+
+
+
+
+ 90 Minuti
+
+
+
+
+ Chatmix:
+
+
+
+
+ Nessun valore
+
+
+
+
+ Equalizzatore
+
+
+
+
+ Preset Equalizzatore:
+
+
+
+
+ Equalizzatore:
+
+
+
+
+ Applica Equalizzatore
+
+
+
+
+ Limitatore Volume:
+
+
+
+
+ Limitatore Spento
+
+
+
+
+ Limitatore Acceso
+
+
+
+
+ Microfono
+
+
+
+
+ Ruota per mutare:
+
+
+
+
+ Spento
+
+
+
+
+ Acceso
+
+
+
+
+ Luminosità microfono mutato:
+
+
+
+
+ Basso (Spento)
+
+
+
+
+ Alto
+
+
+
+
+ Volume microfono:
+
+
+
+
+ Basso
+
+
+
+
+ Bluetooth
+
+
+
+
+ Bluetooth quando accese:
+
+
+
+
+ Bluetooth Spento
+
+
+
+
+ Bluetooth Acceso
+
+
+
+
+ Bluetoot volume chiamata:
+
+
+
+
+ BT e PC
+
+
+
+
+ PC -12dB
+
+
+
+
+ Solo BT
+
+
+
+
+ File
+
+
+
+
+ Aiuto
+
+
+
+
+ Controlla Aggiornamenti
+
+
+
+
+ About
+
+
+
+
+
+ Crediti
+
+
+
+
+ Carica Dispositivo
+
+
+
+
+ Impostazioni
+
+
+
+
+ Nascondi/Mostra
+
+
+
+
+ Accendi le Luci
+
+
+
+
+ Spegni le Luci
+
+
+
+
+ Esci
+
+
+
+
+ Manca headsetcontrol.exe
+
+
+
+
+ Manca headsetcontrol.exe<br>Scarica <a href='https://github.com/Sapd/HeadsetControl/releases/latest'>headsetcontrol</a> nella cartella aperta.
+
+
+
+
+ Cuffie Spente
+
+
+
+
+ HeadsetControl
+Cuffie Spente
+
+
+
+
+ % - In Carica
+
+
+
+
+ HeadsetControl
+Batteria in Carica
+
+
+
+
+ % - Batteria in scarica
+
+
+
+
+ HeadsetControl
+Batteria:
+
+
+
+
+ Attenzione Batteria!
+
+
+
+
+ La batteria delle tue cuffie è scarica
+
+
+
+
+ No informazioni sulla batteria
+
+
+
+
+ Gioco
+
+
+
+
+ Chat
+
+
+
+
+ Controlla Aggirnamenti
+
+
+
+
+
+ aggiornato
+
+
+
+
+
+ Nuova versione
+
+
+
+
+
+
+
+
+
+ <a href='https://github.com/nicola02nb/HeadsetControl-GUI'>Questa</a> è il fork della versione <a href='https://github.com/LeoKlaus/HeadsetControl-GUI'>HeadsetControl-GUI</a>.<br>Fatta da <a href='https://github.com/nicola02nb/HeadsetControl-GUI'>nicola02nb</a><br>Version:
+
+
+
+
+ Un grande ringraziamento va a:<br> - Sapd per <a href='https://github.com/Sapd/HeadsetControl'>HeadsetCoontrol</a><br> - LeoKlaus per <a href='https://github.com/LeoKlaus/HeadsetControl-GUI'>HeadsetControl-GUI</a>
+
+
+
+ dialogInfo
+
+
+
+
+
+
+
+ loaddevicewindow
+
+
+
+ Seleziona dispositivo da caricare
+
+
+
+
+ Seleziona dispositivo:
+
+
+
+ settingswindow
+
+
+
+ Impostazioni
+
+
+
+
+ Esecuzione all'avvio:
+
+
+
+
+ Soglia batteria scarica:
+
+
+
+
+ <html><head/><body><p>Intervallo di aggiornamento info (secondi):<br/>Predefinito: 30,0 secondi<br/>NON IMPOSTARE VALORI TROPPO BASSI</p></body></html>
+
+
+
diff --git a/src/Resources/translations.qrc b/src/Resources/translations.qrc
new file mode 100644
index 0000000..c246505
--- /dev/null
+++ b/src/Resources/translations.qrc
@@ -0,0 +1,6 @@
+
+
+ tr/HeadsetControl_GUI_en_US.qm
+ tr/HeadsetControl_GUI_it_IT.qm
+
+
diff --git a/src/UI/dialoginfo.cpp b/src/UI/dialoginfo.cpp
new file mode 100644
index 0000000..4a44966
--- /dev/null
+++ b/src/UI/dialoginfo.cpp
@@ -0,0 +1,25 @@
+#include "dialoginfo.h"
+#include "ui_dialoginfo.h"
+
+DialogInfo::DialogInfo(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::dialogInfo)
+{
+ setModal(true);
+ ui->setupUi(this);
+}
+
+DialogInfo::~DialogInfo()
+{
+ delete ui;
+}
+
+void DialogInfo::setTitle(const QString& title)
+{
+ this->setWindowTitle(title);
+}
+
+void DialogInfo::setLabel(const QString& text)
+{
+ ui->label->setText(text);
+}
diff --git a/src/UI/dialoginfo.h b/src/UI/dialoginfo.h
new file mode 100644
index 0000000..10c4209
--- /dev/null
+++ b/src/UI/dialoginfo.h
@@ -0,0 +1,25 @@
+#ifndef DIALOGINFO_H
+#define DIALOGINFO_H
+
+#include
+
+namespace Ui {
+class dialogInfo;
+}
+
+class DialogInfo : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit DialogInfo(QWidget *parent = nullptr);
+ ~DialogInfo();
+
+ void setTitle(const QString& title);
+ void setLabel(const QString& text);
+
+private:
+ Ui::dialogInfo *ui;
+};
+
+#endif // DIALOGINFO_H
diff --git a/src/UI/dialoginfo.ui b/src/UI/dialoginfo.ui
new file mode 100644
index 0000000..c3db3f9
--- /dev/null
+++ b/src/UI/dialoginfo.ui
@@ -0,0 +1,143 @@
+
+
+ dialogInfo
+
+
+
+ 0
+ 0
+ 305
+ 86
+
+
+
+
+ 0
+ 0
+
+
+
+ Dialog
+
+
+
+ :/icons/headphones-inv.png:/icons/headphones-inv.png
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ true
+
+
+ Qt::TextBrowserInteraction
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Close
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ dialogInfo
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ dialogInfo
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/UI/loaddevicewindow.cpp b/src/UI/loaddevicewindow.cpp
new file mode 100644
index 0000000..e949b41
--- /dev/null
+++ b/src/UI/loaddevicewindow.cpp
@@ -0,0 +1,21 @@
+#include "loaddevicewindow.h"
+#include "ui_loaddevicewindow.h"
+
+LoaddeviceWindow::LoaddeviceWindow(const QStringList& devices, QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::loaddevicewindow)
+{
+ setModal(true);
+ ui->setupUi(this);
+
+ ui->devicelistComboBox->addItems(devices);
+}
+
+int LoaddeviceWindow::getDeviceIndex(){
+ return ui->devicelistComboBox->currentIndex();
+}
+
+LoaddeviceWindow::~LoaddeviceWindow()
+{
+ delete ui;
+}
diff --git a/src/UI/loaddevicewindow.h b/src/UI/loaddevicewindow.h
new file mode 100644
index 0000000..1dbcc21
--- /dev/null
+++ b/src/UI/loaddevicewindow.h
@@ -0,0 +1,24 @@
+#ifndef LOADDEVICEWINDOW_H
+#define LOADDEVICEWINDOW_H
+
+#include
+
+namespace Ui {
+class loaddevicewindow;
+}
+
+class LoaddeviceWindow : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit LoaddeviceWindow(const QStringList& devices, QWidget *parent = nullptr);
+ ~LoaddeviceWindow();
+
+ int getDeviceIndex();
+
+private:
+ Ui::loaddevicewindow *ui;
+};
+
+#endif // LOADDEVICEWINDOW_H
diff --git a/src/UI/loaddevicewindow.ui b/src/UI/loaddevicewindow.ui
new file mode 100644
index 0000000..cd34f27
--- /dev/null
+++ b/src/UI/loaddevicewindow.ui
@@ -0,0 +1,111 @@
+
+
+ loaddevicewindow
+
+
+
+ 0
+ 0
+ 174
+ 112
+
+
+
+
+ 0
+ 0
+
+
+
+ Select device to load
+
+
+
+ :/icons/headphones-inv.png:/icons/headphones-inv.png
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Select device:
+
+
+
+ -
+
+
+
+
+
+ 99
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ loaddevicewindow
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ loaddevicewindow
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/UI/mainwindow.cpp b/src/UI/mainwindow.cpp
new file mode 100644
index 0000000..2234ffb
--- /dev/null
+++ b/src/UI/mainwindow.cpp
@@ -0,0 +1,838 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "device.h"
+#include "dialoginfo.h"
+#include "settingswindow.h"
+#include "loaddevicewindow.h"
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
+ , ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+ this->bindEvents();
+
+ settings=loadSettingsFromFile(PROGRAM_SETTINGS_FILENAME);
+ darkMode = isOsDarkMode();
+
+ if(darkMode){
+ this->setWindowIcon(QIcon(":/icons/headphones-inv.png"));
+ trayIconPath = ":/icons/headphones-inv.png";
+ }
+ else{
+ this->setWindowIcon(QIcon(":/icons/headphones.png"));
+ trayIconPath = ":/icons/headphones.png";
+ }
+
+ tray->setIcon(QIcon(trayIconPath));
+ tray->show();
+ tray->setToolTip("HeadsetControl");
+
+ menu = new QMenu(nullptr);
+ menu->addAction(tr("Hide/Show"), this, &MainWindow::toggleWindow);
+ ledOn = menu->addAction(tr("Turn Lights On"), this, &MainWindow::onlightButton_clicked);
+ ledOff = menu->addAction(tr("Turn Lights Off"), this, &MainWindow::offlightButton_clicked);
+ menu->addAction(tr("Exit"), this, &QApplication::quit);
+
+ tray->setContextMenu(menu);
+ tray->connect(tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
+
+ this->disableFrames();
+
+ QString exe = "headsetcontrol";
+#ifdef Q_OS_WIN
+ exe = exe+".exe";
+#endif
+
+ if(!fileExists(exe)){
+ openFileExplorer(".");
+ DialogInfo* dialog=new DialogInfo(this);
+ dialog->setTitle(tr("Missing headsetcontrol"));
+ dialog->setLabel(tr("Missing headsetcontrol
"
+ "Download headsetcontrol in the opened folder."));
+ dialog->exec();
+ }
+
+ this->loadDevices();
+ if(deviceList.length() && n_connected>0){
+ this->loadDevice();
+ }
+
+ this->setMaximumHeight(this->minimumHeight());
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::bindEvents(){
+ // Tool Bar
+ connect(ui->actionSettings, &QAction::triggered, this, &MainWindow::editProgramSetting);
+ connect(ui->actionLoad_Device, &QAction::triggered, this, &MainWindow::selectDevice);
+ connect(ui->actionCheck_Updates, &QAction::triggered, this, &MainWindow::checkForUpdates);
+
+ connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::showAbout);
+ connect(ui->actionCredits, &QAction::triggered, this, &MainWindow::showCredits);
+
+ // Other Section
+ connect(ui->onlightButton, &QPushButton::clicked, this, &MainWindow::onlightButton_clicked);
+ connect(ui->offlightButton, &QPushButton::clicked, this, &MainWindow::offlightButton_clicked);
+ connect(ui->sidetoneSlider, &QSlider::sliderReleased, this, &MainWindow::sidetoneSlider_sliderReleased);
+ connect(ui->voiceOnButton, &QPushButton::clicked, this, &MainWindow::voiceOnButton_clicked);
+ connect(ui->voiceOffButton, &QPushButton::clicked, this, &MainWindow::voiceOffButton_clicked);
+ connect(ui->notification0Button, &QPushButton::clicked, this, &MainWindow::notification0Button_clicked);
+ connect(ui->notification1Button, &QPushButton::clicked, this, &MainWindow::notification1Button_clicked);
+ connect(ui->inactivitySlider, &QSlider::sliderReleased, this, &MainWindow::inactivitySlider_sliderReleased);
+
+ // Equalizer Section
+ connect(ui->equalizerPresetcomboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &MainWindow::equalizerPresetcomboBox_currentIndexChanged);
+ connect(ui->applyEqualizer, &QPushButton::clicked, this, &MainWindow::applyEqualizer_clicked);
+ connect(ui->volumelimiterOffButton, &QPushButton::clicked, this, &MainWindow::volumelimiterOffButton_clicked);
+ connect(ui->volumelimiterOnButton, &QPushButton::clicked, this, &MainWindow::volumelimiterOnButton_clicked);
+
+ // Microphone Section
+ connect(ui->muteledbrightnessSlider, &QSlider::sliderReleased, this, &MainWindow::muteledbrightnessSlider_sliderReleased);
+ connect(ui->micvolumeSlider, &QSlider::sliderReleased, this, &MainWindow::micvolumeSlider_sliderReleased);
+ connect(ui->rotateOn, &QPushButton::clicked, this, &MainWindow::rotateOn_clicked);
+ connect(ui->rotateOff, &QPushButton::clicked, this, &MainWindow::rotateOff_clicked);
+
+ // Bluetooth Section
+ connect(ui->btwhenonOffButton, &QPushButton::clicked, this, &MainWindow::btwhenonOffButton_clicked);
+ connect(ui->btwhenonOnButton, &QPushButton::clicked, this, &MainWindow::btwhenonOnButton_clicked);
+ connect(ui->btbothRadioButton, &QRadioButton::clicked, this, &MainWindow::btbothRadioButton_clicked);
+ connect(ui->btpcdbRadioButton, &QRadioButton::clicked, this, &MainWindow::btpcdbRadioButton_clicked);
+ connect(ui->btonlyRadioButton, &QRadioButton::clicked, this, &MainWindow::btonlyRadioButton_clicked);
+}
+
+void MainWindow::changeEvent(QEvent* e)
+{
+ switch (e->type()){
+ case QEvent::PaletteChange:
+ darkMode = isOsDarkMode();
+ updateIcons();
+ break;
+ case QEvent::WindowStateChange:
+ if (this->windowState()==Qt::WindowMinimized){
+ this->hide();
+ }
+ default:
+ break;
+ }
+
+ QMainWindow::changeEvent(e);
+}
+
+void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
+{
+ if(reason == QSystemTrayIcon::ActivationReason::Trigger)
+ {
+ toggleWindow();
+ }
+}
+
+void MainWindow::toggleWindow(){
+ if(this->isHidden()){
+ this->show();
+ if(firstShow){
+ checkForUpdates(firstShow);
+ firstShow = false;
+ }
+ } else{
+ this->hide();
+ }
+}
+
+bool MainWindow::isOsDarkMode(){
+ // Check if the application is using a dark palette
+ QPalette palette = QApplication::palette();
+ QColor textColor = palette.color(QPalette::WindowText);
+ QColor backgroundColor = palette.color(QPalette::Window);
+
+ // If text is brighter than background, it's likely a dark theme
+ return textColor.lightness() > backgroundColor.lightness();
+}
+
+void MainWindow::updateIcons(){
+ QString inv = "";
+ if(darkMode){
+ inv = "-inv";
+ trayIconPath.replace(".png", "-inv.png");
+ }
+ else{
+ trayIconPath.replace("-inv.png", ".png");
+ }
+
+ this->setWindowIcon(QIcon(":/icons/headphones"+inv+".png"));
+ tray->setIcon(QIcon(trayIconPath));
+}
+
+void MainWindow::disableFrames(){
+ ledOn->setEnabled(false);
+ ledOff->setEnabled(false);
+
+ ui->notSupportedFrame->setHidden(false);
+
+ ui->deviceinfoFrame->setHidden(true);
+ ui->batteryFrame->setHidden(true);
+
+ ui->tabWidget->hide();
+ ui->tabWidget->setTabEnabled(3, false);
+ ui->tabWidget->setTabEnabled(2, false);
+ ui->tabWidget->setTabEnabled(1, false);
+ ui->tabWidget->setTabEnabled(0, false);
+
+ ui->lightFrame->setHidden(true);
+ ui->voicepromptFrame->setHidden(true);
+ ui->notificationFrame->setHidden(true);
+ ui->sidetoneFrame->setHidden(true);
+ ui->inactivityFrame->setHidden(true);
+ ui->chatmixFrame->setHidden(true);
+ ui->volumelimiterFrame->setHidden(true);
+
+ ui->equalizerpresetFrame->setHidden(true);
+ ui->equalizerFrame->setHidden(true);
+ ui->applyEqualizer->setEnabled(false);
+
+ ui->rotatetomuteFrame->setHidden(true);
+ ui->muteledbrightnessFrame->setHidden(true);
+ ui->micvolumeFrame->setHidden(true);
+
+ ui->btwhenonFrame->setHidden(true);
+ ui->btcallvolumeFrame->setHidden(true);
+}
+
+void MainWindow::loadDevices(){
+ QList c=getConnectedDevices(), s=deserializeDevices(FILE_DEVICES_SETTINGS);
+ n_connected=c.length(); n_saved=s.length();
+ deviceList = mergeDevices(c, s);
+}
+
+void MainWindow::loadDevice(int deviceIndex){
+ disableFrames();
+
+ if(deviceIndex<0){
+ selectedDevice=nullptr;
+ return;
+ }
+
+ selectedDevice=deviceList.value(deviceIndex);
+ QSet& capabilities=selectedDevice->capabilities;
+
+ if(timerGUI!=nullptr){
+ timerGUI->stop();
+ timerGUI=nullptr;
+ }
+ timerGUI = new QTimer(this);
+ connect(timerGUI, SIGNAL(timeout()), this, SLOT(updateDevice()));
+ connect(timerGUI, SIGNAL(timeout()), this, SLOT(saveDevicesSettings()));
+ connect(timerGUI, SIGNAL(timeout()), this, SLOT(updateGUI()));
+ timerGUI->start(settings.msecUpdateIntervalTime);
+
+ ui->notSupportedFrame->setHidden(true);
+
+ //Info section
+ ui->deviceinfovalueLabel->setText(selectedDevice->device+"\n"+selectedDevice->vendor+"\n"+selectedDevice->product);
+ ui->deviceinfoFrame->setHidden(false);
+ if (capabilities.contains("CAP_BATTERY_STATUS")){
+ ui->batteryFrame->setHidden(false);
+ this->setBatteryStatus();
+ qDebug() << "Battery percentage supported";
+ }
+
+ ui->tabWidget->show();
+ //Other Section
+ if (capabilities.contains("CAP_LIGHTS")){
+ ui->lightFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(0, true);
+ ledOn->setEnabled(true);
+ ledOff->setEnabled(true);
+ qDebug() << "Light control supported";
+ }
+ if (capabilities.contains("CAP_SIDETONE")){
+ ui->sidetoneFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(0, true);
+ qDebug() << "Sidetone supported";
+ }
+ if (capabilities.contains("CAP_VOICE_PROMPTS")){
+ ui->voicepromptFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(0, true);
+ qDebug() << "Voice prompt supported";
+ }
+ if (capabilities.contains("CAP_NOTIFICATION_SOUND")){
+ ui->notificationFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(0, true);
+ qDebug() << "Notification sound supported";
+ }
+ if (capabilities.contains("CAP_INACTIVE_TIME")){
+ ui->inactivityFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(0, true);
+ qDebug() << "Inactivity timer supported";
+ }
+ if (capabilities.contains("CAP_CHATMIX_STATUS")){
+ ui->chatmixFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(0, true);
+ this->setChatmixStatus();
+ qDebug() << "Chatmix supported";
+ }
+ //Eualizer Section
+ if (capabilities.contains("CAP_EQUALIZER_PRESET") && !selectedDevice->presets_list.empty()){
+ ui->equalizerpresetFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(1, true);
+ qDebug() << "Eqaulizer preset supported";
+ }
+ if (capabilities.contains("CAP_EQUALIZER") && selectedDevice->equalizer.bands_number>0){
+ ui->equalizerFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(1, true);
+ qDebug() << "Equalizer supported";
+ }
+ if (capabilities.contains("CAP_VOLUME_LIMITER")){
+ ui->volumelimiterFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(1, true);
+ qDebug() << "Volume limiter preset supported";
+ }
+ //Microphone Section
+ if (capabilities.contains("CAP_ROTATE_TO_MUTE")){
+ ui->rotatetomuteFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(2, true);
+ qDebug() << "Rotate to mute supported";
+ }
+ if (capabilities.contains("CAP_MICROPHONE_MUTE_LED_BRIGHTNESS")){
+ ui->muteledbrightnessFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(2, true);
+ qDebug() << "Muted led brightness supported";
+ }
+ if (capabilities.contains("CAP_MICROPHONE_VOLUME")){
+ ui->micvolumeFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(2, true);
+ qDebug() << "Microphone volume supported";
+ }
+ //Bluetooth Section
+ if (capabilities.contains("CAP_BT_WHEN_POWERED_ON")){
+ ui->btwhenonFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(3, true);
+ qDebug() << "Bluetooth when powered on volume supported";
+ }
+ if (capabilities.contains("CAP_BT_CALL_VOLUME")){
+ ui->btcallvolumeFrame->setHidden(false);
+ ui->tabWidget->setTabEnabled(3, true);
+ qDebug() << "Bluetooth call volume volume supported";
+ }
+
+ loadGUIValues();
+ this->setMaximumHeight(this->minimumHeight());
+}
+
+void MainWindow::loadGUIValues(){
+ if(selectedDevice->lights>=0){
+ ui->onlightButton->setChecked(selectedDevice->lights);
+ ui->offlightButton->setChecked(!selectedDevice->lights);
+ }
+ if(selectedDevice->sidetone>=0){
+ ui->sidetoneSlider->setSliderPosition(selectedDevice->sidetone);
+ }
+ if(selectedDevice->voice_prompts>=0){
+ ui->voiceOnButton->setChecked(selectedDevice->voice_prompts);
+ ui->voiceOffButton->setChecked(!selectedDevice->voice_prompts);
+ }
+ if(selectedDevice->inactive_time>=0){
+ ui->inactivitySlider->setSliderPosition(selectedDevice->inactive_time);
+ }
+
+ ui->equalizerPresetcomboBox->clear();
+ ui->equalizerPresetcomboBox->addItem("-");
+ ui->equalizerPresetcomboBox->setCurrentIndex(0);
+ for (int i = 0; i < selectedDevice->presets_list.size(); ++i) {
+ ui->equalizerPresetcomboBox->addItem(selectedDevice->presets_list.at(i).name);
+ }
+ if(selectedDevice->equalizer_preset>=0){
+ ui->equalizerPresetcomboBox->setCurrentIndex(selectedDevice->equalizer_preset);
+ }
+
+ QHBoxLayout *equalizerLayout = ui->equalizerLayout;
+ clearLayout(equalizerLayout);
+ if(selectedDevice->equalizer.bands_number>0){
+ int i;
+ for (i = 0; i < selectedDevice->equalizer.bands_number; ++i) {
+ QLabel *l = new QLabel(QString::number(i));
+ l->setAlignment(Qt::AlignHCenter);
+
+ QSlider *s = new QSlider(Qt::Vertical);
+ s->setMaximum(selectedDevice->equalizer.band_max/selectedDevice->equalizer.band_step);
+ s->setMinimum(selectedDevice->equalizer.band_min/selectedDevice->equalizer.band_step);
+ s->setSingleStep(1);
+ s->setTickInterval(1/selectedDevice->equalizer.band_step);
+ s->setTickPosition(QSlider::TicksBothSides);
+ if(selectedDevice->equalizer_curve.size()==selectedDevice->equalizer.bands_number){
+ s->setValue(selectedDevice->equalizer_curve.value(i));
+ } else{
+ s->setValue(selectedDevice->equalizer.band_baseline);
+ }
+
+ QVBoxLayout *lb = new QVBoxLayout();
+ lb->addWidget(l);
+ lb->addWidget(s);
+
+ slidersEq.append(s);
+ equalizerLayout->addLayout(lb);
+ }
+ ui->applyEqualizer->setEnabled(true);
+ }
+
+ if(selectedDevice->volume_limiter>=0){
+ ui->volumelimiterOnButton->setChecked(selectedDevice->volume_limiter);
+ ui->volumelimiterOffButton->setChecked(!selectedDevice->volume_limiter);
+ }
+
+ if(selectedDevice->rotate_to_mute>=0){
+ ui->rotateOn->setChecked(selectedDevice->rotate_to_mute);
+ ui->rotateOff->setChecked(!selectedDevice->rotate_to_mute);
+ }
+ if(selectedDevice->mic_mute_led_brightness>=0){
+ ui->muteledbrightnessSlider->setSliderPosition(selectedDevice->mic_mute_led_brightness);
+ }
+ if(selectedDevice->mic_volume>=0){
+ ui->micvolumeSlider->setSliderPosition(selectedDevice->mic_volume);
+ }
+
+ if(selectedDevice->bt_call_volume>=0){
+ switch (selectedDevice->bt_call_volume) {
+ case 0:
+ ui->btbothRadioButton->setChecked(true);
+ break;
+ case 1:
+ ui->btpcdbRadioButton->setChecked(true);
+ break;
+ case 2:
+ ui->btonlyRadioButton->setChecked(true);
+ break;
+ default:
+ break;
+ }
+ }
+ if(selectedDevice->bt_when_powered_on>=0){
+ ui->btwhenonOnButton->setChecked(selectedDevice->bt_when_powered_on);
+ ui->btwhenonOffButton->setChecked(!selectedDevice->bt_when_powered_on);
+ }
+}
+
+void MainWindow::saveDevicesSettings(){
+ if(!savedDevices){
+ serializeDevices(deviceList, FILE_DEVICES_SETTINGS);
+ }
+}
+
+void MainWindow::updateDevice(){
+ if(selectedDevice!=nullptr){
+ QList newDl=getConnectedDevices();
+ selectedDevice->updateDevice(newDl);
+ }
+}
+
+void MainWindow::updateGUI(){
+ setBatteryStatus();
+ setChatmixStatus();
+}
+
+//Info Section Events
+void MainWindow::setBatteryStatus()
+{
+ QString status = selectedDevice->battery.status;
+ int batteryLevel = selectedDevice->battery.level;
+ QString level=QString::number(batteryLevel);
+
+ if(batteryLevel>=0){
+ ui->batteryProgressBar->show();
+ ui->batteryProgressBar->setValue(batteryLevel);
+ }
+ else{
+ ui->batteryProgressBar->hide();
+ }
+
+ if (status == "BATTERY_UNAVAILABLE"){
+ ui->batteryPercentage->setText(tr("Headset Off"));
+ tray->setToolTip(tr("HeadsetControl \r\nHeadset Off"));
+ trayIconPath =":/icons/headphones-inv.png";
+ }
+ else if (status == "BATTERY_CHARGING") {
+ ui->batteryPercentage->setText(level+tr("% - Charging"));
+ tray->setToolTip(tr("HeadsetControl \r\nBattery Charging"));
+ trayIconPath = ":/icons/battery-charging-inv.png";
+ }
+ else if(status == "BATTERY_AVAILABLE"){
+ ui->batteryPercentage->setText(level+tr("% - Descharging"));
+ tray->setToolTip(tr("HeadsetControl \r\nBattery: ") + level + "%");
+ if (level.toInt() > 75){
+ trayIconPath = ":/icons/battery-level-full-inv.png";
+ notified = false;
+ }
+ else if (level.toInt() > settings.batteryLowThreshold) {
+ trayIconPath = ":/icons/battery-medium-inv.png";
+ notified = false;
+ }
+ else {
+ trayIconPath = ":/icons/battery-low-inv.png";
+ if (!notified){
+ tray->showMessage(tr("Battery Alert!"), tr("The battery of your headset is running low"), QIcon(":/icons/battery-low-inv.png"));
+ notified = true;
+ }
+ }
+ } else{
+ ui->batteryPercentage->setText(tr("No battery info"));
+ tray->setToolTip("HeadsetControl");
+ trayIconPath = ":/icons/headphones-inv.png";
+ }
+
+ if(!darkMode){
+ trayIconPath.replace("-inv", "");
+ }
+ tray->setIcon(QIcon(trayIconPath));
+}
+
+//Other Section Events
+void MainWindow::onlightButton_clicked()
+{
+ QStringList args=QStringList() << QString("--light") << QString("1");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->lights=1;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::offlightButton_clicked()
+{
+ QStringList args=QStringList() << QString("--light") << QString("0");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->lights=0;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::sidetoneSlider_sliderReleased(){
+ QStringList args=QStringList() << QString("--sidetone") << QString::number(ui->sidetoneSlider->sliderPosition());
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->sidetone=ui->sidetoneSlider->value();
+ savedDevices=false;
+ }
+}
+
+void MainWindow::voiceOnButton_clicked()
+{
+ QStringList args=QStringList() << QString("--voice-prompt") << QString("1");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->voice_prompts=1;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::voiceOffButton_clicked()
+{
+ QStringList args=QStringList() << QString("--voice-prompt") << QString("0");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->voice_prompts=0;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::notification0Button_clicked()
+{
+ QStringList args=QStringList() << QString("--notificate") << QString("0");
+ Action s=sendAction(args);
+ if(s.status!="success"){
+
+ }
+}
+
+void MainWindow::notification1Button_clicked()
+{
+ QStringList args=QStringList() << QString("--notificate") << QString("1");
+ Action s=sendAction(args);
+ if(s.status!="success"){
+
+ }
+}
+
+void MainWindow::rotateOn_clicked()
+{
+ QStringList args=QStringList() << QString("--rotate-to-mute") << QString("1");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->rotate_to_mute=1;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::rotateOff_clicked()
+{
+ QStringList args=QStringList() << QString("--rotate-to-mute") << QString("0");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->rotate_to_mute=0;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::inactivitySlider_sliderReleased(){
+ QStringList args=QStringList() << QString("--inactive-time") << QString::number(ui->inactivitySlider->sliderPosition());
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->inactive_time=ui->inactivitySlider->value();
+ savedDevices=false;
+ }
+}
+
+void MainWindow::setChatmixStatus(){
+ int chatmix = selectedDevice->chatmix;
+ QString chatmixValue = QString::number(chatmix);
+ QString chatmixStatus;
+ if(chatmix<65)chatmixStatus=tr("Game");
+ else if(chatmix>65)chatmixStatus=tr("Chat");
+ ui->chatmixvalueLabel->setText(chatmixValue);
+ ui->chatmixstatusLabel->setText(chatmixStatus);
+}
+
+//Equalizer Section Events
+void MainWindow::equalizerPresetcomboBox_currentIndexChanged(){
+ int preset=ui->equalizerPresetcomboBox->currentIndex();
+ if(preset==0){
+ //setSliders(selectedDevice->equalizer.band_baseline);
+ } else if(preset>=1 && preset<=selectedDevice->presets_list.length()){
+ this->setSliders(selectedDevice->presets_list.value(preset-1).values);
+ QStringList args=QStringList() << QString("--equalizer-preset") << QString::number(preset-1);
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->equalizer_preset=ui->equalizerPresetcomboBox->currentIndex();
+ savedDevices=false;
+ }
+ }
+}
+
+void MainWindow::applyEqualizer_clicked(){
+ ui->equalizerPresetcomboBox->setCurrentIndex(0);
+ QString eq_string="";
+ QList values;
+ for (QSlider* slider : slidersEq) {
+ eq_string+= QString::number(slider->value())+",";
+ values.append(slider->value()/selectedDevice->equalizer.band_step);
+ }
+ eq_string.removeLast();
+ QStringList args=QStringList() << QString("--equalizer") << eq_string;
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->equalizer_curve=values;
+ selectedDevice->equalizer_preset=-1;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::setSliders(int value){
+ for (QSlider* slider : slidersEq) {
+ slider->setValue(value/selectedDevice->equalizer.band_step);
+ }
+}
+
+void MainWindow::setSliders(QList values){
+ int i=0;
+ if(values.length()==selectedDevice->equalizer.bands_number){
+ for (QSlider* slider : slidersEq) {
+ slider->setValue(values[i++]/selectedDevice->equalizer.band_step);
+ }
+ }
+ else{
+ qDebug() << "ERROR: Bad Equalizer Preset";
+ }
+}
+
+void MainWindow::clearLayout(QLayout* layout){
+ if (!layout) {
+ return;
+ }
+
+ QLayoutItem* item;
+ while ((item = layout->takeAt(0))) {
+ if (item->layout()) {
+ clearLayout(item->layout()); // Delete the layout if it exists
+ }
+ if (item->widget()) {
+ delete item->widget(); // Delete the widget
+ }
+ delete item; // Delete the layout item
+ }
+}
+
+void MainWindow::volumelimiterOffButton_clicked(){
+ QStringList args=QStringList() << QString("--volume-limiter") << QString("0");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->volume_limiter=0;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::volumelimiterOnButton_clicked(){
+ QStringList args=QStringList() << QString("--volume-limiter") << QString("1");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->volume_limiter=1;
+ savedDevices=false;
+ }
+}
+
+//Microphone Section Events
+void MainWindow::muteledbrightnessSlider_sliderReleased(){
+ QStringList args=QStringList() << QString("--microphone-mute-led-brightness") << QString::number(ui->muteledbrightnessSlider->sliderPosition());
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->mic_mute_led_brightness=ui->muteledbrightnessSlider->value();
+ savedDevices=false;
+ }
+}
+
+void MainWindow::micvolumeSlider_sliderReleased(){
+ QStringList args=QStringList() << QString("--microphone-volume") << QString::number(ui->micvolumeSlider->sliderPosition());
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->mic_volume=ui->micvolumeSlider->value();
+ savedDevices=false;
+ }
+}
+
+//Bluetooth Section Events
+void MainWindow::btwhenonOffButton_clicked(){
+ QStringList args=QStringList() << QString("--bt-when-powered-on") << QString("0");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->bt_when_powered_on=0;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::btwhenonOnButton_clicked(){
+ QStringList args=QStringList() << QString("--bt-when-powered-on") << QString("1");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->bt_when_powered_on=1;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::btbothRadioButton_clicked(){
+ QStringList args=QStringList() << QString("--bt-call-volume") << QString("0");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->bt_call_volume=0;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::btpcdbRadioButton_clicked(){
+ QStringList args=QStringList() << QString("--bt-call-volume") << QString("1");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->bt_call_volume=1;
+ savedDevices=false;
+ }
+}
+
+void MainWindow::btonlyRadioButton_clicked(){
+ QStringList args=QStringList() << QString("--bt-call-volume") << QString("2");
+ Action s=sendAction(args);
+ if(s.status=="success"){
+ selectedDevice->bt_call_volume=2;
+ savedDevices=false;
+ }
+}
+
+//Tool Bar Events
+void MainWindow::editProgramSetting(){
+ SettingsWindow* settingsW=new SettingsWindow(settings, this);
+ if (settingsW->exec() == QDialog::Accepted) {
+ settings=settingsW->getSettings();
+ saveSettingstoFile(settings, PROGRAM_SETTINGS_FILENAME);
+ timerGUI->setInterval(settings.msecUpdateIntervalTime);
+ }
+}
+
+void MainWindow::selectDevice(){
+ this->loadDevices();
+
+ QStringList devices=QStringList();
+ for (Device* device : deviceList){
+ if(device->connected){
+ devices<device;
+ }
+ }
+
+ LoaddeviceWindow* loadDevWindow=new LoaddeviceWindow(devices, this);
+ if (loadDevWindow->exec() == QDialog::Accepted) {
+ int index = loadDevWindow->getDeviceIndex();
+ this->disableFrames();
+ if (index>=0) {
+ if(index==0){
+ ui->tabWidget->setDisabled(false);
+ }
+ else {
+ ui->tabWidget->setDisabled(true);
+ }
+ this->loadDevice(index);
+ }
+ }
+}
+
+void MainWindow::checkForUpdates(bool firstStart){
+ bool needsUpdate = false;
+ DialogInfo* dialogWindow = new DialogInfo(this);
+ dialogWindow->setTitle(tr("Check for updates"));
+
+ const QVersionNumber& local_hc=getHCVersion();
+ const QVersionNumber local_gui=QVersionNumber::fromString(qApp->applicationVersion());
+ QString v1 = getLatestGitHubReleaseVersion("Sapd","HeadsetControl");
+ QString v2 = getLatestGitHubReleaseVersion("nicola02nb","HeadsetControl-GUI");
+ QVersionNumber remote_hc =QVersionNumber::fromString(v1);
+ QVersionNumber remote_gui =QVersionNumber::fromString(v2);
+ QString s1 = tr("up-to date v")+local_hc.toString();
+ QString s2 = tr("up-to date v")+local_gui.toString();
+ if(!(v1=="") && remote_hc>local_hc){
+ s1=tr("Newer version")+" -> "+remote_hc.toString()+"";
+ needsUpdate = true;
+ }
+ if(!(v2=="") && remote_gui>local_gui){
+ s2=tr("Newer version")+" -> "+remote_gui.toString()+"";
+ needsUpdate = true;
+ }
+
+ if((needsUpdate && firstStart) || !firstStart){
+ QString text = "HeadesetControl: "+s1+"
HeadesetControl-GUI: "+s2;
+ dialogWindow->setLabel(text);
+
+ dialogWindow->show();
+ }
+
+}
+
+void MainWindow::showAbout(){
+ DialogInfo* dialogWindow=new DialogInfo(this);
+ dialogWindow->setTitle(tr("About this program"));
+ QString text = tr("This is a forked version of HeadsetControl-GUI."
+ "
Made by nicola02nb"
+ "
Version: ")+qApp->applicationVersion();
+ dialogWindow->setLabel(text);
+
+ dialogWindow->show();
+}
+
+void MainWindow::showCredits(){
+ DialogInfo* dialogWindow=new DialogInfo(this);
+ dialogWindow->setTitle(tr("Credits"));
+ QString text = tr("Big shout-out to:"
+ "
- Sapd for HeadsetCoontrol"
+ "
- LeoKlaus for HeadsetControl-GUI");
+ dialogWindow->setLabel(text);
+
+ dialogWindow->show();
+}
diff --git a/src/UI/mainwindow.h b/src/UI/mainwindow.h
new file mode 100644
index 0000000..323bfc5
--- /dev/null
+++ b/src/UI/mainwindow.h
@@ -0,0 +1,129 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "utils.h"
+#include "device.h"
+#include "settings.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class MainWindow;
+}
+QT_END_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow(QWidget *parent = nullptr);
+ ~MainWindow();
+ bool firstShow = true;
+ bool notified = false;
+ bool savedDevices = true;
+ QSystemTrayIcon* tray = new QSystemTrayIcon(this);
+
+private:
+ const QString FILE_DEVICES_SETTINGS = "devices.json";
+ const QString PROGRAM_SETTINGS_FILENAME = "settings.json";
+
+ int n_connected = 0, n_saved = 0;
+
+ Settings settings;
+ bool darkMode;
+ QString trayIconPath;
+
+ QMenu *menu;
+
+ QAction* ledOn;
+ QAction* ledOff;
+
+ Device* selectedDevice;
+ QList deviceList;
+ QList slidersEq;
+
+ QTimer* timerGUI = nullptr;
+
+private slots:
+ void bindEvents();
+ void changeEvent(QEvent *e);
+ void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
+
+ void toggleWindow();
+
+ bool isOsDarkMode();
+ void updateIcons();
+
+ void disableFrames();
+
+ void loadDevices();
+ void loadDevice(int deviceIndex=0);
+ void loadGUIValues();
+
+ void saveDevicesSettings();
+
+ void updateDevice();
+ void updateGUI();
+
+ void setBatteryStatus();
+
+ //Other Section Events
+ void onlightButton_clicked();
+ void offlightButton_clicked();
+
+ void sidetoneSlider_sliderReleased();
+
+ void voiceOnButton_clicked();
+ void voiceOffButton_clicked();
+
+ void notification0Button_clicked();
+ void notification1Button_clicked();
+
+ void inactivitySlider_sliderReleased();
+
+ void rotateOn_clicked();
+ void rotateOff_clicked();
+
+ void setChatmixStatus();
+
+ //Equalizer Section Events
+ void equalizerPresetcomboBox_currentIndexChanged();
+
+ void applyEqualizer_clicked();
+ void setSliders(int value);
+ void setSliders(QList values);
+ void clearLayout(QLayout* layout);
+
+ void volumelimiterOffButton_clicked();
+ void volumelimiterOnButton_clicked();
+
+ //Microphone Section Events
+ void muteledbrightnessSlider_sliderReleased();
+ void micvolumeSlider_sliderReleased();
+
+ //Bluetooth Section Events
+ void btwhenonOffButton_clicked();
+ void btwhenonOnButton_clicked();
+
+ void btbothRadioButton_clicked();
+ void btpcdbRadioButton_clicked();
+ void btonlyRadioButton_clicked();
+
+ //Tool Bar Events
+ void editProgramSetting();
+ void checkForUpdates(bool firstStart = false);
+ void selectDevice();
+ void showAbout();
+ void showCredits();
+
+private:
+ Ui::MainWindow* ui;
+};
+#endif // MAINWINDOW_H
diff --git a/src/UI/mainwindow.ui b/src/UI/mainwindow.ui
new file mode 100644
index 0000000..f2731d4
--- /dev/null
+++ b/src/UI/mainwindow.ui
@@ -0,0 +1,1745 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 488
+ 690
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 11
+
+
+
+ HeadsetControl - GUI
+
+
+
+ :/icons/headphones-inv.png:/icons/headphones-inv.png
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ HeadsetControl couldn't find any compatible or working headsets. :(
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ <html><head/><body><p>Device:<br/>Vendor:<br/>Model:</p></body></html>
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 300
+ 16777215
+
+
+
+
+
+
+ No info of the device
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Expanding
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 6
+
+
+ 9
+
+
+ 9
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 120
+ 16777215
+
+
+
+
+ 11
+ true
+
+
+
+ Battery:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 200
+ 16777215
+
+
+
+ false
+
+
+
+
+
+ No compatible Device found!
+
+
+ false
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 0
+
+
+ false
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ QTabWidget::North
+
+
+ 0
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+
+ 0
+ 0
+
+
+
+ Other
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 120
+ 16777215
+
+
+
+
+ 11
+ true
+
+
+
+ Lights:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 120
+ 0
+
+
+
+ RGB OFF
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 120
+ 0
+
+
+
+ RGB ON
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Sidetone Level:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+ false
+
+
+ Drag to adjust Sidetone Level
+
+
+ 128
+
+
+ 16
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBelow
+
+
+ 16
+
+
+
+ -
+
+
-
+
+
+ Quiet (Off)
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::LeftToRight
+
+
+ Loud
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 10
+
+
+
+
+ 120
+ 16777215
+
+
+
+
+ 11
+ true
+
+
+
+ Voice Prompts:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
-
+
+
+
+ 120
+ 0
+
+
+
+ Voice Off
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 120
+ 0
+
+
+
+ Voice On
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Notification Sound:
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ Test 0
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Test 1
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Inactivity Timer:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
-
+
+
+ 1
+
+
+ 90
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBelow
+
+
+ 10
+
+
+
+ -
+
+
-
+
+
+ 0 Minute (Off)
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ 90 Minutes
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Chatmix:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ None
+
+
+
+ -
+
+
+
+ 30
+ 0
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 217
+ 20
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 0
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Equalizer
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Equalizer preset:
+
+
+
+ -
+
+
+
+ 150
+ 0
+
+
+
+ -1
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Equalizer:
+
+
+
+ -
+
+
+ -
+
+
+
+ 120
+ 30
+
+
+
+ Apply Equalizer
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Volume Limiter:
+
+
+
+ -
+
+
-
+
+
+ Limiter Off
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Limiter On
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Microphone
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Rotate to mute:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
+ Off
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ On
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ false
+
+
+ Muted led brightness:
+
+
+ false
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ 3
+
+
+ 1
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBelow
+
+
+
+ -
+
+
-
+
+
+ Low (Off)
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ High
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Microphone volume:
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ 128
+
+
+ 16
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBelow
+
+
+ 16
+
+
+
+ -
+
+
-
+
+
+ Quiet
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Loud
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Bluetooth
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 11
+ true
+
+
+
+ Bluetooth when powered on:
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ Bluetooth Off
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Bluetooth On
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 0
+
+
+
+
+ 120
+ 16777215
+
+
+
+
+ 11
+ true
+
+
+
+ Bluetooth call volume:
+
+
+ true
+
+
+
+ -
+
+
-
+
+
-
+
+
+ BT and PC
+
+
+
+ -
+
+
+ PC -12dB
+
+
+
+ -
+
+
+ BT only
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Check Updates
+
+
+
+
+
+
+
+ About
+
+
+
+
+
+
+
+ Credits
+
+
+
+
+ true
+
+
+
+
+
+ Load Device
+
+
+
+
+
+
+
+ Settings
+
+
+
+
+ offlightButton
+ onlightButton
+ sidetoneSlider
+ voiceOffButton
+ inactivitySlider
+ equalizerPresetcomboBox
+ applyEqualizer
+ rotateOff
+ rotateOn
+ muteledbrightnessSlider
+ micvolumeSlider
+
+
+
+
+
+
diff --git a/src/UI/settingswindow.cpp b/src/UI/settingswindow.cpp
new file mode 100644
index 0000000..5fa8b2a
--- /dev/null
+++ b/src/UI/settingswindow.cpp
@@ -0,0 +1,37 @@
+#include "settingswindow.h"
+#include "ui_settingswindow.h"
+#include "utils.h"
+
+
+SettingsWindow::SettingsWindow(const Settings& programSettings, QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::settingswindow)
+{
+ setModal(true);
+ ui->setupUi(this);
+
+ connect(ui->runonstartupCheckBox, &QCheckBox::clicked, this, &SettingsWindow::setRunOnStartup);
+
+ ui->runonstartupCheckBox->setChecked(programSettings.runOnstartup);
+ ui->batterylowtresholdSpinBox->setValue(programSettings.batteryLowThreshold);
+ ui->updateintervaltimeDoubleSpinBox->setValue((double)programSettings.msecUpdateIntervalTime/1000);
+}
+
+Settings SettingsWindow::getSettings(){
+ Settings settings;
+ settings.runOnstartup=ui->runonstartupCheckBox->isChecked();
+ settings.batteryLowThreshold=ui->batterylowtresholdSpinBox->value();
+ settings.msecUpdateIntervalTime=ui->updateintervaltimeDoubleSpinBox->value()*1000;
+
+ return settings;
+}
+
+void SettingsWindow::setRunOnStartup(){
+ bool enabled = setOSRunOnStartup(ui->runonstartupCheckBox->isChecked());
+ ui->runonstartupCheckBox->setChecked(enabled);
+}
+
+SettingsWindow::~SettingsWindow()
+{
+ delete ui;
+}
diff --git a/src/UI/settingswindow.h b/src/UI/settingswindow.h
new file mode 100644
index 0000000..577c275
--- /dev/null
+++ b/src/UI/settingswindow.h
@@ -0,0 +1,27 @@
+#ifndef SETTINGSWINDOW_H
+#define SETTINGSWINDOW_H
+
+#include "settings.h"
+#include
+
+namespace Ui {
+class settingswindow;
+}
+
+class SettingsWindow : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit SettingsWindow(const Settings& programSettings, QWidget *parent = nullptr);
+ ~SettingsWindow();
+
+ Settings getSettings();
+
+private:
+ Ui::settingswindow *ui;
+
+ void setRunOnStartup();
+};
+
+#endif // SETTINGSWINDOW_H
diff --git a/src/UI/settingswindow.ui b/src/UI/settingswindow.ui
new file mode 100644
index 0000000..20572e6
--- /dev/null
+++ b/src/UI/settingswindow.ui
@@ -0,0 +1,217 @@
+
+
+ settingswindow
+
+
+
+ 0
+ 0
+ 352
+ 206
+
+
+
+ Settings
+
+
+
+ :/icons/headphones-inv.png:/icons/headphones-inv.png
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ text-align: left;
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ Run on Startup:
+
+
+
+ -
+
+
+ Qt::RightToLeft
+
+
+ text-align: end
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Battery low threshold:
+
+
+
+ -
+
+
+
+ 120
+ 0
+
+
+
+
+ 120
+ 16777215
+
+
+
+ 100
+
+
+ 15
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ <html><head/><body><p>Update Info interval time (seconds):<br/>Default: 30,0 seconds<br/>DON'T PUT TOO LOW VALUES</p></body></html>
+
+
+
+ -
+
+
+
+ 120
+ 0
+
+
+
+
+ 120
+ 16777215
+
+
+
+ 1
+
+
+ 1000.000000000000000
+
+
+ 30.000000000000000
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ settingswindow
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ settingswindow
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/Utils/utils.cpp b/src/Utils/utils.cpp
new file mode 100644
index 0000000..90dbe4c
--- /dev/null
+++ b/src/Utils/utils.cpp
@@ -0,0 +1,140 @@
+#include "utils.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+QString getLatestGitHubReleaseVersion(const QString& owner, const QString& repo)
+{
+ QEventLoop loop;
+ QNetworkAccessManager manager;
+ QNetworkRequest request(QUrl(QString("https://api.github.com/repos/%1/%2/releases/latest").arg(owner, repo)));
+ request.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0");
+
+ QNetworkReply *reply = manager.get(request);
+ QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
+ loop.exec();
+
+ if (reply->error() == QNetworkReply::NoError) {
+ QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
+ QJsonObject jsonObj = doc.object();
+ QString latestVersion = jsonObj.value("tag_name").toString();
+ reply->deleteLater();
+ return latestVersion.removeFirst();
+ } else {
+ qDebug() << "Error:" << reply->errorString();
+ reply->deleteLater();
+ return QString();
+ }
+}
+
+bool fileExists(const QString& filepath)
+{
+ QFileInfo checkFile(filepath);
+ return checkFile.exists();
+}
+
+bool downloadAndUnzipGithubRepo(const QString& user, const QString& repo, const QString& savePath)
+{
+ // Step 1: Download the zip file
+ QString url = QString("https://github.com/%1/%2/archive/refs/heads/headsetcontrol-windows.zip").arg(user, repo);
+ QString zipFilePath = savePath + "/headsetcontrol-windows.zip";
+
+ url= "https://github.com/Sapd/HeadsetControl/releases/download/3.0.0/headsetcontrol-windows.zip";
+ QNetworkAccessManager manager;
+ QEventLoop loop;
+ QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url)));
+ QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
+ loop.exec();
+
+ if (reply->error() != QNetworkReply::NoError) {
+ qDebug() << "Download Error:" << reply->errorString();
+ reply->deleteLater();
+ return false;
+ }
+
+ QFile file(zipFilePath);
+ if (!file.open(QIODevice::WriteOnly)) {
+ qDebug() << "Could not open file for writing:" << file.errorString();
+ reply->deleteLater();
+ return false;
+ }
+
+ file.write(reply->readAll());
+ file.close();
+ reply->deleteLater();
+
+ // Step 2: Unzip the file
+ QDir().mkpath(savePath);
+ QProcess unzip;
+ unzip.setWorkingDirectory(savePath);
+ unzip.start("unzip", QStringList() << "-o" << zipFilePath << "-d" << savePath);
+ if (!unzip.waitForFinished()) {
+ qDebug() << "Unzip Error:" << unzip.errorString();
+ return false;
+ }
+
+ // Optional: Remove the zip file after extraction
+ QFile::remove(zipFilePath);
+
+ return true;
+}
+
+bool openFileExplorer(const QString& path)
+{
+ QDir dir(path);
+ if (!dir.exists())
+ {
+ qDebug() << "Path does not exist:" << path;
+ return false;
+ }
+
+ QUrl url = QUrl::fromLocalFile(dir.absolutePath());
+ return QDesktopServices::openUrl(url);
+}
+
+bool setOSRunOnStartup(bool enable){
+ QString appName = QCoreApplication::applicationName();
+ QString appDir = QCoreApplication::applicationDirPath();
+ QString appPath = QCoreApplication::applicationFilePath();
+
+#ifdef Q_OS_WIN
+ QString startupPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + QDir::separator() + "Startup";
+ QString linkPath = startupPath + "\\" + appName + ".lnk";
+ if(enable){
+ QFile::remove(linkPath);
+ return QFile::link(appPath, linkPath);
+ }
+ QFile::remove(linkPath);
+ return false;
+
+#elif defined(Q_OS_LINUX)
+ QString autostartPath = QDir::homePath() + "/.config/autostart/";
+ QString desktopFilePath = autostartPath + appName + ".desktop";
+
+ if(enable){
+ QFile::remove(desktopFilePath);
+ QFile desktopFile(desktopFilePath);
+ if (desktopFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QTextStream out(&desktopFile);
+ out << "[Desktop Entry]\n";
+ out << "Path=" + appDir + "\n";
+ out << "Type=Application\n";
+ out << "Exec=" << appPath << "\n";
+ out << "Name=" << appName << "\n";
+ out << "Comment=Auto-starts " << appName << " on boot\n";
+ desktopFile.close();
+ return true;
+ }
+ }
+ QFile::remove(desktopFilePath);
+
+ return false;
+#endif
+}
+
diff --git a/src/Utils/utils.h b/src/Utils/utils.h
new file mode 100644
index 0000000..89c53b9
--- /dev/null
+++ b/src/Utils/utils.h
@@ -0,0 +1,16 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include
+
+QString getLatestGitHubReleaseVersion(const QString& owner, const QString& repo);
+
+bool downloadAndUnzipGithubRepo(const QString& user, const QString& repo, const QString& savePath);
+
+bool fileExists(const QString& filepath);
+
+bool openFileExplorer(const QString& path);
+
+bool setOSRunOnStartup(bool enable);
+
+#endif // UTILS_H
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..21b23ec
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,21 @@
+#include "mainwindow.h"
+
+#include
+#include
+
+const QString GUI_VERSION = "0.15.0";
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ app.setApplicationVersion(GUI_VERSION);
+ QLocale locale = QLocale::system();
+ QString languageCode = locale.name();
+ QTranslator translator;
+ if (translator.load(":/translations/tr/HeadsetControl_GUI_"+languageCode+".qm")) {
+ app.installTranslator(&translator);
+ }
+ MainWindow window;
+
+ return app.exec();
+}