Skip to content

Commit

Permalink
WIP DPI stages implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
z3ntu committed May 5, 2024
1 parent 8348b59 commit 477459e
Show file tree
Hide file tree
Showing 5 changed files with 321 additions and 151 deletions.
228 changes: 90 additions & 138 deletions src/devicewidget/dpisliderwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#include "util.h"

#include <QCheckBox>
#include <QComboBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QSlider>
#include <QSpinBox>

Expand All @@ -22,173 +24,123 @@ DpiSliderWidget::DpiSliderWidget(QWidget *parent, libopenrazer::Device *device)

QVBoxLayout *verticalLayout = new QVBoxLayout(this);

// Declare header font
QFont headerFont("Arial", 15, QFont::Bold);

// HBoxes
auto *dpiXHBox = new QHBoxLayout();
auto *dpiYHBox = new QHBoxLayout();
auto *dpiHeaderHBox = new QHBoxLayout();

// Header
QLabel *dpiHeader = new QLabel(tr("DPI"), this);
QLabel *dpiHeader = new QLabel(tr("DPI"));
dpiHeader->setFont(headerFont);
dpiHeaderHBox->addWidget(dpiHeader);

dpiHeaderHBox->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));

if (device->hasFeature("dpi_stages")) {
auto *dpiStagesCheckbox = new QCheckBox();
dpiStagesCheckbox->setText(tr("Enable stages"));
dpiStagesCheckbox->setChecked(true); // FIXME determine based on something
dpiHeaderHBox->addWidget(dpiStagesCheckbox);

connect(dpiStagesCheckbox, &QCheckBox::clicked, this, [=](bool checked) {
/* Show/hide stage 2-5 */
for (int i = 1; i < dpiStageWidgets.size(); i++) {
if (checked) {
dpiStageWidgets[i]->show();
} else {
dpiStageWidgets[i]->hide();
}
}

dpiStageWidgets[0]->setSingleStage(!checked);
});
}

// Sync checkbox
auto *dpiSyncCheckbox = new QCheckBox(this);
auto *dpiSyncCheckbox = new QCheckBox();
dpiSyncCheckbox->setText(tr("Lock X/Y"));

dpiHeaderHBox->addWidget(dpiHeader);
dpiHeaderHBox->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
dpiHeaderHBox->addWidget(dpiSyncCheckbox);
verticalLayout->addLayout(dpiHeaderHBox);

// Labels
dpiXLabel = new QLabel("X");
dpiYLabel = new QLabel("Y");

// Read-only spinboxes
dpiXSpinBox = new QSpinBox(this);
dpiYSpinBox = new QSpinBox(this);
dpiXSpinBox->setObjectName("dpiXSpinBox");
dpiYSpinBox->setObjectName("dpiYSpinBox");
dpiXSpinBox->setEnabled(false);
dpiYSpinBox->setEnabled(false);

// Sliders
dpiXSlider = new QSlider(Qt::Horizontal, this);
dpiYSlider = new QSlider(Qt::Horizontal, this);
dpiXSlider->setObjectName("dpiX");
dpiYSlider->setObjectName("dpiY");

// Get the current DPI and set the slider&text
openrazer::RazerDPI currDPI = { 0, 0 };
try {
currDPI = device->getDPI();
} catch (const libopenrazer::DBusException &e) {
qWarning("Failed to get dpi");
}
connect(dpiSyncCheckbox, &QCheckBox::clicked, this, [=](bool checked) {
for (DpiStageWidget *stageWidget : dpiStageWidgets) {
stageWidget->setSyncDpi(checked);
}
});

const int minimumDPI = 100;
dpiXSpinBox->setMinimum(minimumDPI);
dpiYSpinBox->setMinimum(minimumDPI);
dpiXSlider->setMinimum(minimumDPI / 100);
dpiYSlider->setMinimum(minimumDPI / 100);
// DPI stages
const int minimumDpi = 100;

int maxDPI = 0;
int maximumDpi = 0;
try {
maxDPI = device->maxDPI();
maximumDpi = device->maxDPI();
} catch (const libopenrazer::DBusException &e) {
qWarning("Failed to get max dpi");
}
dpiXSpinBox->setMaximum(maxDPI);
dpiYSpinBox->setMaximum(maxDPI);
dpiXSlider->setMaximum(maxDPI / 100);
dpiYSlider->setMaximum(maxDPI / 100);

dpiXSlider->setTickInterval(10);
dpiYSlider->setTickInterval(10);
dpiXSlider->setTickPosition(QSlider::TickPosition::TicksBelow);
dpiYSlider->setTickPosition(QSlider::TickPosition::TicksBelow);

dpiXSpinBox->setValue(currDPI.dpi_x);
dpiYSpinBox->setValue(currDPI.dpi_y);
dpiXSlider->setValue(currDPI.dpi_x / 100);
dpiYSlider->setValue(currDPI.dpi_y / 100);

dpiSyncCheckbox->setChecked(syncDpi);
updateXYVisibility();

dpiXHBox->addWidget(dpiXLabel);
dpiXHBox->addWidget(dpiXSpinBox);
dpiXHBox->addWidget(dpiXSlider);

dpiYHBox->addWidget(dpiYLabel);
dpiYHBox->addWidget(dpiYSpinBox);
dpiYHBox->addWidget(dpiYSlider);

connect(dpiXSlider, &QSlider::valueChanged, this, &DpiSliderWidget::dpiChanged);
connect(dpiYSlider, &QSlider::valueChanged, this, &DpiSliderWidget::dpiChanged);
connect(dpiSyncCheckbox, &QCheckBox::clicked, this, [=](bool checked) {
syncDpi = checked;
updateXYVisibility();

/* Snap the Y value to the current X value when the box is checked */
if (checked) {
dpiYSlider->setValue(dpiXSlider->value());
/* Set DPI on the device manually, the dpiChanged function doesn't
* do that for just setting Y with syncDpi=true */
ushort dpi = dpiXSlider->value() * 100;
device->setDPI({ dpi, dpi });

if (device->hasFeature("dpi_stages")) {
QPair<uchar, QVector<openrazer::RazerDPI>> stagesPair = { 1, {} };
try {
stagesPair = device->getDPIStages();
} catch (const libopenrazer::DBusException &e) {
qWarning("Failed to get dpi stages");
}
});
uchar activeStage = stagesPair.first;
QVector<openrazer::RazerDPI> stages = stagesPair.second;

verticalLayout->addLayout(dpiHeaderHBox);
verticalLayout->addLayout(dpiXHBox);
verticalLayout->addLayout(dpiYHBox);
}
// Assume user wants DPI synced if all values are currently equal
bool isSynced = true;
for (openrazer::RazerDPI dpi : stages) {
isSynced &= dpi.dpi_x == dpi.dpi_y;
}
dpiSyncCheckbox->setChecked(isSynced);

void DpiSliderWidget::dpiChanged(int orig_value)
{
ushort value = orig_value * 100;
qDebug() << "activeStage:" << activeStage; // FIXME remove
qDebug() << "stages:" << stages; // FIXME remove

auto *sender = qobject_cast<QSlider *>(QObject::sender());
/* Create widgets for the 5 possible DPI stages */
for (int stageNumber = 1; stageNumber <= 5; stageNumber++) {
/* Get DPI for current stage - or default value */
openrazer::RazerDPI dpi = stages.value(stageNumber - 1);

openrazer::RazerDPI dpi = { 0, 0 };
auto *stageWidget = new DpiStageWidget(stageNumber, minimumDpi, maximumDpi, dpi, activeStage == stageNumber);
stageWidget->setSyncDpi(isSynced);

// if DPI should be synced
if (syncDpi) {
if (sender->objectName() == "dpiX") {
// set the other slider
dpiYSlider->setValue(orig_value);
connect(stageWidget, &DpiStageWidget::stageActivated, this, [=]() {
qDebug() << "stage active=" << stageNumber;
for (int i = 0; i < dpiStageWidgets.size(); i++) {
/* Set all other stages as not active (loop is 0-based) */
if (i + 1 == stageNumber)
continue;
dpiStageWidgets[i]->setStageActive(false);
}
});

// set DPI
dpi = { value, value }; // set for both X & Y
} else {
// just set the slider (as the rest was done already or will be done)
dpiXSlider->setValue(orig_value);
}
} else { /* if DPI should NOT be synced */
// set DPI (with value from other slider)
if (sender->objectName() == "dpiX") {
dpi = { value, static_cast<ushort>(dpiYSlider->value() * 100) };
} else {
dpi = { static_cast<ushort>(dpiXSlider->value() * 100), value };
}
}
connect(stageWidget, &DpiStageWidget::dpiChanged, this, [=](openrazer::RazerDPI dpi) {
qDebug() << "stage=" << stageNumber << "dpi changed=" << dpi;
});

// Update spinbox with new value
if (sender->objectName() == "dpiX") {
dpiXSpinBox->setValue(value);
} else {
dpiYSpinBox->setValue(value);
}
verticalLayout->addWidget(stageWidget);

// Check if we need to actually set the DPI
if (dpi.dpi_x == 0 && dpi.dpi_y == 0) {
return;
}
dpiStageWidgets.append(stageWidget);
}
} else {
openrazer::RazerDPI currentDpi = { 0, 0 };
try {
currentDpi = device->getDPI();
} catch (const libopenrazer::DBusException &e) {
qWarning("Failed to get dpi");
}

try {
device->setDPI(dpi);
} catch (const libopenrazer::DBusException &e) {
qWarning("Failed to set dpi");
util::showError(tr("Failed to set dpi"));
}
}
// Assume user wants DPI synced if both values are currently equal
bool isSynced = currentDpi.dpi_x == currentDpi.dpi_y;
dpiSyncCheckbox->setChecked(isSynced);

void DpiSliderWidget::updateXYVisibility()
{
if (syncDpi) {
dpiXLabel->hide();
auto *stageWidget = new DpiStageWidget(0, minimumDpi, maximumDpi, currentDpi, false);
stageWidget->setSingleStage(true);
stageWidget->setSyncDpi(isSynced);

dpiYLabel->hide();
dpiYSpinBox->hide();
dpiYSlider->hide();
} else {
dpiXLabel->show();
verticalLayout->addWidget(stageWidget);

dpiYLabel->show();
dpiYSpinBox->show();
dpiYSlider->show();
dpiStageWidgets.append(stageWidget);
}
}
16 changes: 3 additions & 13 deletions src/devicewidget/dpisliderwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef DPISLIDERWIDGET_H
#define DPISLIDERWIDGET_H

#include "dpistagewidget.h"

#include <QLabel>
#include <QSlider>
#include <QSpinBox>
Expand All @@ -17,22 +19,10 @@ class DpiSliderWidget : public QWidget
public:
DpiSliderWidget(QWidget *parent, libopenrazer::Device *device);

public slots:
// DPI checkbox & slider
void dpiChanged(int value);

private:
bool syncDpi = true;
libopenrazer::Device *device;

QLabel *dpiXLabel;
QLabel *dpiYLabel;
QSpinBox *dpiXSpinBox;
QSpinBox *dpiYSpinBox;
QSlider *dpiXSlider;
QSlider *dpiYSlider;

void updateXYVisibility();
QVector<DpiStageWidget *> dpiStageWidgets;
};

#endif // DPISLIDERWIDGET_H
Loading

0 comments on commit 477459e

Please sign in to comment.