diff --git a/examples/dwidget-examples/collections/mainwindow.cpp b/examples/dwidget-examples/collections/mainwindow.cpp index bfc3ac37d..d972ac4d2 100644 --- a/examples/dwidget-examples/collections/mainwindow.cpp +++ b/examples/dwidget-examples/collections/mainwindow.cpp @@ -22,11 +22,12 @@ #include #include #include +#include -#include -#include - +#include "qsettingbackend.h" #include "dsettingsdialog.h" +#include "dsettingsoption.h" +#include "dsettings.h" #include "dslider.h" #include "dthememanager.h" @@ -43,6 +44,7 @@ #include "cameraform.h" #include "graphicseffecttab.h" #include "simplelistviewtab.h" +#include "dtoast.h" DTK_USE_NAMESPACE DWIDGET_USE_NAMESPACE @@ -114,10 +116,19 @@ MainWindow::MainWindow(QWidget *parent) | Qt::WindowMaximizeButtonHint | Qt::WindowSystemMenuHint); } -} -#include -#include + auto toast = new DToast(this); + toast->setText("Successfully close window"); + toast->setIcon(":/images/light/images/window/close_press.svg"); + QTimer::singleShot(1000, [ = ]() { + toast->pop(); + toast->move((width() - toast->width()) / 2, + (height() - toast->height()) / 2); + }); + QTimer::singleShot(4000, [ = ]() { + toast->pop(); + }); +} void MainWindow::menuItemInvoked(QAction *action) { @@ -196,7 +207,7 @@ void MainWindow::initTabWidget() GraphicsEffectTab *effectTab = new GraphicsEffectTab(this); SimpleListViewTab *simplelistviewTab = new SimpleListViewTab(this); - + m_mainTab->addTab(widgetsTab, "Widgets"); m_mainTab->addTab(effectTab, "GraphicsEffect"); m_mainTab->addTab(comboBoxTab, "ComboBox"); diff --git a/src/widgets/dgraphicsgloweffect.cpp b/src/widgets/dgraphicsgloweffect.cpp index ae02dda39..719b29cde 100644 --- a/src/widgets/dgraphicsgloweffect.cpp +++ b/src/widgets/dgraphicsgloweffect.cpp @@ -30,10 +30,10 @@ DGraphicsGlowEffect::DGraphicsGlowEffect(QObject *parent) : } QT_BEGIN_NAMESPACE - extern Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0 ); +extern Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); QT_END_NAMESPACE -void DGraphicsGlowEffect::draw(QPainter* painter) +void DGraphicsGlowEffect::draw(QPainter *painter) { // if nothing to show outside the item, just draw source if ((blurRadius() + distance()) <= 0) { @@ -46,8 +46,12 @@ void DGraphicsGlowEffect::draw(QPainter* painter) const QPixmap sourcePx = sourcePixmap(Qt::DeviceCoordinates, &offset, mode); // return if no source - if (sourcePx.isNull()) + if (sourcePx.isNull()) { return; + } + + qreal restoreOpacity = painter->opacity(); + painter->setOpacity(m_opacity); // save world transform QTransform restoreTransform = painter->worldTransform(); @@ -87,9 +91,10 @@ void DGraphicsGlowEffect::draw(QPainter* painter) // restore world transform painter->setWorldTransform(restoreTransform); + painter->setOpacity(restoreOpacity); } -QRectF DGraphicsGlowEffect::boundingRectFor(const QRectF& rect) const +QRectF DGraphicsGlowEffect::boundingRectFor(const QRectF &rect) const { qreal delta = blurRadius() + distance(); return rect.united(rect.adjusted(-delta - xOffset(), -delta - yOffset(), delta - xOffset(), delta - yOffset())); diff --git a/src/widgets/dgraphicsgloweffect.h b/src/widgets/dgraphicsgloweffect.h index b336519f5..37b0cf4f0 100644 --- a/src/widgets/dgraphicsgloweffect.h +++ b/src/widgets/dgraphicsgloweffect.h @@ -32,8 +32,8 @@ class LIBDTKWIDGETSHARED_EXPORT DGraphicsGlowEffect : public QGraphicsEffect public: explicit DGraphicsGlowEffect(QObject *parent = 0); - void draw(QPainter* painter); - QRectF boundingRectFor(const QRectF& rect) const; + void draw(QPainter *painter); + QRectF boundingRectFor(const QRectF &rect) const; inline void setOffset(qreal dx, qreal dy) {m_xOffset = dx; m_yOffset = dy;} @@ -49,10 +49,15 @@ class LIBDTKWIDGETSHARED_EXPORT DGraphicsGlowEffect : public QGraphicsEffect inline void setBlurRadius(qreal blurRadius) { m_blurRadius = blurRadius; updateBoundingRect(); } inline qreal blurRadius() const { return m_blurRadius; } - inline void setColor(const QColor& color) { m_color = color; } + inline void setColor(const QColor &color) { m_color = color; } inline QColor color() const { return m_color; } + // TODO: refactor with d-pointer; + inline qreal opacity() const { return m_opacity; } + inline void setOpacity(qreal opacity) { m_opacity = opacity; } + private: + qreal m_opacity = 1.0; qreal m_xOffset; qreal m_yOffset; qreal m_distance; diff --git a/src/widgets/dtoast.cpp b/src/widgets/dtoast.cpp new file mode 100644 index 000000000..06f985c63 --- /dev/null +++ b/src/widgets/dtoast.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2016 ~ 2017 Deepin Technology Co., Ltd. + * + * Author: Iceyer + * + * Maintainer: Iceyer + * + * 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 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "dtoast.h" + +#include + + +#include +#include +#include +#include +#include + +#include "dthememanager.h" +#include "dgraphicsgloweffect.h" +#include "dhidpihelper.h" + +DWIDGET_BEGIN_NAMESPACE + +class DToastPrivate: public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + DToastPrivate(DToast *qq); + + QBrush background = Qt::white; + int radius = 4; + QColor borderColor = QColor(0, 0, 0, 255 / 10); + QIcon icon; + QLabel *iconLabel = Q_NULLPTR; + QLabel *textLabel = Q_NULLPTR; + + QPropertyAnimation *animation = Q_NULLPTR; + DGraphicsGlowEffect *effect = Q_NULLPTR; + + void initUI(); +private: + D_DECLARE_PUBLIC(DToast) +}; + +DToast::DToast(QWidget *parent) : + QFrame(parent), DObject(*new DToastPrivate(this)) +{ + D_D(DToast); + D_THEME_INIT_WIDGET(DToast); + d->initUI(); +} + +DToast::~DToast() +{ + +} + +QString DToast::text() const +{ + D_DC(DToast); + return d->textLabel->text(); +} + +QIcon DToast::icon() const +{ + D_DC(DToast); + return d->icon; +} + +qreal DToast::opacity() const +{ + D_DC(DToast); + return d->effect->opacity(); +} + +QColor Dtk::Widget::DToast::borderColor() const +{ + D_DC(DToast); + return d->borderColor; +} + +QBrush DToast::background() const +{ + D_DC(DToast); + return d->background; +} + +int DToast::radius() const +{ + D_DC(DToast); + return d->radius; + +} + +void DToast::setText(QString text) +{ + D_D(DToast); + d->textLabel->setText(text); +} + +void DToast::setIcon(QString iconfile) +{ + D_D(DToast); + d->icon = QIcon(iconfile); + d->iconLabel->setPixmap(DHiDPIHelper::loadNxPixmap(iconfile)); +} + +void DToast::setIcon(QIcon icon, QSize defaultSize) +{ + D_D(DToast); + d->icon = icon; + d->iconLabel->setPixmap(d->icon.pixmap(icon.actualSize(defaultSize))); +} + +void DToast::paintEvent(QPaintEvent *) +{ + D_D(DToast); + + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing); + + // draw border outer + auto outer = true; + auto radius = d->radius; + auto penWidthf = 1.0; + auto background = d->background; + auto borderColor = d->borderColor; + auto margin = 2.0; + auto shadowMargins = QMarginsF(margin, margin, margin, margin); + + // draw background + auto backgroundRect = QRectF(rect()).marginsRemoved(shadowMargins); + QPainterPath backgroundPath; + backgroundPath.addRoundedRect(backgroundRect, radius, radius); + painter.fillPath(backgroundPath, background); + + // draw border + QPainterPath borderPath; + QRectF borderRect = QRectF(rect()); + auto borderRadius = d->radius;//radius; + QMarginsF borderMargin(penWidthf / 2, penWidthf / 2, penWidthf / 2, penWidthf / 2); + if (outer) { + borderRadius += penWidthf / 2; + borderRect = borderRect.marginsAdded(borderMargin).marginsRemoved(shadowMargins); + } else { + borderRadius -= penWidthf / 2; + borderRect = borderRect.marginsRemoved(borderMargin).marginsRemoved(shadowMargins); + } + borderPath.addRoundedRect(borderRect, borderRadius, borderRadius); + QPen borderPen(borderColor); + borderPen.setWidthF(penWidthf); + painter.strokePath(borderPath, borderPen); +} + +void DToast::setBorderColor(QColor borderColor) +{ + D_D(DToast); + d->borderColor = borderColor; +} + +void DToast::setOpacity(qreal opacity) +{ + D_D(DToast); + d->effect->setOpacity(opacity); + update(); +} + +void DToast::setBackground(QBrush background) +{ + D_D(DToast); + d->background = background; +} + +void DToast::setRadius(int radius) +{ + D_D(DToast); + d->radius = radius; +} + +void DToast::pop() +{ + Q_D(DToast); + + adjustSize(); + show(); + + if (d->animation) { + return; + } + + d->animation = new QPropertyAnimation(this, "opacity"); + d->animation->setDuration(2000); + d->animation->setStartValue(0); + d->animation->setKeyValueAt(0.4, 1.0); + d->animation->setKeyValueAt(0.8, 1.0); + d->animation->setEndValue(0); + d->animation->start(); + d->animation->connect(d->animation, &QPropertyAnimation::finished, + this, [ = ]() { + hide(); + d->animation->deleteLater(); + d->animation = Q_NULLPTR; + }); +} + +void DToast::pack() +{ + Q_D(DToast); + hide(); + if (d->animation) { + d->animation->stop(); + d->animation->deleteLater(); + d->animation = Q_NULLPTR; + } +} + +DToastPrivate::DToastPrivate(DToast *qq) + : DObjectPrivate(qq) +{ + +} + +void DToastPrivate::initUI() +{ + D_Q(DToast); + q->setWindowFlags(q->windowFlags() | Qt::WindowStaysOnTopHint); + + auto layout = new QHBoxLayout(q); + layout->setContentsMargins(10, 10, 10, 10); + layout->setSpacing(12); + + iconLabel = new QLabel; + textLabel = new QLabel; + + layout->addWidget(iconLabel); + layout->addWidget(textLabel); + + effect = new DGraphicsGlowEffect(q); + effect->setBlurRadius(20.0); + effect->setColor(QColor(0, 0, 0, 255 / 10)); + effect->setOffset(0, 0); + q->setGraphicsEffect(effect); + q->hide(); +} + + +DWIDGET_END_NAMESPACE diff --git a/src/widgets/dtoast.h b/src/widgets/dtoast.h new file mode 100644 index 000000000..688fb1c72 --- /dev/null +++ b/src/widgets/dtoast.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 ~ 2017 Deepin Technology Co., Ltd. + * + * Author: Iceyer + * + * Maintainer: Iceyer + * + * 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 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#pragma once + +#include +#include +#include + +#include "dtkwidget_global.h" +#include + +DWIDGET_BEGIN_NAMESPACE + +class DToastPrivate; +class DToast : public QFrame, public DTK_CORE_NAMESPACE::DObject +{ + Q_OBJECT + + Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) + Q_PROPERTY(int radius READ radius WRITE setRadius) + Q_PROPERTY(QBrush background READ background WRITE setBackground) + Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor) +public: + explicit DToast(QWidget *parent = 0); + ~DToast(); + + QString text() const; + QIcon icon() const; + +public Q_SLOTS: + void pop(); + void pack(); + + void setText(QString text); + void setIcon(QString icon); + void setIcon(QIcon icon, QSize defaultSize = QSize(20, 20)); + +protected: + void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; + +private: + qreal opacity() const; + QColor borderColor() const; + QBrush background() const; + int radius() const; + + void setBorderColor(QColor borderColor); + void setOpacity(qreal); + void setBackground(QBrush background); + void setRadius(int radius); + + D_DECLARE_PRIVATE(DToast) +}; + + +DWIDGET_END_NAMESPACE diff --git a/src/widgets/themes/dark/DToast.theme b/src/widgets/themes/dark/DToast.theme new file mode 100644 index 000000000..e09a7230d --- /dev/null +++ b/src/widgets/themes/dark/DToast.theme @@ -0,0 +1,5 @@ +Dtk--Widget--DToast { + qproperty-background: rgba(49,49,49, 100%); + qproperty-borderColor: rgba(0,0,0,10%); + qproperty-radius: 4.0; +} diff --git a/src/widgets/themes/dui_theme_dark.qrc b/src/widgets/themes/dui_theme_dark.qrc index 4f74a55dc..58e1f90a5 100644 --- a/src/widgets/themes/dui_theme_dark.qrc +++ b/src/widgets/themes/dui_theme_dark.qrc @@ -63,6 +63,7 @@ dark/images/window/unmaximize_normal.svg dark/images/window/unmaximize_press.svg dark/dialogs/DSettingsDialog.theme + dark/DToast.theme dark/images/add_hover.png diff --git a/src/widgets/themes/dui_theme_light.qrc b/src/widgets/themes/dui_theme_light.qrc index a46da1d7a..203517d7d 100644 --- a/src/widgets/themes/dui_theme_light.qrc +++ b/src/widgets/themes/dui_theme_light.qrc @@ -37,6 +37,7 @@ light/DTitlebar.theme light/DBoxWidget.theme light/DFileChooserEdit.theme + light/DToast.theme light/images/arrow_down_hover.png diff --git a/src/widgets/themes/light/DToast.theme b/src/widgets/themes/light/DToast.theme new file mode 100644 index 000000000..c0d60e749 --- /dev/null +++ b/src/widgets/themes/light/DToast.theme @@ -0,0 +1,5 @@ +Dtk--Widget--DToast { + qproperty-background: rgba(255,255,255,100%); + qproperty-borderColor: rgba(0,0,0,10%); + qproperty-radius: 4.0px; +} diff --git a/src/widgets/widgets.pri b/src/widgets/widgets.pri index 5a7dc7151..05886fe30 100644 --- a/src/widgets/widgets.pri +++ b/src/widgets/widgets.pri @@ -110,7 +110,8 @@ HEADERS += $$PWD/dslider.h\ $$PWD/dcrumbedit.h \ $$PWD/dtabbar.h \ $$PWD/dsuggestbutton.h \ - $$PWD/dstyleoption.h + $$PWD/dstyleoption.h \ + $$PWD/dtoast.h SOURCES += $$PWD/dslider.cpp \ $$PWD/dthememanager.cpp \ @@ -189,7 +190,8 @@ SOURCES += $$PWD/dslider.cpp \ $$PWD/dcrumbedit.cpp \ $$PWD/dtabbar.cpp \ $$PWD/dsuggestbutton.cpp \ - $$PWD/dstyleoption.cpp + $$PWD/dstyleoption.cpp \ + $$PWD/dtoast.cpp RESOURCES += \ $$PWD/themes/dui_theme_dark.qrc \