Publish LumaOps source

This commit is contained in:
LumaOps release export
2026-09-03 01:18:36 +02:00
commit 7f1c0e5f71
2363 changed files with 501543 additions and 0 deletions
@@ -0,0 +1,27 @@
/*-----------------------------------------------------------------*\
| BaseManualDeviceEntry.cpp |
| |
| Base class to all user-defined device settings entries |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*-----------------------------------------------------------------*/
#include "BaseManualDeviceEntry.h"
#include "ManualDevicesTypeManager.h"
void BaseManualDeviceEntry::setSettingsSection(const std::string& section)
{
settingsSection = section;
}
std::string BaseManualDeviceEntry::getSettingsSection()
{
return settingsSection;
}
ManualDeviceTypeRegistrator::ManualDeviceTypeRegistrator(const std::string& name, const std::string& settingsEntry, ManualDeviceEntrySpawnFunction entrySpawnFunction)
{
ManualDevicesTypeManager::get()->registerType(name, settingsEntry, entrySpawnFunction);
};
@@ -0,0 +1,41 @@
/*-----------------------------------------------------------------*\
| BaseManualDeviceEntry.h |
| |
| Base class to all user-defined device settings entries |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*-----------------------------------------------------------------*/
#pragma once
#include <QWidget>
#include "nlohmann/json.hpp"
using json = nlohmann::json;
class BaseManualDeviceEntry: public QWidget
{
Q_OBJECT
public:
explicit BaseManualDeviceEntry(QWidget *parent = nullptr): QWidget(parent) {}
virtual json saveSettings() = 0;
virtual bool isDataValid() = 0;
void setSettingsSection(const std::string& section);
std::string getSettingsSection();
private:
std::string settingsSection;
};
typedef std::function<BaseManualDeviceEntry*(const json& data)> ManualDeviceEntrySpawnFunction;
class ManualDeviceTypeRegistrator
{
public:
ManualDeviceTypeRegistrator(const std::string& name, const std::string& settingsEntry, ManualDeviceEntrySpawnFunction entrySpawnFunction);
};
#define REGISTER_MANUAL_DEVICE_TYPE(name, settingsEntry, func) static ManualDeviceTypeRegistrator device_detector_obj_##func(name, settingsEntry, func)
@@ -0,0 +1,100 @@
/*---------------------------------------------------------*\
| DDPSettingsEntry.cpp |
| |
| User interface for OpenRGB DDP settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "DDPSettingsEntry.h"
#include "ui_DDPSettingsEntry.h"
#include "ManualDevicesTypeManager.h"
#include "nlohmann/json.hpp"
using json = nlohmann::json;
DDPSettingsEntry::DDPSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::DDPSettingsEntry)
{
ui->setupUi(this);
}
DDPSettingsEntry::~DDPSettingsEntry()
{
delete ui;
}
void DDPSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void DDPSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
if(data.contains("port"))
{
ui->PortSpinBox->setValue(data["port"]);
}
else
{
ui->PortSpinBox->setValue(4048);
}
if(data.contains("num_leds"))
{
ui->NumLedsSpinBox->setValue(data["num_leds"]);
}
if(data.contains("keepalive_time"))
{
ui->KeepaliveTimeSpinBox->setValue(data["keepalive_time"]);
}
}
json DDPSettingsEntry::saveSettings()
{
json result;
result["name"] = ui->NameEdit->text().toStdString();
result["ip"] = ui->IPEdit->text().toStdString();
result["port"] = ui->PortSpinBox->value();
result["num_leds"] = ui->NumLedsSpinBox->value();
if(ui->KeepaliveTimeSpinBox->value() > 0)
{
result["keepalive_time"] = ui->KeepaliveTimeSpinBox->value();
}
return result;
}
bool DDPSettingsEntry::isDataValid()
{
return !ui->IPEdit->text().isEmpty() && ui->NumLedsSpinBox->value() > 0;
}
static BaseManualDeviceEntry* SpawnDDPEntry(const json& data)
{
DDPSettingsEntry* entry = new DDPSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
static const char* DDPDeviceName = QT_TRANSLATE_NOOP("ManualDevice", "DDP (Distributed Display Protocol)");
REGISTER_MANUAL_DEVICE_TYPE(DDPDeviceName, "DDPDevices", SpawnDDPEntry);
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| DDPSettingsEntry.h |
| |
| User interface for OpenRGB DDP settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class DDPSettingsEntry;
}
class DDPSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit DDPSettingsEntry(QWidget *parent = nullptr);
~DDPSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::DDPSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
};
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DDPSettingsEntry</class>
<widget class="QWidget" name="DDPSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>200</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">DDP Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>DDP Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP Address:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="IPEdit">
<property name="placeholderText">
<string>192.168.1.100</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="NameEdit">
<property name="placeholderText">
<string>Device Name</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="PortLabel">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="PortSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>4048</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="NumLedsLabel">
<property name="text">
<string>Number of LEDs:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="NumLedsSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="KeepaliveTimeLabel">
<property name="text">
<string>Keepalive Time (ms):</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="KeepaliveTimeSpinBox">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="value">
<number>1000</number>
</property>
<property name="specialValueText">
<string>Disabled</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,136 @@
/*---------------------------------------------------------*\
| DMXSettingsEntry.cpp |
| |
| User interface for OpenRGB DMX settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "DMXSettingsEntry.h"
#include "ui_DMXSettingsEntry.h"
#include "serial_port.h"
#include <QStandardItemModel>
DMXSettingsEntry::DMXSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::DMXSettingsEntry)
{
ui->setupUi(this);
std::vector<std::string> serialPorts = serial_port::getSerialPorts();
for(size_t i = 0; i < serialPorts.size(); ++i)
{
ui->PortComboBox->addItem(QString::fromStdString(serialPorts[i]));
}
if(serialPorts.empty())
{
/*---------------------------------------------------*\
| When no ports were found, add an unselectable entry |
| denoting this fact istead |
\*---------------------------------------------------*/
QStandardItemModel* comboBoxModel = qobject_cast<QStandardItemModel *>(ui->PortComboBox->model());
if(comboBoxModel != nullptr)
{
ui->PortComboBox->addItem(tr("No serial ports found"));
QStandardItem *item = comboBoxModel->item(0);
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
}
}
ui->PortComboBox->clearEditText();
}
DMXSettingsEntry::~DMXSettingsEntry()
{
delete ui;
}
void DMXSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void DMXSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
if(data.contains("port"))
{
ui->PortComboBox->setCurrentText(QString::fromStdString(data["port"]));
}
if(data.contains("red_channel"))
{
ui->RedEdit->setText(QString::number((int)data["red_channel"]));
}
if(data.contains("green_channel"))
{
ui->GreenEdit->setText(QString::number((int)data["green_channel"]));
}
if(data.contains("blue_channel"))
{
ui->BlueEdit->setText(QString::number((int)data["blue_channel"]));
}
if(data.contains("brightness_channel"))
{
ui->BrightnessEdit->setText(QString::number((int)data["brightness_channel"]));
}
if(data.contains("keepalive_time"))
{
ui->KeepaliveTimeEdit->setText(QString::number((int)data["keepalive_time"]));
}
}
json DMXSettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["name"] = ui->NameEdit->text().toStdString();
result["port"] = ui->PortComboBox->currentText().toStdString();
result["red_channel"] = ui->RedEdit->text().toUInt();
result["green_channel"] = ui->GreenEdit->text().toUInt();
result["blue_channel"] = ui->BlueEdit->text().toUInt();
/*-------------------------------------------------*\
| Optional parameters |
\*-------------------------------------------------*/
if(ui->BrightnessEdit->text() != "")
{
result["brightness_channel"] = ui->BrightnessEdit->text().toUInt();
}
if(ui->KeepaliveTimeEdit->text() != "")
{
result["keepalive_time"] = ui->KeepaliveTimeEdit->text().toUInt();
}
return result;
}
bool DMXSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnDMXEntry(const json& data)
{
DMXSettingsEntry* entry = new DMXSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("DMX", "DMXDevices", SpawnDMXEntry);
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| DMXSettingsEntry.h |
| |
| User interface for OpenRGB DMX settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class DMXSettingsEntry;
}
class DMXSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit DMXSettingsEntry(QWidget *parent = nullptr);
~DMXSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::DMXSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
};
@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DMXSettingsEntry</class>
<widget class="QWidget" name="DMXSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>531</width>
<height>206</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">DMX Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>DMX Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="4">
<widget class="QLabel" name="BrightnessLabel">
<property name="text">
<string>Brightness Channel:</string>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QLineEdit" name="BrightnessEdit"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Blue Channel:</string>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QLineEdit" name="GreenEdit"/>
</item>
<item row="3" column="3">
<widget class="QLineEdit" name="RedEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QLabel" name="GreenLabel">
<property name="text">
<string>Green Channel:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="RedLabel">
<property name="text">
<string>Red Channel:</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QLineEdit" name="BlueEdit"/>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="NameEdit"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="KeepaliveTimeLabel">
<property name="text">
<string>Keepalive Time:</string>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QLineEdit" name="KeepaliveTimeEdit"/>
</item>
<item row="1" column="4">
<widget class="QLabel" name="PortLabel">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QComboBox" name="PortComboBox">
<property name="editable">
<bool>true</bool>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>NameEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,145 @@
/*---------------------------------------------------------*\
| DebugSettingsEntry.cpp |
| |
| User interface for OpenRGB Debug settings entry |
| |
| Adam Honse <calcprogrammer1@gmail.com> 30 Jul 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "DebugSettingsEntry.h"
#include "ui_DebugSettingsEntry.h"
#include "ManualDevicesTypeManager.h"
#include "nlohmann/json.hpp"
using json = nlohmann::json;
#define NUM_TYPES 6
const std::string types[] =
{
"motherboard",
"dram",
"gpu",
"keyboard",
"mouse",
"argb"
};
DebugSettingsEntry::DebugSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::DebugSettingsEntry)
{
ui->setupUi(this);
ui->TypeComboBox->addItem("motherboard");
ui->TypeComboBox->addItem("dram");
ui->TypeComboBox->addItem("gpu");
ui->TypeComboBox->addItem("keyboard");
ui->TypeComboBox->addItem("mouse");
ui->TypeComboBox->addItem("argb");
ui->LayoutComboBox->addItem("Default");
ui->LayoutComboBox->addItem("ANSI QWERTY");
ui->LayoutComboBox->addItem("ISO QWERTY");
ui->LayoutComboBox->addItem("ISO QWERTZ");
ui->LayoutComboBox->addItem("ISO AZERTY");
ui->LayoutComboBox->addItem("JIS");
}
DebugSettingsEntry::~DebugSettingsEntry()
{
delete ui;
}
void DebugSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void DebugSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
if(data.contains("type"))
{
for(unsigned int type_idx = 0; type_idx < NUM_TYPES; type_idx++)
{
if(data["type"] == types[type_idx])
{
ui->TypeComboBox->setCurrentIndex(type_idx);
break;
}
}
}
if(data.contains("layout"))
{
ui->LayoutComboBox->setCurrentIndex(data["layout"]);
}
if(data.contains("single"))
{
ui->SingleCheckBox->setChecked(data["single"]);
}
if(data.contains("linear"))
{
ui->LinearCheckBox->setChecked(data["linear"]);
}
if(data.contains("resizable"))
{
ui->ResizableCheckBox->setChecked(data["resizable"]);
}
if(data.contains("keyboard"))
{
ui->KeyboardCheckBox->setChecked(data["keyboard"]);
}
if(data.contains("underglow"))
{
ui->UnderglowCheckBox->setChecked(data["underglow"]);
}
}
json DebugSettingsEntry::saveSettings()
{
json result;
result["name"] = ui->NameEdit->text().toStdString();
result["type"] = types[ui->TypeComboBox->currentIndex()];
result["layout"] = ui->LayoutComboBox->currentIndex();
result["single"] = ui->SingleCheckBox->isChecked();
result["linear"] = ui->LinearCheckBox->isChecked();
result["resizable"] = ui->ResizableCheckBox->isChecked();
result["keyboard"] = ui->KeyboardCheckBox->isChecked();
result["underglow"] = ui->UnderglowCheckBox->isChecked();
return result;
}
bool DebugSettingsEntry::isDataValid()
{
return true;
}
static BaseManualDeviceEntry* SpawnDebugEntry(const json& data)
{
DebugSettingsEntry* entry = new DebugSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
static const char* DebugDeviceName = QT_TRANSLATE_NOOP("ManualDevice", "Debug Device");
REGISTER_MANUAL_DEVICE_TYPE(DebugDeviceName, "DebugDevices", SpawnDebugEntry);
@@ -0,0 +1,37 @@
/*---------------------------------------------------------*\
| DebugSettingsEntry.h |
| |
| User interface for OpenRGB Debug settings entry |
| |
| Adam Honse <calcprogrammer1@gmail.com> 30 Jul 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class DebugSettingsEntry;
}
class DebugSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit DebugSettingsEntry(QWidget *parent = nullptr);
~DebugSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::DebugSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
};
@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DebugSettingsEntry</class>
<widget class="QWidget" name="DebugSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>293</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Debug Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Debug Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QLabel" name="TypeLabel">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="NameEdit">
<property name="placeholderText">
<string>Device Name</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="TypeComboBox"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_Zones">
<property name="title">
<string>Zones</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QCheckBox" name="KeyboardCheckBox">
<property name="text">
<string>Keyboard</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="LinearCheckBox">
<property name="text">
<string>Linear</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="SingleCheckBox">
<property name="text">
<string>Single</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ResizableCheckBox">
<property name="text">
<string>Resizable</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="UnderglowCheckBox">
<property name="text">
<string>Underglow</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="LayoutLabel">
<property name="text">
<string>Layout:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="LayoutComboBox"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,302 @@
/*---------------------------------------------------------*\
| E131SettingsEntry.cpp |
| |
| User interface for OpenRGB E1.31 settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "E131SettingsEntry.h"
#include "ui_E131SettingsEntry.h"
E131SettingsEntry::E131SettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::E131SettingsEntry)
{
ui->setupUi(this);
ui->TypeComboBox->addItem(tr("Single"));
ui->TypeComboBox->addItem(tr("Linear"));
ui->TypeComboBox->addItem(tr("Matrix"));
ui->MatrixOrderComboBox->addItem(tr("Horizontal Top Left"));
ui->MatrixOrderComboBox->addItem(tr("Horizontal Top Right"));
ui->MatrixOrderComboBox->addItem(tr("Horizontal Bottom Left"));
ui->MatrixOrderComboBox->addItem(tr("Horizontal Bottom Right"));
ui->MatrixOrderComboBox->addItem(tr("Vertical Top Left"));
ui->MatrixOrderComboBox->addItem(tr("Vertical Top Right"));
ui->MatrixOrderComboBox->addItem(tr("Vertical Bottom Left"));
ui->MatrixOrderComboBox->addItem(tr("Vertical Bottom Right"));
ui->RGBOrderComboBox->addItem("RGB");
ui->RGBOrderComboBox->addItem("RBG");
ui->RGBOrderComboBox->addItem("GRB");
ui->RGBOrderComboBox->addItem("GBR");
ui->RGBOrderComboBox->addItem("BRG");
ui->RGBOrderComboBox->addItem("BGR");
HideMatrixSettings();
}
E131SettingsEntry::~E131SettingsEntry()
{
delete ui;
}
void E131SettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void E131SettingsEntry::HideMatrixSettings()
{
ui->MatrixWidthLabel->setDisabled(true);
ui->MatrixWidthEdit->setDisabled(true);
ui->MatrixHeightLabel->setDisabled(true);
ui->MatrixHeightEdit->setDisabled(true);
ui->MatrixOrderLabel->setDisabled(true);
ui->MatrixOrderComboBox->setDisabled(true);
}
void E131SettingsEntry::ShowMatrixSettings()
{
ui->MatrixWidthLabel->setDisabled(false);
ui->MatrixWidthEdit->setDisabled(false);
ui->MatrixHeightLabel->setDisabled(false);
ui->MatrixHeightEdit->setDisabled(false);
ui->MatrixOrderLabel->setDisabled(false);
ui->MatrixOrderComboBox->setDisabled(false);
}
void E131SettingsEntry::on_TypeComboBox_currentIndexChanged(int index)
{
if(index == 2)
{
ShowMatrixSettings();
}
else
{
HideMatrixSettings();
}
}
void E131SettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
if(data.contains("start_universe"))
{
ui->StartUniverseEdit->setText(QString::number((int)data["start_universe"]));
}
if(data.contains("start_channel"))
{
ui->StartChannelEdit->setText(QString::number((int)data["start_channel"]));
}
if(data.contains("num_leds"))
{
ui->NumLEDsEdit->setText(QString::number((int)data["num_leds"]));
}
if(data.contains("type"))
{
if(data["type"].is_string())
{
std::string type_val = data["type"];
if(type_val == "SINGLE")
{
ui->TypeComboBox->setCurrentIndex(0);
}
else if(type_val == "LINEAR")
{
ui->TypeComboBox->setCurrentIndex(1);
}
else if(type_val == "MATRIX")
{
ui->TypeComboBox->setCurrentIndex(2);
}
}
else
{
ui->TypeComboBox->setCurrentIndex(data["type"]);
}
}
if(data.contains("rgb_order"))
{
if(data["rgb_order"].is_string())
{
std::string rgb_order_val = data["rgb_order"];
if(rgb_order_val == "RGB")
{
ui->RGBOrderComboBox->setCurrentIndex(0);
}
else if(rgb_order_val == "RBG")
{
ui->RGBOrderComboBox->setCurrentIndex(1);
}
else if(rgb_order_val == "GRB")
{
ui->RGBOrderComboBox->setCurrentIndex(2);
}
else if(rgb_order_val == "GBR")
{
ui->RGBOrderComboBox->setCurrentIndex(3);
}
else if(rgb_order_val == "BRG")
{
ui->RGBOrderComboBox->setCurrentIndex(4);
}
else if(rgb_order_val == "BGR")
{
ui->RGBOrderComboBox->setCurrentIndex(5);
}
}
else
{
ui->RGBOrderComboBox->setCurrentIndex(data["rgb_order"]);
}
}
if(data.contains("matrix_width"))
{
ui->MatrixWidthEdit->setText(QString::number((int)data["matrix_width"]));
}
if(data.contains("matrix_height"))
{
ui->MatrixHeightEdit->setText(QString::number((int)data["matrix_height"]));
}
if(data.contains("matrix_order"))
{
if(data["matrix_order"].is_string())
{
std::string matrix_order_val = data["matrix_order"];
if(matrix_order_val == "HORIZONTAL_TOP_LEFT")
{
ui->MatrixOrderComboBox->setCurrentIndex(0);
}
else if(matrix_order_val == "HORIZONTAL_TOP_RIGHT")
{
ui->MatrixOrderComboBox->setCurrentIndex(1);
}
else if(matrix_order_val == "HORIZONTAL_BOTTOM_LEFT")
{
ui->MatrixOrderComboBox->setCurrentIndex(2);
}
else if(matrix_order_val == "HORIZONTAL_BOTTOM_RIGHT")
{
ui->MatrixOrderComboBox->setCurrentIndex(3);
}
else if(matrix_order_val == "VERTICAL_TOP_LEFT")
{
ui->MatrixOrderComboBox->setCurrentIndex(4);
}
else if(matrix_order_val == "VERTICAL_TOP_RIGHT")
{
ui->MatrixOrderComboBox->setCurrentIndex(5);
}
else if(matrix_order_val == "VERTICAL_BOTTOM_LEFT")
{
ui->MatrixOrderComboBox->setCurrentIndex(6);
}
else if(matrix_order_val == "VERTICAL_BOTTOM_RIGHT")
{
ui->MatrixOrderComboBox->setCurrentIndex(7);
}
}
else
{
ui->MatrixOrderComboBox->setCurrentIndex(data["matrix_order"]);
}
}
if(data.contains("universe_size"))
{
ui->UniverseSizeEdit->setText(QString::number((int)data["universe_size"]));
}
if(data.contains("keepalive_time"))
{
ui->KeepaliveTimeEdit->setText(QString::number((int)data["keepalive_time"]));
}
}
json E131SettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["name"] = ui->NameEdit->text().toStdString();
result["start_universe"] = ui->StartUniverseEdit->text().toUInt();
result["start_channel"] = ui->StartChannelEdit->text().toUInt();
result["num_leds"] = ui->NumLEDsEdit->text().toUInt();
result["type"] = ui->TypeComboBox->currentIndex();
result["rgb_order"] = ui->RGBOrderComboBox->currentIndex();
/*-------------------------------------------------*\
| Optional parameters |
\*-------------------------------------------------*/
if(ui->IPEdit->text() != "")
{
result["ip"] = ui->IPEdit->text().toStdString();
}
if(result["type"] == 2)
{
result["matrix_width"] = ui->MatrixWidthEdit->text().toUInt();
result["matrix_height"] = ui->MatrixHeightEdit->text().toUInt();
result["matrix_order"] = ui->MatrixOrderComboBox->currentIndex();
}
if(ui->UniverseSizeEdit->text() != "")
{
result["universe_size"] = ui->UniverseSizeEdit->text().toUInt();
}
if(ui->KeepaliveTimeEdit->text() != "")
{
result["keepalive_time"] = ui->KeepaliveTimeEdit->text().toUInt();
}
return result;
}
bool E131SettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnE131Entry(const json& data)
{
E131SettingsEntry* entry = new E131SettingsEntry;
entry->loadFromSettings(data);
return entry;
}
static const char* E131DeviceName = QT_TRANSLATE_NOOP("ManualDevice", "E1.31 (including WLED)");
REGISTER_MANUAL_DEVICE_TYPE(E131DeviceName, "E131Devices", SpawnE131Entry);
@@ -0,0 +1,40 @@
/*---------------------------------------------------------*\
| E131SettingsEntry.h |
| |
| User interface for OpenRGB E1.31 settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class E131SettingsEntry;
}
class E131SettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit E131SettingsEntry(QWidget *parent = nullptr);
~E131SettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::E131SettingsEntry *ui;
private:
void HideMatrixSettings();
void ShowMatrixSettings();
private slots:
void changeEvent(QEvent *event) override;
void on_TypeComboBox_currentIndexChanged(int index);
};
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>E131SettingsEntry</class>
<widget class="QWidget" name="E131SettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>531</width>
<height>256</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">E.131 Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>E1.31 Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="5">
<widget class="QLineEdit" name="StartChannelEdit"/>
</item>
<item row="5" column="3">
<widget class="QLineEdit" name="NumLEDsEdit"/>
</item>
<item row="6" column="3">
<widget class="QLineEdit" name="MatrixWidthEdit"/>
</item>
<item row="2" column="4">
<widget class="QLabel" name="StartChannelLabel">
<property name="text">
<string>Start Channel:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="NumLEDsLabel">
<property name="text">
<string>Number of LEDs:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="StartUniverseEdit"/>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="NameEdit"/>
</item>
<item row="7" column="3">
<widget class="QComboBox" name="MatrixOrderComboBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="StartUniverseLabel">
<property name="text">
<string>Start Universe:</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QLineEdit" name="IPEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="MatrixOrderLabel">
<property name="text">
<string>Matrix Order:</string>
</property>
</widget>
</item>
<item row="5" column="5">
<widget class="QComboBox" name="TypeComboBox"/>
</item>
<item row="6" column="5">
<widget class="QLineEdit" name="MatrixHeightEdit"/>
</item>
<item row="6" column="4">
<widget class="QLabel" name="MatrixHeightLabel">
<property name="text">
<string>Matrix Height:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="MatrixWidthLabel">
<property name="text">
<string>Matrix Width:</string>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QLabel" name="TypeLabel">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP (Unicast):</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="UniverseSizeLabel">
<property name="text">
<string>Universe Size:</string>
</property>
</widget>
</item>
<item row="8" column="3">
<widget class="QLineEdit" name="UniverseSizeEdit"/>
</item>
<item row="8" column="4">
<widget class="QLabel" name="KeepaliveTimeLabel">
<property name="text">
<string>Keepalive Time:</string>
</property>
</widget>
</item>
<item row="8" column="5">
<widget class="QLineEdit" name="KeepaliveTimeEdit"/>
</item>
<item row="7" column="4">
<widget class="QLabel" name="RGBOrderLabel">
<property name="text">
<string>RGB Order:</string>
</property>
</widget>
</item>
<item row="7" column="5">
<widget class="QComboBox" name="RGBOrderComboBox"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>NameEdit</tabstop>
<tabstop>IPEdit</tabstop>
<tabstop>StartUniverseEdit</tabstop>
<tabstop>StartChannelEdit</tabstop>
<tabstop>NumLEDsEdit</tabstop>
<tabstop>TypeComboBox</tabstop>
<tabstop>MatrixWidthEdit</tabstop>
<tabstop>MatrixHeightEdit</tabstop>
<tabstop>MatrixOrderComboBox</tabstop>
<tabstop>UniverseSizeEdit</tabstop>
<tabstop>KeepaliveTimeEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,62 @@
/*---------------------------------------------------------*\
| ElgatoKeyLightSettingsEntry.cpp |
| |
| User interface for OpenRGB Elgato Key Light entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "ElgatoKeyLightSettingsEntry.h"
#include "ui_ElgatoKeyLightSettingsEntry.h"
ElgatoKeyLightSettingsEntry::ElgatoKeyLightSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::ElgatoKeyLightSettingsEntry)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
}
ElgatoKeyLightSettingsEntry::~ElgatoKeyLightSettingsEntry()
{
delete ui;
}
void ElgatoKeyLightSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void ElgatoKeyLightSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
}
json ElgatoKeyLightSettingsEntry::saveSettings()
{
json result;
result["ip"] = ui->IPEdit->text().toStdString();
return result;
}
bool ElgatoKeyLightSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnElgatoKeyLightEntry(const json& data)
{
ElgatoKeyLightSettingsEntry* entry = new ElgatoKeyLightSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("Elgato Key Light", "ElgatoKeyLightDevices", SpawnElgatoKeyLightEntry);
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| ElgatoKeyLightSettingsEntry.h |
| |
| User interface for OpenRGB Elgato Key Light entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class ElgatoKeyLightSettingsEntry;
}
class ElgatoKeyLightSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit ElgatoKeyLightSettingsEntry(QWidget *parent = nullptr);
~ElgatoKeyLightSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::ElgatoKeyLightSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
};
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ElgatoKeyLightSettingsEntry</class>
<widget class="QWidget" name="ElgatoKeyLightSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>225</width>
<height>108</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Elgato Key Light Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Elgato Key Light</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0" rowspan="2" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLineEdit" name="IPEdit"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,63 @@
/*---------------------------------------------------------*\
| ElgatoLightStripSettingsEntry.cpp |
| |
| User interface for OpenRGB Elgato Light Strips entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "ElgatoLightStripSettingsEntry.h"
#include "ui_ElgatoLightStripSettingsEntry.h"
ElgatoLightStripSettingsEntry::ElgatoLightStripSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::ElgatoLightStripSettingsEntry)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
}
ElgatoLightStripSettingsEntry::~ElgatoLightStripSettingsEntry()
{
delete ui;
}
void ElgatoLightStripSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void ElgatoLightStripSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
}
json ElgatoLightStripSettingsEntry::saveSettings()
{
json result;
result["ip"] = ui->IPEdit->text().toStdString();
return result;
}
bool ElgatoLightStripSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnElgatoLightStripEntry(const json& data)
{
ElgatoLightStripSettingsEntry* entry = new ElgatoLightStripSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("Elgato Light Strip", "ElgatoLightStripDevices", SpawnElgatoLightStripEntry);
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| ElgatoLightStripSettingsEntry.h |
| |
| User interface for OpenRGB Elgato Light Strips entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class ElgatoLightStripSettingsEntry;
}
class ElgatoLightStripSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit ElgatoLightStripSettingsEntry(QWidget *parent = nullptr);
~ElgatoLightStripSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::ElgatoLightStripSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
};
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ElgatoLightStripSettingsEntry</class>
<widget class="QWidget" name="ElgatoLightStripSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>225</width>
<height>108</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Elgato Light Strip Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Elgato Light Strip</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0" rowspan="2" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLineEdit" name="IPEdit"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,63 @@
/*---------------------------------------------------------*\
| GoveeSettingsEntry.cpp |
| |
| User interface for OpenRGB Govee settings entry |
| |
| Adam Honse (calcprogrammer1@gmail.com) 15 May 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "GoveeSettingsEntry.h"
#include "ui_GoveeSettingsEntry.h"
GoveeSettingsEntry::GoveeSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::GoveeSettingsEntry)
{
ui->setupUi(this);
}
GoveeSettingsEntry::~GoveeSettingsEntry()
{
delete ui;
}
void GoveeSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void GoveeSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
}
json GoveeSettingsEntry::saveSettings()
{
json result;
result["ip"] = ui->IPEdit->text().toStdString();
return result;
}
bool GoveeSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnGoveeSettingsEntry(const json& data)
{
GoveeSettingsEntry* entry = new GoveeSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("Govee", "GoveeDevices", SpawnGoveeSettingsEntry);
@@ -0,0 +1,37 @@
/*---------------------------------------------------------*\
| GoveeSettingsEntry.h |
| |
| User interface for OpenRGB Govee settings entry |
| |
| Adam Honse (calcprogrammer1@gmail.com) 15 May 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class GoveeSettingsEntry;
}
class GoveeSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit GoveeSettingsEntry(QWidget *parent = nullptr);
~GoveeSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::GoveeSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
};
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GoveeSettingsEntry</class>
<widget class="QWidget" name="GoveeSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>328</width>
<height>81</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Philips Wiz Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Govee Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="IPEdit"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,71 @@
/*---------------------------------------------------------*\
| KasaSmartSettingsEntry.cpp |
| |
| User interface for OpenRGB Kasa Smart settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "KasaSmartSettingsEntry.h"
#include "ui_KasaSmartSettingsEntry.h"
KasaSmartSettingsEntry::KasaSmartSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::KasaSmartSettingsEntry)
{
ui->setupUi(this);
}
KasaSmartSettingsEntry::~KasaSmartSettingsEntry()
{
delete ui;
}
void KasaSmartSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void KasaSmartSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
}
json KasaSmartSettingsEntry::saveSettings()
{
json result;
result["ip"] = ui->IPEdit->text().toStdString();
result["name"] = ui->NameEdit->text().toStdString();
return result;
}
void KasaSmartSettingsEntry::setName(QString name)
{
ui->NameEdit->setText(name);
}
bool KasaSmartSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnKasaSmartSettingsEntry(const json& data)
{
KasaSmartSettingsEntry* entry = new KasaSmartSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("Kasa Smart", "KasaSmartDevices", SpawnKasaSmartSettingsEntry);
@@ -0,0 +1,37 @@
/*---------------------------------------------------------*\
| KasaSmartSettingsEntry.h |
| |
| User interface for OpenRGB Kasa Smart settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class KasaSmartSettingsEntry;
}
class KasaSmartSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit KasaSmartSettingsEntry(QWidget *parent = nullptr);
~KasaSmartSettingsEntry();
void loadFromSettings(const json& data);
void setName(QString name);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::KasaSmartSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
};
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>KasaSmartSettingsEntry</class>
<widget class="QWidget" name="KasaSmartSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>216</width>
<height>89</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Kasa Smart Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Kasa Smart Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="5">
<widget class="QLineEdit" name="NameEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="IPEdit"/>
</item>
<item row="1" column="4">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>IPEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,96 @@
/*---------------------------------------------------------*\
| LIFXSettingsEntry.cpp |
| |
| User interface for OpenRGB LIFX settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "LIFXSettingsEntry.h"
#include "ui_LIFXSettingsEntry.h"
LIFXSettingsEntry::LIFXSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::LIFXSettingsEntry)
{
ui->setupUi(this);
connect(ui->MultizoneCheckBox, SIGNAL(stateChanged(int)), this, SLOT(on_MultizoneCheckBox_stateChanged(int)));
}
LIFXSettingsEntry::~LIFXSettingsEntry()
{
delete ui;
}
void LIFXSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void LIFXSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
if(data.contains("multizone") && data["multizone"].is_boolean())
{
ui->MultizoneCheckBox->setCheckState(data["multizone"] == true ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
}
if(data.contains("extended_multizone") && data["extended_multizone"].is_boolean())
{
ui->ExtendedMultizoneCheckBox->setCheckState(data["extended_multizone"] == true ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
}
}
json LIFXSettingsEntry::saveSettings()
{
json result;
result["ip"] = ui->IPEdit->text().toStdString();
result["name"] = ui->NameEdit->text().toStdString();
result["multizone"] = ui->MultizoneCheckBox->checkState() == Qt::Checked;
result["extended_multizone"] = ui->ExtendedMultizoneCheckBox->checkState() == Qt::Checked;
return result;
}
void LIFXSettingsEntry::setName(QString name)
{
ui->NameEdit->setText(name);
}
void LIFXSettingsEntry::on_MultizoneCheckBox_stateChanged(int checkState)
{
if (checkState == Qt::Checked)
{
ui->ExtendedMultizoneCheckBox->setEnabled(true);
}
else
{
ui->ExtendedMultizoneCheckBox->setEnabled(false);
ui->ExtendedMultizoneCheckBox->setCheckState(Qt::Unchecked);
}
}
bool LIFXSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnLIFXSettingsEntry(const json& data)
{
LIFXSettingsEntry* entry = new LIFXSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("LIFX", "LIFXDevices", SpawnLIFXSettingsEntry);
@@ -0,0 +1,36 @@
/*---------------------------------------------------------*\
| LIFXSettingsEntry.h |
| |
| User interface for OpenRGB LIFX settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class LIFXSettingsEntry;
}
class LIFXSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit LIFXSettingsEntry(QWidget *parent = nullptr);
~LIFXSettingsEntry();
void loadFromSettings(const json& data);
void setName(QString name);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::LIFXSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
void on_MultizoneCheckBox_stateChanged(int arg1);
};
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LIFXSettingsEntry</class>
<widget class="QWidget" name="LIFXSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>89</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">LIFX Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>LIFX Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="3">
<widget class="QLineEdit" name="IPEdit"/>
</item>
<item row="1" column="6">
<widget class="QCheckBox" name="MultizoneCheckBox">
<property name="text">
<string>Multizone</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QLineEdit" name="NameEdit"/>
</item>
<item row="1" column="7">
<widget class="QCheckBox" name="ExtendedMultizoneCheckBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Extended Multizone</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>IPEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,340 @@
/*---------------------------------------------------------*\
| ManualDevicesSettingsPage.cpp |
| |
| User interface for OpenRGB Manually Added Devices |
| settings page |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "ManualDevicesSettingsPage.h"
#include "ui_ManualDevicesSettingsPage.h"
#include "NanoleafSettingsEntry.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
#include <QLineEdit>
static void ManualDevicesPageReloadCallback(void* this_ptr)
{
ManualDevicesSettingsPage * this_obj = (ManualDevicesSettingsPage *)this_ptr;
QMetaObject::invokeMethod(this_obj, "reloadList", Qt::QueuedConnection);
}
ManualDevicesSettingsPage::ManualDevicesSettingsPage(QWidget *parent) :
QWidget(parent),
ui(new Ui::ManualDevicesSettingsPage)
{
ui->setupUi(this);
ResourceManager::get()->RegisterDetectionEndCallback(&ManualDevicesPageReloadCallback, this);
addDeviceMenu = new QMenu(this);
ui->addDeviceButton->setMenu(addDeviceMenu);
connect(addDeviceMenu, &QMenu::triggered, this, &ManualDevicesSettingsPage::onAddDeviceItemSelected);
QMenu* saveButtonMenu = new QMenu(this);
saveButtonMenu->addAction(ui->ActionSaveAndRescan);
saveButtonMenu->addAction(ui->ActionSaveNoRescan);
ui->saveConfigurationButton->setMenu(saveButtonMenu);
ui->saveConfigurationButton->setDefaultAction(ui->ActionSaveAndRescan);
reloadList();
}
ManualDevicesSettingsPage::~ManualDevicesSettingsPage()
{
ResourceManager::get()->UnregisterDetectionEndCallback(&ManualDevicesPageReloadCallback, this);
clearList();
delete ui;
}
void ManualDevicesSettingsPage::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
reloadMenu();
}
}
void ManualDevicesSettingsPage::on_removeDeviceButton_clicked()
{
int cur_row = ui->deviceList->currentRow();
if(cur_row < 0)
{
return;
}
QListWidgetItem* item = ui->deviceList->takeItem(cur_row);
ui->deviceList->removeItemWidget(item);
delete item;
BaseManualDeviceEntry* entry = entries[cur_row];
entries.erase(entries.begin() + cur_row);
delete entry;
setUnsavedChanges(true);
}
void ManualDevicesSettingsPage::saveSettings()
{
SettingsManager* sm = ResourceManager::get()->GetSettingsManager();
json result;
/*-----------------------------------------------------------------------------*\
| First, cache the data that will be stored as JSON |
| We wrap data into arrays by type (except Nanoleaf) |
| Nanoleaf stores it's data as an object with "location" as key for some reason |
\*-----------------------------------------------------------------------------*/
for(std::size_t idx = 0; idx < entries.size(); idx++)
{
std::string section = entries[idx]->getSettingsSection();
if(section == "NanoleafDevices")
{
NanoleafSettingsEntry* entry = dynamic_cast<NanoleafSettingsEntry*>(entries[idx]);
result[section]["devices"][entry->getLocation()] = entries[idx]->saveSettings();
}
else if(section == "PhilipsHueDevices")
{
result[section]["bridges"].push_back(entries[idx]->saveSettings());
}
else
{
result[section]["devices"].push_back(entries[idx]->saveSettings());
}
}
/*---------------------------------------------------------*\
| Transfer data from the cached object into config sections |
| Use ALL possible settings entry names, so that those with |
| all entries deleted are cleared properly |
\*---------------------------------------------------------*/
std::vector<ManualDeviceTypeBlock> blocks = ManualDevicesTypeManager::get()->getRegisteredTypes();
for(std::size_t i = 0; i < blocks.size(); i++)
{
sm->SetSettings(blocks[i].settingsSection, result[blocks[i].settingsSection]);
}
sm->SaveSettings();
setUnsavedChanges(false);
}
void ManualDevicesSettingsPage::reloadMenu()
{
std::vector<std::string> names = ManualDevicesTypeManager::get()->getRegisteredTypeNames();
addDeviceMenu->clear();
for(std::size_t i = 0; i < names.size(); i++)
{
QAction* action = addDeviceMenu->addAction(qApp->translate("ManualDevice", names[i].c_str()));
action->setData(QString::fromStdString(names[i]));
}
}
void ManualDevicesSettingsPage::reloadList()
{
clearList();
addDeviceMenu->clear();
std::vector<ManualDeviceTypeBlock> blocks = ManualDevicesTypeManager::get()->getRegisteredTypes();
for(std::size_t i = 0; i < blocks.size(); i++)
{
addEntries(blocks[i]);
/*------------------------------------------------------------*\
| While we have all the data at hand, load in the menu as well |
\*------------------------------------------------------------*/
QAction* action = addDeviceMenu->addAction(qApp->translate("ManualDevice", blocks[i].name.c_str()));
action->setData(QString::fromStdString(blocks[i].name));
}
/*---------------------------------------------------------*\
| Refresh button state |
\*---------------------------------------------------------*/
setUnsavedChanges(false);
on_deviceList_itemSelectionChanged();
}
void ManualDevicesSettingsPage::onTextEditChanged()
{
setUnsavedChanges(true);
}
void ManualDevicesSettingsPage::clearList()
{
std::vector<BaseManualDeviceEntry*> entries_copy;
entries_copy.swap(entries);
ui->deviceList->clear();
for(std::size_t i = 0; i < entries_copy.size(); i++)
{
delete entries_copy[i];
}
entries_copy.clear();
setUnsavedChanges(true);
}
void ManualDevicesSettingsPage::setUnsavedChanges(bool v)
{
unsavedChanges = v;
if(v)
{
ui->saveConfigurationButton->setStyleSheet("font: bold");
}
else
{
ui->saveConfigurationButton->setStyleSheet("");
}
}
bool ManualDevicesSettingsPage::checkValidToSave()
{
for(std::size_t i = 0; i < entries.size(); i++)
{
if(!entries[i]->isDataValid())
{
return false;
}
}
return true;
}
QListWidgetItem* ManualDevicesSettingsPage::addEntry(BaseManualDeviceEntry* entry)
{
if(!entry)
{
return nullptr;
}
/*---------------------------------------------------------*\
| Find EVERY QLineEdit in the entry and get notified if ANY |
| text in them changes - for validation |
| Validation mostly affects the "Save" button state |
\*---------------------------------------------------------*/
QList<QLineEdit*> textEditList = entry->findChildren<QLineEdit*>(QString(), Qt::FindChildrenRecursively);
for(qsizetype i = 0; i < textEditList.size(); i++)
{
connect(textEditList[i], &QLineEdit::textChanged, this, &ManualDevicesSettingsPage::onTextEditChanged);
}
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(entry->sizeHint());
ui->deviceList->addItem(item);
ui->deviceList->setItemWidget(item, entry);
ui->deviceList->show();
entries.push_back(entry);
/*---------------------------------------------------------*\
| New entries generally indicate unsaved changes |
\*---------------------------------------------------------*/
setUnsavedChanges(true);
return item;
}
void ManualDevicesSettingsPage::addEntries(const ManualDeviceTypeBlock& block)
{
/*---------------------------------------------------------*\
| Spawn list entries for all config entries of one type |
\*---------------------------------------------------------*/
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings(block.settingsSection);
const char* array_name = "devices";
if(block.settingsSection == "PhilipsHueDevices")
{
array_name = "bridges";
}
if(settings.contains(array_name))
{
json& array_ref = settings[array_name];
if(!array_ref.is_array() && !array_ref.is_object())
{
return;
}
/*-----------------------------------------------------------------*\
| Nanoleaf stores it's data as objects with location field as "key" |
| everything else is arrays |
| For uniformity, use iterators, as if it's always an object |
\*-----------------------------------------------------------------*/
for(json::const_iterator iter = array_ref.begin(); iter != array_ref.end(); ++iter)
{
if(!iter.value().empty())
{
BaseManualDeviceEntry* entry = block.spawn(iter.value());
/*---------------------------------------------------*\
| Note: spawn functions are allowed to return nullptr |
\*---------------------------------------------------*/
if(entry)
{
addEntry(entry);
}
}
}
}
}
void ManualDevicesSettingsPage::onAddDeviceItemSelected(QAction* action)
{
/*---------------------------------------------------------*\
| Spawn new entry based on name |
\*---------------------------------------------------------*/
std::string entryName = action->data().toString().toStdString();
BaseManualDeviceEntry* entry = ManualDevicesTypeManager::get()->spawnByTypeName(entryName, json());
/*---------------------------------------------------------*\
| Note: spawn functions are allowed to return nullptr |
\*---------------------------------------------------------*/
if(entry)
{
QListWidgetItem* item = addEntry(entry);
/*-----------------------------------------------------*\
| Scroll to the newly added entry (last one in the list |
\*-----------------------------------------------------*/
if(item)
{
ui->deviceList->scrollToItem(item);
}
}
}
void ManualDevicesSettingsPage::on_deviceList_itemSelectionChanged()
{
/*---------------------------------------------------------*\
| Enable Remove button if any entry is selected |
\*---------------------------------------------------------*/
int cur_row = ui->deviceList->currentRow();
bool anySelected = (cur_row >= 0);
ui->removeDeviceButton->setEnabled(anySelected);
}
void ManualDevicesSettingsPage::on_ActionSaveNoRescan_triggered()
{
saveSettings();
}
void ManualDevicesSettingsPage::on_ActionSaveAndRescan_triggered()
{
saveSettings();
/*---------------------------------------------------------*\
| Trigger rescan |
\*---------------------------------------------------------*/
ResourceManager::get()->RescanDevices();
}
@@ -0,0 +1,61 @@
/*-----------------------------------------------------------------*\
| ManualDevicesSettingsPage.h |
| |
| User interface for OpenRGB Manually Added Devices settings page |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*-----------------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
#include "ManualDevicesTypeManager.h"
#include "nlohmann/json.hpp"
#include <QWidget>
#include <QMenu>
#include <QListWidgetItem>
using json = nlohmann::json;
namespace Ui
{
class ManualDevicesSettingsPage;
}
class ManualDevicesSettingsPage : public QWidget
{
Q_OBJECT
public:
explicit ManualDevicesSettingsPage(QWidget *parent = nullptr);
~ManualDevicesSettingsPage();
public slots:
void reloadList();
void reloadMenu();
private slots:
void onTextEditChanged(); // Slot connected to all text edits in all entries; for validation & marking dirty changes
void onAddDeviceItemSelected(QAction* action);
void changeEvent(QEvent *event);
void on_removeDeviceButton_clicked();
void on_deviceList_itemSelectionChanged();
void on_ActionSaveNoRescan_triggered();
void on_ActionSaveAndRescan_triggered();
private:
Ui::ManualDevicesSettingsPage* ui;
std::vector<BaseManualDeviceEntry*> entries;
QMenu* addDeviceMenu;
bool unsavedChanges;
QListWidgetItem* addEntry(BaseManualDeviceEntry* entry);
void addEntries(const ManualDeviceTypeBlock&);
void clearList();
void saveSettings();
void setUnsavedChanges(bool v);
bool checkValidToSave();
};
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ManualDevicesSettingsPage</class>
<widget class="QWidget" name="ManualDevicesSettingsPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Manually Added Devices Settings Page</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListWidget" name="deviceList">
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="addDeviceButton">
<property name="text">
<string>Add Device...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeDeviceButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="saveConfigurationButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Save and Rescan</string>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<action name="ActionSaveAndRescan">
<property name="text">
<string>Save and Rescan</string>
</property>
</action>
<action name="ActionSaveNoRescan">
<property name="text">
<string>Save without Rescan</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,84 @@
/*---------------------------------------------------------*\
| ManualDevicesTypeManager.cpp |
| |
| OpenRGB Manual Devices Type Manager registers available |
| types of Manually Added devices and generates UI |
| elements for their settings |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "ManualDevicesTypeManager.h"
ManualDeviceTypeBlock::ManualDeviceTypeBlock(const std::string& _name, const std::string& _settingsSection, ManualDeviceEntrySpawnFunction _entrySpawnFunction)
{
name = _name;
settingsSection = _settingsSection;
entrySpawnFunction = _entrySpawnFunction;
}
BaseManualDeviceEntry* ManualDeviceTypeBlock::spawn(const json& data) const
{
BaseManualDeviceEntry* result = entrySpawnFunction(data);
if(result)
{
result->setSettingsSection(settingsSection);
}
return result;
}
ManualDevicesTypeManager* ManualDevicesTypeManager::instance;
ManualDevicesTypeManager *ManualDevicesTypeManager::get()
{
if(!instance)
{
instance = new ManualDevicesTypeManager();
}
return instance;
}
ManualDevicesTypeManager::ManualDevicesTypeManager()
{
}
void ManualDevicesTypeManager::registerType(const std::string& name, const std::string& settingsSection, ManualDeviceEntrySpawnFunction entrySpawnFunction)
{
types.push_back(ManualDeviceTypeBlock(name, settingsSection, entrySpawnFunction));
}
std::vector<ManualDeviceTypeBlock> ManualDevicesTypeManager::getRegisteredTypes()
{
return types;
}
std::vector<std::string> ManualDevicesTypeManager::getRegisteredTypeNames()
{
std::vector<std::string> result;
result.resize(types.size());
for(std::size_t i = 0; i < types.size(); i++)
{
result[i] = types[i].name;
}
return result;
}
BaseManualDeviceEntry* ManualDevicesTypeManager::spawnByTypeName(const std::string& typeName, const json& data)
{
for(std::size_t i = 0; i < types.size(); i++)
{
if(types[i].name == typeName)
{
return types[i].spawn(data);
}
}
return nullptr;
}
@@ -0,0 +1,50 @@
/*---------------------------------------------------------*\
| ManualDevicesTypeManager.h |
| |
| OpenRGB Manual Devices Type Manager registers UI |
| classes for managing Manually Added devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
#include <vector>
#include <string>
#include "nlohmann/json.hpp"
using json = nlohmann::json;
class ManualDeviceTypeBlock
{
public:
ManualDeviceTypeBlock(const std::string& name, const std::string& settingsSection, ManualDeviceEntrySpawnFunction entrySpawnFunction);
std::string name; // Name as listed in the drop-down list
std::string settingsSection; // Settings Section name, as listed in Config file
BaseManualDeviceEntry* spawn(const json &data) const;
private:
ManualDeviceEntrySpawnFunction entrySpawnFunction;
};
class ManualDevicesTypeManager
{
public:
static ManualDevicesTypeManager* get();
void registerType(const std::string& name, const std::string& settingsSection, ManualDeviceEntrySpawnFunction entrySpawnFunction);
std::vector<ManualDeviceTypeBlock> getRegisteredTypes();
std::vector<std::string> getRegisteredTypeNames();
BaseManualDeviceEntry* spawnByTypeName(const std::string& typeName, const json& data);
private:
static ManualDevicesTypeManager* instance;
std::vector<ManualDeviceTypeBlock> types;
ManualDevicesTypeManager();
};
@@ -0,0 +1,58 @@
/*---------------------------------------------------------*\
| NanoleafNewDeviceDialog.cpp |
| |
| User interface for OpenRGB Nanoleaf dialog |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <QCloseEvent>
#include "ResourceManager.h"
#include "NanoleafNewDeviceDialog.h"
#include "ui_NanoleafNewDeviceDialog.h"
#ifdef _WIN32
#include <QSettings>
#endif
NanoleafNewDeviceDialog::NanoleafNewDeviceDialog(QWidget *parent) :
QDialog(parent), ui(new Ui::NanoleafNewDeviceDialog)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
ui->devicePortEdit->setText("16021");
}
NanoleafNewDeviceDialog::~NanoleafNewDeviceDialog()
{
delete ui;
}
void NanoleafNewDeviceDialog::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
NanoleafDevice NanoleafNewDeviceDialog::show()
{
NanoleafDevice return_device;
int result = this->exec();
if(result != QDialog::Rejected)
{
return_device.ip = ui->deviceIPEdit->text().toStdString();
return_device.port = ui->devicePortEdit->text().toInt();
}
else
{
return_device.ip = "";
return_device.port = 0;
}
return(return_device);
}
@@ -0,0 +1,38 @@
/*---------------------------------------------------------*\
| NanoleafNewDeviceDialog.h |
| |
| User interface for OpenRGB Nanoleaf dialog |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <QDialog>
struct NanoleafDevice
{
std::string ip;
unsigned int port;
};
namespace Ui
{
class NanoleafNewDeviceDialog;
}
class NanoleafNewDeviceDialog : public QDialog
{
Q_OBJECT
public:
explicit NanoleafNewDeviceDialog(QWidget *parent = nullptr);
~NanoleafNewDeviceDialog();
NanoleafDevice show();
private:
Ui::NanoleafNewDeviceDialog *ui;
private slots:
void changeEvent(QEvent *event);
};
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NanoleafNewDeviceDialog</class>
<widget class="QDialog" name="NanoleafNewDeviceDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>184</width>
<height>186</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>New Nanoleaf device</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="deviceIPLabel">
<property name="text">
<string>IP address:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="deviceIPEdit"/>
</item>
<item>
<widget class="QLabel" name="devicePortLabel">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="devicePortEdit"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>NanoleafNewDeviceDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>NanoleafNewDeviceDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,149 @@
/*---------------------------------------------------------*\
| NanoleafScanDialog.cpp |
| |
| User interface for Nanoleaf scan & pairing page |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "NanoleafScanDialog.h"
#include "ui_NanoleafScanDialog.h"
#include "NanoleafNewDeviceDialog.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
#include "LogManager.h"
using json = nlohmann::json;
NanoleafScanDialog::NanoleafScanDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::NanoleafScanDialog)
{
ui->setupUi(this);
on_NanoleafDeviceList_itemSelectionChanged(); // Refresh button state
}
NanoleafScanDialog::~NanoleafScanDialog()
{
delete ui;
}
void NanoleafScanDialog::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void NanoleafScanDialog::on_AddNanoleafDeviceButton_clicked()
{
/*-----------------------------------------------------*\
| Open a popup to manually add a device by setting ip |
| and port |
\*-----------------------------------------------------*/
NanoleafNewDeviceDialog dialog;
NanoleafDevice device = dialog.show();
if(!device.ip.empty())
{
LOG_TRACE("[%s] Add %s:%d", "Nanoleaf", device.ip.c_str(), device.port);
std::string location = device.ip+":"+std::to_string(device.port);
if(entries.find(location) == entries.end())
{
NanoleafSettingsEntry* entry = new NanoleafSettingsEntry(QString::fromUtf8(device.ip.c_str()), device.port);
entries[location] = entry;
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(entry->sizeHint());
ui->NanoleafDeviceList->addItem(item);
ui->NanoleafDeviceList->setItemWidget(item, entry);
ui->NanoleafDeviceList->show();
json nanoleaf_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("NanoleafDevices");
nanoleaf_settings["devices"][location]["ip"] = device.ip;
nanoleaf_settings["devices"][location]["port"] = device.port;
ResourceManager::get()->GetSettingsManager()->SetSettings("NanoleafDevices", nanoleaf_settings);
ResourceManager::get()->GetSettingsManager()->SaveSettings();
}
}
}
void NanoleafScanDialog::on_RemoveNanoleafDeviceButton_clicked()
{
/*-------------------------------------------------*\
| Remove the selected device |
\*-------------------------------------------------*/
int cur_row = ui->NanoleafDeviceList->currentRow();
if(cur_row < 0)
{
return;
}
QListWidgetItem* item = ui->NanoleafDeviceList->item(cur_row);
NanoleafSettingsEntry* entry = (NanoleafSettingsEntry*) ui->NanoleafDeviceList->itemWidget(item);
ui->NanoleafDeviceList->removeItemWidget(item);
delete item;
std::string location = entry->getLocation();
delete entries[location];
entries.erase(location);
json nanoleaf_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("NanoleafDevices");
nanoleaf_settings["devices"].erase(location);
ResourceManager::get()->GetSettingsManager()->SetSettings("NanoleafDevices", nanoleaf_settings);
ResourceManager::get()->GetSettingsManager()->SaveSettings();
}
void NanoleafScanDialog::on_ScanForNanoleafDevicesButton_clicked()
{
/*-----------------------------------------------------*\
| Create a worker thread for the mDNS query and hookup |
| callbacks for when it finds devices |
\*-----------------------------------------------------*/
NanoleafScanningThread *scanThread = new NanoleafScanningThread;
connect(scanThread, SIGNAL(DeviceFound(QString, int)),
SLOT(on_DeviceFound(QString, int)));
connect(scanThread, SIGNAL(finished()),
scanThread, SLOT(deleteLater()));
scanThread->start();
}
void NanoleafScanDialog::on_DeviceFound(QString address, int port)
{
std::string location = address.toStdString()+":"+std::to_string(port);
if(entries.find(location) == entries.end())
{
NanoleafSettingsEntry* entry = new NanoleafSettingsEntry(address, port);
entries[location] = entry;
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(entry->sizeHint());
ui->NanoleafDeviceList->addItem(item);
ui->NanoleafDeviceList->setItemWidget(item, entry);
ui->NanoleafDeviceList->show();
}
}
void NanoleafScanDialog::on_NanoleafDeviceList_itemSelectionChanged()
{
int cur_row = ui->NanoleafDeviceList->currentRow();
bool anySelected = (cur_row >= 0);
ui->RemoveNanoleafDeviceButton->setEnabled(anySelected);
}
@@ -0,0 +1,40 @@
/*---------------------------------------------------------*\
| NanoleafScanDialog.h |
| |
| User interface for OpenRGB Nanoleaf scan & pairing page |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <QDialog>
#include "NanoleafSettingsEntry.h"
namespace Ui
{
class NanoleafScanDialog;
}
class NanoleafScanDialog : public QDialog
{
Q_OBJECT
public:
explicit NanoleafScanDialog(QWidget *parent = nullptr);
~NanoleafScanDialog();
private slots:
void changeEvent(QEvent *event);
void on_AddNanoleafDeviceButton_clicked();
void on_RemoveNanoleafDeviceButton_clicked();
void on_ScanForNanoleafDevicesButton_clicked();
void on_DeviceFound(QString address, int port);
void on_NanoleafDeviceList_itemSelectionChanged();
private:
Ui::NanoleafScanDialog *ui;
std::map<std::string, NanoleafSettingsEntry*> entries;
};
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NanoleafScanDialog</class>
<widget class="QDialog" name="NanoleafScanDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Nanoleaf Scan Page</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="SyncLabel">
<property name="text">
<string>To pair, hold the on-off button down for 5-7 seconds until the LED starts flashing in a pattern, a new entry should appear in the list below, then click the &quot;Pair&quot; button on the entry within 30 seconds.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="NanoleafDeviceList">
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="ScanForNanoleafDevicesButton">
<property name="text">
<string>Scan</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="AddNanoleafDeviceButton">
<property name="text">
<string>Add manually</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="RemoveNanoleafDeviceButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,477 @@
/*---------------------------------------------------------*\
| NanoleafScanningThread.cpp |
| |
| OpenRGB Nanoleaf scanning thread |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#ifdef _WIN32
#include <winsock2.h>
#include <iphlpapi.h>
#else
#include <netdb.h>
#include <ifaddrs.h>
#include <sys/select.h>
#endif
#include "mdns.h"
#include "NanoleafScanningThread.h"
static char namebuffer[256];
static struct sockaddr_in service_address_ipv4;
static struct sockaddr_in6 service_address_ipv6;
static int has_ipv4;
static int has_ipv6;
static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr, size_t addrlen)
{
char host[NI_MAXHOST] = {0};
char service[NI_MAXSERV] = {0};
int ret = getnameinfo((const struct sockaddr*)addr, (socklen_t)addrlen, host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST);
int len = 0;
if(ret == 0)
{
len = snprintf(buffer, capacity, "%s", host);
}
if(len >= (int)capacity)
{
len = (int)capacity - 1;
}
mdns_string_t str;
str.str = buffer;
str.length = len;
return str;
}
static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr, size_t addrlen)
{
char host[NI_MAXHOST] = {0};
char service[NI_MAXSERV] = {0};
int ret = getnameinfo((const struct sockaddr*)addr, (socklen_t)addrlen, host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST);
int len = 0;
if(ret == 0)
{
if(addr->sin6_port != 0)
{
len = snprintf(buffer, capacity, "[%s]:%s", host, service);
}
else
{
len = snprintf(buffer, capacity, "%s", host);
}
}
if(len >= (int)capacity)
{
len = (int)capacity - 1;
}
mdns_string_t str;
str.str = buffer;
str.length = len;
return str;
}
/*-----------------------------------------------------*\
| Open sockets for sending one-shot multicast queries |
| from an ephemeral port |
\*-----------------------------------------------------*/
static int open_client_sockets(int* sockets, int max_sockets, int port)
{
/*-----------------------------------------------------*\
| When sending, each socket can only send to one |
| network interface from an ephemeral port, thus we |
| need to open one socket for each interface and |
| address family |
\*-----------------------------------------------------*/
int num_sockets = 0;
#ifdef _WIN32
IP_ADAPTER_ADDRESSES* adapter_address = 0;
ULONG address_size = 8000;
unsigned int ret;
unsigned int num_retries = 4;
do
{
adapter_address = (IP_ADAPTER_ADDRESSES*)malloc(address_size);
ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST, 0, adapter_address, &address_size);
if(ret == ERROR_BUFFER_OVERFLOW)
{
free(adapter_address);
adapter_address = 0;
address_size *= 2;
}
else
{
break;
}
}
while(num_retries-- > 0);
if(!adapter_address || (ret != NO_ERROR))
{
free(adapter_address);
return num_sockets;
}
int first_ipv4 = 1;
int first_ipv6 = 1;
for(PIP_ADAPTER_ADDRESSES adapter = adapter_address; adapter; adapter = adapter->Next)
{
if(adapter->TunnelType == TUNNEL_TYPE_TEREDO)
{
continue;
}
if(adapter->OperStatus != IfOperStatusUp)
{
continue;
}
for(IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress; unicast; unicast = unicast->Next)
{
if(unicast->Address.lpSockaddr->sa_family == AF_INET)
{
struct sockaddr_in* saddr = (struct sockaddr_in*)unicast->Address.lpSockaddr;
if((saddr->sin_addr.S_un.S_un_b.s_b1 != 127) ||
(saddr->sin_addr.S_un.S_un_b.s_b2 != 0) ||
(saddr->sin_addr.S_un.S_un_b.s_b3 != 0) ||
(saddr->sin_addr.S_un.S_un_b.s_b4 != 1))
{
int log_addr = 0;
if(first_ipv4)
{
service_address_ipv4 = *saddr;
first_ipv4 = 0;
log_addr = 1;
}
has_ipv4 = 1;
if(num_sockets < max_sockets)
{
saddr->sin_port = htons((unsigned short)port);
int sock = mdns_socket_open_ipv4(saddr);
if(sock >= 0)
{
sockets[num_sockets++] = sock;
log_addr = 1;
}
else
{
log_addr = 0;
}
}
if(log_addr)
{
char buffer[128];
ipv4_address_to_string(buffer, sizeof(buffer), saddr, sizeof(struct sockaddr_in));
}
}
}
else if(unicast->Address.lpSockaddr->sa_family == AF_INET6)
{
struct sockaddr_in6* saddr = (struct sockaddr_in6*)unicast->Address.lpSockaddr;
static const unsigned char localhost[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1};
static const unsigned char localhost_mapped[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0xff, 0xff, 0x7f, 0, 0, 1};
if((unicast->DadState == NldsPreferred) &&
memcmp(saddr->sin6_addr.s6_addr, localhost, 16) &&
memcmp(saddr->sin6_addr.s6_addr, localhost_mapped, 16))
{
int log_addr = 0;
if(first_ipv6)
{
service_address_ipv6 = *saddr;
first_ipv6 = 0;
log_addr = 1;
}
has_ipv6 = 1;
if(num_sockets < max_sockets)
{
saddr->sin6_port = htons((unsigned short)port);
int sock = mdns_socket_open_ipv6(saddr);
if(sock >= 0)
{
sockets[num_sockets++] = sock;
log_addr = 1;
}
else
{
log_addr = 0;
}
}
if(log_addr)
{
char buffer[128];
ipv6_address_to_string(buffer, sizeof(buffer), saddr, sizeof(struct sockaddr_in6));
}
}
}
}
}
free(adapter_address);
#else
struct ifaddrs* ifaddr = 0;
struct ifaddrs* ifa = 0;
getifaddrs(&ifaddr);
int first_ipv4 = 1;
int first_ipv6 = 1;
for(ifa = ifaddr; ifa; ifa = ifa->ifa_next)
{
if(!ifa->ifa_addr)
{
continue;
}
if(ifa->ifa_addr->sa_family == AF_INET)
{
struct sockaddr_in* saddr = (struct sockaddr_in*)ifa->ifa_addr;
if(saddr->sin_addr.s_addr != htonl(INADDR_LOOPBACK))
{
int log_addr = 0;
if(first_ipv4)
{
service_address_ipv4 = *saddr;
first_ipv4 = 0;
log_addr = 1;
}
has_ipv4 = 1;
if(num_sockets < max_sockets)
{
saddr->sin_port = htons(port);
int sock = mdns_socket_open_ipv4(saddr);
if(sock >= 0)
{
sockets[num_sockets++] = sock;
log_addr = 1;
}
else
{
log_addr = 0;
}
}
if(log_addr)
{
char buffer[128];
ipv4_address_to_string(buffer, sizeof(buffer), saddr, sizeof(struct sockaddr_in));
}
}
}
else if(ifa->ifa_addr->sa_family == AF_INET6)
{
struct sockaddr_in6* saddr = (struct sockaddr_in6*)ifa->ifa_addr;
static const unsigned char localhost[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1};
static const unsigned char localhost_mapped[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0xff, 0xff, 0x7f, 0, 0, 1};
if (memcmp(saddr->sin6_addr.s6_addr, localhost, 16) &&
memcmp(saddr->sin6_addr.s6_addr, localhost_mapped, 16))
{
int log_addr = 0;
if(first_ipv6)
{
service_address_ipv6 = *saddr;
first_ipv6 = 0;
log_addr = 1;
}
has_ipv6 = 1;
if(num_sockets < max_sockets)
{
saddr->sin6_port = htons(port);
int sock = mdns_socket_open_ipv6(saddr);
if (sock >= 0)
{
sockets[num_sockets++] = sock;
log_addr = 1;
}
else
{
log_addr = 0;
}
}
if(log_addr)
{
char buffer[128];
ipv6_address_to_string(buffer, sizeof(buffer), saddr, sizeof(struct sockaddr_in6));
}
}
}
}
freeifaddrs(ifaddr);
#endif
return num_sockets;
}
/*-----------------------------------------------------*\
| Callback handling parsing answers to queries sent |
\*-----------------------------------------------------*/
static int query_callback(
int sock,
[[maybe_unused]] const struct sockaddr* from,
[[maybe_unused]] size_t addrlen,
[[maybe_unused]] mdns_entry_type_t entry,
uint16_t query_id,
uint16_t rtype,
[[maybe_unused]] uint16_t rclass,
[[maybe_unused]] uint32_t ttl,
const void* data,
size_t size,
[[maybe_unused]] size_t name_offset,
size_t name_length,
size_t record_offset,
size_t record_length,
void* user_data)
{
(void)sizeof(sock);
(void)sizeof(query_id);
(void)sizeof(name_length);
(void)sizeof(user_data);
if(rtype == MDNS_RECORDTYPE_A)
{
struct sockaddr_in address;
mdns_record_parse_a(data, size, record_offset, record_length, &address);
if(address.sin_port == 0)
{
address.sin_port = 16021; // Default Nanoleaf port.
}
mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), &address, sizeof(address));
(static_cast<NanoleafScanningThread*>(user_data))->EmitDeviceFound(addrstr.str, address.sin_port);
}
return 0;
}
void NanoleafScanningThread::EmitDeviceFound(QString address, int port)
{
emit DeviceFound(address, port);
}
/*-----------------------------------------------------*\
| Send a mDNS query |
\*-----------------------------------------------------*/
int NanoleafScanningThread::SendMDNSQuery()
{
const char* service = "_nanoleafapi._tcp.local.";
mdns_record_type record = MDNS_RECORDTYPE_PTR;
int sockets[32];
int query_id[32];
int num_sockets = open_client_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]), 0);
if (num_sockets <= 0)
{
return -1;
}
size_t capacity = 2048;
void* buffer = malloc(capacity);
size_t records;
//const char* record_name;
if(record == MDNS_RECORDTYPE_SRV)
{
//record_name = "SRV";
}
else if(record == MDNS_RECORDTYPE_A)
{
//record_name = "A";
}
else if(record == MDNS_RECORDTYPE_AAAA)
{
//record_name = "AAAA";
}
else
{
record = MDNS_RECORDTYPE_PTR;
}
for(int isock = 0; isock < num_sockets; ++isock)
{
query_id[isock] = mdns_query_send(sockets[isock], record, service, strlen(service), buffer, capacity, 0);
}
/*-----------------------------------------------------*\
| This is a simple implementation that loops for |
| 5 seconds or as long as we get replies |
\*-----------------------------------------------------*/
int res;
do
{
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
int nfds = 0;
fd_set readfs;
FD_ZERO(&readfs);
for(int isock = 0; isock < num_sockets; ++isock)
{
if(sockets[isock] >= nfds)
{
nfds = sockets[isock] + 1;
}
FD_SET(sockets[isock], &readfs);
}
records = 0;
res = select(nfds, &readfs, 0, 0, &timeout);
if(res > 0)
{
for(int isock = 0; isock < num_sockets; ++isock)
{
if(FD_ISSET(sockets[isock], &readfs))
{
records += mdns_query_recv(sockets[isock], buffer, capacity, query_callback, this, query_id[isock]);
}
FD_SET(sockets[isock], &readfs);
}
}
}
while (res > 0);
free(buffer);
for(int isock = 0; isock < num_sockets; ++isock)
{
mdns_socket_close(sockets[isock]);
}
return 0;
}
void NanoleafScanningThread::run()
{
SendMDNSQuery();
}
@@ -0,0 +1,25 @@
/*---------------------------------------------------------*\
| NanoleafScanningThread.h |
| |
| OpenRGB Nanoleaf scanning thread |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <QThread>
class NanoleafScanningThread : public QThread
{
Q_OBJECT
void run();
int SendMDNSQuery();
signals:
void DeviceFound(QString address, int port);
public:
void EmitDeviceFound(QString address, int port);
};
@@ -0,0 +1,177 @@
/*---------------------------------------------------------*\
| NanoleafSettingsEntry.cpp |
| |
| User interface for OpenRGB Nanoleaf settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "NanoleafSettingsEntry.h"
#include "ui_NanoleafSettingsEntry.h"
#include "NanoleafScanDialog.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
#include "NanoleafController.h"
NanoleafSettingsEntry::NanoleafSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::NanoleafSettingsEntry),
paired(false)
{
ui->setupUi(this);
}
NanoleafSettingsEntry::NanoleafSettingsEntry(QString a_address, int a_port) :
NanoleafSettingsEntry(nullptr)
{
address = a_address;
port = a_port;
const std::string location = getLocation();
ui->IPValue->setText(address);
ui->PortValue->setText(QString::fromStdString(std::to_string(a_port)));
json nanoleaf_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("NanoleafDevices");
if(nanoleaf_settings["devices"].contains(location) &&
nanoleaf_settings["devices"][location].contains("auth_token") &&
nanoleaf_settings["devices"][location]["auth_token"].size())
{
paired = true;
auth_token = nanoleaf_settings["devices"][location]["auth_token"];
ui->AuthKeyValue->setText(QString::fromStdString(auth_token));
ui->PairButton->hide();
}
else
{
ui->UnpairButton->hide();
}
}
NanoleafSettingsEntry::~NanoleafSettingsEntry()
{
delete ui;
}
void NanoleafSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void NanoleafSettingsEntry::on_PairButton_clicked()
{
try
{
auth_token = NanoleafController::Pair(address.toStdString(), port);
// Save auth token.
std::string location = getLocation();
json nanoleaf_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("NanoleafDevices");
nanoleaf_settings["devices"][location]["ip"] = address.toStdString();
nanoleaf_settings["devices"][location]["port"] = port;
nanoleaf_settings["devices"][location]["auth_token"] = auth_token;
ResourceManager::get()->GetSettingsManager()->SetSettings("NanoleafDevices", nanoleaf_settings);
ResourceManager::get()->GetSettingsManager()->SaveSettings();
// Update UI.
paired = true;
ui->AuthKeyValue->setText(QString::fromStdString(auth_token));
ui->PairButton->hide();
ui->UnpairButton->show();
}
catch(const std::exception& /*e*/)
{
paired = false;
ui->AuthKeyValue->setText("PAIRING FAILED");
}
}
void NanoleafSettingsEntry::on_UnpairButton_clicked()
{
NanoleafController::Unpair(address.toStdString(), port, auth_token);
std::string location = getLocation();
json nanoleaf_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("NanoleafDevices");
nanoleaf_settings["devices"].erase(location);
ResourceManager::get()->GetSettingsManager()->SetSettings("NanoleafDevices", nanoleaf_settings);
ResourceManager::get()->GetSettingsManager()->SaveSettings();
paired = false;
ui->AuthKeyValue->setText("");
ui->PairButton->show();
ui->UnpairButton->hide();
}
void NanoleafSettingsEntry::loadFromSettings(const json& data)
{
address = QString::fromStdString(data["ip"]);
port = data["port"];
ui->IPValue->setText(address);
ui->PortValue->setText(QString::fromStdString(std::to_string(port)));
if(data.contains("auth_token") && data["auth_token"].size())
{
auth_token = data["auth_token"];
ui->AuthKeyValue->setText(QString::fromStdString(auth_token));
ui->PairButton->hide();
}
else
{
auth_token.clear();
ui->UnpairButton->hide();
}
}
json NanoleafSettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["ip"] = address.toStdString();
result["port"] = port;
if(!auth_token.empty())
{
result["auth_token"] = auth_token;
}
return result;
}
std::string NanoleafSettingsEntry::getLocation()
{
return (address.toStdString() + ":" + std::to_string(port));
}
bool NanoleafSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnNanoleafSettingsEntry(const json& data)
{
if(data.empty())
{
// A special case: we open a new scanning dialog instead of returning a new entry
// The caller should be able to handle this
NanoleafScanDialog scanPage;
scanPage.exec();
return nullptr;
}
else
{
NanoleafSettingsEntry* entry = new NanoleafSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
}
REGISTER_MANUAL_DEVICE_TYPE("Nanoleaf", "NanoleafDevices", SpawnNanoleafSettingsEntry);
@@ -0,0 +1,45 @@
/*---------------------------------------------------------*\
| NanoleafSettingsEntry.h |
| |
| User interface for OpenRGB Nanoleaf settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
#include "NanoleafScanningThread.h"
namespace Ui
{
class NanoleafSettingsEntry;
}
class NanoleafSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit NanoleafSettingsEntry(QWidget *parent = nullptr);
NanoleafSettingsEntry(QString a_address, int a_port);
~NanoleafSettingsEntry();
void loadFromSettings(const json& data);
std::string getLocation();
json saveSettings() override;
bool isDataValid() override;
private slots:
void changeEvent(QEvent *event) override;
void on_UnpairButton_clicked();
void on_PairButton_clicked();
private:
Ui::NanoleafSettingsEntry *ui;
QString address;
int port;
std::string auth_token;
bool paired;
};
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NanoleafSettingsEntry</class>
<widget class="QWidget" name="NanoleafSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>287</width>
<height>207</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Nanoleaf Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Nanoleaf Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
<widget class="QLabel" name="IPValue">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="PortLabel">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="PortValue">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="AuthKeyLabel">
<property name="text">
<string>Auth Key:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="AuthKeyValue">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="UnpairButton">
<property name="text">
<string>Unpair</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="PairButton">
<property name="text">
<string>Pair</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,109 @@
/*---------------------------------------------------------*\
| PhilipsHueSettingsEntry.cpp |
| |
| User interface for OpenRGB Philips Hue settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "PhilipsHueSettingsEntry.h"
#include "ui_PhilipsHueSettingsEntry.h"
PhilipsHueSettingsEntry::PhilipsHueSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::PhilipsHueSettingsEntry)
{
ui->setupUi(this);
}
PhilipsHueSettingsEntry::~PhilipsHueSettingsEntry()
{
delete ui;
}
void PhilipsHueSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void PhilipsHueSettingsEntry::on_UnpairButton_clicked()
{
ui->UsernameValue->setText("");
ui->ClientKeyValue->setText("");
}
void PhilipsHueSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
if(data.contains("mac"))
{
ui->MACEdit->setText(QString::fromStdString(data["mac"]));
}
if(data.contains("entertainment"))
{
ui->EntertainmentCheckBox->setChecked(data["entertainment"]);
}
if(data.contains("autoconnect"))
{
ui->AutoConnectCheckBox->setChecked(data["autoconnect"]);
}
if(data.contains("username"))
{
ui->UsernameValue->setText(QString::fromStdString(data["username"]));
}
if(data.contains("clientkey"))
{
ui->ClientKeyValue->setText(QString::fromStdString(data["clientkey"]));
}
}
json PhilipsHueSettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["ip"] = ui->IPEdit->text().toStdString();
result["mac"] = ui->MACEdit->text().toStdString();
result["entertainment"] = ui->EntertainmentCheckBox->isChecked();
result["autoconnect"] = ui->AutoConnectCheckBox->isChecked();
if(ui->UsernameValue->text() != "")
{
result["username"] = ui->UsernameValue->text().toStdString();
}
if(ui->ClientKeyValue->text() != "")
{
result["clientkey"] = ui->ClientKeyValue->text().toStdString();
}
return result;
}
bool PhilipsHueSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnPhilipsHueSettingsEntry(const json& data)
{
PhilipsHueSettingsEntry* entry = new PhilipsHueSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("Philips Hue", "PhilipsHueDevices", SpawnPhilipsHueSettingsEntry);
@@ -0,0 +1,36 @@
/*---------------------------------------------------------*\
| PhilipsHueSettingsEntry.h |
| |
| User interface for OpenRGB Philips Hue settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class PhilipsHueSettingsEntry;
}
class PhilipsHueSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit PhilipsHueSettingsEntry(QWidget *parent = nullptr);
~PhilipsHueSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::PhilipsHueSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
void on_UnpairButton_clicked();
};
@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PhilipsHueSettingsEntry</class>
<widget class="QWidget" name="PhilipsHueSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>297</width>
<height>260</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Philips Hue Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Philips Hue Bridge</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="0">
<widget class="QLabel" name="EntertainmentLabel">
<property name="text">
<string>Entertainment Mode:</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QCheckBox" name="EntertainmentCheckBox">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="AutoConnectLabel">
<property name="text">
<string>Auto Connect Group:</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QCheckBox" name="AutoConnectCheckBox">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QLabel" name="ClientKeyValue">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="ClientKeyLabel">
<property name="text">
<string>Client Key:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="UsernameLabel">
<property name="text">
<string>Username:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="MACLabel">
<property name="text">
<string>MAC:</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="4">
<widget class="QPushButton" name="UnpairButton">
<property name="text">
<string>Unpair Bridge</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="MACEdit"/>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="IPEdit"/>
</item>
<item row="5" column="3">
<widget class="QLabel" name="UsernameValue">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>IPEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,86 @@
/*---------------------------------------------------------*\
| PhilipsWizSettingsEntry.cpp |
| |
| User interface for OpenRGB Philips Wiz settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "PhilipsWizSettingsEntry.h"
#include "ui_PhilipsWizSettingsEntry.h"
PhilipsWizSettingsEntry::PhilipsWizSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::PhilipsWizSettingsEntry)
{
ui->setupUi(this);
ui->WhiteStrategyComboBox->addItem(tr("Average"));
ui->WhiteStrategyComboBox->addItem(tr("Minimum"));
}
PhilipsWizSettingsEntry::~PhilipsWizSettingsEntry()
{
delete ui;
}
void PhilipsWizSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void PhilipsWizSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
if(data.contains("use_cool_white"))
{
ui->UseCoolWhiteCheckBox->setChecked(data["use_cool_white"]);
}
if(data.contains("use_warm_white"))
{
ui->UseWarmWhiteCheckBox->setChecked(data["use_warm_white"]);
}
if(data.contains("selected_white_strategy"))
{
ui->WhiteStrategyComboBox->setCurrentText(QString::fromStdString(data["selected_white_strategy"]));
}
}
json PhilipsWizSettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["ip"] = ui->IPEdit->text().toStdString();
result["use_cool_white"] = ui->UseCoolWhiteCheckBox->isChecked();
result["use_warm_white"] = ui->UseWarmWhiteCheckBox->isChecked();
result["selected_white_strategy"] = ui->WhiteStrategyComboBox->currentText().toStdString();
return result;
}
bool PhilipsWizSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnPhilipsWizSettingsEntry(const json& data)
{
PhilipsWizSettingsEntry* entry = new PhilipsWizSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("Philips Wiz", "PhilipsWizDevices", SpawnPhilipsWizSettingsEntry);
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| PhilipsWizSettingsEntry.h |
| |
| User interface for OpenRGB Philips Wiz settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class PhilipsWizSettingsEntry;
}
class PhilipsWizSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit PhilipsWizSettingsEntry(QWidget *parent = nullptr);
~PhilipsWizSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::PhilipsWizSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
};
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PhilipsWizSettingsEntry</class>
<widget class="QWidget" name="PhilipsWizSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>327</width>
<height>149</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Philips Wiz Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Philips Wiz Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="0">
<widget class="QCheckBox" name="UseCoolWhiteCheckBox">
<property name="text">
<string>Use Cool White</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="UseWarmWhiteCheckBox">
<property name="text">
<string>Use Warm White</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="IPEdit"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="WhiteStrategyComboBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="WhiteStrategyLabel">
<property name="text">
<string>White Strategy:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,79 @@
/*---------------------------------------------------------*\
| QMKORGBSettingsEntry.cpp |
| |
| User interface entry for OpenRGB QMK configuration |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "QMKORGBSettingsEntry.h"
#include "ui_QMKORGBSettingsEntry.h"
QMKORGBSettingsEntry::QMKORGBSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::QMKORGBSettingsEntry)
{
ui->setupUi(this);
}
QMKORGBSettingsEntry::~QMKORGBSettingsEntry()
{
delete ui;
}
void QMKORGBSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void QMKORGBSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
if(data.contains("usb_vid"))
{
ui->USBVIDEdit->setText(QString::fromStdString(data["usb_vid"]));
}
if(data.contains("usb_pid"))
{
ui->USBPIDEdit->setText(QString::fromStdString(data["usb_pid"]));
}
}
json QMKORGBSettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["name"] = ui->NameEdit->text().toStdString();
result["usb_vid"] = ui->USBVIDEdit->text().toStdString();
result["usb_pid"] = ui->USBPIDEdit->text().toStdString();
return result;
}
bool QMKORGBSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnQMKORGBSettingsEntry(const json& data)
{
QMKORGBSettingsEntry* entry = new QMKORGBSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
static const char* QMKDeviceName = QT_TRANSLATE_NOOP("ManualDevice", "QMK (OpenRGB Protocol)");
REGISTER_MANUAL_DEVICE_TYPE(QMKDeviceName, "QMKOpenRGBDevices", SpawnQMKORGBSettingsEntry);
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| QMKORGBSettingsEntry.h |
| |
| User interface entry for OpenRGB QMK configuration |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class QMKORGBSettingsEntry;
}
class QMKORGBSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
private slots:
void changeEvent(QEvent *event) override;
public:
explicit QMKORGBSettingsEntry(QWidget *parent = nullptr);
~QMKORGBSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::QMKORGBSettingsEntry *ui;
};
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QMKORGBSettingsEntry</class>
<widget class="QWidget" name="QMKORGBSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>531</width>
<height>237</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true"> QMK OpenRGB Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>QMK OpenRGB Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="5">
<widget class="QLineEdit" name="USBPIDEdit"/>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="NameEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="USBVIDEdit"/>
</item>
<item row="2" column="4">
<widget class="QLabel" name="USBPIDLabel">
<property name="text">
<string>USB PID:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="USBVIDLabel">
<property name="text">
<string>USB VID:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>NameEdit</tabstop>
<tabstop>USBVIDEdit</tabstop>
<tabstop>USBPIDEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,79 @@
/*---------------------------------------------------------*\
| QMKVialRGBSettingsEntry.cpp |
| |
| User interface entry for VialRGB QMK configuration |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "QMKVialRGBSettingsEntry.h"
#include "ui_QMKVialRGBSettingsEntry.h"
QMKVialRGBSettingsEntry::QMKVialRGBSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::QMKVialRGBSettingsEntry)
{
ui->setupUi(this);
}
QMKVialRGBSettingsEntry::~QMKVialRGBSettingsEntry()
{
delete ui;
}
void QMKVialRGBSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void QMKVialRGBSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
if(data.contains("usb_vid"))
{
ui->USBVIDEdit->setText(QString::fromStdString(data["usb_vid"]));
}
if(data.contains("usb_pid"))
{
ui->USBPIDEdit->setText(QString::fromStdString(data["usb_pid"]));
}
}
json QMKVialRGBSettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["name"] = ui->NameEdit->text().toStdString();
result["usb_vid"] = ui->USBVIDEdit->text().toStdString();
result["usb_pid"] = ui->USBPIDEdit->text().toStdString();
return result;
}
bool QMKVialRGBSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnQMKVialRGBSettingsEntry(const json& data)
{
QMKVialRGBSettingsEntry* entry = new QMKVialRGBSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
static const char* QMKDeviceName = QT_TRANSLATE_NOOP("ManualDevice", "QMK (VialRGB Protocol)");
REGISTER_MANUAL_DEVICE_TYPE(QMKDeviceName, "QMKVialRGBDevices", SpawnQMKVialRGBSettingsEntry);
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| QMKVialRGBSettingsEntry.h |
| |
| User interface entry for VialRGB QMK configuration |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class QMKVialRGBSettingsEntry;
}
class QMKVialRGBSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
private slots:
void changeEvent(QEvent *event) override;
public:
explicit QMKVialRGBSettingsEntry(QWidget *parent = nullptr);
~QMKVialRGBSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::QMKVialRGBSettingsEntry *ui;
};
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QMKVialRGBSettingsEntry</class>
<widget class="QWidget" name="QMKVialRGBSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>531</width>
<height>237</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true"> QMK VialRGB Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>QMK VialRGB Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="5">
<widget class="QLineEdit" name="USBPIDEdit"/>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="NameEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="USBVIDEdit"/>
</item>
<item row="2" column="4">
<widget class="QLabel" name="USBPIDLabel">
<property name="text">
<string>USB PID:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="USBVIDLabel">
<property name="text">
<string>USB VID:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>NameEdit</tabstop>
<tabstop>USBVIDEdit</tabstop>
<tabstop>USBPIDEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,164 @@
/*---------------------------------------------------------*\
| SerialSettingsEntry.cpp |
| |
| User interface entry for serial device configuration |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "SerialSettingsEntry.h"
#include "ui_SerialSettingsEntry.h"
#include "serial_port.h"
#include <QStandardItemModel>
SerialSettingsEntry::SerialSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::SerialSettingsEntry)
{
ui->setupUi(this);
ui->ProtocolComboBox->addItem("Keyboard Visualizer");
ui->ProtocolComboBox->addItem("Adalight");
ui->ProtocolComboBox->addItem("TPM2");
ui->ProtocolComboBox->addItem("Basic I2C");
std::vector<std::string> serialPorts = serial_port::getSerialPorts();
for(size_t i = 0; i < serialPorts.size(); ++i)
{
ui->PortComboBox->addItem(QString::fromStdString(serialPorts[i]));
}
if(serialPorts.empty())
{
/*---------------------------------------------------*\
| When no ports were found, add an unselectable entry |
| denoting this fact istead |
\*---------------------------------------------------*/
QStandardItemModel* comboBoxModel = qobject_cast<QStandardItemModel *>(ui->PortComboBox->model());
if(comboBoxModel != nullptr)
{
ui->PortComboBox->addItem(tr("No serial ports found"));
QStandardItem *item = comboBoxModel->item(0);
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
}
}
ui->PortComboBox->clearEditText();
}
SerialSettingsEntry::~SerialSettingsEntry()
{
delete ui;
}
void SerialSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void SerialSettingsEntry::on_ProtocolComboBox_currentIndexChanged(int index)
{
if(index == 3)
{
ui->BaudLabel->setText("Address:");
}
else
{
ui->BaudLabel->setText("Baud:");
}
}
void SerialSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("name"))
{
ui->NameEdit->setText(QString::fromStdString(data["name"]));
}
if(data.contains("port"))
{
ui->PortComboBox->setCurrentText(QString::fromStdString(data["port"]));
}
if(data.contains("baud"))
{
ui->BaudEdit->setText(QString::number((int)data["baud"]));
}
if(data.contains("num_leds"))
{
ui->NumLEDsEdit->setText(QString::number((int)data["num_leds"]));
}
if(data.contains("protocol"))
{
std::string protocol_string = data["protocol"];
if(protocol_string == "keyboard_visualizer")
{
ui->ProtocolComboBox->setCurrentIndex(0);
}
else if(protocol_string == "adalight")
{
ui->ProtocolComboBox->setCurrentIndex(1);
}
else if(protocol_string == "tpm2")
{
ui->ProtocolComboBox->setCurrentIndex(2);
}
else if(protocol_string == "basic_i2c")
{
ui->ProtocolComboBox->setCurrentIndex(3);
}
}
}
json SerialSettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["name"] = ui->NameEdit->text().toStdString();
result["port"] = ui->PortComboBox->currentText().toStdString();
result["num_leds"] = ui->NumLEDsEdit->text().toUInt();
result["baud"] = ui->BaudEdit->text().toUInt();
switch(ui->ProtocolComboBox->currentIndex())
{
case 0:
result["protocol"] = "keyboard_visualizer";
break;
case 1:
result["protocol"] = "adalight";
break;
case 2:
result["protocol"] = "tpm2";
break;
case 3:
result["protocol"] = "basic_i2c";
break;
}
return result;
}
bool SerialSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnSerialSettingsEntry(const json& data)
{
SerialSettingsEntry* entry = new SerialSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
static const char* SerialDeviceName = QT_TRANSLATE_NOOP("ManualDevice", "Serial Device");
REGISTER_MANUAL_DEVICE_TYPE(SerialDeviceName, "LEDStripDevices", SpawnSerialSettingsEntry);
@@ -0,0 +1,37 @@
/*---------------------------------------------------------*\
| SerialSettingsEntry.h |
| |
| User interface entry for serial device configuration |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class SerialSettingsEntry;
}
class SerialSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
private slots:
void changeEvent(QEvent *event) override;
void on_ProtocolComboBox_currentIndexChanged(int index);
public:
explicit SerialSettingsEntry(QWidget *parent = nullptr);
~SerialSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::SerialSettingsEntry *ui;
};
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SerialSettingsEntry</class>
<widget class="QWidget" name="SerialSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>531</width>
<height>237</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Serial Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Serial Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="4">
<widget class="QLabel" name="NumLEDsLabel">
<property name="text">
<string>Number of LEDs:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="BaudLabel">
<property name="text">
<string>Baud:</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QComboBox" name="ProtocolComboBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="NameEdit"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="ProtocolLabel">
<property name="text">
<string>Protocol:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="BaudEdit"/>
</item>
<item row="2" column="5">
<widget class="QLineEdit" name="NumLEDsEdit"/>
</item>
<item row="1" column="4">
<widget class="QLabel" name="PortLabel">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QComboBox" name="PortComboBox">
<property name="editable">
<bool>true</bool>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>NameEdit</tabstop>
<tabstop>BaudEdit</tabstop>
<tabstop>NumLEDsEdit</tabstop>
<tabstop>ProtocolComboBox</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,109 @@
/*---------------------------------------------------------*\
| YeelightSettingsEntry.cpp |
| |
| User interface for Yeelight settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <QInputDialog>
#include "YeelightSettingsEntry.h"
#include "ui_YeelightSettingsEntry.h"
#include "net_port.h"
YeelightSettingsEntry::YeelightSettingsEntry(QWidget *parent) :
BaseManualDeviceEntry(parent),
ui(new Ui::YeelightSettingsEntry)
{
ui->setupUi(this);
}
YeelightSettingsEntry::~YeelightSettingsEntry()
{
delete ui;
}
void YeelightSettingsEntry::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}
void YeelightSettingsEntry::on_HostIPChooserButton_clicked()
{
char hostname[256];
gethostname(hostname, 256);
char **in_addrs = gethostbyname(hostname)->h_addr_list;
QStringList in_addr_list;
while (*in_addrs != NULL)
{
in_addr_list << inet_ntoa(*((struct in_addr*) *in_addrs));
in_addrs++;
}
QInputDialog inp;
inp.setOptions(QInputDialog::UseListViewForComboBoxItems);
inp.setComboBoxItems(in_addr_list);
inp.setWindowTitle(tr("Choose an IP..."));
inp.setLabelText(tr("Choose the correct IP for the host"));
if(!inp.exec())
{
return;
}
ui->HostIPEdit->setText(inp.textValue());
}
void YeelightSettingsEntry::loadFromSettings(const json& data)
{
if(data.contains("ip"))
{
ui->IPEdit->setText(QString::fromStdString(data["ip"]));
}
if(data.contains("host_ip"))
{
ui->HostIPEdit->setText(QString::fromStdString(data["host_ip"]));
}
if(data.contains("music_mode"))
{
ui->MusicModeCheckBox->setChecked(data["music_mode"]);
}
}
json YeelightSettingsEntry::saveSettings()
{
json result;
/*-------------------------------------------------*\
| Required parameters |
\*-------------------------------------------------*/
result["ip"] = ui->IPEdit->text().toStdString();
result["host_ip"] = ui->HostIPEdit->text().toStdString();
result["music_mode"] = ui->MusicModeCheckBox->isChecked();
return result;
}
bool YeelightSettingsEntry::isDataValid()
{
// stub
return true;
}
static BaseManualDeviceEntry* SpawnYeelightSettingsEntry(const json& data)
{
YeelightSettingsEntry* entry = new YeelightSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("Yeelight", "YeelightDevices", SpawnYeelightSettingsEntry);
@@ -0,0 +1,36 @@
/*---------------------------------------------------------*\
| YeelightSettingsEntry.h |
| |
| User interface for Yeelight settings entry |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "BaseManualDeviceEntry.h"
namespace Ui
{
class YeelightSettingsEntry;
}
class YeelightSettingsEntry : public BaseManualDeviceEntry
{
Q_OBJECT
public:
explicit YeelightSettingsEntry(QWidget *parent = nullptr);
~YeelightSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::YeelightSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event) override;
void on_HostIPChooserButton_clicked();
};
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>YeelightSettingsEntry</class>
<widget class="QWidget" name="YeelightSettingsEntry">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>972</width>
<height>385</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Yeelight Settings Entry</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Yeelight Device</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="1">
<widget class="QCheckBox" name="MusicModeCheckBox">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="IPLabel">
<property name="text">
<string>IP:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="HostIPEdit"/>
</item>
<item row="5" column="2">
<widget class="QToolButton" name="HostIPChooserButton">
<property name="text">
<string>?</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="MusicModeLabel">
<property name="text">
<string>Music Mode:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Override host IP:</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLineEdit" name="IPEdit"/>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Left blank for auto discovering host ip</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>