Drop-down list in manual devices

This commit is contained in:
Dmitry Kychanov
2025-06-27 03:00:27 +04:00
parent dcd2031e47
commit 2940982b02
40 changed files with 483 additions and 1087 deletions

View File

@@ -149,7 +149,6 @@ INCLUDEPATH +=
dependencies/httplib \
dependencies/json/ \
dependencies/mdns \
dependencies/slidingstackedwidget \
dmiinfo/ \
hidapi_wrapper/ \
i2c_smbus/ \
@@ -173,7 +172,6 @@ HEADERS +=
Colors.h \
dependencies/ColorWheel/ColorWheel.h \
dependencies/json/nlohmann/json.hpp \
dependencies/slidingstackedwidget/slidingstackedwidget.h \
LogManager.h \
NetworkClient.h \
NetworkProtocol.h \
@@ -242,7 +240,6 @@ SOURCES +=
dependencies/hueplusplus-1.2.0/src/UPnP.cpp \
dependencies/hueplusplus-1.2.0/src/Utils.cpp \
dependencies/hueplusplus-1.2.0/src/ZLLSensors.cpp \
dependencies/slidingstackedwidget/slidingstackedwidget.cpp \
main.cpp \
cli.cpp \
dmiinfo/dmiinfo.cpp \

View File

@@ -97,7 +97,7 @@ bool BasicHIDBlock::compare(hid_device_info* info)
);
}
ResourceManager* ResourceManager::instance;
ResourceManager* ResourceManager::instance = nullptr;
using namespace std::chrono_literals;

View File

@@ -1,209 +0,0 @@
/*
* MIT License
Copyright (c) 2020 Tim Schneeberger (ThePBone) <tim.schneeberger(at)outlook.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*
*/
#include "slidingstackedwidget.h"
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QGraphicsOpacityEffect>
SlidingStackedWidget::SlidingStackedWidget(QWidget *parent)
: QStackedWidget(parent)
{
if (parent!=nullptr) {
m_mainwindow=parent;
}
else {
m_mainwindow=this;
}
m_vertical=false;
m_speed=300;
m_animationtype = QEasingCurve::OutQuart;
m_now=0;
m_next=0;
m_wrap=false;
m_pnow=QPoint(0,0);
m_active=false;
}
void SlidingStackedWidget::setVerticalMode(bool vertical) {
m_vertical=vertical;
}
void SlidingStackedWidget::setSpeed(int speed) {
m_speed = speed;
}
void SlidingStackedWidget::setAnimation(enum QEasingCurve::Type animationtype) {
m_animationtype = animationtype;
}
void SlidingStackedWidget::setWrap(bool wrap) {
m_wrap=wrap;
}
bool SlidingStackedWidget::slideInNext() {
int now=currentIndex();
if (m_wrap||(now<count()-1))
slideInIdx(now+1);
else
return false;
return true;
}
bool SlidingStackedWidget::slideInPrev() {
int now=currentIndex();
if (m_wrap||(now>0))
slideInIdx(now-1);
else
return false;
return true;
}
void SlidingStackedWidget::slideInIdx(int idx, enum t_direction direction) {
if (idx>count()-1) {
direction=m_vertical ? TOP2BOTTOM : RIGHT2LEFT;
idx=(idx)%count();
}
else if (idx<0) {
direction= m_vertical ? BOTTOM2TOP: LEFT2RIGHT;
idx=(idx+count())%count();
}
slideInWgt(widget ( idx ),direction);
}
void SlidingStackedWidget::slideInWgt(QWidget * newwidget, enum t_direction direction) {
if (m_active) {
return;
}
else m_active=true;
enum t_direction directionhint;
int now = currentIndex();
int next = indexOf(newwidget);
if (now == next) {
m_active=false;
return;
}
else if (now<next){
directionhint=m_vertical ? TOP2BOTTOM : RIGHT2LEFT;
}
else {
directionhint=m_vertical ? BOTTOM2TOP : LEFT2RIGHT;
}
if (direction == AUTOMATIC) {
direction=directionhint;
}
int offsetx=frameRect().width();
int offsety=frameRect().height();
widget(next)->setGeometry ( 0, 0, offsetx, offsety );
if (direction==BOTTOM2TOP) {
offsetx=0;
offsety=-offsety;
}
else if (direction==TOP2BOTTOM) {
offsetx=0;
}
else if (direction==RIGHT2LEFT) {
offsetx=-offsetx;
offsety=0;
}
else if (direction==LEFT2RIGHT) {
offsety=0;
}
QPoint pnext=widget(next)->pos();
QPoint pnow=widget(now)->pos();
m_pnow=pnow;
widget(next)->move(pnext.x()-offsetx,pnext.y()-offsety);
widget(next)->show();
widget(next)->raise();
QPropertyAnimation *animnow = new QPropertyAnimation(widget(now), "pos");
animnow->setDuration(m_speed);
animnow->setEasingCurve(m_animationtype);
animnow->setStartValue(QPoint(pnow.x(), pnow.y()));
animnow->setEndValue(QPoint(offsetx+pnow.x(), offsety+pnow.y()));
QGraphicsOpacityEffect *animnow_op_eff = new QGraphicsOpacityEffect();
widget(now)->setGraphicsEffect(animnow_op_eff);
QPropertyAnimation *animnow_op = new QPropertyAnimation(animnow_op_eff, "opacity");
animnow_op->setDuration(m_speed/2);
animnow_op->setStartValue(1);
animnow_op->setEndValue(0);
connect(animnow_op,&QPropertyAnimation::finished,[=](){
if(animnow_op_eff != nullptr)
animnow_op_eff->deleteLater();
});
QGraphicsOpacityEffect *animnext_op_eff = new QGraphicsOpacityEffect();
animnext_op_eff->setOpacity(0);
widget(next)->setGraphicsEffect(animnext_op_eff);
QPropertyAnimation *animnext_op = new QPropertyAnimation(animnext_op_eff, "opacity");
animnext_op->setDuration(m_speed/2);
animnext_op->setStartValue(0);
animnext_op->setEndValue(1);
connect(animnext_op,&QPropertyAnimation::finished,[=](){
if(animnext_op_eff != nullptr)
animnext_op_eff->deleteLater();
});
QPropertyAnimation *animnext = new QPropertyAnimation(widget(next), "pos");
animnext->setDuration(m_speed);
animnext->setEasingCurve(m_animationtype);
animnext->setStartValue(QPoint(-offsetx+pnext.x(), offsety+pnext.y()));
animnext->setEndValue(QPoint(pnext.x(), pnext.y()));
animgroup = new QParallelAnimationGroup;
animgroup->addAnimation(animnow);
animgroup->addAnimation(animnext);
animgroup->addAnimation(animnow_op);
animgroup->addAnimation(animnext_op);
QObject::connect(animgroup, SIGNAL(finished()),this,SLOT(animationDoneSlot()));
m_next=next;
m_now=now;
m_active=true;
animgroup->start(QAbstractAnimation::DeleteWhenStopped);
}
void SlidingStackedWidget::animationDoneSlot()
{
setCurrentIndex(m_next);
widget(m_now)->hide();
widget(m_now)->move(m_pnow);
m_active=false;
emit animationFinished();
}

View File

@@ -1,80 +0,0 @@
/*
* MIT License
Copyright (c) 2020 Tim Schneeberger (ThePBone) <tim.schneeberger(at)outlook.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*
* Copied from https://github.com/Qt-Widgets/SlidingStackedWidget-1
*/
#ifndef SLIDINGSTACKEDWIDGET_H
#define SLIDINGSTACKEDWIDGET_H
#include <QStackedWidget>
#include <QEasingCurve>
#include <QParallelAnimationGroup>
class SlidingStackedWidget : public QStackedWidget {
Q_OBJECT
public:
//! Animation direction
enum t_direction {
LEFT2RIGHT,
RIGHT2LEFT,
TOP2BOTTOM,
BOTTOM2TOP,
AUTOMATIC
};
SlidingStackedWidget(QWidget *parent);
public slots:
//! Set animation speed
void setSpeed(int speed);
//! Set easing curve
void setAnimation(enum QEasingCurve::Type animationtype);
//! Change positioning mode
void setVerticalMode(bool vertical = true);
//! Enables page wrap for \c slideInNext and \c slideInPrev
void setWrap(bool wrap);
//! Slide to next page
bool slideInNext();
//! Slide to previous page
bool slideInPrev();
//! Slide to page x
void slideInIdx(int idx, enum t_direction direction=AUTOMATIC);
//! Slide to page with widget
void slideInWgt(QWidget * widget, enum t_direction direction=AUTOMATIC);
signals:
//! Animation is finished
void animationFinished(void);
protected slots:
void animationDoneSlot(void);
protected:
QWidget *m_mainwindow;
int m_speed;
enum QEasingCurve::Type m_animationtype;
bool m_vertical;
int m_now;
int m_next;
bool m_wrap;
QPoint m_pnow;
bool m_active;
QList<QWidget*> blockedPageList;
QParallelAnimationGroup *animgroup;
};
#endif // SLIDINGSTACKEDWIDGET_H

View File

@@ -1,312 +0,0 @@
/*---------------------------------------------------------*\
| AddDeviceDialog.h |
| |
| Device adding helper window |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "AddDeviceDialog.h"
#include "ui_AddDeviceDialog.h"
#include "RGBController.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
#include "LogManager.h"
// Device entries
#include "DMXSettingsEntry.h"
#include "E131SettingsEntry.h"
#include "ElgatoKeyLightSettingsEntry.h"
#include "ElgatoLightStripSettingsEntry.h"
#include "KasaSmartSettingsEntry.h"
#include "LIFXSettingsEntry.h"
#include "PhilipsHueSettingsEntry.h"
#include "PhilipsWizSettingsEntry.h"
#include "QMKORGBSettingsEntry.h"
#include "SerialSettingsEntry.h"
#include "YeelightSettingsEntry.h"
#include "GoveeSettingsEntry.h"
#include "NanoleafScanPage.h"
#include <QDesktopServices>
static void DetectionProgressChangedCallback(void* param)
{
AddDeviceDialog* this_obj = (AddDeviceDialog*)(param);
QMetaObject::invokeMethod(this_obj, "onDetectionProgressChanged", Qt::QueuedConnection);
}
static void DetectionEndedCallback(void* param)
{
AddDeviceDialog* this_obj = (AddDeviceDialog*)(param);
QMetaObject::invokeMethod(this_obj, "onDetectionEnded", Qt::QueuedConnection);
}
AddDeviceDialog::AddDeviceDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::AddDeviceDialog)
{
ui->setupUi(this);
ResourceManager* rm = ResourceManager::get();
rm->RegisterDetectionEndCallback(&DetectionEndedCallback, this);
rm->RegisterDetectionProgressCallback(&DetectionProgressChangedCallback, this);
home();
}
AddDeviceDialog::~AddDeviceDialog()
{
ResourceManager* rm = ResourceManager::get();
rm->UnregisterDetectionEndCallback(&DetectionEndedCallback, this);
rm->UnregisterDetectionProgressCallback(&DetectionProgressChangedCallback, this);
delete ui;
}
void AddDeviceDialog::setScanButtons(bool scan)
{
ui->progressBar->setVisible(scan);
ui->ButtonScanBack->setVisible(!scan);
ui->ButtonScanRescan->setVisible(!scan);
if(scan)
{
ui->ButtonScanBeginning->hide();
ui->ButtonScanClose->hide();
}
}
void AddDeviceDialog::home()
{
scanFromPage = -1;
helpFromPage = -1;
configureFromPage = -1;
ui->stackedWidget->slideInWgt(ui->PageConnectionType, SlidingStackedWidget::LEFT2RIGHT);
}
void AddDeviceDialog::rescan()
{
if(scanFromPage == -1)
{
// Save the index of the page we came from
scanFromPage = ui->stackedWidget->currentIndex();
// Cache the names of all devices that were found so far
cachedDevices.clear();
std::vector<RGBController*> controllers = ResourceManager::get()->GetRGBControllers();
for(int i = 0; i < (int)controllers.size(); ++i)
{
cachedDevices.push_back(controllers[i]->name);
}
}
ui->LabelScan->setText(tr("<h2>Re-scanning devices...</h2>"));
setScanButtons(true);
ui->stackedWidget->slideInWgt(ui->PageScan, SlidingStackedWidget::RIGHT2LEFT);
ResourceManager::get()->DetectDevices();
}
void AddDeviceDialog::configure(QWidget* entry)
{
configureFromPage = ui->stackedWidget->currentIndex();
delete ui->ConfigureEntry;
ui->ConfigureEntry = entry;
ui->PageConfigureLayout->insertWidget(1, entry);
ui->stackedWidget->slideInWgt(ui->PageConfigure, SlidingStackedWidget::RIGHT2LEFT);
}
void AddDeviceDialog::on_ButtonSerial_clicked()
{
configure(new SerialSettingsEntry);
}
void AddDeviceDialog::on_ButtonDMX_clicked()
{
configure(new DMXSettingsEntry);
}
void AddDeviceDialog::on_ButtonQMK_clicked()
{
configure(new QMKORGBSettingsEntry);
}
void AddDeviceDialog::on_ButtonE131_clicked()
{
configure(new E131SettingsEntry);
}
void AddDeviceDialog::on_ButtonKasaSmart_clicked()
{
configure(new KasaSmartSettingsEntry);
}
void AddDeviceDialog::on_ButtonLIFX_clicked()
{
configure(new LIFXSettingsEntry);
}
void AddDeviceDialog::on_ButtonPhilipsHue_clicked()
{
configure(new PhilipsHueSettingsEntry);
}
void AddDeviceDialog::on_ButtonPhilipsWiz_clicked()
{
configure(new PhilipsWizSettingsEntry);
}
void AddDeviceDialog::on_ButtonYeelight_clicked()
{
configure(new YeelightSettingsEntry);
}
void AddDeviceDialog::on_ButtonNanloeaf_clicked()
{
configure(new NanoleafScanPage);
}
void AddDeviceDialog::on_ButtonElgatoKeyLight_clicked()
{
configure(new ElgatoKeyLightSettingsEntry);
}
void AddDeviceDialog::on_ButtonElgatoLightStrip_clicked()
{
configure(new ElgatoLightStripSettingsEntry);
}
void AddDeviceDialog::on_ButtonGovee_clicked()
{
configure(new GoveeSettingsEntry);
}
// ===== CONFIGURE =====
void AddDeviceDialog::on_ButtonConfigureBack_clicked()
{
ui->stackedWidget->slideInIdx(configureFromPage, SlidingStackedWidget::LEFT2RIGHT);
configureFromPage = -1;
}
void AddDeviceDialog::on_ButtonConfigureScan_clicked()
{
BaseManualDeviceEntry* manualEntry = dynamic_cast<BaseManualDeviceEntry*>(ui->ConfigureEntry);
if(manualEntry)
{
SettingsManager* sm = ResourceManager::get()->GetSettingsManager();
const char* section = manualEntry->settingsSection();
json result = sm->GetSettings(section);
if(!strcmp(section, "NanoleafDevices"))
{
NanoleafSettingsEntry* entry = dynamic_cast<NanoleafSettingsEntry*>(manualEntry);
if(entry)
{
result["devices"][entry->getLocation()] = manualEntry->saveSettings();
}
else
{
LOG_ERROR("[AddDeviceDialog]: nanoleaf entry failed to cast, saving entry aborted");
}
}
else if(!strcmp(section, "PhilipsHueDevices"))
{
result["bridges"].push_back(manualEntry->saveSettings());
}
else
{
result["devices"].push_back(manualEntry->saveSettings());
}
sm->SetSettings(section, result);
sm->SaveSettings();
}
rescan();
}
// ===== SCAN =====
void AddDeviceDialog::on_ButtonScanBack_clicked()
{
ui->stackedWidget->slideInIdx(scanFromPage, SlidingStackedWidget::LEFT2RIGHT);
scanFromPage = -1;
}
void AddDeviceDialog::on_ButtonScanRescan_clicked()
{
rescan();
}
void AddDeviceDialog::on_ButtonScanBeginning_clicked()
{
home();
}
void AddDeviceDialog::on_ButtonScanClose_clicked()
{
close();
}
void AddDeviceDialog::onDetectionProgressChanged()
{
ui->progressBar->setValue(ResourceManager::get()->GetDetectionPercent());
ui->progressBar->setFormat(QString::fromStdString(ResourceManager::get()->GetDetectionString()));
if(ResourceManager::get()->GetDetectionPercent() != 100)
{
setScanButtons(true);
};
}
void AddDeviceDialog::onDetectionEnded()
{
setScanButtons(false);
// Set text
std::vector<RGBController*> controllers = ResourceManager::get()->GetRGBControllers();
if(controllers.empty())
{
ui->LabelScan->setText(tr("<h2>Still nothing O_O</h2>"
"Scan reported no devices"));
}
else
{
QString text = tr("<h2>Scan complete</h2>");
bool foundNew = false;
for(int i = 0; i < (int)controllers.size(); ++i)
{
std::vector<std::string>::iterator it = std::find(cachedDevices.begin(), cachedDevices.end(), controllers[i]->name);
if(it == cachedDevices.end())
{
if(!foundNew)
{
text.append(tr("New devices that were found:<ul>"));
}
foundNew = true;
text.append("<li>");
text.append(controllers[i]->name.c_str());
text.append("</li>");
}
}
if(!foundNew)
{
text.append(tr("No new devices were found. Please go back and check the parameters, or file a new device issue."));
}
else
{
text.append("</ul>");
// Detection has gained results - show buttons to "complete" the hunt
ui->ButtonScanBeginning->show();
ui->ButtonScanClose->show();
}
ui->LabelScan->setText(text);
}
}

View File

@@ -1,67 +0,0 @@
/*---------------------------------------------------------*\
| AddDeviceDialog.h |
| |
| Device adding helper window |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#pragma once
#include <QDialog>
#include <QSortFilterProxyModel>
namespace Ui
{
class AddDeviceDialog;
}
class AddDeviceDialog : public QDialog
{
Q_OBJECT
public:
explicit AddDeviceDialog(QWidget *parent = nullptr);
~AddDeviceDialog();
private slots:
void on_ButtonSerial_clicked();
void on_ButtonDMX_clicked();
void on_ButtonQMK_clicked();
void on_ButtonE131_clicked();
void on_ButtonElgatoKeyLight_clicked();
void on_ButtonElgatoLightStrip_clicked();
void on_ButtonGovee_clicked();
void on_ButtonKasaSmart_clicked();
void on_ButtonLIFX_clicked();
void on_ButtonPhilipsHue_clicked();
void on_ButtonPhilipsWiz_clicked();
void on_ButtonYeelight_clicked();
void on_ButtonNanloeaf_clicked();
void on_ButtonConfigureBack_clicked();
void on_ButtonConfigureScan_clicked();
void on_ButtonScanBack_clicked();
void on_ButtonScanRescan_clicked();
void on_ButtonScanBeginning_clicked();
void on_ButtonScanClose_clicked();
void onDetectionProgressChanged();
void onDetectionEnded();
private:
Ui::AddDeviceDialog *ui;
void home();
void rescan();
void setScanButtons(bool scan);
void configure(QWidget* entry);
int scanFromPage = -1;
int helpFromPage = -1;
int configureFromPage = -1;
std::string title; // Cached device name & manufacturer from Hardware IDs
std::vector<std::string> cachedDevices;
};

View File

@@ -1,273 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddDeviceDialog</class>
<widget class="QWidget" name="AddDeviceDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>645</width>
<height>556</height>
</rect>
</property>
<property name="windowTitle">
<string>Add device</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="SlidingStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="PageConnectionType">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;h2&gt;What kind of a device is it?&lt;/h2&gt;
Please make sure the device is plugged in (or turned on) before proceeding&lt;br&gt;
Anything not listed here should be detected automatically, if supported</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="margin">
<number>5</number>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QPushButton" name="ButtonDMX">
<property name="text">
<string>DMX</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="ButtonGovee">
<property name="text">
<string>Govee</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="ButtonKasaSmart">
<property name="text">
<string>Kasa Smart</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="ButtonPhilipsWiz">
<property name="text">
<string>Philips Wiz</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="ButtonQMK">
<property name="text">
<string>QMK Device</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="ButtonNanloeaf">
<property name="text">
<string>Nanoleaf</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="ButtonElgatoKeyLight">
<property name="text">
<string>Elgato KeyLight</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="ButtonE131">
<property name="text">
<string>E1.31 (including WLED)</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="ButtonLIFX">
<property name="text">
<string>LIFX</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="ButtonSerial">
<property name="text">
<string>Serial Port Device</string>
</property>
<property name="autoDefault">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="ButtonPhilipsHue">
<property name="text">
<string>Philips Hue</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="ButtonElgatoLightStrip">
<property name="text">
<string>Elgato LightStrip</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="ButtonYeelight">
<property name="text">
<string>Yeelight</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="PageScan">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QLabel" name="LabelScan">
<property name="text">
<string>&lt;h2&gt;Re-scanning devices...&lt;/h2&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="margin">
<number>5</number>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="ButtonScanBack">
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ButtonScanRescan">
<property name="text">
<string>Scan again</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ButtonScanBeginning">
<property name="text">
<string>Add another device</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ButtonScanClose">
<property name="text">
<string>All good!</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="PageConfigure">
<layout class="QVBoxLayout" name="PageConfigureLayout">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>&lt;h2&gt;Please configure your device here&lt;/h2&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="margin">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="ConfigureEntry" native="true"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QPushButton" name="ButtonConfigureBack">
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ButtonConfigureScan">
<property name="text">
<string>Save &amp;&amp; Scan</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SlidingStackedWidget</class>
<extends>QStackedWidget</extends>
<header>slidingstackedwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -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);
};

View File

@@ -20,7 +20,22 @@ class BaseManualDeviceEntry: public QWidget
public:
explicit BaseManualDeviceEntry(QWidget *parent = nullptr): QWidget(parent) {}
virtual void loadFromSettings(const json& data) = 0;
virtual json saveSettings() = 0;
virtual const char* settingsSection() = 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)

View File

@@ -96,7 +96,17 @@ json DMXSettingsEntry::saveSettings()
return result;
}
const char* DMXSettingsEntry::settingsSection()
bool DMXSettingsEntry::isDataValid()
{
return "DMXDevices";
// 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);

View File

@@ -24,12 +24,12 @@ public:
explicit DMXSettingsEntry(QWidget *parent = nullptr);
~DMXSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::DMXSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
};

View File

@@ -284,7 +284,17 @@ json E131SettingsEntry::saveSettings()
return result;
}
const char* E131SettingsEntry::settingsSection()
bool E131SettingsEntry::isDataValid()
{
return "E131Devices";
// stub
return true;
}
static BaseManualDeviceEntry* SpawnE131Entry(const json& data)
{
E131SettingsEntry* entry = new E131SettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("E1.31 (including WLED)", "E131Devices", SpawnE131Entry);

View File

@@ -24,8 +24,8 @@ public:
explicit E131SettingsEntry(QWidget *parent = nullptr);
~E131SettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::E131SettingsEntry *ui;
@@ -35,6 +35,6 @@ private:
void ShowMatrixSettings();
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
void on_TypeComboBox_currentIndexChanged(int index);
};

View File

@@ -46,7 +46,17 @@ json ElgatoKeyLightSettingsEntry::saveSettings()
return result;
}
const char* ElgatoKeyLightSettingsEntry::settingsSection()
bool ElgatoKeyLightSettingsEntry::isDataValid()
{
return "ElgatoKeyLightDevices";
// 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);

View File

@@ -24,12 +24,12 @@ public:
explicit ElgatoKeyLightSettingsEntry(QWidget *parent = nullptr);
~ElgatoKeyLightSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::ElgatoKeyLightSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
};

View File

@@ -46,7 +46,18 @@ json ElgatoLightStripSettingsEntry::saveSettings()
return result;
}
const char* ElgatoLightStripSettingsEntry::settingsSection()
bool ElgatoLightStripSettingsEntry::isDataValid()
{
return "ElgatoLightStripDevices";
// 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);

View File

@@ -24,12 +24,12 @@ public:
explicit ElgatoLightStripSettingsEntry(QWidget *parent = nullptr);
~ElgatoLightStripSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::ElgatoLightStripSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
};

View File

@@ -47,7 +47,17 @@ json GoveeSettingsEntry::saveSettings()
return result;
}
const char* GoveeSettingsEntry::settingsSection()
bool GoveeSettingsEntry::isDataValid()
{
return "GoveeDevices";
// 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);

View File

@@ -26,12 +26,12 @@ public:
explicit GoveeSettingsEntry(QWidget *parent = nullptr);
~GoveeSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::GoveeSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
};

View File

@@ -50,12 +50,22 @@ json KasaSmartSettingsEntry::saveSettings()
return result;
}
const char* KasaSmartSettingsEntry::settingsSection()
{
return "KasaSmartDevices";
}
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);

View File

@@ -24,13 +24,14 @@ public:
explicit KasaSmartSettingsEntry(QWidget *parent = nullptr);
~KasaSmartSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
void setName(QString name);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::KasaSmartSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
};

View File

@@ -50,12 +50,22 @@ json LIFXSettingsEntry::saveSettings()
return result;
}
const char* LIFXSettingsEntry::settingsSection()
{
return "LIFXDevices";
}
void LIFXSettingsEntry::setName(QString name)
{
ui->NameEdit->setText(name);
}
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);

View File

@@ -22,13 +22,14 @@ public:
explicit LIFXSettingsEntry(QWidget *parent = nullptr);
~LIFXSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
void setName(QString name);
json saveSettings() override;
bool isDataValid() override;
private:
Ui::LIFXSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
};

View File

@@ -9,21 +9,10 @@
#include "ManualDevicesSettingsPage.h"
#include "ui_ManualDevicesSettingsPage.h"
#include "DMXSettingsEntry.h"
#include "E131SettingsEntry.h"
#include "ElgatoKeyLightSettingsEntry.h"
#include "ElgatoLightStripSettingsEntry.h"
#include "KasaSmartSettingsEntry.h"
#include "LIFXSettingsEntry.h"
#include "NanoleafSettingsEntry.h"
#include "PhilipsHueSettingsEntry.h"
#include "PhilipsWizSettingsEntry.h"
#include "QMKORGBSettingsEntry.h"
#include "SerialSettingsEntry.h"
#include "YeelightSettingsEntry.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
#include "AddDeviceDialog.h"
static void ManualDevicesPageReloadCallback(void* this_ptr)
{
@@ -39,6 +28,10 @@ ManualDevicesSettingsPage::ManualDevicesSettingsPage(QWidget *parent) :
ui->setupUi(this);
ResourceManager::get()->RegisterDetectionEndCallback(&ManualDevicesPageReloadCallback, this);
addDeviceMenu = new QMenu();
ui->addDeviceButton->setMenu(addDeviceMenu);
connect(addDeviceMenu, &QMenu::triggered, this, &ManualDevicesSettingsPage::onAddDeviceItemSelected);
reloadList();
on_deviceList_itemSelectionChanged(); // Refresh button state
}
@@ -48,6 +41,7 @@ ManualDevicesSettingsPage::~ManualDevicesSettingsPage()
ResourceManager::get()->UnregisterDetectionEndCallback(&ManualDevicesPageReloadCallback, this);
clearList();
delete ui;
delete addDeviceMenu;
}
void ManualDevicesSettingsPage::changeEvent(QEvent *event)
@@ -58,12 +52,6 @@ void ManualDevicesSettingsPage::changeEvent(QEvent *event)
}
}
void ManualDevicesSettingsPage::on_addDeviceButton_clicked()
{
AddDeviceDialog dialog(this);
dialog.exec();
}
void ManualDevicesSettingsPage::on_removeDeviceButton_clicked()
{
int cur_row = ui->deviceList->currentRow();
@@ -96,7 +84,7 @@ void ManualDevicesSettingsPage::on_saveConfigurationButton_clicked()
\*-----------------------------------------------------------------------------*/
for(size_t idx = 0; idx < entries.size(); ++idx)
{
std::string section = entries[idx]->settingsSection();
std::string section = entries[idx]->getSettingsSection();
if(section == "NanoleafDevices")
{
NanoleafSettingsEntry* entry = dynamic_cast<NanoleafSettingsEntry*>(entries[idx]);
@@ -123,22 +111,31 @@ void ManualDevicesSettingsPage::on_saveConfigurationButton_clicked()
sm->SaveSettings();
}
void ManualDevicesSettingsPage::reloadMenu()
{
std::vector<std::string> names = ManualDevicesTypeManager::get()->getRegisteredTypeNames();
addDeviceMenu->clear();
for(int i = 0; i < names.size(); ++i)
{
QAction* action = addDeviceMenu->addAction(QString::fromStdString(names[i]));
action->setData(QString::fromStdString(names[i]));
}
}
void ManualDevicesSettingsPage::reloadList()
{
clearList();
addDeviceMenu->clear();
addEntries("DMXDevices", [](){return new DMXSettingsEntry();});
addEntries("E131Devices", [](){return new E131SettingsEntry();});
addEntries("ElgatoKeyLightDevices", [](){return new ElgatoKeyLightSettingsEntry();});
addEntries("ElgatoLightStripDevices", [](){return new ElgatoLightStripSettingsEntry();});
addEntries("KasaSmartDevices", [](){return new KasaSmartSettingsEntry();});
addEntries("LIFXDevices", [](){return new LIFXSettingsEntry();});
addEntries("NanoleafDevices", [](){return new NanoleafSettingsEntry();});
addEntries("PhilipsHueDevices", [](){return new PhilipsHueSettingsEntry();});
addEntries("PhilipsWizDevices", [](){return new PhilipsWizSettingsEntry();});
addEntries("QMKOpenRGBDevices", [](){return new QMKORGBSettingsEntry();});
addEntries("LEDStripDevices", [](){return new SerialSettingsEntry();});
addEntries("YeelightDevices", [](){return new YeelightSettingsEntry();});
std::vector<ManualDeviceTypeBlock> blocks = ManualDevicesTypeManager::get()->getRegisteredTypes();
for(int i = 0; i < blocks.size(); ++i)
{
QAction* action = addDeviceMenu->addAction(QString::fromStdString(blocks[i].name));
action->setData(QString::fromStdString(blocks[i].name));
addEntries(blocks[i]);
}
}
void ManualDevicesSettingsPage::clearList()
@@ -154,11 +151,14 @@ void ManualDevicesSettingsPage::clearList()
entries_copy.clear();
}
void ManualDevicesSettingsPage::addEntry(const json& source, EntrySpawnFunction spawn)
void ManualDevicesSettingsPage::addEntry(BaseManualDeviceEntry* entry)
{
if(!entry)
{
return;
}
QListWidgetItem* item = new QListWidgetItem;
BaseManualDeviceEntry* entry = spawn();
entry->loadFromSettings(source);
item->setSizeHint(entry->sizeHint());
@@ -169,11 +169,11 @@ void ManualDevicesSettingsPage::addEntry(const json& source, EntrySpawnFunction
entries.push_back(entry);
}
void ManualDevicesSettingsPage::addEntries(const std::string& settingsName, EntrySpawnFunction spawn)
void ManualDevicesSettingsPage::addEntries(const ManualDeviceTypeBlock& block)
{
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings(settingsName);
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings(block.settingsSection);
const char* array_name = "devices";
if(settingsName == "PhilipsHueDevices")
if(block.settingsSection == "PhilipsHueDevices")
{
array_name = "bridges";
}
@@ -187,13 +187,28 @@ void ManualDevicesSettingsPage::addEntries(const std::string& settingsName, Entr
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)
{
addEntry(iter.value(), spawn);
BaseManualDeviceEntry* entry = block.spawn(iter.value());
if(entry)
{
addEntry(entry);
}
}
}
}
void ManualDevicesSettingsPage::onAddDeviceItemSelected(QAction* action)
{
std::string entryName = action->data().toString().toStdString();
BaseManualDeviceEntry* entry = ManualDevicesTypeManager::get()->spawnByTypeName(entryName, json());
if(entry)
{
addEntry(entry);
}
}
void ManualDevicesSettingsPage::on_deviceList_itemSelectionChanged()
{
int cur_row = ui->deviceList->currentRow();
@@ -201,4 +216,3 @@ void ManualDevicesSettingsPage::on_deviceList_itemSelectionChanged()
bool anySelected = (cur_row >= 0);
ui->removeDeviceButton->setEnabled(anySelected);
}

View File

@@ -10,8 +10,10 @@
#pragma once
#include "BaseManualDeviceEntry.h"
#include "ManualDevicesTypeManager.h"
#include "nlohmann/json.hpp"
#include <QWidget>
#include <QMenu>
using json = nlohmann::json;
@@ -20,8 +22,6 @@ namespace Ui
class ManualDevicesSettingsPage;
}
typedef std::function<BaseManualDeviceEntry*()> EntrySpawnFunction;
class ManualDevicesSettingsPage : public QWidget
{
Q_OBJECT
@@ -32,10 +32,11 @@ public:
private slots:
void reloadList();
void reloadMenu();
void onAddDeviceItemSelected(QAction* action);
void changeEvent(QEvent *event);
void on_addDeviceButton_clicked();
void on_removeDeviceButton_clicked();
void on_saveConfigurationButton_clicked();
@@ -44,8 +45,9 @@ private slots:
private:
Ui::ManualDevicesSettingsPage* ui;
std::vector<BaseManualDeviceEntry*> entries;
QMenu* addDeviceMenu;
void addEntry(const json& source, EntrySpawnFunction);
void addEntries(const std::string& settingsName, EntrySpawnFunction);
void addEntry(BaseManualDeviceEntry* entry);
void addEntries(const ManualDeviceTypeBlock&);
void clearList();
};

View File

@@ -13,35 +13,39 @@
<property name="windowTitle">
<string notr="true">Manually Added Devices Settings Page</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QPushButton" name="addDeviceButton">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="removeDeviceButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="saveConfigurationButton">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<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="QPushButton" name="saveConfigurationButton">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>

View File

@@ -0,0 +1,80 @@
/*---------------------------------------------------------*\
| 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-only |
\*---------------------------------------------------------*/
#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(int i = 0; i < types.size(); ++i)
{
result[i] = types[i].name;
}
return result;
}
BaseManualDeviceEntry* ManualDevicesTypeManager::spawnByTypeName(const std::string& typeName, const json& data)
{
for(int i = 0; i < types.size(); ++i)
{
if(types[i].name == typeName)
{
return types[i].spawn(data);
}
}
return nullptr;
}

View File

@@ -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-only |
\*---------------------------------------------------------*/
#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();
};

View File

@@ -9,6 +9,8 @@
#include "NanoleafSettingsEntry.h"
#include "ui_NanoleafSettingsEntry.h"
#include "NanoleafScanPage.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
#include "NanoleafController.h"
@@ -143,12 +145,34 @@ json NanoleafSettingsEntry::saveSettings()
return result;
}
const char* NanoleafSettingsEntry::settingsSection()
{
return "NanoleafDevices";
}
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
QWidget* parentWindow = QApplication::activeWindow();
NanoleafScanPage scanPage;
scanPage.show();
return nullptr;
}
else
{
NanoleafSettingsEntry* entry = new NanoleafSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
}
REGISTER_MANUAL_DEVICE_TYPE("Nanoleaf", "NanoleafDevices", SpawnNanoleafSettingsEntry);

View File

@@ -26,12 +26,13 @@ public:
NanoleafSettingsEntry(QString a_address, int a_port);
~NanoleafSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
std::string getLocation();
json saveSettings() override;
bool isDataValid() override;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
void on_UnpairButton_clicked();
void on_PairButton_clicked();

View File

@@ -93,7 +93,17 @@ json PhilipsHueSettingsEntry::saveSettings()
return result;
}
const char* PhilipsHueSettingsEntry::settingsSection()
bool PhilipsHueSettingsEntry::isDataValid()
{
return "PhilipsHueDevices";
// 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);

View File

@@ -24,13 +24,13 @@ public:
explicit PhilipsHueSettingsEntry(QWidget *parent = nullptr);
~PhilipsHueSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::PhilipsHueSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
void on_UnpairButton_clicked();
};

View File

@@ -70,7 +70,17 @@ json PhilipsWizSettingsEntry::saveSettings()
return result;
}
const char* PhilipsWizSettingsEntry::settingsSection()
bool PhilipsWizSettingsEntry::isDataValid()
{
return "PhilipsWizDevices";
// 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);

View File

@@ -24,12 +24,12 @@ public:
explicit PhilipsWizSettingsEntry(QWidget *parent = nullptr);
~PhilipsWizSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::PhilipsWizSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
};

View File

@@ -61,7 +61,17 @@ json QMKORGBSettingsEntry::saveSettings()
return result;
}
const char* QMKORGBSettingsEntry::settingsSection()
bool QMKORGBSettingsEntry::isDataValid()
{
return "QMKOpenRGBDevices";
// stub
return true;
}
static BaseManualDeviceEntry* SpawnQMKORGBSettingsEntry(const json& data)
{
QMKORGBSettingsEntry* entry = new QMKORGBSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("QMK", "QMKOpenRGBDevices", SpawnQMKORGBSettingsEntry);

View File

@@ -27,8 +27,8 @@ public:
explicit QMKORGBSettingsEntry(QWidget *parent = nullptr);
~QMKORGBSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::QMKORGBSettingsEntry *ui;

View File

@@ -122,7 +122,17 @@ json SerialSettingsEntry::saveSettings()
return result;
}
const char* SerialSettingsEntry::settingsSection()
bool SerialSettingsEntry::isDataValid()
{
return "LEDStripDevices";
// stub
return true;
}
static BaseManualDeviceEntry* SpawnSerialSettingsEntry(const json& data)
{
SerialSettingsEntry* entry = new SerialSettingsEntry;
entry->loadFromSettings(data);
return entry;
}
REGISTER_MANUAL_DEVICE_TYPE("Serial Device", "LEDStripDevices", SpawnSerialSettingsEntry);

View File

@@ -21,7 +21,7 @@ class SerialSettingsEntry : public BaseManualDeviceEntry
Q_OBJECT
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
void on_ProtocolComboBox_currentIndexChanged(int index);
@@ -29,8 +29,8 @@ public:
explicit SerialSettingsEntry(QWidget *parent = nullptr);
~SerialSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::SerialSettingsEntry *ui;

View File

@@ -93,7 +93,17 @@ json YeelightSettingsEntry::saveSettings()
return result;
}
const char* YeelightSettingsEntry::settingsSection()
bool YeelightSettingsEntry::isDataValid()
{
return "YeelightDevices";
// 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);

View File

@@ -24,13 +24,13 @@ public:
explicit YeelightSettingsEntry(QWidget *parent = nullptr);
~YeelightSettingsEntry();
void loadFromSettings(const json& data);
json saveSettings();
const char* settingsSection();
json saveSettings() override;
bool isDataValid() override;
private:
Ui::YeelightSettingsEntry *ui;
private slots:
void changeEvent(QEvent *event);
void changeEvent(QEvent *event) override;
void on_HostIPChooserButton_clicked();
};