View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0017522 | Scribus | User Interface | public | 2025-05-13 20:33 | 2025-12-13 22:27 |
| Reporter | nitramr | Assigned To | nitramr | ||
| Priority | normal | Severity | feature | Reproducibility | N/A |
| Status | assigned | Resolution | open | ||
| Platform | Desktop PC | OS | Ubuntu | OS Version | 24.10 64-bit |
| Product Version | 1.7.1.svn | ||||
| Target Version | 1.7 milestone | ||||
| Summary | 0017522: New Color Slider widget | ||||
| Description | I made a new color slider that has the render logic inside the widget. In short term, it will replace the existing ScColorSlider. Supported Color Modes: - RGB - RGB Web - CMYK - Lab - HLC - HSV <- new - Shade <- new - Alpha <- new The patch implements the new color slider in color picker for alpha and shade settings. To replace the color slider in cmykfw widget, it takes more time. | ||||
| Tags | No tags attached. | ||||
| Attached Files | colorslider_2025-05-13_01.patch (10,348 bytes)
Index: scribus/CMakeLists_Sources.txt
===================================================================
--- scribus/CMakeLists_Sources.txt (Revision 26867)
+++ scribus/CMakeLists_Sources.txt (Arbeitskopie)
@@ -562,6 +562,7 @@
ui/docks/dock_centralwidget.cpp
ui/docks/dock_panelbase.cpp
ui/widgets/color_button.cpp
+ ui/widgets/color_slider.cpp
ui/widgets/combo_blendmode.cpp
ui/widgets/combo_linestyle.cpp
ui/widgets/dropdown_button.cpp
Index: scribus/ui/colorpicker/colorpicker_color.cpp
===================================================================
--- scribus/ui/colorpicker/colorpicker_color.cpp (Revision 26867)
+++ scribus/ui/colorpicker/colorpicker_color.cpp (Arbeitskopie)
@@ -26,6 +26,9 @@
languageChange();
+ sliderAlpha->setMode(ColorSlider::Opacity);
+ sliderShade->setMode(ColorSlider::Shade);
+
connectSlots();
connect(sectionSwatches, &SectionContainer::sizeChanged, this, &ColorPickerColor::updateSize);
}
@@ -34,7 +37,9 @@
{
connect(swatches, &ColorPickerColorSwatches::colorChanged, this, &ColorPickerColor::updateColorFromSwatches);
connect(numberShade, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorShade);
+ connect(sliderShade, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorShade);
connect(numberAlpha, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorAlpha);
+ connect(sliderAlpha, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorAlpha);
}
void ColorPickerColor::disconnectSlots()
@@ -41,7 +46,9 @@
{
disconnect(swatches, &ColorPickerColorSwatches::colorChanged, this, &ColorPickerColor::updateColorFromSwatches);
disconnect(numberShade, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorShade);
+ disconnect(sliderShade, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorShade);
disconnect(numberAlpha, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorAlpha);
+ disconnect(sliderAlpha, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorAlpha);
}
/* ********************************************************************************* *
@@ -73,8 +80,10 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(false);
labelShade->setVisible(false);
+ sliderShade->setVisible(false);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Text:
case Context::TextBackground:
@@ -82,22 +91,28 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Fill:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Line:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::FillMask:
case Context::LineMask:
@@ -104,8 +119,10 @@
sectionSwatches->setVisible(false);
numberShade->setVisible(false);
labelShade->setVisible(false);
+ sliderShade->setVisible(false);
numberAlpha->setVisible(true);
labelAlpha->setVisible(true);
+ sliderAlpha->setVisible(true);
isMask = true;
break;
case Context::DropShadow:
@@ -112,8 +129,10 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
}
@@ -183,12 +202,19 @@
void ColorPickerColor::setDoc(ScribusDoc *doc)
{
m_doc = doc;
+ sliderAlpha->setDoc(m_doc);
+ sliderShade->setDoc(m_doc);
}
void ColorPickerColor::setColorData(const CPColorData& color)
{
+ if (!m_doc)
+ return;
+
m_color = color;
+ bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+
// update UI + controls
QSignalBlocker sigSwatches(swatches);
swatches->setCurrentColor(m_color.Name);
@@ -195,12 +221,20 @@
QSignalBlocker sigShade(numberShade);
numberShade->setValue(m_color.Shade);
- numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ numberShade->setEnabled(hasColor);
QSignalBlocker sigAlpha(numberAlpha);
numberAlpha->setValue(qRound(100 - (m_color.Opacity * 100)));
- numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ numberAlpha->setEnabled(hasColor);
+ QSignalBlocker sigAlphaSlider(sliderAlpha);
+ sliderAlpha->setEnabled(hasColor);
+ sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
+ QSignalBlocker sigShadeSlider(sliderShade);
+ sliderShade->setEnabled(hasColor);
+ sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
}
void ColorPickerColor::languageChange()
@@ -211,14 +245,33 @@
void ColorPickerColor::updateColorFromSwatches()
{
m_color.Name = swatches->currentColor();
- numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
- numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+
+ numberShade->setEnabled(hasColor);
+ sliderShade->setEnabled(hasColor);
+ sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+ numberAlpha->setEnabled(hasColor);
+ sliderAlpha->setEnabled(hasColor);
+ sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
updateColor();
}
void ColorPickerColor::updateColorShade()
{
+ QObject* obj = sender();
+ if( obj == sliderShade )
+ {
+ QSignalBlocker sigBlocker(numberShade);
+ numberShade->setValue(sliderShade->value());
+ }
+ else if( obj == numberShade )
+ {
+ QSignalBlocker sigBlocker(sliderShade);
+ sliderShade->setValue(numberShade->value());
+ }
+
m_color.Shade = numberShade->value();
updateColor();
}
@@ -225,6 +278,18 @@
void ColorPickerColor::updateColorAlpha()
{
+ QObject* obj = sender();
+ if( obj == sliderAlpha )
+ {
+ QSignalBlocker sigBlocker(numberAlpha);
+ numberAlpha->setValue(sliderAlpha->value());
+ }
+ else if( obj == numberAlpha )
+ {
+ QSignalBlocker sigBlocker(sliderAlpha);
+ sliderAlpha->setValue(numberAlpha->value());
+ }
+
m_color.Opacity = (100 - numberAlpha->value()) / 100.0;
updateColor();
}
@@ -242,5 +307,3 @@
resize(w, sizeHint().height());
emit sizeChanged();
}
-
-
Index: scribus/ui/colorpicker/colorpicker_color.ui
===================================================================
--- scribus/ui/colorpicker/colorpicker_color.ui (Revision 26867)
+++ scribus/ui/colorpicker/colorpicker_color.ui (Arbeitskopie)
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>300</width>
- <height>122</height>
+ <height>112</height>
</rect>
</property>
<property name="windowTitle">
@@ -46,8 +46,28 @@
<property name="spacing">
<number>4</number>
</property>
- <item row="1" column="2">
- <widget class="ScrSpinBox" name="numberAlpha">
+ <item row="0" column="1">
+ <widget class="ColorSlider" name="sliderShade">
+ <property name="orientation">
+ <enum>Qt::Orientation::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TickPosition::TicksAbove</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="ColorSlider" name="sliderAlpha">
+ <property name="orientation">
+ <enum>Qt::Orientation::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TickPosition::TicksAbove</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="ScrSpinBox" name="numberShade">
<property name="suffix">
<string> %</string>
</property>
@@ -59,28 +79,28 @@
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="1" column="0">
<widget class="QLabel" name="labelAlpha">
<property name="text">
<string>Opacity:</string>
</property>
<property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
- <item row="0" column="1">
+ <item row="0" column="0">
<widget class="QLabel" name="labelShade">
<property name="text">
<string>Shade:</string>
</property>
<property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
- <item row="0" column="2">
- <widget class="ScrSpinBox" name="numberShade">
+ <item row="1" column="2">
+ <widget class="ScrSpinBox" name="numberAlpha">
<property name="suffix">
<string> %</string>
</property>
@@ -92,19 +112,6 @@
</property>
</widget>
</item>
- <item row="1" column="0">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
</layout>
</item>
<item>
@@ -136,6 +143,11 @@
<header>ui/colorpicker/colorpicker_color_swatches.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>ColorSlider</class>
+ <extends>QSlider</extends>
+ <header>ui/widgets/color_slider.h</header>
+ </customwidget>
</customwidgets>
<tabstops>
<tabstop>numberShade</tabstop>
| ||||
| Patch | Yes | ||||
|
|
Not sure what's different on Mac. No numbers on the slider.. slider is higher |
|
|
@cbradney I fixed the style issue. The new patch requires the ScribusProxyStyle class from this patch: https://bugs.scribus.net/view.php?id=17571 colorslider_2025-10-25_01.patch (21,671 bytes)
Index: scribus/CMakeLists_Sources.txt
===================================================================
--- scribus/CMakeLists_Sources.txt (Revision 27094)
+++ scribus/CMakeLists_Sources.txt (Arbeitskopie)
@@ -565,7 +565,8 @@
ui/delegates/sclistitemdelegate.cpp
ui/docks/dock_centralwidget.cpp
ui/docks/dock_panelbase.cpp
ui/factories/scribusproxystyle.cpp
ui/widgets/buttongroup.cpp
ui/widgets/color_button.cpp
+ ui/widgets/color_slider.cpp
ui/widgets/combo_blendmode.cpp
ui/widgets/combo_linestyle.cpp
ui/widgets/dropdown_button.cpp
Index: scribus/ui/colorpicker/colorpicker_color.cpp
===================================================================
--- scribus/ui/colorpicker/colorpicker_color.cpp (Revision 27094)
+++ scribus/ui/colorpicker/colorpicker_color.cpp (Arbeitskopie)
@@ -26,6 +26,9 @@
languageChange();
+ sliderAlpha->setMode(ColorSlider::Opacity);
+ sliderShade->setMode(ColorSlider::Shade);
+
connectSlots();
connect(sectionSwatches, &SectionContainer::sizeChanged, this, &ColorPickerColor::updateSize);
}
@@ -34,7 +37,9 @@
{
connect(swatches, &ColorPickerColorSwatches::colorChanged, this, &ColorPickerColor::updateColorFromSwatches);
connect(numberShade, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorShade);
+ connect(sliderShade, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorShade);
connect(numberAlpha, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorAlpha);
+ connect(sliderAlpha, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorAlpha);
}
void ColorPickerColor::disconnectSlots()
@@ -41,7 +46,9 @@
{
disconnect(swatches, &ColorPickerColorSwatches::colorChanged, this, &ColorPickerColor::updateColorFromSwatches);
disconnect(numberShade, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorShade);
+ disconnect(sliderShade, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorShade);
disconnect(numberAlpha, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorAlpha);
+ disconnect(sliderAlpha, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorAlpha);
}
/* ********************************************************************************* *
@@ -73,8 +80,10 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(false);
labelShade->setVisible(false);
+ sliderShade->setVisible(false);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Text:
case Context::TextBackground:
@@ -82,22 +91,28 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Fill:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Line:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::FillMask:
case Context::LineMask:
@@ -104,8 +119,10 @@
sectionSwatches->setVisible(false);
numberShade->setVisible(false);
labelShade->setVisible(false);
+ sliderShade->setVisible(false);
numberAlpha->setVisible(true);
labelAlpha->setVisible(true);
+ sliderAlpha->setVisible(true);
isMask = true;
break;
case Context::DropShadow:
@@ -112,8 +129,10 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
}
@@ -183,12 +202,19 @@
void ColorPickerColor::setDoc(ScribusDoc *doc)
{
m_doc = doc;
+ sliderAlpha->setDoc(m_doc);
+ sliderShade->setDoc(m_doc);
}
void ColorPickerColor::setColorData(const CPColorData& color)
{
+ if (!m_doc)
+ return;
+
m_color = color;
+ bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+
// update UI + controls
QSignalBlocker sigSwatches(swatches);
swatches->setCurrentColor(m_color.Name);
@@ -195,12 +221,20 @@
QSignalBlocker sigShade(numberShade);
numberShade->setValue(m_color.Shade);
- numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ numberShade->setEnabled(hasColor);
QSignalBlocker sigAlpha(numberAlpha);
numberAlpha->setValue(qRound(100 - (m_color.Opacity * 100)));
- numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ numberAlpha->setEnabled(hasColor);
+ QSignalBlocker sigAlphaSlider(sliderAlpha);
+ sliderAlpha->setEnabled(hasColor);
+ sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
+ QSignalBlocker sigShadeSlider(sliderShade);
+ sliderShade->setEnabled(hasColor);
+ sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
}
void ColorPickerColor::languageChange()
@@ -211,14 +245,33 @@
void ColorPickerColor::updateColorFromSwatches()
{
m_color.Name = swatches->currentColor();
- numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
- numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+
+ numberShade->setEnabled(hasColor);
+ sliderShade->setEnabled(hasColor);
+ sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+ numberAlpha->setEnabled(hasColor);
+ sliderAlpha->setEnabled(hasColor);
+ sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
updateColor();
}
void ColorPickerColor::updateColorShade()
{
+ QObject* obj = sender();
+ if( obj == sliderShade )
+ {
+ QSignalBlocker sigBlocker(numberShade);
+ numberShade->setValue(sliderShade->value());
+ }
+ else if( obj == numberShade )
+ {
+ QSignalBlocker sigBlocker(sliderShade);
+ sliderShade->setValue(numberShade->value());
+ }
+
m_color.Shade = numberShade->value();
updateColor();
}
@@ -225,6 +278,18 @@
void ColorPickerColor::updateColorAlpha()
{
+ QObject* obj = sender();
+ if( obj == sliderAlpha )
+ {
+ QSignalBlocker sigBlocker(numberAlpha);
+ numberAlpha->setValue(sliderAlpha->value());
+ }
+ else if( obj == numberAlpha )
+ {
+ QSignalBlocker sigBlocker(sliderAlpha);
+ sliderAlpha->setValue(numberAlpha->value());
+ }
+
m_color.Opacity = (100 - numberAlpha->value()) / 100.0;
updateColor();
}
@@ -242,5 +307,3 @@
resize(w, sizeHint().height());
emit sizeChanged();
}
-
-
Index: scribus/ui/colorpicker/colorpicker_color.ui
===================================================================
--- scribus/ui/colorpicker/colorpicker_color.ui (Revision 27094)
+++ scribus/ui/colorpicker/colorpicker_color.ui (Arbeitskopie)
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>300</width>
- <height>122</height>
+ <height>112</height>
</rect>
</property>
<property name="windowTitle">
@@ -46,8 +46,28 @@
<property name="spacing">
<number>4</number>
</property>
- <item row="1" column="2">
- <widget class="ScrSpinBox" name="numberAlpha">
+ <item row="0" column="1">
+ <widget class="ColorSlider" name="sliderShade">
+ <property name="orientation">
+ <enum>Qt::Orientation::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TickPosition::TicksAbove</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="ColorSlider" name="sliderAlpha">
+ <property name="orientation">
+ <enum>Qt::Orientation::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TickPosition::TicksAbove</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="ScrSpinBox" name="numberShade">
<property name="suffix">
<string> %</string>
</property>
@@ -59,28 +79,28 @@
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="1" column="0">
<widget class="QLabel" name="labelAlpha">
<property name="text">
<string>Opacity:</string>
</property>
<property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
- <item row="0" column="1">
+ <item row="0" column="0">
<widget class="QLabel" name="labelShade">
<property name="text">
<string>Shade:</string>
</property>
<property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
- <item row="0" column="2">
- <widget class="ScrSpinBox" name="numberShade">
+ <item row="1" column="2">
+ <widget class="ScrSpinBox" name="numberAlpha">
<property name="suffix">
<string> %</string>
</property>
@@ -92,19 +112,6 @@
</property>
</widget>
</item>
- <item row="1" column="0">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
</layout>
</item>
<item>
@@ -136,6 +143,11 @@
<header>ui/colorpicker/colorpicker_color_swatches.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>ColorSlider</class>
+ <extends>QSlider</extends>
+ <header>ui/widgets/color_slider.h</header>
+ </customwidget>
</customwidgets>
<tabstops>
<tabstop>numberShade</tabstop>
Index: scribus/ui/dasheditor.cpp
===================================================================
--- scribus/ui/dasheditor.cpp (Revision 27094)
+++ scribus/ui/dasheditor.cpp (Arbeitskopie)
@@ -55,7 +55,6 @@
*
* ********************************************************************************* */
-const int RADIUS = 6;
const double HAIRLINE = 0.001;
DashPreview::DashPreview(QWidget *pa) : QFrame(pa)
Index: scribus/ui/factories/scribusproxystyle.cpp
===================================================================
--- scribus/ui/factories/scribusproxystyle.cpp (Revision 27094)
+++ scribus/ui/factories/scribusproxystyle.cpp (Arbeitskopie)
@@ -16,6 +16,8 @@
#include "prefsmanager.h"
#include "scribus.h"
#include "ui/widgets/buttongroup.h"
+#include "ui/widgets/color_slider.h"
+#include "util_gui.h"
// https://doc.qt.io/qt-6/qstyle.html#standardPalette
QPalette createLightPalette()
@@ -32,7 +34,7 @@
QPalette createDarkPalette()
{
- QPalette darkPalette/*(QColor(53, 53, 53))*/;
+ QPalette darkPalette;
darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, QColor(42, 42, 42));
@@ -65,15 +67,17 @@
{
QRect rect = QProxyStyle::subControlRect(cc, opt, sc, widget);
- if (cc == CC_ToolButton)
+ switch (cc)
{
- const ToolButton *tb = qobject_cast<const ToolButton*>(widget);
- if (!tb)
+ case QStyle::ComplexControl::CC_ToolButton:
+ {
+ const ToolButton *wdg = qobject_cast<const ToolButton *>(widget);
+ if (!wdg)
return rect;
- if (const QStyleOptionToolButton *button = qstyleoption_cast<const QStyleOptionToolButton *>(opt))
+ if (const QStyleOptionToolButton *styleOption = qstyleoption_cast<const QStyleOptionToolButton *>(opt))
{
- switch (tb->position())
+ switch (wdg->position())
{
case ToolButton::Left:
rect.adjust(0, 0, rect.width(), 0);
@@ -89,30 +93,92 @@
break;
}
- return visualRect(button->direction, button->rect, rect);
+ return visualRect(styleOption->direction, styleOption->rect, rect);
}
}
+ break;
+ case QStyle::ComplexControl::CC_Slider:
+ {
+ const ColorSlider *wdg = qobject_cast<const ColorSlider *>(widget);
+ if (!wdg)
+ return rect;
+
+ if (const QStyleOptionSlider *styleOption = qstyleoption_cast<const QStyleOptionSlider *>(opt))
+ {
+ QRect ret;
+ bool horizontal = styleOption->orientation == Qt::Horizontal;
+ int thickness = RADIUS * 2;
+ int center = (horizontal) ? (styleOption->rect.height() - thickness) / 2 : (styleOption->rect.width() - thickness) / 2;
+ int sliderOffset = (styleOption->tickPosition != QSlider::NoTicks) ? thickness : center;
+
+ switch (sc)
+ {
+ case SC_SliderHandle:
+ {
+ int len = thickness + 2; //proxy()->pixelMetric(PM_SliderLength, styleOption, widget);
+ int sliderPos = sliderPositionFromValue(styleOption->minimum, styleOption->maximum, styleOption->sliderPosition, (horizontal ? styleOption->rect.width() : styleOption->rect.height()) - len, styleOption->upsideDown);
+
+ if (horizontal)
+ ret.setRect(styleOption->rect.x() + sliderPos, styleOption->rect.y() + sliderOffset, len, thickness);
+ else
+ ret.setRect(styleOption->rect.x() + 1, styleOption->rect.y() + sliderPos, thickness, len);
+
+ break;
+ }
+ case SC_SliderGroove:
+ if (horizontal)
+ ret.setRect(styleOption->rect.x(), styleOption->rect.y() + sliderOffset + 1, styleOption->rect.width(), thickness - 3);
+ else
+ ret.setRect(styleOption->rect.x() + 2, styleOption->rect.y(), thickness - 3, styleOption->rect.height());
+
+ break;
+ case SC_SliderTickmarks:
+ {
+ int tickOffset = (styleOption->tickPosition != QSlider::NoTicks) ? thickness : 0;
+
+ if (styleOption->tickPosition != QSlider::NoTicks)
+ {
+ if (horizontal)
+ ret.setRect(styleOption->rect.x() + 1, styleOption->rect.y(), styleOption->rect.width() - 3, thickness);
+ else
+ ret.setRect(styleOption->rect.x() + tickOffset, styleOption->rect.y() + 1, thickness, styleOption->rect.height() - 3);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return visualRect(styleOption->direction, styleOption->rect, ret);
+ }
+ }
+ break;
+ default:
+ break;
+ }
return rect;
}
-void ScribusProxyStyle::drawControl(ControlElement el, const QStyleOption *opt, QPainter *painter, const QWidget *widget) const
+void ScribusProxyStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *painter, const QWidget *widget) const
{
- if (el == CE_ToolButtonLabel)
+ switch (ce)
+ {
+ case QStyle::ControlElement::CE_ToolButtonLabel:
{
QStyleOptionToolButton styleOption = *static_cast<const QStyleOptionToolButton *>(opt);
- const ToolButton *tb = qobject_cast<const ToolButton*>(widget);
+ const ToolButton *wdg = qobject_cast<const ToolButton*>(widget);
- if (!tb)
- return QProxyStyle::drawControl(el, opt, painter, widget);
+ if (!wdg)
+ return QProxyStyle::drawControl(ce, opt, painter, widget);
QRect rect = styleOption.rect;
int t = widget->rect().top() + 4;
int b = widget->rect().bottom() - 4;
int r = widget->rect().right();
- switch (tb->position())
+ switch (wdg->position())
{
case ToolButton::Right:
styleOption.rect.adjust(0, 0, rect.width() / 2, 0);
@@ -132,10 +198,113 @@
break;
}
- return QProxyStyle::drawControl(el, &styleOption, painter, widget);
+ return QProxyStyle::drawControl(ce, &styleOption, painter, widget);
+ }
+ break;
+ default:
+ break;
}
- return QProxyStyle::drawControl(el, opt, painter, widget);
+ return QProxyStyle::drawControl(ce, opt, painter, widget);
+}
+
+void ScribusProxyStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const
+{
+ switch (cc)
+ {
+ case QStyle::ComplexControl::CC_Slider:
+ {
+ const ColorSlider *wdg = qobject_cast<const ColorSlider*>(widget);
+
+ if (!wdg)
+ return QProxyStyle::drawComplexControl(cc, opt, painter, widget);
+
+ if (const QStyleOptionSlider *styleOption = qstyleoption_cast<const QStyleOptionSlider *>(opt))
+ {
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ QRect groove = subControlRect(CC_Slider, styleOption, SC_SliderGroove, widget);
+ QRect handle = subControlRect(CC_Slider, styleOption, SC_SliderHandle, widget);
+ QRect tickmarks = subControlRect(CC_Slider, styleOption, SC_SliderTickmarks, widget);
+
+ // Draw Slider
+ if ((styleOption->subControls & SC_SliderGroove) && groove.isValid())
+ {
+ double radius = (styleOption->orientation == Qt::Horizontal) ? groove.height() / 2 + 0.5 : groove.width() / 2 + 0.5;
+
+ QPainterPath border;
+ border.addRoundedRect(groove.toRectF().adjusted(0.5, 0.5, -0.5, -0.5), radius, radius);
+
+ // Draw Slider Gradients
+ painter->setClipPath(border);
+ if (wdg->m_background.isNull() || !widget->isEnabled())
+ painter->fillRect(groove, widget->palette().color(QPalette::Window));
+ else
+ {
+ renderCheckerPattern(painter, groove);
+ painter->drawImage(groove, wdg->m_background);
+ }
+ painter->setClipping(false);
+
+ // Draw Slider Border
+ painter->setPen(widget->palette().color(QPalette::Mid));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(border);
+ painter->setPen(Qt::NoPen);
+
+ }
+
+ // Draw Handle
+ if ((styleOption->subControls & SC_SliderHandle) && handle.isValid())
+ {
+ drawCircularHandle(painter, handle.center() + QPointF(0.5, 0.5), RADIUS * 2, Qt::NoBrush, widget->isEnabled());
+ }
+
+ // Draw Tickmarks
+ if ((styleOption->subControls & SC_SliderTickmarks) && tickmarks.isValid() && styleOption->tickInterval > 0)
+ {
+ QFont font = widget->font();
+ font.setPixelSize(8);
+ painter->setFont(font);
+
+ if (styleOption->orientation == Qt::Horizontal)
+ {
+ double ratio = double(tickmarks.width() - (2 * RADIUS)) / double(styleOption->tickInterval);
+
+ for (int x = 0; x <= styleOption->tickInterval; x++)
+ {
+ QRect tick(double(x) * ratio + RADIUS + 1, tickmarks.bottom() - 3, 1, 2);
+ QString label = QString::number((x * styleOption->maximum / styleOption->tickInterval) - abs(styleOption->minimum));
+ int offset = QFontMetrics(painter->font()).size(Qt::TextSingleLine, label).width() / 2;
+
+ painter->setPen(widget->palette().color(QPalette::WindowText));
+ painter->drawText(qBound(0, tick.left() - offset, tickmarks.width()), tickmarks.bottom() - 4, label);
+ painter->fillRect(tick, widget->palette().color(QPalette::WindowText));
+ }
+ }
+ else
+ {
+ double ratio = double(tickmarks.height() - (2 * RADIUS)) / double(styleOption->tickInterval);
+
+ for (int y = 0; y <= styleOption->tickInterval; y++)
+ {
+ QRect tick(tickmarks.left() + 2, double(y) * ratio + RADIUS + 1, 2, 1);
+ painter->fillRect(tick, widget->palette().color(QPalette::WindowText));
+ }
+ }
+ }
+
+ painter->restore();
+ return;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ QProxyStyle::drawComplexControl(cc, opt, painter, widget);
}
bool ScribusProxyStyle::eventFilter(QObject *object, QEvent *event)
Index: scribus/ui/factories/scribusproxystyle.h
===================================================================
--- scribus/ui/factories/scribusproxystyle.h (Revision 27094)
+++ scribus/ui/factories/scribusproxystyle.h (Arbeitskopie)
@@ -21,7 +21,9 @@
static ScribusProxyStyle* instance();
QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget = nullptr) const override;
- void drawControl(QStyle::ControlElement el, const QStyleOption *opt, QPainter *painter, const QWidget *widget = nullptr) const override;
+ void drawControl(QStyle::ControlElement ce, const QStyleOption *opt, QPainter *painter, const QWidget *widget = nullptr) const override;
+ void drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const override;
+
protected:
bool eventFilter(QObject *object, QEvent *event) override;
Index: scribus/ui/gradientpreview.cpp
===================================================================
--- scribus/ui/gradientpreview.cpp (Revision 27094)
+++ scribus/ui/gradientpreview.cpp (Arbeitskopie)
@@ -29,7 +29,6 @@
#include "gradientpreview.h"
#include "util_gui.h"
-const int RADIUS = 6;
const int GRADIENT_HEIGHT = 20;
/* ********************************************************************************* *
Index: scribus/util_gui.h
===================================================================
--- scribus/util_gui.h (Revision 27094)
+++ scribus/util_gui.h (Arbeitskopie)
@@ -9,6 +9,8 @@
class VColorStop;
class ScPattern;
+const int RADIUS = 6;
+
void SCRIBUS_API drawCircularHandle(QPainter * painter, QPointF center, qreal width, QBrush background, bool isEnabled = true);
void SCRIBUS_API drawPointerHandle(QPainter * painter, QPointF pointer, qreal width, QColor background, bool isEnabled = true, bool isEmpty = false);
void SCRIBUS_API renderCheckerPattern(QPainter *painter, QRectF rect);
|
|
|
Works ok here, pending Jeans review of the other patch first thanks |
|
|
Updated patch colorslider_2025-12-13_01.diff (41,944 bytes)
diff --git a/scribus/CMakeLists_Sources.txt b/scribus/CMakeLists_Sources.txt
index 8a71d0a99..afb5817be 100644
--- a/scribus/CMakeLists_Sources.txt
+++ b/scribus/CMakeLists_Sources.txt
@@ -567,6 +567,7 @@ set(SCRIBUS_SOURCES
ui/docks/dock_panelbase.cpp
ui/factories/scribusproxystyle.cpp
ui/widgets/color_button.cpp
+ ui/widgets/color_slider.cpp
ui/widgets/combo_blendmode.cpp
ui/widgets/combo_linestyle.cpp
ui/widgets/dropdown_button.cpp
diff --git a/scribus/ui/colorpicker/colorpicker_color.cpp b/scribus/ui/colorpicker/colorpicker_color.cpp
index 8e4d5c709..ac0907a1c 100644
--- a/scribus/ui/colorpicker/colorpicker_color.cpp
+++ b/scribus/ui/colorpicker/colorpicker_color.cpp
@@ -26,6 +26,9 @@ ColorPickerColor::ColorPickerColor(QWidget *parent) : QWidget(parent)
languageChange();
+ sliderAlpha->setMode(ColorSlider::Opacity);
+ sliderShade->setMode(ColorSlider::Shade);
+
connectSlots();
connect(sectionSwatches, &SectionContainer::sizeChanged, this, &ColorPickerColor::updateSize);
}
@@ -34,14 +37,18 @@ void ColorPickerColor::connectSlots()
{
connect(swatches, &ColorPickerColorSwatches::colorChanged, this, &ColorPickerColor::updateColorFromSwatches);
connect(numberShade, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorShade);
+ connect(sliderShade, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorShade);
connect(numberAlpha, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorAlpha);
+ connect(sliderAlpha, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorAlpha);
}
void ColorPickerColor::disconnectSlots()
{
disconnect(swatches, &ColorPickerColorSwatches::colorChanged, this, &ColorPickerColor::updateColorFromSwatches);
disconnect(numberShade, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorShade);
+ disconnect(sliderShade, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorShade);
disconnect(numberAlpha, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorAlpha);
+ disconnect(sliderAlpha, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorAlpha);
}
/* ********************************************************************************* *
@@ -73,8 +80,10 @@ void ColorPickerColor::setContext(Context config)
sectionSwatches->setVisible(true);
numberShade->setVisible(false);
labelShade->setVisible(false);
+ sliderShade->setVisible(false);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Text:
case Context::TextBackground:
@@ -82,38 +91,48 @@ void ColorPickerColor::setContext(Context config)
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Fill:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Line:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::FillMask:
case Context::LineMask:
sectionSwatches->setVisible(false);
numberShade->setVisible(false);
labelShade->setVisible(false);
+ sliderShade->setVisible(false);
numberAlpha->setVisible(true);
labelAlpha->setVisible(true);
+ sliderAlpha->setVisible(true);
isMask = true;
break;
case Context::DropShadow:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
}
@@ -183,23 +202,38 @@ QString ColorPickerColor::toolTipText() const
void ColorPickerColor::setDoc(ScribusDoc *doc)
{
m_doc = doc;
+ sliderAlpha->setDoc(m_doc);
+ sliderShade->setDoc(m_doc);
}
void ColorPickerColor::setColorData(const CPColorData& color)
{
+ if (!m_doc)
+ return;
+
m_color = color;
+ bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+
// update UI + controls
QSignalBlocker sigSwatches(swatches);
swatches->setCurrentColor(m_color.Name);
QSignalBlocker sigShade(numberShade);
numberShade->setValue(m_color.Shade);
- numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ numberShade->setEnabled(hasColor);
QSignalBlocker sigAlpha(numberAlpha);
numberAlpha->setValue(qRound(100 - (m_color.Opacity * 100)));
- numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ numberAlpha->setEnabled(hasColor);
+
+ QSignalBlocker sigAlphaSlider(sliderAlpha);
+ sliderAlpha->setEnabled(hasColor);
+ sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
+ QSignalBlocker sigShadeSlider(sliderShade);
+ sliderShade->setEnabled(hasColor);
+ sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
}
@@ -211,20 +245,50 @@ void ColorPickerColor::languageChange()
void ColorPickerColor::updateColorFromSwatches()
{
m_color.Name = swatches->currentColor();
- numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
- numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+
+ numberShade->setEnabled(hasColor);
+ sliderShade->setEnabled(hasColor);
+ sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+ numberAlpha->setEnabled(hasColor);
+ sliderAlpha->setEnabled(hasColor);
+ sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
updateColor();
}
void ColorPickerColor::updateColorShade()
{
+ QObject* obj = sender();
+ if( obj == sliderShade )
+ {
+ QSignalBlocker sigBlocker(numberShade);
+ numberShade->setValue(sliderShade->value());
+ }
+ else if( obj == numberShade )
+ {
+ QSignalBlocker sigBlocker(sliderShade);
+ sliderShade->setValue(numberShade->value());
+ }
+
m_color.Shade = numberShade->value();
updateColor();
}
void ColorPickerColor::updateColorAlpha()
{
+ QObject* obj = sender();
+ if( obj == sliderAlpha )
+ {
+ QSignalBlocker sigBlocker(numberAlpha);
+ numberAlpha->setValue(sliderAlpha->value());
+ }
+ else if( obj == numberAlpha )
+ {
+ QSignalBlocker sigBlocker(sliderAlpha);
+ sliderAlpha->setValue(numberAlpha->value());
+ }
+
m_color.Opacity = (100 - numberAlpha->value()) / 100.0;
updateColor();
}
diff --git a/scribus/ui/colorpicker/colorpicker_color.ui b/scribus/ui/colorpicker/colorpicker_color.ui
index 4ee50c4ed..96550bf2f 100644
--- a/scribus/ui/colorpicker/colorpicker_color.ui
+++ b/scribus/ui/colorpicker/colorpicker_color.ui
@@ -59,51 +59,58 @@
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QLabel" name="labelAlpha">
- <property name="text">
- <string>Opacity:</string>
+ <item row="0" column="2">
+ <widget class="ScrSpinBox" name="numberShade">
+ <property name="suffix">
+ <string> %</string>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <property name="maximum">
+ <double>100.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>10.000000000000000</double>
</property>
</widget>
</item>
- <item row="0" column="1">
+ <item row="0" column="0">
<widget class="QLabel" name="labelShade">
<property name="text">
<string>Shade:</string>
</property>
<property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
- <item row="0" column="2">
- <widget class="ScrSpinBox" name="numberShade">
- <property name="suffix">
- <string> %</string>
- </property>
- <property name="maximum">
- <double>100.000000000000000</double>
+ <item row="0" column="1">
+ <widget class="ColorSlider" name="sliderShade">
+ <property name="orientation">
+ <enum>Qt::Orientation::Horizontal</enum>
</property>
- <property name="singleStep">
- <double>10.000000000000000</double>
+ <property name="tickPosition">
+ <enum>QSlider::TickPosition::TicksAbove</enum>
</property>
</widget>
</item>
<item row="1" column="0">
- <spacer name="horizontalSpacer">
+ <widget class="QLabel" name="labelAlpha">
+ <property name="text">
+ <string>Opacity:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="ColorSlider" name="sliderAlpha">
<property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <enum>Qt::Orientation::Horizontal</enum>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
+ <property name="tickPosition">
+ <enum>QSlider::TickPosition::TicksAbove</enum>
</property>
- </spacer>
+ </widget>
</item>
</layout>
</item>
@@ -136,6 +143,11 @@
<header>ui/colorpicker/colorpicker_color_swatches.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>ColorSlider</class>
+ <extends>QSlider</extends>
+ <header>ui/widgets/color_slider.h</header>
+ </customwidget>
</customwidgets>
<tabstops>
<tabstop>numberShade</tabstop>
diff --git a/scribus/ui/dasheditor.cpp b/scribus/ui/dasheditor.cpp
index c0cfbf77b..6d6d3d358 100644
--- a/scribus/ui/dasheditor.cpp
+++ b/scribus/ui/dasheditor.cpp
@@ -55,7 +55,6 @@ for which a new license (GPL+exception) is in place.
*
* ********************************************************************************* */
-const int RADIUS = 6;
const double HAIRLINE = 0.001;
DashPreview::DashPreview(QWidget *pa) : QFrame(pa)
diff --git a/scribus/ui/factories/scribusproxystyle.cpp b/scribus/ui/factories/scribusproxystyle.cpp
index 5295b27a4..94ce7dbde 100644
--- a/scribus/ui/factories/scribusproxystyle.cpp
+++ b/scribus/ui/factories/scribusproxystyle.cpp
@@ -18,6 +18,8 @@
#include "prefsmanager.h"
#include "scribus.h"
+#include "ui/widgets/color_slider.h"
+#include "util_gui.h"
// https://doc.qt.io/qt-6/qstyle.html#standardPalette
QPalette createLightPalette()
@@ -64,6 +66,167 @@ ScribusProxyStyle* ScribusProxyStyle::instance()
return static_cast<ScribusProxyStyle*>(qApp->style());
}
+QRect ScribusProxyStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const
+{
+ QRect rect = QProxyStyle::subControlRect(cc, option, sc, widget);
+
+ switch (cc)
+ {
+ case QStyle::ComplexControl::CC_Slider:
+ {
+ const QStyleOptionSlider *soSlider = qstyleoption_cast<const QStyleOptionSlider *>(option);
+
+ if (soSlider && widget->inherits("ColorSlider") )
+ {
+ QRect ret;
+ bool horizontal = soSlider->orientation == Qt::Horizontal;
+ int thickness = RADIUS * 2;
+ int center = (horizontal) ? (soSlider->rect.height() - thickness) / 2 : (soSlider->rect.width() - thickness) / 2;
+ int sliderOffset = (soSlider->tickPosition != QSlider::NoTicks) ? thickness : center;
+
+ switch (sc)
+ {
+ case SC_SliderHandle:
+ {
+ int len = thickness + 2; //proxy()->pixelMetric(PM_SliderLength, styleOption, widget);
+ int sliderPos = sliderPositionFromValue(soSlider->minimum, soSlider->maximum, soSlider->sliderPosition, (horizontal ? soSlider->rect.width() : soSlider->rect.height()) - len, soSlider->upsideDown);
+
+ if (horizontal)
+ ret.setRect(soSlider->rect.x() + sliderPos, soSlider->rect.y() + sliderOffset, len, thickness);
+ else
+ ret.setRect(soSlider->rect.x() + 1, soSlider->rect.y() + sliderPos, thickness, len);
+
+ break;
+ }
+ case SC_SliderGroove:
+ if (horizontal)
+ ret.setRect(soSlider->rect.x(), soSlider->rect.y() + sliderOffset + 1, soSlider->rect.width(), thickness - 3);
+ else
+ ret.setRect(soSlider->rect.x() + 2, soSlider->rect.y(), thickness - 3, soSlider->rect.height());
+
+ break;
+ case SC_SliderTickmarks:
+ {
+ int tickOffset = (soSlider->tickPosition != QSlider::NoTicks) ? thickness : 0;
+
+ if (soSlider->tickPosition != QSlider::NoTicks)
+ {
+ if (horizontal)
+ ret.setRect(soSlider->rect.x() + 1, soSlider->rect.y(), soSlider->rect.width() - 3, thickness);
+ else
+ ret.setRect(soSlider->rect.x() + tickOffset, soSlider->rect.y() + 1, thickness, soSlider->rect.height() - 3);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return visualRect(soSlider->direction, soSlider->rect, ret);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rect;
+}
+
+void ScribusProxyStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const
+{
+ switch (cc)
+ {
+ case QStyle::ComplexControl::CC_Slider:
+ {
+ const ColorSlider *wdg = qobject_cast<const ColorSlider *>(widget);
+ const QStyleOptionSlider *soSlider = qstyleoption_cast<const QStyleOptionSlider *>(opt);
+
+ if (soSlider && wdg)
+ {
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ QRect groove = subControlRect(CC_Slider, soSlider, SC_SliderGroove, widget);
+ QRect handle = subControlRect(CC_Slider, soSlider, SC_SliderHandle, widget);
+ QRect tickmarks = subControlRect(CC_Slider, soSlider, SC_SliderTickmarks, widget);
+
+ // Draw Slider
+ if ((soSlider->subControls & SC_SliderGroove) && groove.isValid())
+ {
+ double radius = (soSlider->orientation == Qt::Horizontal) ? groove.height() / 2 + 0.5 : groove.width() / 2 + 0.5;
+
+ QPainterPath border;
+ border.addRoundedRect(groove.toRectF().adjusted(0.5, 0.5, -0.5, -0.5), radius, radius);
+
+ // Draw Slider Gradients
+ painter->setClipPath(border);
+ if (wdg->m_background.isNull() || !widget->isEnabled())
+ painter->fillRect(groove, widget->palette().color(QPalette::Window));
+ else
+ {
+ renderCheckerPattern(painter, groove);
+ painter->drawImage(groove, wdg->m_background);
+ }
+ painter->setClipping(false);
+
+ // Draw Slider Border
+ painter->setPen(widget->palette().color(QPalette::Mid));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(border);
+ painter->setPen(Qt::NoPen);
+ }
+
+ // Draw Handle
+ if ((soSlider->subControls & SC_SliderHandle) && handle.isValid())
+ drawCircularHandle(painter, handle.center() + QPointF(0.5, 0.5), RADIUS * 2, Qt::NoBrush, widget->isEnabled());
+
+ // Draw Tickmarks
+ if ((soSlider->subControls & SC_SliderTickmarks) && tickmarks.isValid() && soSlider->tickInterval > 0)
+ {
+ QFont font = widget->font();
+ font.setPixelSize(8);
+ painter->setFont(font);
+
+ if (soSlider->orientation == Qt::Horizontal)
+ {
+ double ratio = double(tickmarks.width() - (2 * RADIUS)) / double(soSlider->tickInterval);
+
+ for (int x = 0; x <= soSlider->tickInterval; x++)
+ {
+ QRect tick(double(x) * ratio + RADIUS + 1, tickmarks.bottom() - 3, 1, 2);
+ QString label = QString::number((x * soSlider->maximum / soSlider->tickInterval) - abs(soSlider->minimum));
+ int offset = QFontMetrics(painter->font()).size(Qt::TextSingleLine, label).width() / 2;
+
+ painter->setPen(widget->palette().color(QPalette::WindowText));
+ painter->drawText(qBound(0, tick.left() - offset, tickmarks.width()), tickmarks.bottom() - 4, label);
+ painter->fillRect(tick, widget->palette().color(QPalette::WindowText));
+ }
+ }
+ else
+ {
+ double ratio = double(tickmarks.height() - (2 * RADIUS)) / double(soSlider->tickInterval);
+
+ for (int y = 0; y <= soSlider->tickInterval; y++)
+ {
+ QRect tick(tickmarks.left() + 2, double(y) * ratio + RADIUS + 1, 2, 1);
+ painter->fillRect(tick, widget->palette().color(QPalette::WindowText));
+ }
+ }
+ }
+
+ painter->restore();
+ return;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ QProxyStyle::drawComplexControl(cc, opt, painter, widget);
+}
+
bool ScribusProxyStyle::eventFilter(QObject *object, QEvent *event)
{
if(object == qApp && event->type() == QEvent::ThemeChange)
diff --git a/scribus/ui/factories/scribusproxystyle.h b/scribus/ui/factories/scribusproxystyle.h
index 6924af8d2..308d8594b 100644
--- a/scribus/ui/factories/scribusproxystyle.h
+++ b/scribus/ui/factories/scribusproxystyle.h
@@ -20,6 +20,9 @@ public:
static ScribusProxyStyle* instance();
+ QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget = nullptr) const override;
+ void drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const override;
+
protected:
bool eventFilter(QObject *object, QEvent *event) override;
diff --git a/scribus/ui/gradientpreview.cpp b/scribus/ui/gradientpreview.cpp
index b3684304c..191276a2d 100644
--- a/scribus/ui/gradientpreview.cpp
+++ b/scribus/ui/gradientpreview.cpp
@@ -29,7 +29,6 @@ for which a new license (GPL+exception) is in place.
#include "gradientpreview.h"
#include "util_gui.h"
-const int RADIUS = 6;
const int GRADIENT_HEIGHT = 20;
/* ********************************************************************************* *
diff --git a/scribus/ui/widgets/color_slider.cpp b/scribus/ui/widgets/color_slider.cpp
new file mode 100644
index 000000000..2d45d1bd7
--- /dev/null
+++ b/scribus/ui/widgets/color_slider.cpp
@@ -0,0 +1,721 @@
+#include "color_slider.h"
+
+#include <QPaintEvent>
+#include <QPainter>
+#include <QPainterPath>
+#include <QPalette>
+#include <QStyle>
+#include <QStyleOption>
+#include <QWidget>
+
+#include "sccolorengine.h"
+#include "scribusdoc.h"
+#include "util_gui.h"
+
+/* ********************************************************************************* *
+ *
+ * Constructor + Setup
+ *
+ * ********************************************************************************* */
+
+ColorSlider::ColorSlider(QWidget *parent): ColorSlider(Mode::RGBRed, parent) {}
+
+ColorSlider::ColorSlider(Mode mode, QWidget *parent): QSlider(parent)
+{
+ m_mode = mode;
+ m_color = ScColor(255, 0, 0);
+
+ setMinimumSize(24, 24);
+ setOrientation(Qt::Horizontal);
+ setup();
+ updateValues();
+}
+
+void ColorSlider::setDoc(ScribusDoc *doc)
+{
+ m_doc = doc;
+}
+
+/* ********************************************************************************* *
+ *
+ * Slots
+ *
+ * ********************************************************************************* */
+
+void ColorSlider::setMode(Mode mode)
+{
+ m_mode = mode;
+ setup();
+ updateValues();
+ renderMap();
+ update();
+}
+
+void ColorSlider::setColor(const QString &colorName)
+{
+ if (!m_doc)
+ return;
+
+ if (colorName == CommonStrings::tr_NoneColor || colorName == CommonStrings::None)
+ {
+ m_background = QImage(width(), height(), QImage::Format_ARGB32); // if there is no image we draw the window color
+ m_background.fill(Qt::transparent);
+ }
+ else if (colorName.isEmpty())
+ setColor(m_doc->PageColors.value("White"));
+ else
+ setColor(m_doc->PageColors.value(colorName));
+}
+
+void ColorSlider::setColor(ScColor color)
+{
+ m_color = color;
+ updateValues();
+ renderMap();
+ update();
+}
+
+void ColorSlider::setShade(double shade)
+{
+ m_shade = shade;
+ updateValues();
+ update();
+}
+
+void ColorSlider::setOpacity(double opacity)
+{
+ m_opacity = opacity;
+ updateValues();
+ update();
+}
+
+void ColorSlider::setIsDynamic(double dynamic)
+{
+ m_dynamicColor = dynamic;
+ renderMap();
+ update();
+}
+
+void ColorSlider::setValues(const QString &colorName, double opacity, double shade)
+{
+ if (!m_doc)
+ return;
+
+ if (colorName == CommonStrings::tr_NoneColor || colorName == CommonStrings::None)
+ {
+ m_background = QImage(width(), height(), QImage::Format_ARGB32); // if there is no image we draw the window color
+ m_background.fill(Qt::transparent);
+ }
+ else if (!colorName.isEmpty() || m_doc->PageColors.contains(colorName))
+ setValues(m_doc->PageColors.value(colorName), opacity, shade);
+ else
+ setValues(m_doc->PageColors.value("White"), opacity, shade);
+}
+
+void ColorSlider::setValues(ScColor color, double opacity, double shade)
+{
+ m_color = color;
+ m_shade = shade;
+ m_opacity = opacity;
+ updateValues();
+ renderMap();
+ update();
+}
+
+/* ********************************************************************************* *
+ *
+ * Functions
+ *
+ * ********************************************************************************* */
+
+void ColorSlider::updateColor()
+{
+ if (!m_doc)
+ return;
+
+ double v1, v2, v3, v4;
+
+ switch (m_mode)
+ {
+ case Mode::Opacity:
+ m_opacity = value();
+ break;
+ case Mode::Shade:
+ m_shade = value();
+ break;
+ case Mode::CMYKCyan:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelCMYK);
+ m_color.getCMYK(&v1, &v2, &v3, &v4);
+ m_color.setCmykColorF(value() / (double) maximum(), v2, v3, v4);
+ break;
+ case Mode::CMYKMagenta:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelCMYK);
+ m_color.getCMYK(&v1, &v2, &v3, &v4);
+ m_color.setCmykColorF(v1, value() / (double) maximum(), v3, v4);
+ break;
+ case Mode::CMYKYellow:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelCMYK);
+ m_color.getCMYK(&v1, &v2, &v3, &v4);
+ m_color.setCmykColorF(v1, v2, value() / (double) maximum(), v4);
+ break;
+ case Mode::CMYKKey:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelCMYK);
+ m_color.getCMYK(&v1, &v2, &v3, &v4);
+ m_color.setCmykColorF(v1, v2, v3, value() / (double) maximum());
+ break;
+ case Mode::HSVHue:
+ {
+ QColor color = ScColorEngine::getRGBColor(m_color, m_doc);
+ color.setHslF(value() / (double) maximum(), color.saturationF(), color.valueF());
+ m_color.fromQColor(color);
+ break;
+ }
+ case Mode::HSVSaturation:
+ {
+ QColor color = ScColorEngine::getRGBColor(m_color, m_doc);
+ color.setHslF(color.hslHueF(), value() / (double) maximum(), color.valueF());
+ m_color.fromQColor(color);
+ break;
+ }
+ case Mode::HSVValue:
+ {
+ QColor color = ScColorEngine::getRGBColor(m_color, m_doc);
+ color.setHslF(color.hslHueF(), color.saturationF(), value() / (double) maximum());
+ m_color.fromQColor(color);
+ break;
+ }
+ case Mode::HLCHue:
+ {
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ QLineF lin(QPointF(0.0, 0.0), QPointF(v2, v3));
+ lin = QLineF::fromPolar(lin.length(), 360 - value());
+ m_color.setLabColor(v1, lin.p2().x(), lin.p2().y());
+ break;
+ }
+ case Mode::HLCChroma:
+ {
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ QLineF lin(QPointF(0.0, 0.0), QPointF(v2, v3));
+ lin = QLineF::fromPolar(value(), lin.angle());
+ m_color.setLabColor(v1, lin.p2().x(), lin.p2().y());
+ break;
+ }
+ case Mode::HLCLightness:
+ case Mode::LabLightness:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ m_color.setLabColor(value(), v2, v3);
+ break;
+ case Mode::LabA:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ m_color.setLabColor(v1, value(), v3);
+ break;
+ case Mode::LabB:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ m_color.setLabColor(v1, v2, value());
+ break;
+ case Mode::RGBRed:
+ case Mode::RGBWebRed:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelRGB);
+ m_color.getRGB(&v1, &v2, &v3);
+ m_color.setRgbColorF(QSlider::value() / (double) maximum(), v2, v3);
+ break;
+ case Mode::RGBGreen:
+ case Mode::RGBWebGreen:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelRGB);
+ m_color.getRGB(&v1, &v2, &v3);
+ m_color.setRgbColorF(v1, QSlider::value() / (double) maximum(), v3);
+ break;
+ case Mode::RGBBlue:
+ case Mode::RGBWebBlue:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelRGB);
+ m_color.getRGB(&v1, &v2, &v3);
+ m_color.setRgbColorF(v1, v2, QSlider::value() / (double) maximum());
+ break;
+ }
+
+ emit colorChanged(m_color);
+}
+
+void ColorSlider::setup()
+{
+ disconnectSlots();
+
+ switch (m_mode)
+ {
+ default:
+ case Mode::Opacity:
+ case Mode::CMYKCyan:
+ case Mode::CMYKMagenta:
+ case Mode::CMYKYellow:
+ case Mode::CMYKKey:
+ case Mode::HSVSaturation:
+ case Mode::HSVValue:
+ case Mode::HLCLightness:
+ case Mode::LabLightness:
+ case Mode::Shade:
+ setMinimum(0);
+ setMaximum(100);
+ setTickInterval(4);
+ m_colorSteps = 100;
+ break;
+ case Mode::HSVHue:
+ case Mode::HLCHue:
+ setMinimum(0);
+ setMaximum(359);
+ setTickInterval(6);
+ m_colorSteps = 359;
+ break;
+ case Mode::LabA:
+ case Mode::LabB:
+ setMinimum(-128);
+ setMaximum(128);
+ setTickInterval(4);
+ m_colorSteps = 256;
+ break;
+ case Mode::HLCChroma:
+ setMinimum(0);
+ setMaximum(128);
+ setTickInterval(4);
+ m_colorSteps = 128;
+ break;
+ case Mode::RGBRed:
+ case Mode::RGBGreen:
+ case Mode::RGBBlue:
+ setMinimum(0);
+ setMaximum(255);
+ setTickInterval(2);
+ m_colorSteps = 255;
+ break;
+ case Mode::RGBWebRed:
+ case Mode::RGBWebGreen:
+ case Mode::RGBWebBlue:
+ setMinimum(0);
+ setMaximum(255);
+ setTickInterval(5);
+ m_colorSteps = 5;
+ break;
+ }
+
+ setSingleStep(maximum() / m_colorSteps);
+ setPageStep(maximum() / m_colorSteps);
+
+ connectSlots();
+}
+
+void ColorSlider::connectSlots()
+{
+ connect(this, &QSlider::valueChanged, this, &ColorSlider::updateColor);
+}
+
+void ColorSlider::disconnectSlots()
+{
+ disconnect(this, &QSlider::valueChanged, this, &ColorSlider::updateColor);
+}
+
+void ColorSlider::renderMap()
+{
+ if (!m_doc || !isVisible())
+ return;
+
+ QRect rect;
+ QPoint pEnd;
+ QColor color = ScColorEngine::getDisplayColor(m_color, m_doc);
+
+ if (orientation() == Qt::Horizontal)
+ {
+ rect = QRect(0, 0, width(), 1);
+ pEnd = rect.topRight();
+ }
+ else
+ {
+ rect = QRect(0, 0, 1, height());
+ pEnd = rect.bottomLeft();
+ }
+
+ m_background = QImage(rect.width(), rect.height(), QImage::Format_ARGB32);
+ m_background.fill(Qt::transparent);
+
+ QPainter p(&m_background);
+ p.setPen(Qt::NoPen);
+
+ // For opacity and shade we can use simple linear gradients
+ if (m_mode == Mode::Opacity || m_mode == Mode::Shade)
+ {
+ QLinearGradient grad = QLinearGradient(QPoint(0, 0), pEnd);
+
+ switch (m_mode)
+ {
+ case Mode::Opacity:
+ {
+ QColor colorA = color;
+ colorA.setAlphaF(0);
+ grad.setColorAt(0, colorA);
+ grad.setColorAt(1, color);
+ p.setBrush(grad);
+ p.drawRect(m_background.rect());
+ break;
+ }
+ default:
+ case Mode::Shade:
+ {
+ grad.setColorAt(0, Qt::white);
+ grad.setColorAt(1, color);
+ p.setBrush(grad);
+ p.drawRect(m_background.rect());
+ break;
+ }
+ }
+ }
+ else
+ {
+ double l, a, b;
+ int c, m, y, k, red, green, blue;
+ int length = qMax(rect.width(), rect.height());
+ int step = qMax(1, (length - RADIUS * 2) / m_colorSteps); // it must be at leat 1 (px)
+
+ // CMYK
+ CMYKColor cmyk;
+ ScColorEngine::getCMYKValues(m_color, m_doc, cmyk);
+ cmyk.getValues(c, m, y, k);
+
+ // RGB
+ RGBColor rgb;
+ ScColorEngine::getRGBValues(m_color, m_doc, rgb);
+ rgb.getValues(red, green, blue);
+
+ // Lab / HLC
+ ScColor sColor = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ sColor.getLab(&l, &a, &b);
+ QLineF lin(QPointF(0.0, 0.0), QPointF(a, b));
+ double H = lin.angle();
+ double C = lin.length();
+
+ for (int x = 0; x <= length; x += step)
+ {
+ switch (m_mode)
+ {
+ default:
+ case Mode::CMYKCyan:
+ {
+ int val = qRound(((orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length) * 255);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(val, m, y, k), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(val, 0, 0, 0), m_doc);
+ }
+ break;
+ case Mode::CMYKMagenta:
+ {
+ int val = qRound(((orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length) * 255);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(c, val, y, k), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(0, val, 0, 0), m_doc);
+ }
+ break;
+ case Mode::CMYKYellow:
+ {
+ int val = qRound(((orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length) * 255);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(c, m, val, k), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(0, 0, val, 0), m_doc);
+ }
+ break;
+ case Mode::CMYKKey:
+ {
+ int val = qRound(((orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length) * 255);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(c, m, y, val), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(0, 0, 0, val), m_doc);
+ }
+ break;
+ case Mode::HLCHue:
+ {
+ qreal val = (orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length;
+ lin = QLineF::fromPolar(C, -360 * val);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(l, lin.p2().x(), lin.p2().y()), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(100.0, lin.p2().x(), lin.p2().y()), m_doc);
+ }
+ break;
+ case Mode::HLCChroma:
+ {
+ qreal val = (orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length;
+ lin = QLineF::fromPolar(128 * val, H);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(l, lin.p2().x(), lin.p2().y()), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(100.0, lin.p2().x(), lin.p2().y()), m_doc);
+ }
+ break;
+ case Mode::HLCLightness:
+ case Mode::LabLightness:
+ {
+ qreal val = ((orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length) * 100.0;
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(val, a, b), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(val, 0.0, 0.0), m_doc);
+ }
+ break;
+ case Mode::LabA:
+ {
+ qreal val = ((orientation() == Qt::Horizontal) ? -(0.5 - qreal(x) / length) : (0.5 - qreal(x) / length)) * 255.;
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(l, val, b), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(0.0, val, 0.0), m_doc);
+ }
+ break;
+ case Mode::LabB:
+ {
+ qreal val = ((orientation() == Qt::Horizontal) ? -(0.5 - qreal(x) / length) : (0.5 - qreal(x) / length)) * 255.;
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(l, a, val), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(0.0, 0.0, val), m_doc);
+ }
+ break;
+ case Mode::RGBRed:
+ case Mode::RGBWebRed:
+ {
+ int val = qRound(((orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length) * 255);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(val, green, blue), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(val, 0, 0), m_doc);
+ }
+ break;
+ case Mode::RGBGreen:
+ case Mode::RGBWebGreen:
+ {
+ int val = qRound(((orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length) * 255);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(red, val, blue), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(0, val, 0), m_doc);
+ }
+ break;
+ case Mode::RGBBlue:
+ case Mode::RGBWebBlue:
+ {
+ int val = qRound(((orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length) * 255);
+ if (isDynamic())
+ color = ScColorEngine::getDisplayColorGC(ScColor(red, green, val), m_doc);
+ else
+ color = ScColorEngine::getDisplayColorGC(ScColor(0, 0, val), m_doc);
+ }
+ break;
+ case Mode::HSVHue:
+ {
+ qreal val = (orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length;
+ if (isDynamic())
+ color.setHsvF(val, color.saturationF(), color.valueF());
+ else
+ color.setHsvF(val, 1.0, 0.5);
+ }
+ break;
+ case Mode::HSVSaturation:
+ {
+ qreal val = (orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length;
+ if (isDynamic())
+ color.setHsvF(color.hueF(), val, color.valueF());
+ else
+ color.setHsvF(0.0, val, 0.5);
+ }
+ break;
+ case Mode::HSVValue:
+ {
+ qreal val = (orientation() == Qt::Horizontal) ? qreal(x) / length : 1. - qreal(x) / length;
+ if (isDynamic())
+ color.setHsvF(color.hueF(), color.saturationF(), val);
+ else
+ color.setHsvF(0.0, 1.0, val);
+ }
+ break;
+ }
+
+ int w = (x == 0) ? step + RADIUS : step;
+ int o = (x == 0) ? 0 : RADIUS;
+
+ p.setBrush(color);
+ p.drawRect((orientation() == Qt::Horizontal) ? QRect(o + x - step / 2, 0, w, 1) : QRect(0, o + x - step / 2, 1, w));
+ }
+ }
+ p.end();
+
+}
+
+void ColorSlider::updateValues()
+{
+ if (!m_doc)
+ return;
+
+ disconnectSlots();
+
+ QSignalBlocker blocker(this);
+
+ double v1, v2, v3, v4;
+
+ switch (m_mode)
+ {
+ case Mode::Opacity:
+ setValue(m_opacity);
+ break;
+ case Mode::Shade:
+ setValue(m_shade);
+ break;
+ case Mode::CMYKCyan:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelCMYK);
+ m_color.getCMYK(&v1, &v2, &v3, &v4);
+ setValue(v1 * maximum());
+ break;
+ case Mode::CMYKMagenta:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelCMYK);
+ m_color.getCMYK(&v1, &v2, &v3, &v4);
+ setValue(v2 * maximum());
+ break;
+ case Mode::CMYKYellow:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelCMYK);
+ m_color.getCMYK(&v1, &v2, &v3, &v4);
+ setValue(v3 * maximum());
+ break;
+ case Mode::CMYKKey:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelCMYK);
+ m_color.getCMYK(&v1, &v2, &v3, &v4);
+ setValue(v4 * maximum());
+ break;
+ case Mode::HSVHue:
+ setValue(ScColorEngine::getRGBColor(m_color, m_doc).hueF() * maximum());
+ break;
+ case Mode::HSVSaturation:
+ setValue(ScColorEngine::getRGBColor(m_color, m_doc).saturationF() * maximum());
+ break;
+ case Mode::HSVValue:
+ setValue(ScColorEngine::getRGBColor(m_color, m_doc).valueF() * maximum());
+ break;
+ case Mode::HLCHue:
+ {
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ QLineF lin(QPointF(0.0, 0.0), QPointF(v2, v3));
+ setValue(360 - lin.angle());
+ break;
+ }
+ case Mode::HLCChroma:
+ {
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ QLineF lin(QPointF(0.0, 0.0), QPointF(v2, v3));
+ setValue(lin.length());
+ break;
+ }
+ case Mode::HLCLightness:
+ case Mode::LabLightness:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ setValue(v1);
+ break;
+ case Mode::LabA:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ setValue(v2);
+ break;
+ case Mode::LabB:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelLab);
+ m_color.getLab(&v1, &v2, &v3);
+ setValue(v3);
+ break;
+ case Mode::RGBWebRed:
+ case Mode::RGBRed:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelRGB);
+ m_color.getRGB(&v1, &v2, &v3);
+ setValue(v1 * maximum());
+ break;
+ case Mode::RGBWebGreen:
+ case Mode::RGBGreen:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelRGB);
+ m_color.getRGB(&v1, &v2, &v3);
+ setValue(v2 * maximum());
+ break;
+ case Mode::RGBWebBlue:
+ case Mode::RGBBlue:
+ m_color = ScColorEngine::convertToModel(m_color, m_doc, colorModelRGB);
+ m_color.getRGB(&v1, &v2, &v3);
+ setValue(v3 * maximum());
+ break;
+ }
+
+ connectSlots();
+}
+
+/* ********************************************************************************* *
+ *
+ * Events
+ *
+ * ********************************************************************************* */
+
+void ColorSlider::resizeEvent(QResizeEvent *e)
+{
+ QWidget::resizeEvent(e);
+
+ if (e->oldSize() != e->size())
+ renderMap();
+}
+
+void ColorSlider::showEvent(QShowEvent *e)
+{
+ QWidget::showEvent(e);
+ renderMap();
+}
+
+void ColorSlider::mouseMoveEvent(QMouseEvent *e)
+{
+ if (e->buttons() & Qt::LeftButton)
+ {
+ switch (m_mode)
+ {
+ // Override slider movement for custom steps
+ case Mode::RGBWebBlue:
+ case Mode::RGBWebGreen:
+ case Mode::RGBWebRed:
+ setSliderPosition(pixelPosToRangeValue(e->pos()));
+ break;
+ default:
+ QSlider::mouseMoveEvent(e);
+ break;
+ }
+
+ return;
+ }
+
+ QSlider::mouseMoveEvent(e);
+}
+
+int ColorSlider::pixelPosToRangeValue(QPoint pt) const
+{
+ int pos, sliderMin, sliderMax;
+ if (orientation() == Qt::Horizontal)
+ {
+ pos = pt.x();
+ sliderMin = rect().x();
+ sliderMax = rect().right() - RADIUS * 2 + 1;
+ }
+ else
+ {
+ pos = pt.y();
+ sliderMin = rect().y();
+ sliderMax = rect().bottom() - RADIUS * 2 + 1;
+ }
+
+ return roundToStep(QStyle::sliderValueFromPosition(minimum(), maximum(), pos - sliderMin, sliderMax - sliderMin));
+}
+
diff --git a/scribus/ui/widgets/color_slider.h b/scribus/ui/widgets/color_slider.h
new file mode 100644
index 000000000..b497f18bd
--- /dev/null
+++ b/scribus/ui/widgets/color_slider.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/*
+For general Scribus copyright and licensing information please refer
+to the COPYING file provided with the program.
+*/
+#ifndef COLOR_SLIDER_H
+#define COLOR_SLIDER_H
+
+#include <QPointer>
+#include <QSlider>
+#include "sccolor.h"
+#include "scribusapi.h"
+
+class QPaintEvent;
+class QWidget;
+class ScribusDoc;
+
+class SCRIBUS_API ColorSlider : public QSlider
+{
+ Q_OBJECT
+
+friend class ScribusProxyStyle;
+
+public:
+ enum Mode
+ {
+ RGBRed = 0,
+ RGBGreen,
+ RGBBlue,
+ RGBWebRed,
+ RGBWebGreen,
+ RGBWebBlue,
+ LabLightness,
+ LabA,
+ LabB,
+ CMYKCyan,
+ CMYKMagenta,
+ CMYKYellow,
+ CMYKKey,
+ HLCHue,
+ HLCLightness,
+ HLCChroma,
+ HSVHue,
+ HSVSaturation,
+ HSVValue,
+ Shade,
+ Opacity
+ };
+
+ ColorSlider(QWidget* parent = nullptr);
+ ColorSlider(Mode mode, QWidget* parent = nullptr);
+
+ ScColor color() { return m_color; }
+ double opacity() { return m_opacity; } // 0.0 - 100.0
+ double shade() { return m_shade; } // 0.0 - 100.0
+ Mode mode() { return m_mode; }
+ bool isDynamic() { return m_dynamicColor; }
+
+public slots:
+ void setDoc(ScribusDoc *doc);
+ void setMode(ColorSlider::Mode mode);
+ void setValues(const QString &colorName, double opacity, double shade);
+ void setValues(ScColor color, double opacity, double shade);
+ void setColor(const QString &colorName);
+ void setColor(ScColor color);
+ void setShade(double shade);
+ void setOpacity(double opacity);
+ void setIsDynamic(double dynamic);
+
+private slots:
+ void updateColor();
+
+protected:
+ void resizeEvent(QResizeEvent* e);
+ void showEvent(QShowEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+
+private:
+ QPointer<ScribusDoc> m_doc;
+ QGradientStops m_stops;
+ ScColor m_color;
+ double m_opacity {100.0}; // full opacity
+ double m_shade {100.0}; // no shade
+ int m_colorSteps {100};
+ bool m_dynamicColor {true};
+ Mode m_mode {RGBRed};
+ QImage m_background;
+
+ int pixelPosToRangeValue(QPoint pos) const;
+ int roundToStep(int value) const
+ {
+ int mod = maximum() / m_colorSteps;
+ return (value / mod) * mod;
+ }
+
+ void setup();
+ void connectSlots();
+ void disconnectSlots();
+
+ void renderMap();
+ void updateValues();
+
+signals:
+ void colorChanged(ScColor);
+
+};
+
+#endif // COLOR_SLIDER_H
diff --git a/scribus/util_gui.h b/scribus/util_gui.h
index 4ed63b819..9ec661438 100644
--- a/scribus/util_gui.h
+++ b/scribus/util_gui.h
@@ -9,6 +9,8 @@ class VGradient;
class VColorStop;
class ScPattern;
+const int RADIUS = 6;
+
void SCRIBUS_API drawCircularHandle(QPainter * painter, QPointF center, qreal width, QBrush background, bool isEnabled = true);
void SCRIBUS_API drawPointerHandle(QPainter * painter, QPointF pointer, qreal width, QColor background, bool isEnabled = true, bool isEmpty = false);
void SCRIBUS_API renderCheckerPattern(QPainter *painter, QRectF rect);
|
|
|
Updated colorslider_fixed.diff (20,025 bytes)
Index: scribus/CMakeLists_Sources.txt
===================================================================
--- scribus/CMakeLists_Sources.txt (revision 27207)
+++ scribus/CMakeLists_Sources.txt (working copy)
@@ -567,6 +567,7 @@
ui/docks/dock_panelbase.cpp
ui/factories/scribusproxystyle.cpp
ui/widgets/color_button.cpp
+ ui/widgets/color_slider.cpp
ui/widgets/combo_blendmode.cpp
ui/widgets/combo_linestyle.cpp
ui/widgets/dropdown_button.cpp
Index: scribus/ui/colorpicker/colorpicker_color.cpp
===================================================================
--- scribus/ui/colorpicker/colorpicker_color.cpp (revision 27207)
+++ scribus/ui/colorpicker/colorpicker_color.cpp (working copy)
@@ -26,6 +26,9 @@
languageChange();
+ sliderAlpha->setMode(ColorSlider::Opacity);
+ sliderShade->setMode(ColorSlider::Shade);
+
connectSlots();
connect(sectionSwatches, &SectionContainer::sizeChanged, this, &ColorPickerColor::updateSize);
}
@@ -34,7 +37,9 @@
{
connect(swatches, &ColorPickerColorSwatches::colorChanged, this, &ColorPickerColor::updateColorFromSwatches);
connect(numberShade, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorShade);
+ connect(sliderShade, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorShade);
connect(numberAlpha, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorAlpha);
+ connect(sliderAlpha, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorAlpha);
}
void ColorPickerColor::disconnectSlots()
@@ -41,7 +46,9 @@
{
disconnect(swatches, &ColorPickerColorSwatches::colorChanged, this, &ColorPickerColor::updateColorFromSwatches);
disconnect(numberShade, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorShade);
+ disconnect(sliderShade, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorShade);
disconnect(numberAlpha, &ScrSpinBox::valueChanged, this, &ColorPickerColor::updateColorAlpha);
+ disconnect(sliderAlpha, &ColorSlider::valueChanged, this, &ColorPickerColor::updateColorAlpha);
}
/* ********************************************************************************* *
@@ -73,8 +80,10 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(false);
labelShade->setVisible(false);
+ sliderShade->setVisible(false);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Text:
case Context::TextBackground:
@@ -82,22 +91,28 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Fill:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::Line:
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
case Context::FillMask:
case Context::LineMask:
@@ -104,8 +119,10 @@
sectionSwatches->setVisible(false);
numberShade->setVisible(false);
labelShade->setVisible(false);
+ sliderShade->setVisible(false);
numberAlpha->setVisible(true);
labelAlpha->setVisible(true);
+ sliderAlpha->setVisible(true);
isMask = true;
break;
case Context::DropShadow:
@@ -112,8 +129,10 @@
sectionSwatches->setVisible(true);
numberShade->setVisible(true);
labelShade->setVisible(true);
+ sliderShade->setVisible(true);
numberAlpha->setVisible(false);
labelAlpha->setVisible(false);
+ sliderAlpha->setVisible(false);
break;
}
@@ -183,12 +202,19 @@
void ColorPickerColor::setDoc(ScribusDoc *doc)
{
m_doc = doc;
+ sliderAlpha->setDoc(m_doc);
+ sliderShade->setDoc(m_doc);
}
void ColorPickerColor::setColorData(const CPColorData& color)
{
+ if (!m_doc)
+ return;
+
m_color = color;
+ bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+
// update UI + controls
QSignalBlocker sigSwatches(swatches);
swatches->setCurrentColor(m_color.Name);
@@ -195,12 +221,20 @@
QSignalBlocker sigShade(numberShade);
numberShade->setValue(m_color.Shade);
- numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ numberShade->setEnabled(hasColor);
QSignalBlocker sigAlpha(numberAlpha);
numberAlpha->setValue(qRound(100 - (m_color.Opacity * 100)));
- numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ numberAlpha->setEnabled(hasColor);
+ QSignalBlocker sigAlphaSlider(sliderAlpha);
+ sliderAlpha->setEnabled(hasColor);
+ sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
+ QSignalBlocker sigShadeSlider(sliderShade);
+ sliderShade->setEnabled(hasColor);
+ sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
}
void ColorPickerColor::languageChange()
@@ -211,14 +245,32 @@
void ColorPickerColor::updateColorFromSwatches()
{
m_color.Name = swatches->currentColor();
- numberShade->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
- numberAlpha->setEnabled(m_color.Name != CommonStrings::tr_NoneColor);
+ bool hasColor = m_color.Name != CommonStrings::tr_NoneColor;
+ numberShade->setEnabled(hasColor);
+ sliderShade->setEnabled(hasColor);
+ sliderShade->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+ numberAlpha->setEnabled(hasColor);
+ sliderAlpha->setEnabled(hasColor);
+ sliderAlpha->setValues(m_color.Name, numberAlpha->value(), numberShade->value());
+
updateColor();
}
void ColorPickerColor::updateColorShade()
{
+ QObject* obj = sender();
+ if( obj == sliderShade )
+ {
+ QSignalBlocker sigBlocker(numberShade);
+ numberShade->setValue(sliderShade->value());
+ }
+ else if( obj == numberShade )
+ {
+ QSignalBlocker sigBlocker(sliderShade);
+ sliderShade->setValue(numberShade->value());
+ }
+
m_color.Shade = numberShade->value();
updateColor();
}
@@ -225,6 +277,18 @@
void ColorPickerColor::updateColorAlpha()
{
+ QObject* obj = sender();
+ if( obj == sliderAlpha )
+ {
+ QSignalBlocker sigBlocker(numberAlpha);
+ numberAlpha->setValue(sliderAlpha->value());
+ }
+ else if( obj == numberAlpha )
+ {
+ QSignalBlocker sigBlocker(sliderAlpha);
+ sliderAlpha->setValue(numberAlpha->value());
+ }
+
m_color.Opacity = (100 - numberAlpha->value()) / 100.0;
updateColor();
}
Index: scribus/ui/colorpicker/colorpicker_color.ui
===================================================================
--- scribus/ui/colorpicker/colorpicker_color.ui (revision 27207)
+++ scribus/ui/colorpicker/colorpicker_color.ui (working copy)
@@ -59,51 +59,58 @@
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QLabel" name="labelAlpha">
- <property name="text">
- <string>Opacity:</string>
+ <item row="0" column="2">
+ <widget class="ScrSpinBox" name="numberShade">
+ <property name="suffix">
+ <string> %</string>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <property name="maximum">
+ <double>100.000000000000000</double>
</property>
+ <property name="singleStep">
+ <double>10.000000000000000</double>
+ </property>
</widget>
</item>
- <item row="0" column="1">
+ <item row="0" column="0">
<widget class="QLabel" name="labelShade">
<property name="text">
<string>Shade:</string>
</property>
<property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
- <item row="0" column="2">
- <widget class="ScrSpinBox" name="numberShade">
- <property name="suffix">
- <string> %</string>
+ <item row="0" column="1">
+ <widget class="ColorSlider" name="sliderShade">
+ <property name="orientation">
+ <enum>Qt::Orientation::Horizontal</enum>
</property>
- <property name="maximum">
- <double>100.000000000000000</double>
+ <property name="tickPosition">
+ <enum>QSlider::TickPosition::TicksAbove</enum>
</property>
- <property name="singleStep">
- <double>10.000000000000000</double>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelAlpha">
+ <property name="text">
+ <string>Opacity:</string>
</property>
+ <property name="alignment">
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
+ </property>
</widget>
</item>
- <item row="1" column="0">
- <spacer name="horizontalSpacer">
+ <item row="1" column="1">
+ <widget class="ColorSlider" name="sliderAlpha">
<property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <enum>Qt::Orientation::Horizontal</enum>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
+ <property name="tickPosition">
+ <enum>QSlider::TickPosition::TicksAbove</enum>
</property>
- </spacer>
+ </widget>
</item>
</layout>
</item>
@@ -136,6 +143,11 @@
<header>ui/colorpicker/colorpicker_color_swatches.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>ColorSlider</class>
+ <extends>QSlider</extends>
+ <header>ui/widgets/color_slider.h</header>
+ </customwidget>
</customwidgets>
<tabstops>
<tabstop>numberShade</tabstop>
Index: scribus/ui/dasheditor.cpp
===================================================================
--- scribus/ui/dasheditor.cpp (revision 27207)
+++ scribus/ui/dasheditor.cpp (working copy)
@@ -55,7 +55,6 @@
*
* ********************************************************************************* */
-const int RADIUS = 6;
const double HAIRLINE = 0.001;
DashPreview::DashPreview(QWidget *pa) : QFrame(pa)
Index: scribus/ui/factories/scribusproxystyle.cpp
===================================================================
--- scribus/ui/factories/scribusproxystyle.cpp (revision 27207)
+++ scribus/ui/factories/scribusproxystyle.cpp (working copy)
@@ -18,6 +18,8 @@
#include "prefsmanager.h"
#include "scribus.h"
+#include "ui/widgets/color_slider.h"
+#include "util_gui.h"
// https://doc.qt.io/qt-6/qstyle.html#standardPalette
QPalette createLightPalette()
@@ -64,6 +66,167 @@
return static_cast<ScribusProxyStyle*>(qApp->style());
}
+QRect ScribusProxyStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const
+{
+ QRect rect = QProxyStyle::subControlRect(cc, option, sc, widget);
+
+ switch (cc)
+ {
+ case QStyle::ComplexControl::CC_Slider:
+ {
+ const QStyleOptionSlider *soSlider = qstyleoption_cast<const QStyleOptionSlider *>(option);
+
+ if (soSlider && widget->inherits("ColorSlider") )
+ {
+ QRect ret;
+ bool horizontal = soSlider->orientation == Qt::Horizontal;
+ int thickness = RADIUS * 2;
+ int center = (horizontal) ? (soSlider->rect.height() - thickness) / 2 : (soSlider->rect.width() - thickness) / 2;
+ int sliderOffset = (soSlider->tickPosition != QSlider::NoTicks) ? thickness : center;
+
+ switch (sc)
+ {
+ case SC_SliderHandle:
+ {
+ int len = thickness + 2; //proxy()->pixelMetric(PM_SliderLength, styleOption, widget);
+ int sliderPos = sliderPositionFromValue(soSlider->minimum, soSlider->maximum, soSlider->sliderPosition, (horizontal ? soSlider->rect.width() : soSlider->rect.height()) - len, soSlider->upsideDown);
+
+ if (horizontal)
+ ret.setRect(soSlider->rect.x() + sliderPos, soSlider->rect.y() + sliderOffset, len, thickness);
+ else
+ ret.setRect(soSlider->rect.x() + 1, soSlider->rect.y() + sliderPos, thickness, len);
+
+ break;
+ }
+ case SC_SliderGroove:
+ if (horizontal)
+ ret.setRect(soSlider->rect.x(), soSlider->rect.y() + sliderOffset + 1, soSlider->rect.width(), thickness - 3);
+ else
+ ret.setRect(soSlider->rect.x() + 2, soSlider->rect.y(), thickness - 3, soSlider->rect.height());
+
+ break;
+ case SC_SliderTickmarks:
+ {
+ int tickOffset = (soSlider->tickPosition != QSlider::NoTicks) ? thickness : 0;
+
+ if (soSlider->tickPosition != QSlider::NoTicks)
+ {
+ if (horizontal)
+ ret.setRect(soSlider->rect.x() + 1, soSlider->rect.y(), soSlider->rect.width() - 3, thickness);
+ else
+ ret.setRect(soSlider->rect.x() + tickOffset, soSlider->rect.y() + 1, thickness, soSlider->rect.height() - 3);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return visualRect(soSlider->direction, soSlider->rect, ret);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rect;
+}
+
+void ScribusProxyStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const
+{
+ switch (cc)
+ {
+ case QStyle::ComplexControl::CC_Slider:
+ {
+ const ColorSlider *wdg = qobject_cast<const ColorSlider *>(widget);
+ const QStyleOptionSlider *soSlider = qstyleoption_cast<const QStyleOptionSlider *>(opt);
+
+ if (soSlider && wdg)
+ {
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ QRect groove = subControlRect(CC_Slider, soSlider, SC_SliderGroove, widget);
+ QRect handle = subControlRect(CC_Slider, soSlider, SC_SliderHandle, widget);
+ QRect tickmarks = subControlRect(CC_Slider, soSlider, SC_SliderTickmarks, widget);
+
+ // Draw Slider
+ if ((soSlider->subControls & SC_SliderGroove) && groove.isValid())
+ {
+ double radius = (soSlider->orientation == Qt::Horizontal) ? groove.height() / 2 + 0.5 : groove.width() / 2 + 0.5;
+
+ QPainterPath border;
+ border.addRoundedRect(groove.toRectF().adjusted(0.5, 0.5, -0.5, -0.5), radius, radius);
+
+ // Draw Slider Gradients
+ painter->setClipPath(border);
+ if (wdg->backgroundImage().isNull() || !widget->isEnabled())
+ painter->fillRect(groove, widget->palette().color(QPalette::Window));
+ else
+ {
+ renderCheckerPattern(painter, groove);
+ painter->drawImage(groove, wdg->backgroundImage());
+ }
+ painter->setClipping(false);
+
+ // Draw Slider Border
+ painter->setPen(widget->palette().color(QPalette::Mid));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(border);
+ painter->setPen(Qt::NoPen);
+ }
+
+ // Draw Handle
+ if ((soSlider->subControls & SC_SliderHandle) && handle.isValid())
+ drawCircularHandle(painter, handle.center() + QPointF(0.5, 0.5), RADIUS * 2, Qt::NoBrush, widget->isEnabled());
+
+ // Draw Tickmarks
+ if ((soSlider->subControls & SC_SliderTickmarks) && tickmarks.isValid() && soSlider->tickInterval > 0)
+ {
+ QFont font = widget->font();
+ font.setPixelSize(8);
+ painter->setFont(font);
+
+ if (soSlider->orientation == Qt::Horizontal)
+ {
+ double ratio = double(tickmarks.width() - (2 * RADIUS)) / double(soSlider->tickInterval);
+
+ for (int x = 0; x <= soSlider->tickInterval; x++)
+ {
+ QRect tick(double(x) * ratio + RADIUS + 1, tickmarks.bottom() - 3, 1, 2);
+ QString label = QString::number((x * soSlider->maximum / soSlider->tickInterval) - abs(soSlider->minimum));
+ int offset = QFontMetrics(painter->font()).size(Qt::TextSingleLine, label).width() / 2;
+
+ painter->setPen(widget->palette().color(QPalette::WindowText));
+ painter->drawText(qBound(0, tick.left() - offset, tickmarks.width()), tickmarks.bottom() - 4, label);
+ painter->fillRect(tick, widget->palette().color(QPalette::WindowText));
+ }
+ }
+ else
+ {
+ double ratio = double(tickmarks.height() - (2 * RADIUS)) / double(soSlider->tickInterval);
+
+ for (int y = 0; y <= soSlider->tickInterval; y++)
+ {
+ QRect tick(tickmarks.left() + 2, double(y) * ratio + RADIUS + 1, 2, 1);
+ painter->fillRect(tick, widget->palette().color(QPalette::WindowText));
+ }
+ }
+ }
+
+ painter->restore();
+ return;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ QProxyStyle::drawComplexControl(cc, opt, painter, widget);
+}
+
bool ScribusProxyStyle::eventFilter(QObject *object, QEvent *event)
{
if (object == qApp && event->type() == QEvent::ThemeChange)
Index: scribus/ui/factories/scribusproxystyle.h
===================================================================
--- scribus/ui/factories/scribusproxystyle.h (revision 27207)
+++ scribus/ui/factories/scribusproxystyle.h (working copy)
@@ -20,6 +20,9 @@
static ScribusProxyStyle* instance();
+ QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget = nullptr) const override;
+ void drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const override;
+
protected:
bool eventFilter(QObject *object, QEvent *event) override;
Index: scribus/ui/gradientpreview.cpp
===================================================================
--- scribus/ui/gradientpreview.cpp (revision 27207)
+++ scribus/ui/gradientpreview.cpp (working copy)
@@ -29,7 +29,6 @@
#include "gradientpreview.h"
#include "util_gui.h"
-const int RADIUS = 6;
const int GRADIENT_HEIGHT = 20;
/* ********************************************************************************* *
Index: scribus/ui/widgets/color_slider.cpp
===================================================================
--- scribus/ui/widgets/color_slider.cpp (revision 27207)
+++ scribus/ui/widgets/color_slider.cpp (working copy)
@@ -18,8 +18,6 @@
*
* ********************************************************************************* */
-const int RADIUS = 6;
-
ColorSlider::ColorSlider(QWidget *parent): ColorSlider(Mode::RGBRed, parent) {}
ColorSlider::ColorSlider(Mode mode, QWidget *parent): QSlider(parent)
@@ -553,7 +551,7 @@
QSignalBlocker blocker(this);
double v1, v2, v3, v4;
- int multplier = 1;
+ // int multplier = 1;
switch (m_mode)
{
Index: scribus/ui/widgets/color_slider.h
===================================================================
--- scribus/ui/widgets/color_slider.h (revision 27207)
+++ scribus/ui/widgets/color_slider.h (working copy)
@@ -55,11 +55,12 @@
ColorSlider(QWidget* parent = nullptr);
ColorSlider(Mode mode, QWidget* parent = nullptr);
- const ScColor& color() const{ return m_color; }
+ const ScColor& color() const { return m_color; }
double opacity() const { return m_opacity; } // 0.0 - 100.0
double shade() const { return m_shade; } // 0.0 - 100.0
Mode mode() const { return m_mode; }
bool isDynamic() const { return m_dynamicColor; }
+ const QImage& backgroundImage() const { return m_background; }
public slots:
void setDoc(ScribusDoc *doc);
Index: scribus/util_gui.h
===================================================================
--- scribus/util_gui.h (revision 27207)
+++ scribus/util_gui.h (working copy)
@@ -9,6 +9,8 @@
class VColorStop;
class ScPattern;
+const int RADIUS = 6;
+
void SCRIBUS_API drawCircularHandle(QPainter * painter, QPointF center, qreal width, QBrush background, bool isEnabled = true);
void SCRIBUS_API drawPointerHandle(QPainter * painter, QPointF pointer, qreal width, QColor background, bool isEnabled = true, bool isEmpty = false);
void SCRIBUS_API renderCheckerPattern(QPainter *painter, QRectF rect);
|
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2025-05-13 20:33 | nitramr | New Issue | |
| 2025-05-13 20:33 | nitramr | Status | new => assigned |
| 2025-05-13 20:33 | nitramr | Assigned To | => nitramr |
| 2025-05-13 20:33 | nitramr | File Added: color_slider.zip | |
| 2025-05-13 20:33 | nitramr | File Added: colorslider_2025-05-13_01.patch | |
| 2025-05-13 20:33 | nitramr | File Added: preview.png | |
| 2025-05-13 21:06 | cbradney | Note Added: 0052524 | |
| 2025-05-13 21:06 | cbradney | File Added: image.png | |
| 2025-05-30 05:47 | ale | Relationship added | child of 0017540 |
| 2025-10-25 14:16 | nitramr | Note Added: 0053120 | |
| 2025-10-25 14:16 | nitramr | File Added: colorslider_2025-10-25_01.patch | |
| 2025-10-25 14:16 | nitramr | File Added: scribus.zip | |
| 2025-10-25 14:16 | nitramr | File Added: colorslider_mac.png | |
| 2025-10-25 19:36 | cbradney | Note Added: 0053124 | |
| 2025-10-27 18:58 | nitramr | Relationship added | duplicate of 0006434 |
| 2025-12-13 19:04 | nitramr | Note Added: 0053370 | |
| 2025-12-13 19:04 | nitramr | File Added: colorslider_2025-12-13_01.diff | |
| 2025-12-13 22:27 | cbradney | Note Added: 0053372 | |
| 2025-12-13 22:27 | cbradney | File Added: colorslider_fixed.diff |