Customizable ColorPicker (#2202)

* Added spinbox, refactored colorpicker

* Added add preset functionality

* Added delete preset

* Refactored code

* Fix
This commit is contained in:
Dearsh Oberoi
2022-01-31 00:33:07 +05:30
committed by GitHub
parent 1cc5a26292
commit 259e438f96
19 changed files with 563 additions and 142 deletions

View File

@@ -7,7 +7,7 @@
;; The colors are arranged counter-clockwise with the first being set to the right of the cursor ;; The colors are arranged counter-clockwise with the first being set to the right of the cursor
;; Colors are any valid hex code or W3C color name ;; Colors are any valid hex code or W3C color name
;; "picker" adds a custom color picker ;; "picker" adds a custom color picker
;userColors=#800000, #ff0000, #ffff00, #00ff00, #008000, #00ffff, #0000ff, #ff00ff, #800080, picker ;userColors=picker, #800000, #ff0000, #ffff00, #00ff00, #008000, #00ffff, #0000ff, #ff00ff, #800080
; ;
;; Image Save Path ;; Image Save Path
;savePath=/tmp ;savePath=/tmp
@@ -84,6 +84,9 @@
;; Upload to imgur without confirmation (bool) ;; Upload to imgur without confirmation (bool)
;uploadWithoutConfirmation=false ;uploadWithoutConfirmation=false
; ;
;; Use larger color palette as the default one
; predefinedColorPaletteLarge=false
;
;; Shortcut Settings for all tools ;; Shortcut Settings for all tools
;[Shortcuts] ;[Shortcuts]
;TYPE_ARROW=A ;TYPE_ARROW=A

View File

@@ -11,6 +11,7 @@ target_sources(
strftimechooserwidget.cpp strftimechooserwidget.cpp
styleoverride.cpp styleoverride.cpp
uicoloreditor.cpp uicoloreditor.cpp
colorpickereditor.cpp
visualseditor.cpp visualseditor.cpp
shortcutswidget.cpp shortcutswidget.cpp
setshortcutwidget.cpp setshortcutwidget.cpp

View File

@@ -0,0 +1,166 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2022 Dearsh Oberoi
#include "colorpickereditor.h"
#include "src/utils/confighandler.h"
#include "src/utils/globalvalues.h"
#include "src/widgets/colorpickerwidget.h"
#include "src/widgets/colorspinbox.h"
#include <QApplication>
#include <QColor>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QString>
#include <QVector>
ColorPickerEditor::ColorPickerEditor(QWidget* parent)
: QWidget(parent)
, m_selectedIndex(1)
{
ConfigHandler config;
m_color = config.drawColor();
m_gLayout = new QGridLayout(this);
m_colorpicker = new ColorPickerWidget(this);
m_gLayout->addWidget(m_colorpicker, 0, 0);
m_colorWheel = new color_widgets::ColorWheel(this);
m_colorWheel->setColor(m_color);
const int size = GlobalValues::buttonBaseSize() * 3.5;
m_colorWheel->setMinimumSize(size, size);
m_gLayout->addWidget(m_colorWheel, 1, 0);
QVBoxLayout* m_vLocalLayout1 = new QVBoxLayout();
m_vLocalLayout1->addStretch();
m_colorSpinboxLabel = new QLabel(tr("Select Preset:"), this);
m_vLocalLayout1->addWidget(m_colorSpinboxLabel);
m_colorSpinbox = new ColorSpinBox(this);
connect(m_colorSpinbox,
QOverload<int>::of(&QSpinBox::valueChanged),
m_colorpicker,
[=](int val) {
m_selectedIndex = val;
m_colorpicker->updateSelection(val);
});
m_colorSpinbox->setToolTip(tr("Select preset using the spinbox"));
m_vLocalLayout1->addWidget(m_colorSpinbox);
m_deletePresetButton = new QPushButton(tr("Delete"), this);
m_deletePresetButton->setToolTip(
tr("Press button to delete the selected preset"));
connect(m_deletePresetButton,
&QPushButton::pressed,
this,
&ColorPickerEditor::onDeletePreset);
m_vLocalLayout1->addWidget(m_deletePresetButton);
m_vLocalLayout1->addStretch();
m_gLayout->addLayout(m_vLocalLayout1, 0, 1);
QVBoxLayout* m_vLocalLayout2 = new QVBoxLayout();
m_vLocalLayout2->addStretch();
m_addPresetLabel = new QLabel(tr("Add Preset:"), this);
m_vLocalLayout2->addWidget(m_addPresetLabel);
m_colorInput = new QLineEdit(this);
m_colorInput->setText(m_color.name(QColor::HexRgb));
m_colorInput->setToolTip(
tr("Enter color manually or select it using the color-wheel"));
connect(m_colorWheel,
&color_widgets::ColorWheel::colorSelected,
this,
[=](QColor c) {
m_color = c;
m_colorInput->setText(m_color.name(QColor::HexRgb));
});
m_vLocalLayout2->addWidget(m_colorInput);
m_addPresetButton = new QPushButton(tr("Add"), this);
m_addPresetButton->setToolTip(tr("Press button to add preset"));
connect(m_addPresetButton,
&QPushButton::pressed,
this,
&ColorPickerEditor::onAddPreset);
m_vLocalLayout2->addWidget(m_addPresetButton);
m_vLocalLayout2->addStretch();
m_gLayout->addLayout(m_vLocalLayout2, 1, 1);
}
void ColorPickerEditor::addPreset()
{
ConfigHandler config;
QVector<QColor> colors = config.userColors();
if (colors.contains(m_color))
return;
colors << m_color;
const int maxPresetsAllowed = 17;
if (colors.size() > maxPresetsAllowed) {
QMessageBox::critical(
this,
tr("Error"),
tr("Unable to add preset. Maximum limit reached."));
return;
}
config.setUserColors(colors);
}
void ColorPickerEditor::deletePreset()
{
ConfigHandler config;
QVector<QColor> colors = config.userColors();
colors.remove(m_selectedIndex);
const int minPresetsAllowed = 3;
if (colors.size() < minPresetsAllowed) {
QMessageBox::critical(
this,
tr("Error"),
tr("Unable to remove preset. Minimum limit reached."));
return;
}
config.setUserColors(colors);
}
void ColorPickerEditor::onAddPreset()
{
if (QColor::isValidColor(m_colorInput->text())) {
m_color = QColor(m_colorInput->text());
m_colorInput->setText(m_color.name(QColor::HexRgb));
} else {
m_colorInput->setText(m_color.name(QColor::HexRgb));
return;
}
addPreset();
m_colorSpinbox->setValue(1);
m_colorpicker->updateWidget();
m_colorSpinbox->updateWidget();
}
void ColorPickerEditor::onDeletePreset()
{
deletePreset();
m_colorSpinbox->setValue(1);
m_colorpicker->updateWidget();
m_colorSpinbox->updateWidget();
}

View File

@@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2022 Dearsh Oberoi
#pragma once
#include "QtColorWidgets/color_wheel.hpp"
#include <QWidget>
class ColorSpinBox;
class ColorPickerWidget;
class QLabel;
class QPushButton;
class QLineEdit;
class QColor;
class QGridLayout;
class ColorPickerEditor : public QWidget
{
Q_OBJECT
public:
explicit ColorPickerEditor(QWidget* parent = nullptr);
private slots:
void onAddPreset();
void onDeletePreset();
private:
void addPreset();
void deletePreset();
ColorPickerWidget* m_colorpicker;
color_widgets::ColorWheel* m_colorWheel;
QLabel* m_colorSpinboxLabel;
ColorSpinBox* m_colorSpinbox;
QPushButton* m_deletePresetButton;
QLineEdit* m_colorInput;
QLabel* m_addPresetLabel;
QPushButton* m_addPresetButton;
QColor m_color;
int m_selectedIndex;
QGridLayout* m_gLayout;
};

View File

@@ -84,6 +84,8 @@ void GeneralConf::_updateComponents(bool allowEmptySavePath)
m_autoCloseIdleDaemon->setChecked(config.autoCloseIdleDaemon()); m_autoCloseIdleDaemon->setChecked(config.autoCloseIdleDaemon());
#endif #endif
m_predefinedColorPaletteLarge->setChecked(
config.predefinedColorPaletteLarge());
m_showStartupLaunchMessage->setChecked(config.showStartupLaunchMessage()); m_showStartupLaunchMessage->setChecked(config.showStartupLaunchMessage());
m_screenshotPathFixedCheck->setChecked(config.savePathFixed()); m_screenshotPathFixedCheck->setChecked(config.savePathFixed());
m_uploadHistoryMax->setValue(config.uploadHistoryMax()); m_uploadHistoryMax->setValue(config.uploadHistoryMax());

View File

@@ -13,9 +13,8 @@
#include <QVBoxLayout> #include <QVBoxLayout>
UIcolorEditor::UIcolorEditor(QWidget* parent) UIcolorEditor::UIcolorEditor(QWidget* parent)
: QGroupBox(parent) : QWidget(parent)
{ {
setTitle(tr("UI Color Editor"));
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_hLayout = new QHBoxLayout; m_hLayout = new QHBoxLayout;
m_vLayout = new QVBoxLayout; m_vLayout = new QVBoxLayout;

View File

@@ -12,7 +12,7 @@ class QHBoxLayout;
class CaptureToolButton; class CaptureToolButton;
class ClickableLabel; class ClickableLabel;
class UIcolorEditor : public QGroupBox class UIcolorEditor : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:

View File

@@ -3,6 +3,7 @@
#include "visualseditor.h" #include "visualseditor.h"
#include "src/config/buttonlistview.h" #include "src/config/buttonlistview.h"
#include "src/config/colorpickereditor.h"
#include "src/config/extendedslider.h" #include "src/config/extendedslider.h"
#include "src/config/uicoloreditor.h" #include "src/config/uicoloreditor.h"
#include "src/utils/confighandler.h" #include "src/utils/confighandler.h"
@@ -56,8 +57,22 @@ void VisualsEditor::initOpacitySlider()
void VisualsEditor::initWidgets() void VisualsEditor::initWidgets()
{ {
m_tabWidget = new QTabWidget();
m_layout->addWidget(m_tabWidget);
m_colorEditor = new UIcolorEditor(); m_colorEditor = new UIcolorEditor();
m_layout->addWidget(m_colorEditor); m_colorEditorTab = new QWidget();
QVBoxLayout* colorEditorLayout = new QVBoxLayout(m_colorEditorTab);
m_colorEditorTab->setLayout(colorEditorLayout);
colorEditorLayout->addWidget(m_colorEditor);
m_tabWidget->addTab(m_colorEditorTab, tr("UI Color Editor"));
m_colorpickerEditor = new ColorPickerEditor();
m_colorpickerEditorTab = new QWidget();
QVBoxLayout* colorpickerEditorLayout =
new QVBoxLayout(m_colorpickerEditorTab);
colorpickerEditorLayout->addWidget(m_colorpickerEditor);
m_tabWidget->addTab(m_colorpickerEditorTab, tr("Colorpicker Editor"));
initOpacitySlider(); initOpacitySlider();

View File

@@ -3,12 +3,14 @@
#pragma once #pragma once
#include <QTabWidget>
#include <QWidget> #include <QWidget>
class ExtendedSlider; class ExtendedSlider;
class QVBoxLayout; class QVBoxLayout;
class ButtonListView; class ButtonListView;
class UIcolorEditor; class UIcolorEditor;
class ColorPickerEditor;
class VisualsEditor : public QWidget class VisualsEditor : public QWidget
{ {
@@ -21,8 +23,16 @@ public slots:
private: private:
QVBoxLayout* m_layout; QVBoxLayout* m_layout;
ButtonListView* m_buttonList;
QTabWidget* m_tabWidget;
UIcolorEditor* m_colorEditor; UIcolorEditor* m_colorEditor;
QWidget* m_colorEditorTab;
ColorPickerEditor* m_colorpickerEditor;
QWidget* m_colorpickerEditorTab;
ButtonListView* m_buttonList;
ExtendedSlider* m_opacitySlider; ExtendedSlider* m_opacitySlider;
void initWidgets(); void initWidgets();

View File

@@ -112,7 +112,7 @@ static QMap<class QString, QSharedPointer<ValueHandler>>
OPTION("drawThickness" ,LowerBoundedInt (1 , 3 )), OPTION("drawThickness" ,LowerBoundedInt (1 , 3 )),
OPTION("drawFontSize" ,LowerBoundedInt (1 , 8 )), OPTION("drawFontSize" ,LowerBoundedInt (1 , 8 )),
OPTION("drawColor" ,Color ( Qt::red )), OPTION("drawColor" ,Color ( Qt::red )),
OPTION("userColors" ,UserColors ( )), OPTION("userColors" ,UserColors(3, 17 )),
OPTION("ignoreUpdateToVersion" ,String ( "" )), OPTION("ignoreUpdateToVersion" ,String ( "" )),
OPTION("keepOpenAppLauncher" ,Bool ( false )), OPTION("keepOpenAppLauncher" ,Bool ( false )),
OPTION("fontFamily" ,String ( "" )), OPTION("fontFamily" ,String ( "" )),

View File

@@ -1,5 +1,6 @@
#include "valuehandler.h" #include "valuehandler.h"
#include "capturetool.h" #include "capturetool.h"
#include "colorpickerwidget.h"
#include "confighandler.h" #include "confighandler.h"
#include "screengrabber.h" #include "screengrabber.h"
#include <QColor> #include <QColor>
@@ -378,10 +379,15 @@ bool ButtonList::normalizeButtons(QList<int>& buttons)
// USER COLORS // USER COLORS
UserColors::UserColors(int min, int max)
: m_min(min)
, m_max(max)
{}
bool UserColors::check(const QVariant& val) bool UserColors::check(const QVariant& val)
{ {
if (!val.isValid()) { if (!val.isValid()) {
return true; return false;
} }
if (!val.canConvert(QVariant::StringList)) { if (!val.canConvert(QVariant::StringList)) {
return false; return false;
@@ -391,7 +397,10 @@ bool UserColors::check(const QVariant& val)
return false; return false;
} }
} }
return true;
int sz = val.toStringList().size();
return sz >= m_min && sz <= m_max;
} }
QVariant UserColors::process(const QVariant& val) QVariant UserColors::process(const QVariant& val)
@@ -418,40 +427,37 @@ QVariant UserColors::process(const QVariant& val)
QVariant UserColors::fallback() QVariant UserColors::fallback()
{ {
if (ConfigHandler().predefinedColorPaletteLarge()) { if (ConfigHandler().predefinedColorPaletteLarge()) {
return QVariant::fromValue(QVector<QColor>{ Qt::white, return QVariant::fromValue(
Qt::red, ColorPickerWidget::getDefaultLargeColorPalette());
Qt::green,
Qt::blue,
Qt::black,
Qt::darkRed,
Qt::darkGreen,
Qt::darkBlue,
Qt::darkGray,
Qt::cyan,
Qt::magenta,
Qt::yellow,
Qt::lightGray,
Qt::darkCyan,
Qt::darkMagenta,
Qt::darkYellow,
QColor() });
} else { } else {
return QVariant::fromValue(QVector<QColor>{ Qt::darkRed, return QVariant::fromValue(
Qt::red, ColorPickerWidget::getDefaultSmallColorPalette());
Qt::yellow,
Qt::green,
Qt::darkGreen,
Qt::cyan,
Qt::blue,
Qt::magenta,
Qt::darkMagenta,
QColor() });
} }
} }
QString UserColors::expected() QString UserColors::expected()
{ {
return QStringLiteral("list of colors separated by comma"); return QStringLiteral(
"list of colors(min %1 and max %2) separated by comma")
.arg(m_min - 1)
.arg(m_max - 1);
}
QVariant UserColors::representation(const QVariant& val)
{
QVector<QColor> colors = val.value<QVector<QColor>>();
QStringList strColors;
for (const auto& col : colors) {
if (col.isValid()) {
strColors.append(col.name(QColor::HexRgb));
} else {
strColors.append(QStringLiteral("picker"));
}
}
return QVariant::fromValue(strColors);
} }
// SET SAVE FILE AS EXTENSION // SET SAVE FILE AS EXTENSION

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "src/widgets/capture/capturetoolbutton.h" #include "src/widgets/capture/capturetoolbutton.h"
#include "src/widgets/colorpickerwidget.h"
#include <QColor> #include <QColor>
#include <QList> #include <QList>
@@ -193,10 +194,16 @@ public:
class UserColors : public ValueHandler class UserColors : public ValueHandler
{ {
public:
UserColors(int min, int max);
bool check(const QVariant& val) override; bool check(const QVariant& val) override;
QVariant process(const QVariant& val) override; QVariant process(const QVariant& val) override;
QVariant fallback() override; QVariant fallback() override;
QString expected() override; QString expected() override;
QVariant representation(const QVariant& val) override;
private:
int m_min, m_max;
}; };
class SaveFileExtension : public ValueHandler class SaveFileExtension : public ValueHandler

View File

@@ -17,6 +17,8 @@ target_sources(
orientablepushbutton.h orientablepushbutton.h
historywidget.h historywidget.h
updatenotificationwidget.h updatenotificationwidget.h
colorpickerwidget.h
colorspinbox.h
imguploaddialog.h imguploaddialog.h
capture/capturetoolobjects.h capture/capturetoolobjects.h
) )
@@ -32,6 +34,8 @@ target_sources(
orientablepushbutton.cpp orientablepushbutton.cpp
historywidget.cpp historywidget.cpp
updatenotificationwidget.cpp updatenotificationwidget.cpp
colorpickerwidget.cpp
colorspinbox.cpp
imguploaddialog.cpp imguploaddialog.cpp
capture/capturetoolobjects.cpp capture/capturetoolobjects.cpp
) )

View File

@@ -8,16 +8,11 @@
#include <QPainter> #include <QPainter>
ColorPicker::ColorPicker(QWidget* parent) ColorPicker::ColorPicker(QWidget* parent)
: QWidget(parent) : ColorPickerWidget(parent)
, m_selectedIndex(0)
, m_lastIndex(0)
{ {
ConfigHandler config;
m_colorList = config.userColors();
m_colorAreaSize = GlobalValues::buttonBaseSize() * 0.6;
setMouseTracking(true); setMouseTracking(true);
// save the color values in member variables for faster access
m_uiColor = config.uiColor(); ConfigHandler config;
QColor drawColor = config.drawColor(); QColor drawColor = config.drawColor();
for (int i = 0; i < m_colorList.size(); ++i) { for (int i = 0; i < m_colorList.size(); ++i) {
if (m_colorList.at(i) == drawColor) { if (m_colorList.at(i) == drawColor) {
@@ -26,90 +21,6 @@ ColorPicker::ColorPicker(QWidget* parent)
break; break;
} }
} }
// extraSize represents the extra space needed for the highlight of the
// selected color.
const int extraSize = 6;
double radius = (m_colorList.size() * m_colorAreaSize / 1.3) / 3.141592;
resize(radius * 2 + m_colorAreaSize + extraSize,
radius * 2 + m_colorAreaSize + extraSize);
double degree = 360 / (m_colorList.size());
double degreeAcum = degree;
// this line is the radius of the circle which will be rotated to add
// the color components.
QLineF baseLine =
QLineF(QPoint(radius + extraSize / 2, radius + extraSize / 2),
QPoint(radius * 2, radius));
for (int i = 0; i < m_colorList.size(); ++i) {
m_colorAreaList.append(QRect(
baseLine.x2(), baseLine.y2(), m_colorAreaSize, m_colorAreaSize));
baseLine.setAngle(degreeAcum);
degreeAcum += degree;
}
}
void ColorPicker::paintEvent(QPaintEvent* e)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QColor(Qt::black));
for (int i = 0; i < m_colorAreaList.size(); ++i) {
if (e->region().contains(m_colorAreaList.at(i))) {
painter.setClipRegion(e->region());
repaint(i, painter);
}
}
}
void ColorPicker::repaint(int i, QPainter& painter)
{
// draw the highlight when we have to draw the selected color
if (i == m_selectedIndex) {
QColor c = QColor(m_uiColor);
c.setAlpha(155);
painter.setBrush(c);
c.setAlpha(100);
painter.setPen(c);
QRect highlight = m_colorAreaList.at(i);
highlight.moveTo(highlight.x() - 3, highlight.y() - 3);
highlight.setHeight(highlight.height() + 6);
highlight.setWidth(highlight.width() + 6);
painter.drawRoundedRect(highlight, 100, 100);
painter.setPen(QColor(Qt::black));
}
// draw available colors
if (m_colorList.at(i).isValid()) {
// draw preset color
painter.setBrush(QColor(m_colorList.at(i)));
painter.drawRoundedRect(m_colorAreaList.at(i), 100, 100);
} else {
// draw rainbow (part) for custom color
QRect lastRect = m_colorAreaList.at(i);
int nStep = 1;
int nSteps = lastRect.height() / nStep;
// 0.02 - start rainbow color, 0.33 - end rainbow color from range:
// 0.0 - 1.0
float h = 0.02;
for (int radius = nSteps; radius > 0; radius -= nStep * 2) {
// calculate color
float fHStep = (0.33 - h) / (nSteps / nStep / 2);
QColor color = QColor::fromHslF(h, 0.95, 0.5);
// set color and draw circle
painter.setPen(color);
painter.setBrush(color);
painter.drawRoundedRect(lastRect, 100, 100);
// set next color, circle geometry
h += fHStep;
lastRect.setX(lastRect.x() + nStep);
lastRect.setY(lastRect.y() + nStep);
lastRect.setHeight(lastRect.height() - nStep);
lastRect.setWidth(lastRect.width() - nStep);
}
}
} }
void ColorPicker::mouseMoveEvent(QMouseEvent* e) void ColorPicker::mouseMoveEvent(QMouseEvent* e)

View File

@@ -3,9 +3,9 @@
#pragma once #pragma once
#include <QWidget> #include "src/widgets/colorpickerwidget.h"
class ColorPicker : public QWidget class ColorPicker : public ColorPickerWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
@@ -15,17 +15,7 @@ signals:
void colorSelected(QColor c); void colorSelected(QColor c);
protected: protected:
void paintEvent(QPaintEvent* event) override;
void repaint(int i, QPainter& painter);
void mouseMoveEvent(QMouseEvent*) override;
void showEvent(QShowEvent* event) override; void showEvent(QShowEvent* event) override;
void hideEvent(QHideEvent* event) override; void hideEvent(QHideEvent* event) override;
void mouseMoveEvent(QMouseEvent* e) override;
private:
int m_colorAreaSize;
int m_selectedIndex, m_lastIndex;
QVector<QRect> m_colorAreaList;
QVector<QColor> m_colorList;
QColor m_uiColor;
}; };

View File

@@ -0,0 +1,156 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2022 Dearsh Oberoi
#include "colorpickerwidget.h"
#include "src/utils/confighandler.h"
#include "src/utils/globalvalues.h"
#include <QMouseEvent>
#include <QPainter>
ColorPickerWidget::ColorPickerWidget(QWidget* parent)
: QWidget(parent)
, m_selectedIndex(1)
, m_lastIndex(1)
{
initColorPicker();
}
const QVector<QColor>& ColorPickerWidget::getDefaultSmallColorPalette()
{
return defaultSmallColorPalette;
}
const QVector<QColor>& ColorPickerWidget::getDefaultLargeColorPalette()
{
return defaultLargeColorPalette;
}
void ColorPickerWidget::paintEvent(QPaintEvent* e)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QColor(Qt::black));
for (int i = 0; i < m_colorAreaList.size(); ++i) {
if (e->region().contains(m_colorAreaList.at(i))) {
painter.setClipRegion(e->region());
repaint(i, painter);
}
}
}
void ColorPickerWidget::repaint(int i, QPainter& painter)
{
// draw the highlight when we have to draw the selected color
if (i == m_selectedIndex) {
QColor c = QColor(m_uiColor);
c.setAlpha(155);
painter.setBrush(c);
c.setAlpha(100);
painter.setPen(c);
QRect highlight = m_colorAreaList.at(i);
const int highlightThickness = 6;
// makes the highlight and color circles concentric
highlight.moveTo(highlight.x() - (highlightThickness / 2),
highlight.y() - (highlightThickness / 2));
highlight.setHeight(highlight.height() + highlightThickness);
highlight.setWidth(highlight.width() + highlightThickness);
painter.drawRoundedRect(highlight, 100, 100);
painter.setPen(QColor(Qt::black));
}
// draw available colors
if (m_colorList.at(i).isValid()) {
// draw preset color
painter.setBrush(QColor(m_colorList.at(i)));
painter.drawRoundedRect(m_colorAreaList.at(i), 100, 100);
} else {
// draw rainbow (part) for custom color
QRect lastRect = m_colorAreaList.at(i);
int nStep = 1;
int nSteps = lastRect.height() / nStep;
// 0.02 - start rainbow color, 0.33 - end rainbow color from range:
// 0.0 - 1.0
float h = 0.02;
for (int radius = nSteps; radius > 0; radius -= nStep * 2) {
// calculate color
float fHStep = (0.33 - h) / (nSteps / nStep / 2);
QColor color = QColor::fromHslF(h, 0.95, 0.5);
// set color and draw circle
painter.setPen(color);
painter.setBrush(color);
painter.drawRoundedRect(lastRect, 100, 100);
// set next color, circle geometry
h += fHStep;
lastRect.setX(lastRect.x() + nStep);
lastRect.setY(lastRect.y() + nStep);
lastRect.setHeight(lastRect.height() - nStep);
lastRect.setWidth(lastRect.width() - nStep);
painter.setPen(QColor(Qt::black));
}
}
}
void ColorPickerWidget::updateSelection(int index)
{
m_selectedIndex = index;
update(m_colorAreaList.at(index) + QMargins(10, 10, 10, 10));
update(m_colorAreaList.at(m_lastIndex) + QMargins(10, 10, 10, 10));
m_lastIndex = index;
}
void ColorPickerWidget::updateWidget()
{
m_colorAreaList.clear();
initColorPicker();
update();
}
void ColorPickerWidget::initColorPicker()
{
ConfigHandler config;
m_colorList = config.userColors();
m_colorAreaSize = GlobalValues::buttonBaseSize() * 0.6;
// save the color values in member variables for faster access
m_uiColor = config.uiColor();
// extraSize represents the extra space needed for the highlight of the
// selected color.
const int extraSize = 6;
double radius = GlobalValues::buttonBaseSize() * 2;
setMinimumSize(radius * 2 + m_colorAreaSize + extraSize,
radius * 2 + m_colorAreaSize + extraSize);
resize(radius * 2 + m_colorAreaSize + extraSize,
radius * 2 + m_colorAreaSize + extraSize);
double degree = (double)360 / m_colorList.size();
double degreeAcum = 90;
// this line is the radius of the circle which will be rotated to add
// the color components.
QLineF baseLine =
QLineF(QPoint(radius + extraSize / 2, radius + extraSize / 2),
QPoint(radius + extraSize / 2, extraSize / 2));
for (int i = 0; i < m_colorList.size(); ++i) {
m_colorAreaList.append(QRect(
baseLine.x2(), baseLine.y2(), m_colorAreaSize, m_colorAreaSize));
degreeAcum += degree;
baseLine.setAngle(degreeAcum);
}
}
QVector<QColor> ColorPickerWidget::defaultSmallColorPalette = {
QColor(), Qt::darkRed, Qt::red, Qt::yellow, Qt::green,
Qt::darkGreen, Qt::cyan, Qt::blue, Qt::magenta, Qt::darkMagenta
};
QVector<QColor> ColorPickerWidget::defaultLargeColorPalette = {
QColor(), Qt::white, Qt::red, Qt::green, Qt::blue,
Qt::black, Qt::darkRed, Qt::darkGreen, Qt::darkBlue, Qt::darkGray,
Qt::cyan, Qt::magenta, Qt::yellow, Qt::lightGray, Qt::darkCyan,
Qt::darkMagenta, Qt::darkYellow
};

View File

@@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2022 Dearsh Oberoi
#pragma once
#include <QWidget>
class ColorPickerWidget : public QWidget
{
Q_OBJECT
public:
explicit ColorPickerWidget(QWidget* parent = nullptr);
static const QVector<QColor>& getDefaultSmallColorPalette();
static const QVector<QColor>& getDefaultLargeColorPalette();
void updateWidget();
void updateSelection(int index);
protected:
void paintEvent(QPaintEvent* event) override;
void repaint(int i, QPainter& painter);
int m_colorAreaSize;
int m_selectedIndex, m_lastIndex;
QVector<QRect> m_colorAreaList;
QVector<QColor> m_colorList;
QColor m_uiColor;
private:
void initColorPicker();
static QVector<QColor> defaultSmallColorPalette, defaultLargeColorPalette;
};

View File

@@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2022 Dearsh Oberoi
#include "src/widgets/colorspinbox.h"
#include "src/utils/confighandler.h"
ColorSpinBox::ColorSpinBox(QWidget* parent)
: QSpinBox(parent)
{
initColorSpinbox();
}
int ColorSpinBox::valueFromText(const QString& text) const
{
if (!QColor::isValidColor(text)) {
return 1;
}
const QColor color = QColor(text);
for (int i = 1; i < m_colorList.size(); ++i) {
if (m_colorList.at(i) == color) {
return i;
}
}
return 1;
}
QString ColorSpinBox::textFromValue(int value) const
{
return m_colorList[value].name(QColor::HexRgb);
}
void ColorSpinBox::initColorSpinbox()
{
ConfigHandler config;
m_colorList = config.userColors();
setRange(1, m_colorList.size() - 1);
setWrapping(true);
}
void ColorSpinBox::updateWidget()
{
initColorSpinbox();
update();
}

View File

@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2022 Dearsh Oberoi
#pragma once
#include <QColor>
#include <QSpinBox>
class ColorSpinBox : public QSpinBox
{
Q_OBJECT
public:
explicit ColorSpinBox(QWidget* parent = nullptr);
void updateWidget();
protected:
int valueFromText(const QString& text) const override;
QString textFromValue(int value) const override;
private:
void initColorSpinbox();
QVector<QColor> m_colorList;
};