diff --git a/frame/item/quicksettingitem.cpp b/frame/item/quicksettingitem.cpp index 7cf401bb5..55e599896 100644 --- a/frame/item/quicksettingitem.cpp +++ b/frame/item/quicksettingitem.cpp @@ -20,6 +20,7 @@ */ #include "quicksettingitem.h" #include "pluginsiteminterface.h" +#include "imageutil.h" #include #include @@ -113,15 +114,8 @@ void QuickSettingItem::paintEvent(QPaintEvent *e) int marginXSpace = xMarginSpace(); int marginYSpace = yMarginSpace(); QRect iconBg(marginXSpace, marginYSpace, BGSIZE, BGSIZE); - painter.save(); - painter.setPen(Qt::NoPen); - painter.setBrush(shadowColor()); - painter.drawEllipse(iconBg); - painter.restore(); - QRect rctIcon(iconBg.x() + (iconBg.width() - ICONWIDTH) / 2, - iconBg.y() + (iconBg.height() - ICONHEIGHT) / 2, - ICONWIDTH, ICONHEIGHT); - painter.drawPixmap(rctIcon, pm); + QPixmap bgPixmap = ImageUtil::getShadowPixmap(pm, shadowColor(), QSize(BGSIZE, BGSIZE)); + painter.drawPixmap(iconBg, bgPixmap); // 绘制文字 painter.setPen(QColor(0, 0, 0)); @@ -148,10 +142,10 @@ void QuickSettingItem::paintEvent(QPaintEvent *e) painter.setPen(pen); int iconLeft = rect().width() - marginXSpace - expandSize.width(); int iconRight = rect().width() - marginXSpace; - painter.drawLine(QPoint(iconLeft, (rctIcon.y() + (rctIcon.height() - expandSize.height()) / 2)), - QPoint(iconRight, (rctIcon.y() + rctIcon.height() / 2))); - painter.drawLine(QPoint(iconRight, (rctIcon.y() + rctIcon.height() / 2)), - QPoint(iconLeft, (rctIcon.y() + (rctIcon.height() + expandSize.height()) / 2))); + painter.drawLine(QPoint(iconLeft, (iconBg.y() + (iconBg.height() - expandSize.height()) / 2)), + QPoint(iconRight, (iconBg.y() + iconBg.height() / 2))); + painter.drawLine(QPoint(iconRight, (iconBg.y() + iconBg.height() / 2)), + QPoint(iconLeft, (iconBg.y() + (iconBg.height() + expandSize.height()) / 2))); } else { // 绘制图标 QRect rctIcon = iconRect(); diff --git a/frame/util/imageutil.cpp b/frame/util/imageutil.cpp index 3cb66e2a5..8558d5480 100644 --- a/frame/util/imageutil.cpp +++ b/frame/util/imageutil.cpp @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include @@ -81,3 +84,36 @@ QCursor* ImageUtil::loadQCursorFromX11Cursor(const char* theme, const char* curs XcursorImagesDestroy(images); return cursor; } + +const QPixmap ImageUtil::getShadowPixmap(const QPixmap &pixmap, const QColor &shadowColor, const QSize &backSize) +{ + // 新建一个bitmap作为遮罩,尺寸为外部指定(backSize) + QBitmap bitmap(backSize); + QPainter painter(&bitmap); + painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + painter.setPen(Qt::NoPen); + // 往bitmap上绘制圆形区域 + QRect rectBackground(0, 0, backSize.width(), backSize.height()); + painter.fillRect(rectBackground, Qt::white); + painter.setBrush(Qt::black); + painter.drawEllipse(0, 0, backSize.width(), backSize.height()); + + // 新建QPixmap,将上述新建的Bitmap作为它的遮罩 + QPixmap newPixmap(backSize); + newPixmap.setMask(bitmap); + QPainter pixPainter(&newPixmap); + pixPainter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + const QSize iconSize = pixmap.size(); + int startX = (backSize.width() - iconSize.width()) / 2; + int startY = (backSize.height() - iconSize.height()) / 2; + // 将传入参数的背景尺寸(backSize)作为背景,通过画笔路径在上面绘制圆形区域 + QRect rectPixmap(startX, startY, iconSize.width(), iconSize.height()); + QPainterPath path; + path.addEllipse(rectBackground); + pixPainter.fillPath(path, shadowColor); + // 将图像绘制到新建的QPixmap的背景区域,并返回新的QPixmap + pixPainter.drawPixmap(rectPixmap, pixmap); + pixPainter.setPen(shadowColor); + pixPainter.drawEllipse(rectBackground); + return newPixmap; +} diff --git a/frame/util/imageutil.h b/frame/util/imageutil.h index 0ed1b3c37..0205e135c 100644 --- a/frame/util/imageutil.h +++ b/frame/util/imageutil.h @@ -35,6 +35,7 @@ public: static const QPixmap loadSvg(const QString &iconName, const QString &localPath, const int size, const qreal ratio); static const QPixmap loadSvg(const QString &iconName, const QSize size, const qreal ratio = qApp->devicePixelRatio()); static QCursor* loadQCursorFromX11Cursor(const char* theme, const char* cursorName, int cursorSize); + static const QPixmap getShadowPixmap(const QPixmap &pixmap, const QColor &shadowColor, const QSize &backSize); }; #endif // IMAGEUTIL_H diff --git a/frame/window/components/brightnesswidget.cpp b/frame/window/components/brightnesswidget.cpp index 8275657a2..8b67a2c46 100644 --- a/frame/window/components/brightnesswidget.cpp +++ b/frame/window/components/brightnesswidget.cpp @@ -22,10 +22,14 @@ #include "customslider.h" #include "brightnessmodel.h" #include "brightnessmonitorwidget.h" +#include "imageutil.h" #include #include +#define BACKSIZE 36 +#define IMAGESIZE 24 + BrightnessWidget::BrightnessWidget(QWidget *parent) : DBlurEffectWidget(parent) , m_slider(new CustomSlider(CustomSlider::SliderType::Normal, this)) @@ -63,11 +67,16 @@ void BrightnessWidget::initUi() layout->addWidget(m_slider); m_slider->setPageStep(1); - m_slider->setIconSize(QSize(24, 24)); + m_slider->setIconSize(QSize(BACKSIZE, BACKSIZE)); - m_slider->setLeftIcon(QIcon(":/icons/resources/brightness.svg")); - m_slider->setRightIcon(QIcon::fromTheme(":/icons/resources/ICON_Device_Laptop.svg")); - m_slider->setTickPosition(QSlider::TicksBelow); + QIcon leftIcon(QPixmap(":/icons/resources/brightness.svg").scaled(IMAGESIZE, IMAGESIZE)); + m_slider->setLeftIcon(leftIcon); + QPixmap rightPixmap = ImageUtil::getShadowPixmap(QPixmap(QString(":/icons/resources/ICON_Device_Laptop.svg")).scaled(24, 24), Qt::lightGray, QSize(36, 36)); + m_slider->setRightIcon(rightPixmap); + + SliderProxy *style = new SliderProxy; + style->setParent(m_slider->qtSlider()); + m_slider->qtSlider()->setStyle(style); } void BrightnessWidget::initConenction() diff --git a/frame/window/components/customslider.cpp b/frame/window/components/customslider.cpp index 80c1b0a2f..d53e3a1ce 100644 --- a/frame/window/components/customslider.cpp +++ b/frame/window/components/customslider.cpp @@ -20,9 +20,11 @@ */ #include "customslider.h" +#include #include #include +#include #include #include @@ -34,7 +36,6 @@ DWIDGET_USE_NAMESPACE CustomSlider::CustomSlider(CustomSlider::SliderType type, QWidget *parent) : DSlider(Qt::Horizontal, parent) - , m_separateValue(0) { setType(type); DSlider::slider()->setTracking(false); @@ -100,79 +101,11 @@ void CustomSlider::setOrientation(Qt::Orientation orientation) Q_UNUSED(orientation) } -void CustomSlider::setSeparateValue(int value) -{ - m_separateValue = value; -} - void CustomSlider::wheelEvent(QWheelEvent *e) { e->ignore(); } -void CustomSlider::paintEvent(QPaintEvent *e) -{ - Q_UNUSED(e) - - if (m_separateValue <= 0) - return; - - QPainter pa(this); - auto dpa = DApplicationHelper::instance()->palette(this); - QPen penLine = QPen(dpa.color(DPalette::ObviousBackground), 2); - - //超过间隔线后需要更换间隔线颜色为活动色 - if (qtSlider()->value() >= m_separateValue ) { - QPalette pe = this->palette(); - QColor brushColor(pe.color(QPalette::Highlight)); - penLine.setColor(brushColor); - } - - int margin = DStyle::pixelMetric(style(), DStyle::PM_FocusBorderSpacing) + DStyle::pixelMetric(style(), DStyle::PM_FocusBorderSpacing); - int offsetSize = style()->pixelMetric(QStyle::PM_SliderLength, nullptr, this) / 2; - int width = this->qtSlider()->width(); - - width -= 2 * offsetSize + margin * 2; - Qt::Orientation orient = this->orientation(); - QSlider::TickPosition tick = m_tickPosition; - QSlider* slider = DSlider::slider(); - qreal percentage = (m_separateValue - slider->minimum()) * 1.0 / (slider->maximum() - slider->minimum()); - - pa.setPen(penLine); - int leftIconwidth = 0; - //获取左边声音图标宽度 - QGridLayout *gridLayout = dynamic_cast(this->layout()); - if (!gridLayout) - return; - QLayoutItem* item = gridLayout->itemAtPosition(1, 0); - if (item) { - leftIconwidth = item->geometry().size().width(); - } - - qreal startX = offsetSize + margin + leftIconwidth + this->contentsMargins().left(); - qreal startY = slider->y() + 10; - //分别绘制滑动条上方矩形和下方矩形,避免与滑动条重叠, - //画笔宽为2个像素,设置绘制时矩形高设为3,可达到高度为5的效果 - if (orient == Qt::Horizontal) { - qreal sliderX = percentage * width; - if (slider->value() >= m_separateValue) { - int num = (sliderX + 2) / 3; - qAbs(3 * num + 1 - sliderX) - qAbs(sliderX - (3 * num - 2)) >= 0 ? num : num++; - sliderX = 3 * num - 2; - } else { - //将分割线左、右的滚动条进行比较获取距离最相近的位置,绘制分割线 - sliderX = (slider->maximum() - m_separateValue) * 1.0 * width / slider->maximum(); - int num = (sliderX + 1) / 3; - qAbs(3 * num - sliderX) - qAbs(sliderX - 3 * (num - 1)) >= 0 ? num : num++; - sliderX = width - (3 * num - 1); - } - if (tick == QSlider::TicksAbove || tick == QSlider::TicksBelow || tick == QSlider::NoTicks) { - pa.drawLine(QPointF(startX + sliderX, startY), QPointF(startX + sliderX, startY + 3)); - pa.drawLine(QPointF(startX + sliderX, startY + 9), QPointF(startX + sliderX, startY + 12)); - } - } -} - SliderContainer::SliderContainer(CustomSlider::SliderType type, QWidget *parent) : QWidget (parent) , m_slider(new CustomSlider(type, this)) @@ -212,3 +145,48 @@ CustomSlider *SliderContainer::slider() { return m_slider; } + +SliderProxy::SliderProxy(QStyle *style) + : QProxyStyle(style) +{ +} + +SliderProxy::~SliderProxy() +{ +} + +void SliderProxy::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + if (control != ComplexControl::CC_Slider) + return; + + // 绘制之前先保存之前的画笔 + painter->save(); + painter->setRenderHint(QPainter::RenderHint::Antialiasing); + // 获取滑动条和滑块的区域 + const QStyleOptionSlider *sliderOption = static_cast(option); + QRect rectGroove = subControlRect(CC_Slider, sliderOption, SC_SliderGroove, widget); + QRect rectHandle = subControlRect(CC_Slider, sliderOption, SC_SliderHandle, widget); + // 深色背景下,滑块和滑动条白色,浅色背景下,滑块和滑动条黑色 + QBrush brush(DGuiApplicationHelper::DarkType == DGuiApplicationHelper::instance()->themeType() ? Qt::white : Qt::black); + // 此处中绘制圆形滑动条,需要绘制圆角,圆角大小为其高度的一半 + QPainterPath pathGroove; + int radius = rectGroove.height() / 2; + pathGroove.addRoundedRect(rectGroove, radius, radius); + painter->fillPath(pathGroove, brush); + + // 绘制滑块,因为滑块是正圆形,而它本来的区域是一个长方形区域,因此,需要计算当前 + // 区域的正中心区域,将其作为一个正方形区域来绘制圆形滑块 + int handleSize = qMin(rectHandle.width(), rectHandle.height()); + int x = rectHandle.x() + (rectHandle.width() - handleSize) / 2; + int y = rectHandle.y() + (rectHandle.height() - handleSize) / 2; + rectHandle.setX(x); + rectHandle.setY(y); + rectHandle.setWidth(handleSize); + rectHandle.setHeight(handleSize); + + QPainterPath pathHandle; + pathHandle.addEllipse(rectHandle); + painter->fillPath(pathHandle, brush); + painter->restore(); +} diff --git a/frame/window/components/customslider.h b/frame/window/components/customslider.h index 5c8a5ad8f..d4daba0f2 100644 --- a/frame/window/components/customslider.h +++ b/frame/window/components/customslider.h @@ -23,6 +23,7 @@ #define CUSTOMCTRL_H #include +#include #include class QLabel; @@ -52,15 +53,12 @@ public: void setSliderPosition(int Position); void setAnnotations(const QStringList &annotations); void setOrientation(Qt::Orientation orientation); - //当value大于0时,在slider中插入一条分隔线 - void setSeparateValue(int value = 0); protected: void wheelEvent(QWheelEvent *e); - void paintEvent(QPaintEvent *e); + private: QSlider::TickPosition m_tickPosition = QSlider::TicksBelow; - int m_separateValue; }; class SliderContainer : public QWidget @@ -79,4 +77,16 @@ private: QLabel *m_titleLabel; }; +class SliderProxy : public QProxyStyle +{ + Q_OBJECT + +public: + explicit SliderProxy(QStyle *style = nullptr); + ~SliderProxy() override; + +protected: + void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const override; +}; + #endif // VOLUMESLIDER_H diff --git a/frame/window/components/mediawidget.cpp b/frame/window/components/mediawidget.cpp index ae2fe112b..934845166 100644 --- a/frame/window/components/mediawidget.cpp +++ b/frame/window/components/mediawidget.cpp @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include "customslider.h" #include "mediawidget.h" #include @@ -151,6 +152,7 @@ void MediaWidget::onUpdateMediaInfo() * @brief 音乐播放的相关按钮 * @param parent */ + MusicButton::MusicButton(QWidget *parent) : QWidget(parent) { @@ -161,14 +163,28 @@ MusicButton::~MusicButton() { } +int MusicButton::getIconHeight() const +{ + switch (m_buttonType) { + case ButtonType::Pause: + return 21; + case ButtonType::Next: + case ButtonType::Playing: + return 18; + } + + return 18; +} + void MusicButton::paintEvent(QPaintEvent *event) { -#define ICONHEIGHT 20 Q_UNUSED(event); + int ctrlHeight = getIconHeight(); + int width = this->width(); int height = this->height(); int startX = 2; - int startY = (height - ICONHEIGHT) / 2; + int startY = (height - ctrlHeight) / 2; QColor color(0, 0, 0); QPainter painter(this); painter.save(); @@ -176,17 +192,17 @@ void MusicButton::paintEvent(QPaintEvent *event) painter.setPen(color); painter.setBrush(color); if (m_buttonType == ButtonType::Pause) { - painter.drawRect(QRect(startX, startY, 6, ICONHEIGHT)); - painter.drawRect(QRect(width - 6 - 2, startY, 6, ICONHEIGHT)); + painter.drawRect(QRect(startX, startY, 6, ctrlHeight)); + painter.drawRect(QRect(width - 6 - 2, startY, 6, ctrlHeight)); } else { QPainterPath trianglePath; trianglePath.moveTo(startX, startY); trianglePath.lineTo(width - 6, height / 2); - trianglePath.lineTo(startX, startY + ICONHEIGHT); + trianglePath.lineTo(startX, startY + ctrlHeight); trianglePath.lineTo(startX, startY); painter.drawPath(trianglePath); if (m_buttonType == ButtonType::Next) - painter.drawRect(width - 6, startY, 2, ICONHEIGHT); + painter.drawRect(width - 6, startY, 2, ctrlHeight); } painter.restore(); } diff --git a/frame/window/components/mediawidget.h b/frame/window/components/mediawidget.h index d5d870287..4d9b59146 100644 --- a/frame/window/components/mediawidget.h +++ b/frame/window/components/mediawidget.h @@ -87,6 +87,9 @@ protected: void paintEvent(QPaintEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; +private: + int getIconHeight() const; + private: ButtonType m_buttonType; }; diff --git a/frame/window/components/volumewidget.cpp b/frame/window/components/volumewidget.cpp index c36ebe45c..7ad92b581 100644 --- a/frame/window/components/volumewidget.cpp +++ b/frame/window/components/volumewidget.cpp @@ -22,6 +22,7 @@ #include "customslider.h" #include "imageutil.h" #include "volumemodel.h" +#include "imageutil.h" #include @@ -41,6 +42,7 @@ DGUI_USE_NAMESPACE #define ICON_SIZE 24 +#define BACKSIZE 36 VolumeWidget::VolumeWidget(QWidget *parent) : DBlurEffectWidget(parent) @@ -65,9 +67,16 @@ void VolumeWidget::initUi() mainLayout->setContentsMargins(20, 0, 20, 0); mainLayout->addWidget(m_volumnCtrl); - m_volumnCtrl->setIconSize(QSize(36, 36)); - m_volumnCtrl->setLeftIcon(QIcon(leftIcon())); - m_volumnCtrl->setRightIcon(QIcon(rightIcon())); + const QString rightIconFile = rightIcon(); + QIcon rIcon = ImageUtil::getShadowPixmap(QPixmap(rightIconFile), Qt::lightGray, QSize(BACKSIZE, BACKSIZE)); + + m_volumnCtrl->setIconSize(QSize(BACKSIZE, BACKSIZE)); + m_volumnCtrl->setLeftIcon(QIcon(QPixmap(leftIcon()))); + m_volumnCtrl->setRightIcon(rIcon); + + SliderProxy *proxy = new SliderProxy; + proxy->setParent(m_volumnCtrl->qtSlider()); + m_volumnCtrl->qtSlider()->setStyle(proxy); bool existActiveOutputDevice = m_volumeController->existActiveOutputDevice(); setEnabled(existActiveOutputDevice);