From 8f864f33941dcfcb835a97771f5e7f803cf0141b Mon Sep 17 00:00:00 2001 From: Hane Date: Sat, 31 Jan 2026 18:09:02 +0100 Subject: [PATCH] wip: icons --- assets.qrc | 2 ++ bueno.bat | 6 +++--- qtest.pro | 2 +- src/qt/qtclasses.cpp | 38 ++++++++++++++++++++++++++++++--- src/qt/qtclasses.h | 7 +++++- src/qt/qtcommon.h | 32 +++++++++++++++++++++++++++ src/qt/qtvisuals.h | 51 ++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 128 insertions(+), 10 deletions(-) diff --git a/assets.qrc b/assets.qrc index 4ef5956..2206a8a 100644 --- a/assets.qrc +++ b/assets.qrc @@ -4,5 +4,7 @@ assets/notificationAreaIcon.png assets/style.qss assets/logo.ico + assets/mute.svg + assets/unmute.svg diff --git a/bueno.bat b/bueno.bat index 37b5dec..540be60 100644 --- a/bueno.bat +++ b/bueno.bat @@ -1,7 +1,7 @@ taskkill /F /IM "MixerQ.exe" taskkill /F /IM "MixerQd.exe" qmake -o build\Makefile .\qtest.pro -mingw32-make.exe -C .\build -f Makefile.Release +REM mingw32-make.exe -C .\build -f Makefile.Release mingw32-make.exe -C .\build -f Makefile.Debug -makensis /DBUILDTYPE=release install\installer.nsi -makensis /DBUILDTYPE=debug install\installer.nsi +REM makensis /DBUILDTYPE=release install\installer.nsi +REM makensis /DBUILDTYPE=debug install\installer.nsi diff --git a/qtest.pro b/qtest.pro index 0568bca..42a1165 100644 --- a/qtest.pro +++ b/qtest.pro @@ -18,7 +18,7 @@ LIBS += -lWinmm -lodbc32 -lodbccp32 -luuid -loleaut32 -lole32 -lshell32 -ladvapi DEFINES += QT_LOGGING_TO_CONSOLE=1 WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602 DEFINES_DEBUG += DEBUG -QT += widgets network +QT += widgets network svg INCLUDEPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimpl" "$$PWD\src\cont" VPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimpl" "$$PWD\src\cont" diff --git a/src/qt/qtclasses.cpp b/src/qt/qtclasses.cpp index a5c391d..a9148b9 100644 --- a/src/qt/qtclasses.cpp +++ b/src/qt/qtclasses.cpp @@ -207,6 +207,36 @@ void ExtendedCheckBox::customEvent(QEvent* ev) { QCheckBox::customEvent(ev); } +void ExtendedCheckBox::paintEvent(QPaintEvent *event) { + QStylePainter p(this); + QStyleOptionButton opt; + initStyleOption(&opt); + opt.icon = this->icons; + p.drawControl((QStyle::ControlElement)CustomControlElement::CE_ExtendedCheckBox, opt); + //QStyle* style = QApplication::style(); + //style->drawComplexControl((QStyle::ComplexControl)CC_MeterSlider, &sliderComplex2, &painter, this); +} + +void ExtendedCheckBox::addIcon(char* const path, QIcon::State state) { + QString str(path); + QSvgRenderer rr(str); + QPixmap pixmap(64, 64); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + rr.render(&painter); + painter.setCompositionMode(QPainter::CompositionMode_SourceIn); + uint8_t a, r, g, b; + if (StylingHelper::argbToDiscreteValues(osh->getAccentColor(), &r, &g, &b, &a)) { + QColor color(r, g, b, a); + painter.fillRect(pixmap.rect(), color); + } + painter.end(); + icons.addPixmap(pixmap, QIcon::Normal, state); + //this->setIcon(icons); + //icons.addFile(":/Icons/images/second.svg",QSize(32,32),QIcon::Normal,QIcon::Off); +} + + QRect MainWindow::setSizePosition(QScreen* screen, int width, int height) { //setGeometry ignores decoration size, theres others for that QRect trayIconPos = this->trayIcon->geometry(); @@ -276,7 +306,7 @@ void MainWindow::compose(bool isVisible) { * Setting correct widget widths and heights */ log_to_file("[Compose]\n"); - screen = this->getCurrentScreen(); + screen = StylingHelper::getCurrentScreen(); log_debugcpp("Screen: " + screen->model().toStdString() + " " + screen->name().toStdString()); QRect screenRes = screen->geometry(); @@ -336,7 +366,7 @@ void MainWindow::compose(bool isVisible) { } QScreen* MainWindow::getCurrentScreen() { - //todo: Using cursor pos as screen detector. Flawed. + //note: Using cursor pos as screen detector. Flawed. QPoint cursorPos = QCursor::pos(); log_debugcpp("Cursor pos: " + std::to_string(cursorPos.ry()) + " " + std::to_string(cursorPos.rx())); @@ -363,7 +393,9 @@ SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent) widgetLayout->getContentsMargins(&left, &top, &right, &bottom); widgetLayout->setContentsMargins(0, top, 0, bottom); - muteButton = new QCheckBox(this); + muteButton = new ExtendedCheckBox(this); + muteButton->addIcon(":/assets/mute.svg", QIcon::On); + muteButton->addIcon(":/assets/unmute.svg", QIcon::Off); mainLabel = new QLabel(QString::fromStdWString(sh->getName()), this); mainLabel->setToolTip(QString::fromStdWString(sh->getName())); mainSlider = new MeterSlider(Qt::Horizontal, this); diff --git a/src/qt/qtclasses.h b/src/qt/qtclasses.h index 0d5733f..1b2658b 100644 --- a/src/qt/qtclasses.h +++ b/src/qt/qtclasses.h @@ -40,12 +40,17 @@ public: class ExtendedCheckBox : public QCheckBox { Q_OBJECT +private: + QIcon icons; + protected: void customEvent(QEvent* ev) override; + void paintEvent(QPaintEvent* event) override; public: //c++11: this inherits all parent's constructors unconditionally using QCheckBox::QCheckBox; + void addIcon(char* const path, QIcon::State state); //alternative being calling parent ctor directly after declaring child ctor: //B(int x) : A(x) { } }; @@ -68,7 +73,7 @@ private: MeterSlider *mainSlider = nullptr; uint64_t idx; QHBoxLayout *widgetLayout = nullptr; - QCheckBox *muteButton = nullptr; + ExtendedCheckBox *muteButton = nullptr; SessionHandler* sh; QTimer* volumePoller = nullptr; QSpacerItem* widthSpacer; diff --git a/src/qt/qtcommon.h b/src/qt/qtcommon.h index b059504..61873eb 100644 --- a/src/qt/qtcommon.h +++ b/src/qt/qtcommon.h @@ -44,6 +44,7 @@ #include #include #include +#include //#include //#include /* @@ -63,6 +64,10 @@ enum CustomComplexControl { CC_MeterSlider = 0xf0000001 }; +enum CustomControlElement { + CE_ExtendedCheckBox = 0xf0000001 +}; + namespace StylingHelper { static inline void setBackgroundColor(bool lightMode) { @@ -218,5 +223,32 @@ namespace StylingHelper { return pal.color(QPalette::Base); } + static inline QPixmap svg2Pixmap(const QString& svgContent, + const QSize& size, + QPainter::CompositionMode mode = QPainter::CompositionMode_SourceOver) + { + QSvgRenderer rr(svgContent); + QImage image(size.width(), size.height(), QImage::Format_ARGB32); + QPainter painter(&image); + painter.setCompositionMode(mode); + image.fill(Qt::transparent); + rr.render(&painter); + return QPixmap::fromImage(image); + } + + static inline QScreen* getCurrentScreen() { + //note: Using cursor pos as screen detector. Flawed. + QPoint cursorPos = QCursor::pos(); + + for (QScreen *screen : QGuiApplication::screens()) { + QRect screenRect = screen->geometry(); + if (screenRect.contains(cursorPos)) { + return screen; + } + } + + return QGuiApplication::primaryScreen(); + } + } diff --git a/src/qt/qtvisuals.h b/src/qt/qtvisuals.h index 0db58e8..8902ed1 100644 --- a/src/qt/qtvisuals.h +++ b/src/qt/qtvisuals.h @@ -20,8 +20,10 @@ public: return baseStyle()->styleHint(hint, option, widget, returnData); } - QRect subControlRect(ComplexControl control, const QStyleOptionComplex *option, - SubControl subControl, const QWidget *widget) const { + QRect subControlRect(ComplexControl control, + const QStyleOptionComplex *option, + SubControl subControl, + const QWidget *widget) const { QRect rect = QCommonStyle::subControlRect(CC_Slider, option, subControl, widget); switch (control) { @@ -186,6 +188,51 @@ public: } + void drawControl(ControlElement element, const QStyleOption *opt, + QPainter *p, const QWidget *widget) const + { + switch(element) { + case CE_ExtendedCheckBox: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_CheckBoxIndicator, btn, widget); + //proxy()->drawPrimitive(PE_IndicatorCheckBox, &subopt, p, widget); + subopt.rect = subElementRect(SE_CheckBoxContents, btn, widget); + + //proxy()->drawControl(CE_CheckBoxLabel, &subopt, p, widget); + int alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter); + + if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget)) + alignment |= Qt::TextHideMnemonic; + QPixmap pix; + QRect textRect = btn->rect; + if (!btn->icon.isNull()) { + pix = btn->icon.pixmap(btn->iconSize, StylingHelper::getCurrentScreen()->devicePixelRatio(), + QIcon::Mode::Normal, btn->state & State_On ? QIcon::On : QIcon::Off); + proxy()->drawItemPixmap(p, btn->rect, alignment, pix); + if (btn->direction == Qt::RightToLeft) + textRect.setRight(textRect.right() - btn->iconSize.width() - 4); + else + textRect.setLeft(textRect.left() + btn->iconSize.width() + 4); + } + if (!btn->text.isEmpty()){ + proxy()->drawItemText(p, textRect, alignment | Qt::TextShowMnemonic, + btn->palette, btn->state & State_Enabled, btn->text, QPalette::WindowText); + } + // + if (btn->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(SE_CheckBoxFocusRect, btn, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + default: + baseStyle()->drawControl(element, opt, p, widget); + break; + } + } + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { QColor outline;