Creating Style Plugin in QT5
-
I try to create my own style plugin. However i cant get it to work.
Here is the code for it:
QT += widgets CONFIG += c++17 CONFIG += plugin release TEMPLATE = lib TARGET = $$qtLibraryTarget($$TARGET) target.path = $$[QT_INSTALL_PLUGINS]/styles INSTALLS += target #target.path = /home/sandro/Qt/Tools/QtCreator/bin/plugins/styles #INSTALLS += target HEADERS = ../../bronze/bronze/bronzestyle.h \ bronzestyleplugin.h \ bronzestyleplugin.h SOURCES = ../../bronze/bronze/bronzestyle.cpp \ bronzestyleplugin.cpp \ bronzestyleplugin.cpp RESOURCES = ../../bronze/bronze/bronze.qrc OTHER_FILES += bronzestyleplugin.json
#ifndef BRONZESTYLEPLUGIN_H #define BRONZESTYLEPLUGIN_H #include <QStylePlugin> class BronzeStylePlugin : public QStylePlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "bronzestyleplugin.json") public: QStyle *create(const QString &key) override; }; #endif // BRONZESTYLEPLUGIN_H
#include "bronzestyleplugin.h" #include "../../bronze/bronze/bronzestyle.h" QStyle *BronzeStylePlugin::create(const QString &key) { if (key.toLower() == "bronze") { return new BronzeStyle; } return nullptr; }
#ifndef BRONZESTYLE_H #define BRONZESTYLE_H #include <QProxyStyle> class BronzeStyle : public QProxyStyle { Q_OBJECT public: void polish(QPalette &palette) override; void polish(QWidget *widget) override; void unpolish(QWidget *widget) override; int styleHint(StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const override; int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget = nullptr) const override; void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w = nullptr) const override; void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget = nullptr) const override; QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget = nullptr) const override; public: QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget = nullptr) const override; private: void drawBronzeFrame(const QStyleOption *option, QPainter *painter) const; void drawBronzeBevel(const QStyleOption *option, QPainter *painter) const; void drawBronzeCheckBoxIndicator(const QStyleOption *option, QPainter *painter) const; void drawBronzeSpinBoxButton(SubControl which, const QStyleOptionComplex *option, QPainter *painter) const; }; #endif // BRONZESTYLE_H
#include "bronzestyle.h" #include <QAbstractButton> #include <QAbstractSpinBox> #include <QDialogButtonBox> #include <QPainter> #include <QStyleOptionComplex> void BronzeStyle::polish(QPalette &palette) { QPixmap backgroundImage(":/images/background.png"); QColor bronze(207, 155, 95); QColor veryLightBlue(239, 239, 247); QColor lightBlue(223, 223, 239); QColor darkBlue(95, 95, 191); palette = QPalette(bronze); palette.setBrush(QPalette::Window, backgroundImage); palette.setBrush(QPalette::BrightText, Qt::white); palette.setBrush(QPalette::Base, veryLightBlue); palette.setBrush(QPalette::AlternateBase, lightBlue); palette.setBrush(QPalette::Highlight, darkBlue); palette.setBrush(QPalette::Disabled, QPalette::Highlight, Qt::darkGray); } void BronzeStyle::polish(QWidget *widget) { if (qobject_cast<QAbstractButton *>(widget) || qobject_cast<QAbstractSpinBox *>(widget)) { widget->setAttribute(Qt::WA_Hover, true); } } void BronzeStyle::unpolish(QWidget *widget) { if (qobject_cast<QAbstractButton *>(widget) || qobject_cast<QAbstractSpinBox *>(widget)) { widget->setAttribute(Qt::WA_Hover, false); } } int BronzeStyle::styleHint(QStyle::StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const { switch (stylehint) { case SH_DialogButtonLayout: return int(QDialogButtonBox::MacLayout); case SH_EtchDisabledText: return int(true); case SH_DialogButtonBox_ButtonsHaveIcons: return int(true); case SH_UnderlineShortcut: return int(false); default: return QProxyStyle::styleHint(stylehint, opt, widget, returnData); } } int BronzeStyle::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { switch (metric) { case PM_ButtonDefaultIndicator: return 0; case PM_IndicatorWidth: [[fallthrough]]; case PM_IndicatorHeight: return 16; case PM_CheckBoxLabelSpacing: return 8; case PM_DefaultFrameWidth: return 2; default: return QProxyStyle::pixelMetric(metric, option, widget); } } void BronzeStyle::drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const { switch (pe) { case PE_IndicatorCheckBox: drawBronzeCheckBoxIndicator(opt, p); break; case PE_PanelButtonCommand: drawBronzeBevel(opt, p); break; case PE_Frame: drawBronzeFrame(opt, p); break; case PE_FrameDefaultButton: break; default: QProxyStyle::drawPrimitive(pe, opt, p, w); } } void BronzeStyle::drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const { if (cc == CC_SpinBox) { drawBronzeSpinBoxButton(SC_SpinBoxDown, opt, p); drawBronzeSpinBoxButton(SC_SpinBoxUp, opt, p); QRect rect = subControlRect(CC_SpinBox, opt, SC_SpinBoxEditField, widget) .adjusted(-1, 0, +1, 0); p->setPen(QPen(opt->palette.mid(), 1.0)); p->drawLine(rect.topLeft(), rect.bottomLeft()); p->drawLine(rect.topRight(), rect.bottomRight()); } else { return QProxyStyle::drawComplexControl(cc, opt, p, widget); } } QRect BronzeStyle::subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget) const { if (cc == CC_SpinBox) { int frameWidth = pixelMetric(PM_DefaultFrameWidth, opt, widget); int buttonWidth = 16; switch (sc) { case SC_SpinBoxFrame: return opt->rect; case SC_SpinBoxEditField: return opt->rect.adjusted(+buttonWidth, +frameWidth, -buttonWidth, -frameWidth); case SC_SpinBoxDown: return visualRect(opt->direction, opt->rect, QRect(opt->rect.x(), opt->rect.y(), buttonWidth, opt->rect.height())); case SC_SpinBoxUp: return visualRect(opt->direction, opt->rect, QRect(opt->rect.right() - buttonWidth, opt->rect.y(), buttonWidth, opt->rect.height())); default: return QRect(); } } else { return QProxyStyle::subControlRect(cc, opt, sc, widget); } } QIcon BronzeStyle::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { QImage image = QProxyStyle::standardPixmap(standardIcon, option, widget) .toImage(); if (image.isNull()) return QIcon(); QPalette palette; if (option) { palette = option->palette; } else if (widget) { palette = widget->palette(); } QPainter painter(&image); painter.setOpacity(0.25); painter.setCompositionMode(QPainter::CompositionMode_SourceAtop); painter.fillRect(image.rect(), palette.highlight()); painter.end(); return QIcon(QPixmap::fromImage(image)); } void BronzeStyle::drawBronzeFrame(const QStyleOption *option, QPainter *painter) const { painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(QPen(option->palette.windowText(), 1.0)); painter->drawRect(option->rect.adjusted(+1, +1, -1, -1)); painter->restore(); } void BronzeStyle::drawBronzeBevel(const QStyleOption *option, QPainter *painter) const { QColor buttonColor = option->palette.button().color(); int coeff = (option->state & State_MouseOver) ? 115 : 105; QLinearGradient gradient(0, 0, 0, option->rect.height()); gradient.setColorAt(0.0, option->palette.light().color()); gradient.setColorAt(0.2, buttonColor.lighter(coeff)); gradient.setColorAt(0.8, buttonColor.darker(coeff)); gradient.setColorAt(1.0, option->palette.dark().color()); double penWidth = 1.0; if (const QStyleOptionButton *buttonOpt = qstyleoption_cast<const QStyleOptionButton *>(option)) { if (buttonOpt->features & QStyleOptionButton::DefaultButton) { penWidth = 2.0; } } QRect roundRect = option->rect.adjusted(+1, +1, -1, -1); if (!roundRect.isValid()) return; int diameter = 12; int cx = 100 * diameter / roundRect.width(); int cy = 100 * diameter / roundRect.height(); painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(gradient); painter->drawRoundedRect(roundRect, cx, cy); if (option->state & (State_On | State_Sunken)) { QColor slightlyOpaqueBlack(0, 0, 0, 63); painter->setBrush(slightlyOpaqueBlack); painter->drawRoundedRect(roundRect, cx, cy); } painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(QPen(option->palette.windowText(), penWidth)); painter->setBrush(Qt::NoBrush); painter->drawRoundedRect(roundRect, cx, cy); painter->restore(); } void BronzeStyle::drawBronzeCheckBoxIndicator(const QStyleOption *option, QPainter *painter) const { painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); if (option->state & State_MouseOver) { painter->setBrush(option->palette.alternateBase()); } else { painter->setBrush(option->palette.base()); } painter->drawRoundRect(option->rect.adjusted(+1, +1, -1, -1)); if (option->state & (State_On | State_NoChange)) { QPixmap pixmap; if (!(option->state & State_Enabled)) { pixmap.load(":/images/checkmark-disabled.png"); } else if (option->state & State_NoChange) { pixmap.load(":/images/checkmark-partial.png"); } else { pixmap.load(":/images/checkmark.png"); } QRect pixmapRect = pixmap.rect() .translated(option->rect.topLeft()) .translated(+2, -6); QRect painterRect = visualRect(option->direction, option->rect, pixmapRect); if (option->direction == Qt::RightToLeft) { painter->scale(-1.0, +1.0); painterRect.moveLeft(-painterRect.right() - 1); } painter->drawPixmap(painterRect, pixmap); } painter->restore(); } void BronzeStyle::drawBronzeSpinBoxButton(QStyle::SubControl which, const QStyleOptionComplex *option, QPainter *painter) const { PrimitiveElement arrow = PE_IndicatorArrowLeft; QRect buttonRect = option->rect; if ((which == SC_SpinBoxUp) != (option->direction == Qt::RightToLeft)) { arrow = PE_IndicatorArrowRight; buttonRect.translate(buttonRect.width() / 2, 0); } buttonRect.setWidth((buttonRect.width() + 1) / 2); QStyleOption buttonOpt(*option); painter->save(); painter->setClipRect(buttonRect, Qt::IntersectClip); if (!(option->activeSubControls & which)) buttonOpt.state &= ~(State_MouseOver | State_On | State_Sunken); drawBronzeBevel(&buttonOpt, painter); QStyleOption arrowOpt(buttonOpt); arrowOpt.rect = subControlRect(CC_SpinBox, option, which) .adjusted(+3, +3, -3, -3); if (arrowOpt.rect.isValid()) drawPrimitive(arrow, &arrowOpt, painter); painter->restore(); }
When i try to compile this i i get this output:
19:05:23: Running steps for project bronzestyleplugin... 19:05:23: Configuration unchanged, skipping qmake step. 19:05:23: Starting: "/usr/bin/make" -j4 Makefile:975: warning: overriding recipe for target 'moc_bronzestyleplugin.cpp' Makefile:904: warning: ignoring old recipe for target 'moc_bronzestyleplugin.cpp' Makefile:1321: warning: overriding recipe for target 'bronzestyleplugin.o' Makefile:1222: warning: ignoring old recipe for target 'bronzestyleplugin.o' /home/sandro/Qt/5.13.0/gcc_64/bin/qmake -o Makefile ../bronzestyleplugin/bronzestyleplugin.pro -spec linux-g++ CONFIG+=qtquickcompiler Makefile:978: warning: overriding recipe for target 'moc_bronzestyleplugin.cpp' Makefile:907: warning: ignoring old recipe for target 'moc_bronzestyleplugin.cpp' Makefile:1324: warning: overriding recipe for target 'bronzestyleplugin.o' Makefile:1225: warning: ignoring old recipe for target 'bronzestyleplugin.o' g++ -c -pipe -O2 -std=gnu++1z -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_PLUGIN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I../bronzestyleplugin -I. -I/home/sandro/Qt/5.13.0/gcc_64/include -I/home/sandro/Qt/5.13.0/gcc_64/include/QtWidgets -I/home/sandro/Qt/5.13.0/gcc_64/include/QtGui -I/home/sandro/Qt/5.13.0/gcc_64/include/QtCore -I. -isystem /usr/include/libdrm -I/home/sandro/Qt/5.13.0/gcc_64/mkspecs/linux-g++ -o bronzestyle.o ../../bronze/bronze/bronzestyle.cpp g++ -c -pipe -O2 -std=gnu++1z -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_PLUGIN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I../bronzestyleplugin -I. -I/home/sandro/Qt/5.13.0/gcc_64/include -I/home/sandro/Qt/5.13.0/gcc_64/include/QtWidgets -I/home/sandro/Qt/5.13.0/gcc_64/include/QtGui -I/home/sandro/Qt/5.13.0/gcc_64/include/QtCore -I. -isystem /usr/include/libdrm -I/home/sandro/Qt/5.13.0/gcc_64/mkspecs/linux-g++ -o bronzestyleplugin.o ../bronzestyleplugin/bronzestyleplugin.cpp /home/sandro/Qt/5.13.0/gcc_64/bin/moc -DQT_NO_DEBUG -DQT_PLUGIN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB --include /mnt/Programmierung/Cpp/QT/C++_GUI_Programming_with_Qt/CH21_creating_plugins/bronzestyleplugin/build-bronzestyleplugin-Desktop_Qt_5_13_0_GCC_64bit-Release/moc_predefs.h -I/home/sandro/Qt/5.13.0/gcc_64/mkspecs/linux-g++ -I/mnt/Programmierung/Cpp/QT/C++_GUI_Programming_with_Qt/CH21_creating_plugins/bronzestyleplugin/bronzestyleplugin -I/home/sandro/Qt/5.13.0/gcc_64/include -I/home/sandro/Qt/5.13.0/gcc_64/include/QtWidgets -I/home/sandro/Qt/5.13.0/gcc_64/include/QtGui -I/home/sandro/Qt/5.13.0/gcc_64/include/QtCore -I. -I/usr/include/c++/7 -I/usr/include/x86_64-linux-gnu/c++/7 -I/usr/include/c++/7/backward -I/usr/lib/gcc/x86_64-linux-gnu/7/include -I/usr/local/include -I/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed -I/usr/include/x86_64-linux-gnu -I/usr/include ../../bronze/bronze/bronzestyle.h -o moc_bronzestyle.cpp g++ -c -pipe -O2 -std=gnu++1z -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_PLUGIN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I../bronzestyleplugin -I. -I/home/sandro/Qt/5.13.0/gcc_64/include -I/home/sandro/Qt/5.13.0/gcc_64/include/QtWidgets -I/home/sandro/Qt/5.13.0/gcc_64/include/QtGui -I/home/sandro/Qt/5.13.0/gcc_64/include/QtCore -I. -isystem /usr/include/libdrm -I/home/sandro/Qt/5.13.0/gcc_64/mkspecs/linux-g++ -o moc_bronzestyle.o moc_bronzestyle.cpp ../../bronze/bronze/bronzestyle.cpp: In member function ‘void BronzeStyle::drawBronzeCheckBoxIndicator(const QStyleOption*, QPainter*) const’: ../../bronze/bronze/bronzestyle.cpp:254:65: warning: ‘void QPainter::drawRoundRect(const QRect&, int, int)’ is deprecated: Use drawRoundedRect(..., Qt::RelativeSize) instead [-Wdeprecated-declarations] painter->drawRoundRect(option->rect.adjusted(+1, +1, -1, -1)); ^ In file included from /home/sandro/Qt/5.13.0/gcc_64/include/QtGui/QPainter:1:0, from ../../bronze/bronze/bronzestyle.cpp:7: /home/sandro/Qt/5.13.0/gcc_64/include/QtGui/qpainter.h:379:10: note: declared here void drawRoundRect(const QRect &r, int xround = 25, int yround = 25); ^~~~~~~~~~~~~ rm -f libbronzestyleplugin.so g++ -Wl,-O1 -Wl,-rpath,/home/sandro/Qt/5.13.0/gcc_64/lib -shared -o libbronzestyleplugin.so bronzestyle.o bronzestyleplugin.o bronzestyleplugin.o qrc_bronze.o moc_bronzestyle.o moc_bronzestyleplugin.o /home/sandro/Qt/5.13.0/gcc_64/lib/libQt5Widgets.so /home/sandro/Qt/5.13.0/gcc_64/lib/libQt5Gui.so /home/sandro/Qt/5.13.0/gcc_64/lib/libQt5Core.so -lGL -lpthread bronzestyleplugin.o: In function `BronzeStylePlugin::create(QString const&)': bronzestyleplugin.cpp:(.text+0x0): multiple definition of `BronzeStylePlugin::create(QString const&)' bronzestyleplugin.o:bronzestyleplugin.cpp:(.Makefile:277: recipe for target 'libbronzestyleplugin.so' failed text+0x0): first defined here collect2: error: ld returned 1 exit status make: *** [libbronzestyleplugin.so] Error 1 19:05:25: The process "/usr/bin/make" exited with code 2. Error while building/deploying project bronzestyleplugin (kit: Desktop Qt 5.13.0 GCC 64bit) When executing step "Make" 19:05:25: Elapsed time: 00:02.
Any idea how to find the issue here?
-
Hi,
How many create method do you have ?
-
@sandro4912 said in Creating Style Plugin in QT5:
SOURCES = ../../bronze/bronze/bronzestyle.cpp
bronzestyleplugin.cpp
bronzestyleplugin.cppYou add your sources (and also headers) twice.
-
@sandro4912 said in Creating Style Plugin in QT5:
SOURCES = ../../bronze/bronze/bronzestyle.cpp
bronzestyleplugin.cpp
bronzestyleplugin.cppYou add your sources (and also headers) twice.
removing the double declaration fixed the issue. I could compile the style addon.
However i don't see that the styles plugin gets deployed. I only get:
18:15:49: Running steps for project bronzestyleplugin... 18:15:49: Configuration unchanged, skipping qmake step. 18:15:49: Starting: "/usr/bin/make" -j4 /home/sandro/Qt/5.13.0/gcc_64/bin/qmake -o Makefile ../bronzestyleplugin/bronzestyleplugin.pro -spec linux-g++ CONFIG+=qtquickcompiler make: Nothing to be done for 'first'. 18:15:50: The process "/usr/bin/make" exited normally. 18:15:50: Elapsed time: 00:01.
To have it available from qt creator do i have to ?
-
'make' just compiles a library, 'make install' installs it. But since you did not define an install target there won't be done anything. You have to copy it to the correct folder by yourself.
-
I thought i defined it with
TARGET = $$qtLibraryTarget($$TARGET) target.path = $$[QT_INSTALL_PLUGINS]/styles INSTALLS += target
what do i need to add to automatically copy it to the correct folder?
-
So did you actually do a 'make install' ?
-
what do you mean with that?
-
Just because you define an install target nothing happens - you have to call make with the parameter 'install' as I said above.