diff options
Diffstat (limited to 'src/quicknativestyle/items')
29 files changed, 3062 insertions, 0 deletions
diff --git a/src/quicknativestyle/items/items.pri b/src/quicknativestyle/items/items.pri new file mode 100644 index 0000000000..5b6d9251a2 --- /dev/null +++ b/src/quicknativestyle/items/items.pri @@ -0,0 +1,36 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qquickstyleitem.h \ + $$PWD/qquickstyleitembutton.h \ + $$PWD/qquickstyleitemgroupbox.h \ + $$PWD/qquickstyleitemcheckbox.h \ + $$PWD/qquickstyleitemradiobutton.h \ + $$PWD/qquickstyleitemslider.h \ + $$PWD/qquickstyleitemspinbox.h \ + $$PWD/qquickstyleitemtextfield.h \ + $$PWD/qquickstyleitemframe.h \ + $$PWD/qquickstyleitemcombobox.h \ + $$PWD/qquickstyleitemscrollbar.h \ + $$PWD/qquickstyleitemprogressbar.h \ + $$PWD/qquickstyleitemdial.h \ + +SOURCES += \ + $$PWD/qquickstyleitem.cpp \ + $$PWD/qquickstyleitembutton.cpp \ + $$PWD/qquickstyleitemgroupbox.cpp \ + $$PWD/qquickstyleitemcheckbox.cpp \ + $$PWD/qquickstyleitemradiobutton.cpp \ + $$PWD/qquickstyleitemslider.cpp \ + $$PWD/qquickstyleitemspinbox.cpp \ + $$PWD/qquickstyleitemtextfield.cpp \ + $$PWD/qquickstyleitemframe.cpp \ + $$PWD/qquickstyleitemcombobox.cpp \ + $$PWD/qquickstyleitemscrollbar.cpp \ + $$PWD/qquickstyleitemprogressbar.cpp \ + $$PWD/qquickstyleitemdial.cpp \ + +macos { + HEADERS += $$PWD/qquickstyleitemscrollviewcorner.h + SOURCES += $$PWD/qquickstyleitemscrollviewcorner.cpp +} diff --git a/src/quicknativestyle/items/qquickstyleitem.cpp b/src/quicknativestyle/items/qquickstyleitem.cpp new file mode 100644 index 0000000000..ec041d01e0 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitem.cpp @@ -0,0 +1,563 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitem.h" + +#include <QtCore/qscopedvaluerollback.h> +#include <QtCore/qdir.h> + +#include <QtQuick/qsgninepatchnode.h> +#include <QtQuick/private/qquickwindow_p.h> +#include <QtQuick/qquickwindow.h> + +#include <QtQuickTemplates2/private/qquickcontrol_p.h> +#include <QtQuickTemplates2/private/qquickbutton_p.h> + +#include <QtQml/qqml.h> + +#include "qquickstyleitembutton.h" +#include "qquickstylehelper_p.h" + +QT_BEGIN_NAMESPACE + +QDebug operator<<(QDebug debug, const QQuickStyleMargins &padding) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "StyleMargins("; + debug << padding.left() << ", "; + debug << padding.top() << ", "; + debug << padding.right() << ", "; + debug << padding.bottom(); + debug << ')'; + return debug; +} + +QDebug operator<<(QDebug debug, const StyleItemGeometry &cg) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "StyleItemGeometry("; + debug << "implicitSize:" << cg.implicitSize << ", "; + debug << "contentRect:" << cg.contentRect << ", "; + debug << "layoutRect:" << cg.layoutRect << ", "; + debug << "minimumSize:" << cg.minimumSize << ", "; + debug << "9patchMargins:" << cg.ninePatchMargins; + debug << ')'; + return debug; +} + +int QQuickStyleItem::dprAlignedSize(const int size) const +{ + // Return the first value equal to or bigger than size + // that is a whole number when multiplied with the dpr. + static int multiplier = [&]() { + const qreal dpr = window()->devicePixelRatio(); + for (int m = 1; m <= 10; ++m) { + const qreal v = m * dpr; + if (v == int(v)) + return m; + } + + qWarning() << "The current dpr (" << dpr << ") is not supported" + << "by the style and might result in drawing artifacts"; + return 1; + }(); + + return int(qCeil(qreal(size) / qreal(multiplier)) * multiplier); +} + +QQuickStyleItem::QQuickStyleItem(QQuickItem *parent) + : QQuickItem(parent) +{ + setFlag(QQuickItem::ItemHasContents); +} + +QQuickStyleItem::~QQuickStyleItem() +{ +} + +void QQuickStyleItem::connectToControl() const +{ + connect(m_control, &QQuickStyleItem::enabledChanged, this, &QQuickStyleItem::markImageDirty); + connect(m_control, &QQuickItem::activeFocusChanged, this, &QQuickStyleItem::markImageDirty); + + if (QQuickWindow *win = window()) { + connect(win, &QQuickWindow::activeChanged, this, &QQuickStyleItem::markImageDirty); + m_connectedWindow = win; + } +} + +void QQuickStyleItem::markImageDirty() +{ + m_dirty.setFlag(DirtyFlag::Image); + if (isComponentComplete()) + polish(); +} + +void QQuickStyleItem::markGeometryDirty() +{ + m_dirty.setFlag(DirtyFlag::Geometry); + if (isComponentComplete()) + polish(); +} + +QSGNode *QQuickStyleItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *) +{ + QSGNinePatchNode *node = static_cast<QSGNinePatchNode *>(oldNode); + if (!node) + node = window()->createNinePatchNode(); + if (m_paintedImage.isNull()) + return node; + + const auto texture = window()->createTextureFromImage(m_paintedImage, QQuickWindow::TextureCanUseAtlas); + + QRectF bounds = boundingRect(); + const qreal dpr = window()->devicePixelRatio(); + const QSizeF unscaledImageSize = QSizeF(m_paintedImage.size()) / dpr; + + // We can scale the image up with a nine patch node, but should + // avoid to scale it down. Otherwise the nine patch image will look + // wrapped (or look truncated, in case of no padding). So if the + // item is smaller that the image, don't scale. + if (bounds.width() < unscaledImageSize.width()) + bounds.setWidth(unscaledImageSize.width()); + if (bounds.height() < unscaledImageSize.height()) + bounds.setHeight(unscaledImageSize.height()); + +#ifdef QT_DEBUG + if (m_debugFlags.testFlag(Unscaled)) { + bounds.setSize(unscaledImageSize); + qqc2Info() << "Setting qsg node size to the unscaled size of m_paintedImage:" << bounds; + } +#endif + + if (m_useNinePatchImage) { + QMargins padding = m_styleItemGeometry.ninePatchMargins; + if (padding.right() == -1) { + // Special case: a padding of -1 means that + // the image shouldn't scale in the given direction. + padding.setLeft(0); + padding.setRight(0); + } + if (padding.bottom() == -1) { + padding.setTop(0); + padding.setBottom(0); + } + node->setPadding(padding.left(), padding.top(), padding.right(), padding.bottom()); + } + + node->setBounds(bounds); + node->setTexture(texture); + node->setDevicePixelRatio(dpr); + node->update(); + + return node; +} + +QStyle::State QQuickStyleItem::controlSize(QQuickItem *item) +{ + // TODO: add proper API for small and mini + if (item->metaObject()->indexOfProperty("qqc2_style_small") != -1) + return QStyle::State_Small; + if (item->metaObject()->indexOfProperty("qqc2_style_mini") != -1) + return QStyle::State_Mini; + return QStyle::State_None; +} + +void QQuickStyleItem::initStyleOptionBase(QStyleOption &styleOption) const +{ + Q_ASSERT(m_control); + + styleOption.control = const_cast<QQuickItem *>(control<QQuickItem>()); + styleOption.window = window(); + styleOption.palette = QQuickItemPrivate::get(m_control)->palette()->toQPalette(); + styleOption.rect = QRect(QPoint(0, 0), imageSize()); + + styleOption.state = QStyle::State_None; + styleOption.state |= controlSize(styleOption.control); + + // Note: not all controls inherit from QQuickControl (e.g QQuickTextField) + if (const auto quickControl = dynamic_cast<QQuickControl *>(m_control.data())) + styleOption.direction = quickControl->isMirrored() ? Qt::RightToLeft : Qt::LeftToRight; + + if (window()) { + if (styleOption.window->isActive()) + styleOption.state |= QStyle::State_Active; + if (m_control->isEnabled()) + styleOption.state |= QStyle::State_Enabled; + if (m_control->hasActiveFocus()) + styleOption.state |= QStyle::State_HasFocus; + if (m_control->isUnderMouse()) + styleOption.state |= QStyle::State_MouseOver; + // Should this depend on the focusReason (e.g. only TabFocus) ? + styleOption.state |= QStyle::State_KeyboardFocusChange; + } + + if (m_overrideState != None) { + // In Button.qml we fade between two versions of + // the handle, depending on if it's hovered or not + if (m_overrideState & AlwaysHovered) + styleOption.state |= QStyle::State_MouseOver; + else if (m_overrideState & NeverHovered) + styleOption.state &= ~QStyle::State_MouseOver; + } + + qqc2Info() << styleOption; +} + +void QQuickStyleItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QQuickItem::geometryChange(newGeometry, oldGeometry); + + // Ensure that we only schedule a new geometry update + // and polish if this geometry change was caused by + // something else than us already updating geometry. + if (!m_polishing) + markGeometryDirty(); +} + +void QQuickStyleItem::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) +{ + QQuickItem::itemChange(change, data); + + switch (change) { + case QQuickItem::ItemVisibleHasChanged: + if (data.boolValue) + markImageDirty(); + break; + case QQuickItem::ItemSceneChange: { + markImageDirty(); + QQuickWindow *win = data.window; + if (m_connectedWindow) + disconnect(m_connectedWindow, &QQuickWindow::activeChanged, this, &QQuickStyleItem::markImageDirty); + if (win) + connect(win, &QQuickWindow::activeChanged, this, &QQuickStyleItem::markImageDirty); + m_connectedWindow = win; + break;} + default: + break; + } +} + +void QQuickStyleItem::updateGeometry() +{ + qqc2InfoHeading("GEOMETRY"); + m_dirty.setFlag(DirtyFlag::Geometry, false); + + const QQuickStyleMargins oldContentPadding = contentPadding(); + const QQuickStyleMargins oldLayoutMargins = layoutMargins(); + const QSize oldMinimumSize = minimumSize(); + + m_styleItemGeometry = calculateGeometry(); + +#ifdef QT_DEBUG + if (m_styleItemGeometry.minimumSize.isEmpty()) + qmlWarning(this) << "minimumSize is empty!"; +#endif + + if (m_styleItemGeometry.implicitSize.isEmpty()) { + // If the item has no contents (or its size is + // empty), we just use the minimum size as implicit size. + m_styleItemGeometry.implicitSize = m_styleItemGeometry.minimumSize; + qqc2Info() << "implicitSize is empty, using minimumSize instead"; + } + + if (contentPadding() != oldContentPadding) + emit contentPaddingChanged(); + if (layoutMargins() != oldLayoutMargins) + emit layoutMarginsChanged(); + if (minimumSize() != oldMinimumSize) + emit minimumSizeChanged(); + + setImplicitSize(m_styleItemGeometry.implicitSize.width(), m_styleItemGeometry.implicitSize.height()); + + qqc2Info() << m_styleItemGeometry + << "bounding rect:" << boundingRect() + << "layout margins:" << layoutMargins() + << "content padding:" << contentPadding() + << "input content size:" << m_contentSize; +} + +void QQuickStyleItem::paintControlToImage() +{ + qqc2InfoHeading("PAINT"); + const QSize imgSize = imageSize(); + if (imgSize.isEmpty()) + return; + + m_dirty.setFlag(DirtyFlag::Image, false); + + // The size of m_paintedImage should normally be imgSize * dpr. The problem is + // that the dpr can be e.g 1.25, which means that the size can end up having a + // fraction. But an image cannot have a size with a fraction, so it would need + // to be rounded. But on the flip side, rounding the size means that the size + // of the scene graph node (which is, when the texture is not scaled, + // m_paintedImage.size() / dpr), will end up with a fraction instead. And this + // causes rendering artifacts in the scene graph when the texture is mapped + // to physical screen coordinates. So for that reason we calculate an image size + // that might be slightly larger than imgSize, so that imgSize * dpr lands on a + // whole number. The result is that neither the image size, nor the scene graph + // node, ends up with a size that has a fraction. + const qreal dpr = window()->devicePixelRatio(); + const int alignedW = int(dprAlignedSize(imgSize.width()) * dpr); + const int alignedH = int(dprAlignedSize(imgSize.height()) * dpr); + const QSize alignedSize = QSize(alignedW, alignedH); + + if (m_paintedImage.size() != alignedSize) { + m_paintedImage = QImage(alignedSize, QImage::Format_ARGB32_Premultiplied); + m_paintedImage.setDevicePixelRatio(dpr); + qqc2Info() << "created image with dpr aligned size:" << alignedSize; + } + + m_paintedImage.fill(Qt::transparent); + + QPainter painter(&m_paintedImage); + paintEvent(&painter); + +#ifdef QT_DEBUG + if (m_debugFlags != NoDebug) { + painter.setPen(QColor(255, 0, 0, 255)); + if (m_debugFlags.testFlag(ImageRect)) + painter.drawRect(QRect(QPoint(0, 0), alignedSize / dpr)); + if (m_debugFlags.testFlag(LayoutRect)) { + const auto m = layoutMargins(); + QRect rect = QRect(QPoint(0, 0), imgSize); + rect.adjust(m.left(), m.top(), -m.right(), -m.bottom()); + painter.drawRect(rect); + } + if (m_debugFlags.testFlag(ContentRect)) { + const auto p = contentPadding(); + QRect rect = QRect(QPoint(0, 0), imgSize); + rect.adjust(p.left(), p.top(), -p.right(), -p.bottom()); + painter.drawRect(rect); + } + if (m_debugFlags.testFlag(InputContentSize)) { + const int offset = 2; + const QPoint p = m_styleItemGeometry.contentRect.topLeft(); + painter.drawLine(p.x() - offset, p.y() - offset, p.x() + m_contentSize.width(), p.y() - offset); + painter.drawLine(p.x() - offset, p.y() - offset, p.x() - offset, p.y() + m_contentSize.height()); + } + if (m_debugFlags.testFlag(NinePatchMargins)) { + const QMargins m = m_styleItemGeometry.ninePatchMargins; + if (m.right() != -1) { + painter.drawLine(m.left(), 0, m.left(), imgSize.height()); + painter.drawLine(imgSize.width() - m.right(), 0, imgSize.width() - m.right(), imgSize.height()); + } + if (m.bottom() != -1) { + painter.drawLine(0, m.top(), imgSize.width(), m.top()); + painter.drawLine(0, imgSize.height() - m.bottom(), imgSize.width(), imgSize.height() - m.bottom()); + } + } + if (m_debugFlags.testFlag(SaveImage)) { + static int nr = -1; + ++nr; + static QString filename = QStringLiteral("styleitem_saveimage_"); + const QString path = QDir::current().absoluteFilePath(filename); + const QString name = path + QString::number(nr) + QStringLiteral(".png"); + m_paintedImage.save(name); + qDebug() << "image saved to:" << name; + } + } +#endif + + update(); +} + +void QQuickStyleItem::updatePolish() +{ + QScopedValueRollback<bool> guard(m_polishing, true); + + const bool dirtyGeometry = m_dirty & DirtyFlag::Geometry; + const bool dirtyImage = isVisible() && ((m_dirty & DirtyFlag::Image) || (!m_useNinePatchImage && dirtyGeometry)); + + if (dirtyGeometry) + updateGeometry(); + if (dirtyImage) + paintControlToImage(); +} + +#ifdef QT_DEBUG +void QQuickStyleItem::addDebugInfo() +{ + // Example debug strings: + // "QQC2_NATIVESTYLE_DEBUG="myButton output contentRect" + // "QQC2_NATIVESTYLE_DEBUG="ComboBox ninepatchmargins" + // "QQC2_NATIVESTYLE_DEBUG="All layoutrect" + + static const auto debugString = qEnvironmentVariable("QQC2_NATIVESTYLE_DEBUG"); + static const auto matchAll = debugString.startsWith(QLatin1String("All ")); + static const auto prefix = QStringLiteral("QQuickStyleItem"); + if (debugString.isEmpty()) + return; + + const auto objectName = m_control->objectName(); + const auto typeName = QString::fromUtf8(metaObject()->className()).remove(prefix); + const bool matchName = !objectName.isEmpty() && debugString.startsWith(objectName); + const bool matchType = debugString.startsWith(typeName); + + if (!(matchAll || matchName || matchType)) + return; + +#define QQC2_DEBUG_FLAG(FLAG) \ + if (debugString.contains(QLatin1String(#FLAG), Qt::CaseInsensitive)) m_debugFlags |= FLAG + + QQC2_DEBUG_FLAG(Info); + QQC2_DEBUG_FLAG(ImageRect); + QQC2_DEBUG_FLAG(ContentRect); + QQC2_DEBUG_FLAG(LayoutRect); + QQC2_DEBUG_FLAG(InputContentSize); + QQC2_DEBUG_FLAG(DontUseNinePatchImage); + QQC2_DEBUG_FLAG(NinePatchMargins); + QQC2_DEBUG_FLAG(Unscaled); + QQC2_DEBUG_FLAG(Debug); + QQC2_DEBUG_FLAG(SaveImage); + + if (m_debugFlags & (DontUseNinePatchImage + | InputContentSize + | ContentRect + | LayoutRect + | NinePatchMargins)) { + // Some rects will not fit inside the drawn image unless + // we switch off (nine patch) image scaling. + m_debugFlags |= DontUseNinePatchImage; + m_useNinePatchImage = false; + } + + if (m_debugFlags != NoDebug) + qDebug() << "debug options set for" << typeName << "(" << objectName << "):" << m_debugFlags; + else + qDebug() << "available debug options:" << DebugFlags(0xFFFF); +} +#endif + +void QQuickStyleItem::componentComplete() +{ + Q_ASSERT_X(m_control, Q_FUNC_INFO, "You need to assign a value to property 'control'"); +#ifdef QT_DEBUG + addDebugInfo(); +#endif + QQuickItem::componentComplete(); + connectToControl(); + polish(); +} + +qreal QQuickStyleItem::contentWidth() +{ + return m_contentSize.width(); +} + +void QQuickStyleItem::setContentWidth(qreal contentWidth) +{ + if (qFuzzyCompare(m_contentSize.width(), contentWidth)) + return; + + m_contentSize.setWidth(contentWidth); + markGeometryDirty(); +} + +qreal QQuickStyleItem::contentHeight() +{ + return m_contentSize.height(); +} + +void QQuickStyleItem::setContentHeight(qreal contentHeight) +{ + if (qFuzzyCompare(m_contentSize.height(), contentHeight)) + return; + + m_contentSize.setHeight(contentHeight); + markGeometryDirty(); +} + +QQuickStyleMargins QQuickStyleItem::contentPadding() const +{ + const QRect outerRect(QPoint(0, 0), m_styleItemGeometry.implicitSize); + return QQuickStyleMargins(outerRect, m_styleItemGeometry.contentRect); +} + +QQuickStyleMargins QQuickStyleItem::layoutMargins() const +{ + // ### TODO: layoutRect is currently not being used for anything. But + // eventually this information will be needed by layouts to align the controls + // correctly. This because the images drawn by QStyle are usually a bit bigger + // than the control(frame) itself, to e.g make room for shadow effects + // or focus rects/glow. And this will differ from control to control. The + // layoutRect will then inform where the frame of the control is. + QQuickStyleMargins margins; + if (m_styleItemGeometry.layoutRect.isValid()) { + const QRect outerRect(QPoint(0, 0), m_styleItemGeometry.implicitSize); + margins = QQuickStyleMargins(outerRect, m_styleItemGeometry.layoutRect); + } + return margins; +} + +QSize QQuickStyleItem::minimumSize() const +{ + // The style item should not be scaled below this size. + // Otherwise the image will be truncated. + return m_styleItemGeometry.minimumSize; +} + +QSize QQuickStyleItem::imageSize() const +{ + // Returns the size of the QImage (unscaled) that + // is used to draw the control from QStyle. + return m_useNinePatchImage ? m_styleItemGeometry.minimumSize : size().toSize(); +} + +qreal QQuickStyleItem::focusFrameRadius() const +{ + return m_styleItemGeometry.focusFrameRadius; +} + +QFont QQuickStyleItem::styleFont(QQuickItem *control) const +{ + Q_ASSERT(control); + // Note: This function should be treated as if it was static + // (meaning, don't assume anything in this object to be initialized). + // Resolving the font/font size should be done early on from QML, before we get + // around to calculate geometry and paint. Otherwise we typically need to do it + // all over again when/if the font changes. In practice this means that other + // items in QML that uses a style font, and at the same time, affects our input + // contentSize, cannot wait for this item to be fully constructed before it + // gets the font. So we need to resolve it here and now, even if this + // object might be in a half initialized state (hence also the control + // argument, instead of relying on m_control to be set). + return QGuiApplication::font(); +} + +QT_END_NAMESPACE diff --git a/src/quicknativestyle/items/qquickstyleitem.h b/src/quicknativestyle/items/qquickstyleitem.h new file mode 100644 index 0000000000..3b87faf60c --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitem.h @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEM_H +#define QQUICKSTYLEITEM_H + +#include <QtCore/qdebug.h> +#include <QtQml/qqml.h> +#include <QtQml/qqmlinfo.h> +#include <QtQuick/private/qquickitem_p.h> +#include <QtQuickTemplates2/private/qquickcontrol_p.h> + +#include "qquicknativestyle.h" +#include "qquickstyle.h" +#include "qquickstyleoption.h" + +// Work-around for now, to avoid creator getting confused +// about missing macros. Should eventually be defined +// in qt declarative somewhere I assume. +#ifndef QML_NAMED_ELEMENT +#define QML_NAMED_ELEMENT(NAME) +#define QML_UNCREATABLE(NAME) +#endif + +#ifdef QT_DEBUG +#define qqc2Debug() if (m_debugFlags.testFlag(Debug)) qDebug() << __FUNCTION__ << ":" +#define qqc2Info() if (m_debugFlags.testFlag(Info)) qDebug() << __FUNCTION__ << ":" +#define qqc2InfoHeading(HEADING) if (m_debugFlags.testFlag(Info)) qDebug() << "--------" << HEADING << "--------" +#else +#define qqc2Debug() if (false) qDebug() +#define qqc2Info() if (false) qDebug() +#define qqc2InfoHeading(HEADING) if (false) qDebug() +#endif + +QT_BEGIN_NAMESPACE + +using namespace QQC2; + +class QQuickStyleMargins +{ + Q_GADGET + + Q_PROPERTY(int left READ left()) + Q_PROPERTY(int top READ top()) + Q_PROPERTY(int right READ right()) + Q_PROPERTY(int bottom READ bottom()) + + QML_NAMED_ELEMENT(stylemargins) + QML_UNCREATABLE("") + +public: + QQuickStyleMargins() {} + QQuickStyleMargins(const QQuickStyleMargins &other) : m_margins(other.m_margins) {} + QQuickStyleMargins(const QMargins &margins) : m_margins(margins) {} + QQuickStyleMargins(const QRect &outer, const QRect &inner) + { + const int left = inner.left() - outer.left(); + const int top = inner.top() - outer.top(); + const int right = outer.right() - inner.right(); + const int bottom = outer.bottom() - inner.bottom(); + m_margins = QMargins(left, top, right, bottom); + } + + inline void operator=(const QQuickStyleMargins &other) { m_margins = other.m_margins; } + inline bool operator==(const QQuickStyleMargins &other) const { return other.m_margins == m_margins; } + inline bool operator!=(const QQuickStyleMargins &other) const { return other.m_margins != m_margins; } + + inline int left() const { return m_margins.left(); } + inline int right() const { return m_margins.right(); } + inline int top() const { return m_margins.top(); } + inline int bottom() const { return m_margins.bottom(); } + + QMargins m_margins; +}; + +QDebug operator<<(QDebug debug, const QQuickStyleMargins &padding); + +struct StyleItemGeometry +{ + /* + A QQuickStyleItem is responsible for drawing a control, or a part of it. + + 'minimumSize' should be the minimum possible size that the item can + have _without_ taking content size into consideration (and still render + correctly). This will also be the size of the image that the item is drawn + to, unless QQuickStyleItem::useNinePatchImage is set to false. In that + case, the size of the image will be set to the size of the item instead + (which is set from QML, and will typically be the same as the size of the control). + The default way to calculate minimumSize is to call style()->sizeFromContents() + with an empty content size. This is not always well supported by the legacy QStyle + implementation, which means that you might e.g get an empty size in return. + For those cases, the correct solution is to go into the specific platform style + and change it so that it returns a valid size also for this special case. + + 'implicitSize' should reflect the preferred size of the item, taking the + given content size (as set from QML) into account. But not all controls + have contents (slider), and for many controls, the content/label is instead + placed outside the item/background image (radiobutton). In both cases, the + size of the item will not include the content size, and implicitSize can + usually be set equal to minimumSize instead. + + 'contentRect' should be the free space where the contents can be placed. Note that + this rect doesn't need to have the same size as the contentSize provided as input + to the style item. Instead, QStyle can typically calculate a rect that is bigger, to + e.g center the contents inside the control. + + 'layoutRect' can be set to shift the position of the whole control so + that aligns correctly with the other controls. This is important for + controls that draws e.g shadows or focus rings. Such adornments should + be painted, but not be included when aligning the controls. + */ + + QSize minimumSize; + QSize implicitSize; + QRect contentRect; + QRect layoutRect; // If invalid, there are no layout margins! + QMargins ninePatchMargins; + qreal focusFrameRadius; +}; + +QDebug operator<<(QDebug debug, const StyleItemGeometry &cg); + +class QQuickStyleItem : public QQuickItem +{ + Q_OBJECT + + // Input + Q_PROPERTY(QQuickItem *control MEMBER m_control NOTIFY controlChanged) + Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth) + Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight) + Q_PROPERTY(bool useNinePatchImage MEMBER m_useNinePatchImage) + Q_PROPERTY(OverrideState overrideState MEMBER m_overrideState) + + // Output + Q_PROPERTY(QQuickStyleMargins contentPadding READ contentPadding() NOTIFY contentPaddingChanged) + Q_PROPERTY(QQuickStyleMargins layoutMargins READ layoutMargins() NOTIFY layoutMarginsChanged) + Q_PROPERTY(QSize minimumSize READ minimumSize() NOTIFY minimumSizeChanged) + Q_PROPERTY(int transitionDuration MEMBER m_transitionDuration CONSTANT) + + QML_NAMED_ELEMENT(StyleItem) + QML_UNCREATABLE("StyleItem is an abstract base class.") + +public: + enum DirtyFlag { + Nothing = 0, + Geometry, + Image, + Everything = 255 + }; + Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag) + + enum OverrideState { + None = 0, + AlwaysHovered, + NeverHovered, + AlwaysSunken + }; + Q_ENUM(OverrideState) + + +#ifdef QT_DEBUG + enum DebugFlag { + NoDebug = 0x000, + Debug = 0x001, + Info = 0x002, + ImageRect = 0x004, + ContentRect = 0x008, + LayoutRect = 0x010, + Unscaled = 0x020, + InputContentSize = 0x040, + DontUseNinePatchImage = 0x080, + NinePatchMargins = 0x100, + SaveImage = 0x200, + }; + Q_FLAG(DebugFlag) + Q_DECLARE_FLAGS(DebugFlags, DebugFlag) +#endif + + explicit QQuickStyleItem(QQuickItem *parent = nullptr); + ~QQuickStyleItem() override; + + qreal contentWidth(); + void setContentWidth(qreal contentWidth); + qreal contentHeight(); + void setContentHeight(qreal contentHeight); + + QQuickStyleMargins contentPadding() const; + QQuickStyleMargins layoutMargins() const; + QSize minimumSize() const; + QSize imageSize() const; + qreal focusFrameRadius() const; + + Q_INVOKABLE virtual QFont styleFont(QQuickItem *control) const; + + void markGeometryDirty(); + void markImageDirty(); + +signals: + void controlChanged(); + void contentPaddingChanged(); + void layoutMarginsChanged(); + void fontChanged(); + void minimumSizeChanged(); + +protected: + void componentComplete() override; + QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override; + void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void itemChange(ItemChange change, const ItemChangeData &data) override; + void updatePolish() override; + + virtual void connectToControl() const; + virtual void paintEvent(QPainter *painter) const = 0; + virtual StyleItemGeometry calculateGeometry() = 0; + + static QStyle::State controlSize(QQuickItem *item); + void initStyleOptionBase(QStyleOption &styleOption) const; + + inline QSize contentSize() const { return QSize(qCeil(m_contentSize.width()), qCeil(m_contentSize.height())); } + inline static QStyle *style() { return QQuickNativeStyle::style(); } + + template <class T> inline const T* control() const { +#ifdef QT_DEBUG + if (!dynamic_cast<T *>(m_control.data())) { + qmlWarning(this) << "control property is not of correct type"; + Q_UNREACHABLE(); + } +#endif + return static_cast<T *>(m_control.data()); + } + +#ifdef QT_DEBUG + DebugFlags m_debugFlags = NoDebug; +#endif + OverrideState m_overrideState = None; + +private: + inline void updateGeometry(); + inline void paintControlToImage(); + + int dprAlignedSize(const int size) const; + +#ifdef QT_DEBUG + void addDebugInfo(); +#endif + +private: + QPointer<QQuickItem> m_control; + QImage m_paintedImage; + StyleItemGeometry m_styleItemGeometry; + QSizeF m_contentSize; + + DirtyFlags m_dirty = Everything; + bool m_useNinePatchImage = true; + bool m_polishing = false; + mutable QQuickWindow *m_connectedWindow = nullptr; + +#ifdef Q_OS_MACOS + int m_transitionDuration = 150; +#else + int m_transitionDuration = 400; +#endif + +private: + friend class QtQuickControls2MacOSStylePlugin; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickStyleItem::DirtyFlags) + +#ifdef QT_DEBUG +Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickStyleItem::DebugFlags) +#endif + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickStyleItem) + +#endif // QQUICKSTYLEITEM_H diff --git a/src/quicknativestyle/items/qquickstyleitembutton.cpp b/src/quicknativestyle/items/qquickstyleitembutton.cpp new file mode 100644 index 0000000000..5dfe060fad --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitembutton.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitembutton.h" + +QFont QQuickStyleItemButton::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_PushButtonLabel, controlSize(control)); +} + +void QQuickStyleItemButton::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto button = control<QQuickButton>(); + connect(button, &QQuickButton::downChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemButton::calculateGeometry() +{ + QStyleOptionButton styleOption; + initStyleOption(styleOption); + StyleItemGeometry geometry; + + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_PushButton, &styleOption, QSize(0, 0)); + geometry.implicitSize = style()->sizeFromContents(QStyle::CT_PushButton, &styleOption, contentSize()); + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.contentRect = style()->subElementRect(QStyle::SE_PushButtonContents, &styleOption); + geometry.layoutRect = style()->subElementRect(QStyle::SE_PushButtonLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CE_PushButtonBevel, &styleOption, geometry.minimumSize); + geometry.focusFrameRadius = style()->pixelMetric(QStyle::PM_PushButtonFocusFrameRadius, &styleOption); + + return geometry; +} + +void QQuickStyleItemButton::paintEvent(QPainter *painter) const +{ + QStyleOptionButton styleOption; + initStyleOption(styleOption); + style()->drawControl(QStyle::CE_PushButtonBevel, &styleOption, painter); +} + +void QQuickStyleItemButton::initStyleOption(QStyleOptionButton &styleOption) const +{ + initStyleOptionBase(styleOption); + auto button = control<QQuickButton>(); + + if (button->isDown()) + styleOption.state |= QStyle::State_Sunken; + if (!button->isFlat() && !button->isDown()) + styleOption.state |= QStyle::State_Raised; + if (button->isHighlighted() || button->isChecked()) + styleOption.state |= QStyle::State_On; + if (button->isFlat()) + styleOption.features |= QStyleOptionButton::Flat; +} diff --git a/src/quicknativestyle/items/qquickstyleitembutton.h b/src/quicknativestyle/items/qquickstyleitembutton.h new file mode 100644 index 0000000000..41ca0cf176 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitembutton.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMBUTTON_H +#define QQUICKSTYLEITEMBUTTON_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickbutton_p.h> + +class QQuickStyleItemButton : public QQuickStyleItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(Button) + +public: + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionButton &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMBUTTON_H diff --git a/src/quicknativestyle/items/qquickstyleitemcheckbox.cpp b/src/quicknativestyle/items/qquickstyleitemcheckbox.cpp new file mode 100644 index 0000000000..6c4ac8ea30 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemcheckbox.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemcheckbox.h" + +QFont QQuickStyleItemCheckBox::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_RadioButtonLabel, controlSize(control)); +} + +void QQuickStyleItemCheckBox::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto checkbox = control<QQuickCheckBox>(); + connect(checkbox, &QQuickCheckBox::downChanged, this, &QQuickStyleItem::markImageDirty); + connect(checkbox, &QQuickCheckBox::checkStateChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemCheckBox::calculateGeometry() +{ + QStyleOptionButton styleOption; + initStyleOption(styleOption); + StyleItemGeometry geometry; + + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_CheckBox, &styleOption, QSize(0, 0)); + geometry.implicitSize = geometry.minimumSize; + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.contentRect = style()->subElementRect(QStyle::SE_CheckBoxContents, &styleOption); + geometry.layoutRect = style()->subElementRect(QStyle::SE_CheckBoxLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CE_CheckBox, &styleOption, geometry.minimumSize); + geometry.focusFrameRadius = style()->pixelMetric(QStyle::PM_CheckBoxFocusFrameRadius, &styleOption); + + // Spacing seems to already be baked into SE_CheckBoxContents, so ignore until needed + //const int space = style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &styleOption); + + return geometry; +} + +void QQuickStyleItemCheckBox::paintEvent(QPainter *painter) const +{ + QStyleOptionButton styleOption; + initStyleOption(styleOption); + style()->drawControl(QStyle::CE_CheckBox, &styleOption, painter); +} + +void QQuickStyleItemCheckBox::initStyleOption(QStyleOptionButton &styleOption) const +{ + initStyleOptionBase(styleOption); + auto checkbox = control<QQuickCheckBox>(); + + styleOption.state |= checkbox->isDown() ? QStyle::State_Sunken : QStyle::State_Raised; + if (checkbox->isTristate() && checkbox->checkState() == Qt::PartiallyChecked) + styleOption.state |= QStyle::State_NoChange; + else + styleOption.state |= checkbox->isChecked() ? QStyle::State_On : QStyle::State_Off; +} diff --git a/src/quicknativestyle/items/qquickstyleitemcheckbox.h b/src/quicknativestyle/items/qquickstyleitemcheckbox.h new file mode 100644 index 0000000000..03bf34b933 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemcheckbox.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMCHECKBOX_H +#define QQUICKSTYLEITEMCHECKBOX_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickcheckbox_p.h> + +class QQuickStyleItemCheckBox : public QQuickStyleItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(CheckBox) + +public: + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionButton &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMCHECKBOX_H diff --git a/src/quicknativestyle/items/qquickstyleitemcombobox.cpp b/src/quicknativestyle/items/qquickstyleitemcombobox.cpp new file mode 100644 index 0000000000..0ac3756e4e --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemcombobox.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemcombobox.h" + +QFont QQuickStyleItemComboBox::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_PushButtonLabel, controlSize(control)); +} + +void QQuickStyleItemComboBox::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto comboBox = control<QQuickComboBox>(); + connect(comboBox, &QQuickComboBox::downChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemComboBox::calculateGeometry() +{ + QStyleOptionComboBox styleOption; + initStyleOption(styleOption); + StyleItemGeometry geometry; + + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_ComboBox, &styleOption, QSize(0, 0)); + geometry.implicitSize = style()->sizeFromContents(QStyle::CT_ComboBox, &styleOption, contentSize()); + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.contentRect = style()->subControlRect(QStyle::CC_ComboBox, &styleOption, QStyle::SC_ComboBoxEditField); + geometry.layoutRect = style()->subElementRect(QStyle::SE_ComboBoxLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CC_ComboBox, &styleOption, geometry.minimumSize); + geometry.focusFrameRadius = style()->pixelMetric(QStyle::PM_ComboBoxFocusFrameRadius, &styleOption); + + return geometry; +} + +void QQuickStyleItemComboBox::paintEvent(QPainter *painter) const +{ + QStyleOptionComboBox styleOption; + initStyleOption(styleOption); + style()->drawComplexControl(QStyle::CC_ComboBox, &styleOption, painter); +} + +void QQuickStyleItemComboBox::initStyleOption(QStyleOptionComboBox &styleOption) const +{ + initStyleOptionBase(styleOption); + auto comboBox = control<QQuickComboBox>(); + + styleOption.subControls = QStyle::SC_ComboBoxArrow | QStyle::SC_ComboBoxFrame | QStyle::SC_ComboBoxEditField; + styleOption.frame = true; + styleOption.state |= QStyle::State_Selected; + styleOption.editable = comboBox->isEditable(); + + if (comboBox->isDown()) + styleOption.state |= QStyle::State_Sunken; + if (!comboBox->isFlat() && !comboBox->isDown()) + styleOption.state |= QStyle::State_Raised; +} diff --git a/src/quicknativestyle/items/qquickstyleitemcombobox.h b/src/quicknativestyle/items/qquickstyleitemcombobox.h new file mode 100644 index 0000000000..79f1995ed3 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemcombobox.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMCOMBOBOX_H +#define QQUICKSTYLEITEMCOMBOBOX_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickcombobox_p.h> + +class QQuickStyleItemComboBox : public QQuickStyleItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(ComboBox) + +public: + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionComboBox &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMCOMBOBOX_H diff --git a/src/quicknativestyle/items/qquickstyleitemdial.cpp b/src/quicknativestyle/items/qquickstyleitemdial.cpp new file mode 100644 index 0000000000..bf5784e1b5 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemdial.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemdial.h" + +QFont QQuickStyleItemDial::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_ProgressBarLabel, controlSize(control)); +} + +void QQuickStyleItemDial::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto dial = control<QQuickDial>(); + connect(dial, &QQuickDial::fromChanged, this, &QQuickStyleItem::markImageDirty); + connect(dial, &QQuickDial::toChanged, this, &QQuickStyleItem::markImageDirty); + connect(dial, &QQuickDial::positionChanged, this, &QQuickStyleItem::markImageDirty); + connect(dial, &QQuickDial::valueChanged, this, &QQuickStyleItem::markImageDirty); + connect(dial, &QQuickDial::stepSizeChanged, this, &QQuickStyleItem::markImageDirty); + connect(dial, &QQuickDial::pressedChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemDial::calculateGeometry() +{ + QStyleOptionSlider styleOption; + initStyleOption(styleOption); + + StyleItemGeometry geometry; + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_Dial, &styleOption, QSize(0, 0)); + geometry.implicitSize = geometry.minimumSize; + geometry.layoutRect = style()->subElementRect(QStyle::SE_SliderLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CC_Dial, &styleOption, geometry.minimumSize); + geometry.focusFrameRadius = style()->pixelMetric(QStyle::PM_DialFocusFrameRadius, &styleOption); + + return geometry; +} + +void QQuickStyleItemDial::paintEvent(QPainter *painter) const +{ + QStyleOptionSlider styleOption; + initStyleOption(styleOption); + style()->drawComplexControl(QStyle::CC_Dial, &styleOption, painter); +} + +void QQuickStyleItemDial::initStyleOption(QStyleOptionSlider &styleOption) const +{ + initStyleOptionBase(styleOption); + auto dial = control<QQuickDial>(); + + styleOption.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle; + styleOption.activeSubControls = QStyle::SC_None; + styleOption.tickInterval = dial->stepSize(); + styleOption.dialWrapping = dial->wrap(); + styleOption.upsideDown = true; + + if (dial->isPressed()) + styleOption.state |= QStyle::State_Sunken; + + if (dial->stepSize() == 0) { + styleOption.minimum = 0; + styleOption.maximum = 10000; + styleOption.sliderPosition = dial->position() * styleOption.maximum; + } else { + styleOption.minimum = dial->from(); + styleOption.maximum = dial->to(); + styleOption.sliderPosition = dial->value(); + } + + // TODO: add proper API for tickmarks + const int index = dial->metaObject()->indexOfProperty("qqc2_style_tickPosition"); + if (index != -1) { + const int tickPosition = dial->metaObject()->property(index).read(dial).toInt(); + styleOption.tickPosition = QStyleOptionSlider::TickPosition(tickPosition); + if (styleOption.tickPosition != QStyleOptionSlider::NoTicks) + styleOption.subControls |= QStyle::SC_DialTickmarks; + } + +} diff --git a/src/quicknativestyle/items/qquickstyleitemdial.h b/src/quicknativestyle/items/qquickstyleitemdial.h new file mode 100644 index 0000000000..569820fea2 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemdial.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMDIAL_H +#define QQUICKSTYLEITEMDIAL_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickdial_p.h> + +class QQuickStyleItemDial : public QQuickStyleItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(Dial) + +public: + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionSlider &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMDIAL_H diff --git a/src/quicknativestyle/items/qquickstyleitemframe.cpp b/src/quicknativestyle/items/qquickstyleitemframe.cpp new file mode 100644 index 0000000000..cf0604927e --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemframe.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemframe.h" + +StyleItemGeometry QQuickStyleItemFrame::calculateGeometry() +{ + QStyleOptionFrame styleOption; + initStyleOption(styleOption); + StyleItemGeometry geometry; + + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_Frame, &styleOption, QSize(0, 0)); + geometry.implicitSize = contentSize(); + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.contentRect = style()->subElementRect(QStyle::SE_FrameContents, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CE_ShapedFrame, &styleOption, geometry.minimumSize); + + return geometry; +} + +void QQuickStyleItemFrame::paintEvent(QPainter *painter) const +{ + QStyleOptionFrame styleOption; + initStyleOption(styleOption); + style()->drawControl(QStyle::CE_ShapedFrame, &styleOption, painter); +} + +void QQuickStyleItemFrame::initStyleOption(QStyleOptionFrame &styleOption) const +{ + initStyleOptionBase(styleOption); + styleOption.lineWidth = 1; + styleOption.frameShape = QStyleOptionFrame::StyledPanel; + styleOption.features = QStyleOptionFrame::Flat; +} diff --git a/src/quicknativestyle/items/qquickstyleitemframe.h b/src/quicknativestyle/items/qquickstyleitemframe.h new file mode 100644 index 0000000000..8e8da68b35 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemframe.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMFRAME_H +#define QQUICKSTYLEITEMFRAME_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickframe_p.h> + +class QQuickStyleItemFrame : public QQuickStyleItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(Frame) + +protected: + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionFrame &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMFRAME_H diff --git a/src/quicknativestyle/items/qquickstyleitemgroupbox.cpp b/src/quicknativestyle/items/qquickstyleitemgroupbox.cpp new file mode 100644 index 0000000000..a828160d75 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemgroupbox.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemgroupbox.h" + +QFont QQuickStyleItemGroupBox::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_HeaderLabel, controlSize(control)); +} + +StyleItemGeometry QQuickStyleItemGroupBox::calculateGeometry() +{ + QStyleOptionGroupBox styleOption; + initStyleOption(styleOption); + + StyleItemGeometry geometry; + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_GroupBox, &styleOption, QSize(0, 0)); + + if (!control<QQuickGroupBox>()->title().isEmpty()) { + // We don't draw the title, but we need to take + // it into calculation for the control size + styleOption.text = QStringLiteral(" "); + styleOption.subControls |= QStyle::SC_GroupBoxLabel; + } + + geometry.implicitSize = style()->sizeFromContents(QStyle::CT_GroupBox, &styleOption, contentSize()); + styleOption.rect.setSize(geometry.implicitSize); + geometry.contentRect = style()->subControlRect(QStyle::CC_GroupBox, &styleOption, QStyle::SC_GroupBoxContents); + geometry.layoutRect = style()->subElementRect(QStyle::SE_GroupBoxLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CC_GroupBox, &styleOption, geometry.minimumSize); + + const QQuickStyleMargins oldGroupBoxPadding = m_groupBoxPadding; + const QRect frame = style()->subControlRect(QStyle::CC_GroupBox, &styleOption, QStyle::SC_GroupBoxFrame); + m_groupBoxPadding = QQuickStyleMargins(QRect(QPoint(), geometry.implicitSize), frame); + if (m_groupBoxPadding != oldGroupBoxPadding) + emit groupBoxPaddingChanged(); + + const QPointF oldLabelPos = m_labelPos; + m_labelPos = style()->subControlRect(QStyle::CC_GroupBox, &styleOption, QStyle::SC_GroupBoxLabel).topLeft(); + if (m_labelPos != oldLabelPos) + emit labelPosChanged(); + return geometry; +} + +void QQuickStyleItemGroupBox::paintEvent(QPainter *painter) const +{ + QStyleOptionGroupBox styleOption; + initStyleOption(styleOption); + style()->drawComplexControl(QStyle::CC_GroupBox, &styleOption, painter); +} + +void QQuickStyleItemGroupBox::initStyleOption(QStyleOptionGroupBox &styleOption) const +{ + initStyleOptionBase(styleOption); + styleOption.subControls = QStyle::SC_GroupBoxFrame; + styleOption.lineWidth = 1; +} + +QQuickStyleMargins QQuickStyleItemGroupBox::groupBoxPadding() const +{ + return m_groupBoxPadding; +} + +QPointF QQuickStyleItemGroupBox::labelPos() const +{ + return m_labelPos; +} diff --git a/src/quicknativestyle/items/qquickstyleitemgroupbox.h b/src/quicknativestyle/items/qquickstyleitemgroupbox.h new file mode 100644 index 0000000000..2b07287f03 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemgroupbox.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMGROUPBOX_H +#define QQUICKSTYLEITEMGROUPBOX_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickgroupbox_p.h> + +class QQuickStyleItemGroupBox : public QQuickStyleItem +{ + Q_OBJECT + Q_PROPERTY(QQuickStyleMargins groupBoxPadding READ groupBoxPadding NOTIFY groupBoxPaddingChanged) + Q_PROPERTY(QPointF labelPos READ labelPos NOTIFY labelPosChanged) + QML_NAMED_ELEMENT(GroupBox) + +public: + QQuickStyleMargins groupBoxPadding() const; + QPointF labelPos() const; + QFont styleFont(QQuickItem *control) const override; + +signals: + void groupBoxPaddingChanged(); + void labelPosChanged(); + +protected: + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + QQuickStyleMargins m_groupBoxPadding; + QPointF m_labelPos; + + void initStyleOption(QStyleOptionGroupBox &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMGROUPBOX_H diff --git a/src/quicknativestyle/items/qquickstyleitemprogressbar.cpp b/src/quicknativestyle/items/qquickstyleitemprogressbar.cpp new file mode 100644 index 0000000000..480e8981b5 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemprogressbar.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemprogressbar.h" + +QFont QQuickStyleItemProgressBar::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_ProgressBarLabel, controlSize(control)); +} + +void QQuickStyleItemProgressBar::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto progressBar = control<QQuickProgressBar>(); + connect(progressBar, &QQuickProgressBar::fromChanged, this, &QQuickStyleItem::markImageDirty); + connect(progressBar, &QQuickProgressBar::toChanged, this, &QQuickStyleItem::markImageDirty); + connect(progressBar, &QQuickProgressBar::positionChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemProgressBar::calculateGeometry() +{ + QStyleOptionProgressBar styleOption; + initStyleOption(styleOption); + + StyleItemGeometry geometry; + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_ProgressBar, &styleOption, QSize(0, 0)); + + // From qprogressbar.cpp in qtbase: + const int cw = style()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &styleOption); + QFontMetrics fm(control<QQuickProgressBar>()->font()); + QSize size = QSize(qMax(9, cw) * 7 + fm.horizontalAdvance(QLatin1Char('0')) * 4, fm.height() + 8); + if (!(styleOption.state & QStyle::State_Horizontal)) + size = size.transposed(); + + geometry.implicitSize = style()->sizeFromContents(QStyle::CT_ProgressBar, &styleOption, size); + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.contentRect = style()->subElementRect(QStyle::SE_ProgressBarContents, &styleOption); + geometry.layoutRect = style()->subElementRect(QStyle::SE_ProgressBarLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CE_ProgressBar, &styleOption, geometry.minimumSize); + + return geometry; +} + +void QQuickStyleItemProgressBar::paintEvent(QPainter *painter) const +{ + QStyleOptionProgressBar styleOption; + initStyleOption(styleOption); +#ifndef Q_OS_MACOS + const QRect r = styleOption.rect; +#endif + // Note: on macOS, the groove will paint both the background and the contents + styleOption.rect = style()->subElementRect(QStyle::SE_ProgressBarGroove, &styleOption); + style()->drawControl(QStyle::CE_ProgressBarGroove, &styleOption, painter); +#ifndef Q_OS_MACOS + styleOption.rect = r; + styleOption.rect = style()->subElementRect(QStyle::SE_ProgressBarContents, &styleOption); + style()->drawControl(QStyle::CE_ProgressBarContents, &styleOption, painter); +#endif +} + +void QQuickStyleItemProgressBar::initStyleOption(QStyleOptionProgressBar &styleOption) const +{ + initStyleOptionBase(styleOption); + auto progressBar = control<QQuickProgressBar>(); + + styleOption.state = QStyle::State_Horizontal; + + if (progressBar->isIndeterminate()) { + styleOption.minimum = 0; + styleOption.maximum = 0; + } else if (progressBar->to() - progressBar->from() < 100) { + // Add some range to support float numbers + styleOption.minimum = 0; + styleOption.maximum = (progressBar->to() - progressBar->from()) * 100; + styleOption.progress = (progressBar->value() - progressBar->from()) * 100; + } else { + styleOption.minimum = progressBar->from(); + styleOption.maximum = progressBar->to(); + styleOption.progress = progressBar->value(); + } +} diff --git a/src/quicknativestyle/items/qquickstyleitemprogressbar.h b/src/quicknativestyle/items/qquickstyleitemprogressbar.h new file mode 100644 index 0000000000..53692dbe32 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemprogressbar.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMPROGRESSBAR_H +#define QQUICKSTYLEITEMPROGRESSBAR_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickprogressbar_p.h> + +class QQuickStyleItemProgressBar : public QQuickStyleItem +{ + Q_OBJECT + + QML_NAMED_ELEMENT(ProgressBar) + +public: + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionProgressBar &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMPROGRESSBAR_H diff --git a/src/quicknativestyle/items/qquickstyleitemradiobutton.cpp b/src/quicknativestyle/items/qquickstyleitemradiobutton.cpp new file mode 100644 index 0000000000..655bb0b63b --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemradiobutton.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemradiobutton.h" + +QFont QQuickStyleItemRadioButton::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_RadioButtonLabel, controlSize(control)); +} + +void QQuickStyleItemRadioButton::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto checkbox = control<QQuickRadioButton>(); + connect(checkbox, &QQuickRadioButton::downChanged, this, &QQuickStyleItem::markImageDirty); + connect(checkbox, &QQuickRadioButton::checkedChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemRadioButton::calculateGeometry() +{ + QStyleOptionButton styleOption; + initStyleOption(styleOption); + StyleItemGeometry geometry; + + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_RadioButton, &styleOption, QSize(0, 0)); + geometry.implicitSize = geometry.minimumSize; + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.contentRect = style()->subElementRect(QStyle::SE_RadioButtonContents, &styleOption); + geometry.layoutRect = style()->subElementRect(QStyle::SE_RadioButtonLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CE_RadioButton, &styleOption, geometry.minimumSize); + geometry.focusFrameRadius = style()->pixelMetric(QStyle::PM_RadioButtonFocusFrameRadius, &styleOption); + + return geometry; +} + +void QQuickStyleItemRadioButton::paintEvent(QPainter *painter) const +{ + QStyleOptionButton styleOption; + initStyleOption(styleOption); + style()->drawControl(QStyle::CE_RadioButton, &styleOption, painter); +} + +void QQuickStyleItemRadioButton::initStyleOption(QStyleOptionButton &styleOption) const +{ + initStyleOptionBase(styleOption); + auto checkbox = control<QQuickRadioButton>(); + + styleOption.state |= checkbox->isDown() ? QStyle::State_Sunken : QStyle::State_Raised; + styleOption.state |= checkbox->isChecked() ? QStyle::State_On : QStyle::State_Off; +} diff --git a/src/quicknativestyle/items/qquickstyleitemradiobutton.h b/src/quicknativestyle/items/qquickstyleitemradiobutton.h new file mode 100644 index 0000000000..56073d8f49 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemradiobutton.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMRADIOBUTTON_H +#define QQUICKSTYLEITEMRADIOBUTTON_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickradiobutton_p.h> + +class QQuickStyleItemRadioButton : public QQuickStyleItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(RadioButton) + +public: + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionButton &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMRADIOBUTTON_H diff --git a/src/quicknativestyle/items/qquickstyleitemscrollbar.cpp b/src/quicknativestyle/items/qquickstyleitemscrollbar.cpp new file mode 100644 index 0000000000..d6d41d969b --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemscrollbar.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemscrollbar.h" + +QFont QQuickStyleItemScrollBar::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_ProgressBarLabel, controlSize(control)); +} + +void QQuickStyleItemScrollBar::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto scrollBar = control<QQuickScrollBar>(); + connect(scrollBar, &QQuickScrollBar::orientationChanged, this, &QQuickStyleItem::markImageDirty); + connect(scrollBar, &QQuickScrollBar::pressedChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemScrollBar::calculateGeometry() +{ + QStyleOptionSlider styleOption; + initStyleOption(styleOption); + + StyleItemGeometry geometry; + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_ScrollBar, &styleOption, QSize(0, 0)); + if (m_subControl == SubLine || m_subControl == AddLine) { + // So far, we know that only the windows style uses these subcontrols, + // so we can use hardcoded sizes... + QSize sz(16, 17); + if (styleOption.orientation == Qt::Vertical) + sz.transpose(); + geometry.minimumSize = sz; + } + geometry.implicitSize = geometry.minimumSize; + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.layoutRect = style()->subElementRect(QStyle::SE_ScrollBarLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CC_ScrollBar, &styleOption, geometry.minimumSize); + + return geometry; +} + +void QQuickStyleItemScrollBar::paintEvent(QPainter *painter) const +{ + QStyleOptionSlider styleOption; + initStyleOption(styleOption); + if (m_subControl == SubLine || m_subControl == AddLine) { + QStyle::SubControl sc = m_subControl == SubLine ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine; + QStyleOptionSlider opt = styleOption; + opt.subControls = QStyle::SC_ScrollBarAddLine + | QStyle::SC_ScrollBarSubLine + | QStyle::SC_ScrollBarGroove; + + const qreal scale = window()->devicePixelRatio(); + const QSize scrollBarMinSize = style()->sizeFromContents(QStyle::CT_ScrollBar, &opt, QSize(0, 0)); + const QSize sz = scrollBarMinSize * scale; + QImage scrollBarImage(sz, QImage::Format_ARGB32_Premultiplied); + scrollBarImage.setDevicePixelRatio(scale); + QPainter p(&scrollBarImage); + opt.rect = QRect(QPoint(0, 0), scrollBarMinSize); + style()->drawComplexControl(QStyle::CC_ScrollBar, &opt, &p); + QRect sourceImageRect = style()->subControlRect(QStyle::CC_ScrollBar, &opt, sc); + sourceImageRect = QRect(sourceImageRect.topLeft() * scale, sourceImageRect.size() * scale); + painter->drawImage(QPoint(0, 0), scrollBarImage, sourceImageRect); + } else { + style()->drawComplexControl(QStyle::CC_ScrollBar, &styleOption, painter); + } +} + +void QQuickStyleItemScrollBar::initStyleOption(QStyleOptionSlider &styleOption) const +{ + initStyleOptionBase(styleOption); + auto scrollBar = control<QQuickScrollBar>(); + + switch (m_subControl) { + case Groove: + styleOption.subControls = QStyle::SC_ScrollBarGroove | QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine; + break; + case Handle: + styleOption.subControls = QStyle::SC_ScrollBarSlider; + break; + case AddLine: + styleOption.subControls = QStyle::SC_ScrollBarAddLine; + break; + case SubLine: + styleOption.subControls = QStyle::SC_ScrollBarSubLine; + break; + } + + styleOption.activeSubControls = QStyle::SC_None; + styleOption.orientation = scrollBar->orientation(); + if (styleOption.orientation == Qt::Horizontal) + styleOption.state |= QStyle::State_Horizontal; + + if (scrollBar->isPressed()) + styleOption.state |= QStyle::State_Sunken; + + if (m_overrideState != None) { + // In ScrollBar.qml we fade between two versions of + // the handle, depending on if it's hovered or not + + if (m_overrideState == AlwaysHovered) { + styleOption.activeSubControls = (styleOption.subControls & (QStyle::SC_ScrollBarSlider | QStyle::SC_ScrollBarGroove | QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)); + } else if (m_overrideState == NeverHovered) { + styleOption.activeSubControls &= ~(styleOption.subControls & (QStyle::SC_ScrollBarSlider | QStyle::SC_ScrollBarGroove | QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)); + } else if (m_overrideState == AlwaysSunken) { + styleOption.state |= QStyle::State_Sunken; + styleOption.activeSubControls = (styleOption.subControls & (QStyle::SC_ScrollBarSlider | QStyle::SC_ScrollBarGroove | QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)); + } + } + + // The following values will let the handle fill 100% of the + // groove / imageSize. But when the handle is resized by + // QQuickScrollBar, it will end up with the correct size visually. + styleOption.pageStep = 1000; + styleOption.minimum = 0; + styleOption.maximum = 1; + styleOption.sliderValue = 0; +} diff --git a/src/quicknativestyle/items/qquickstyleitemscrollbar.h b/src/quicknativestyle/items/qquickstyleitemscrollbar.h new file mode 100644 index 0000000000..f89d8d3ec3 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemscrollbar.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMSCROLLBAR_H +#define QQUICKSTYLEITEMSCROLLBAR_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickscrollbar_p.h> + +class QQuickStyleItemScrollBar : public QQuickStyleItem +{ + Q_OBJECT + + Q_PROPERTY(SubControl subControl MEMBER m_subControl) + + QML_NAMED_ELEMENT(ScrollBar) + +public: + enum SubControl { + Groove = 1, + Handle, + AddLine, + SubLine + }; + Q_ENUM(SubControl) + + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionSlider &styleOption) const; + +private: + SubControl m_subControl = Groove; +}; + +#endif // QQUICKSTYLEITEMSCROLLBAR_H diff --git a/src/quicknativestyle/items/qquickstyleitemscrollviewcorner.cpp b/src/quicknativestyle/items/qquickstyleitemscrollviewcorner.cpp new file mode 100644 index 0000000000..3a992f2d9b --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemscrollviewcorner.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemscrollviewcorner.h" + +StyleItemGeometry QQuickStyleItemScrollViewCorner::calculateGeometry() +{ + QStyleOptionSlider styleOption; + initStyleOption(styleOption); + + StyleItemGeometry geometry; + + // The size of the corner should be the width of the vertical + // scrollbar and the height of the horizontal scrollbar. + styleOption.orientation = Qt::Vertical; + const auto vScrollBarWidth = style()->sizeFromContents(QStyle::CT_ScrollBar, &styleOption, QSize(0, 0)).width(); + styleOption.orientation = Qt::Horizontal; + const auto hScrollBarHeight = style()->sizeFromContents(QStyle::CT_ScrollBar, &styleOption, QSize(0, 0)).height(); + + geometry.minimumSize = QSize(vScrollBarWidth, hScrollBarHeight); + geometry.implicitSize = geometry.minimumSize; + + return geometry; +} + +void QQuickStyleItemScrollViewCorner::paintEvent(QPainter *painter) const +{ + QStyleOptionSlider styleOption; + initStyleOption(styleOption); + + // Grab a center piece of a vertical scrollbar groove onto a QImage, and use this + // image to draw a corner. We draw the corner by first drawing the piece as it is, and + // then rotate it 90 degrees, clip it into a triangle, and draw it once more on top. + // The result is that we end up with one vertical and one horizontal triangle that + // together form a filled corner rectangle. + + styleOption.orientation = Qt::Vertical; + + const qreal scale = window()->devicePixelRatio(); + const int grooveWidth = minimumSize().width(); + const int grooveHeight = minimumSize().height(); + const QSize scrollBarMinSize = style()->sizeFromContents(QStyle::CT_ScrollBar, &styleOption, QSize(0, 0)); + const QSize scrollBarSize = scrollBarMinSize + QSize(0, grooveHeight); + const int hStart = scrollBarMinSize.height() / 2; + const QRect targetImageRect(0, hStart * scale, grooveWidth * scale, grooveHeight * scale); + + QImage scrollBarImage(scrollBarSize * scale, QImage::Format_ARGB32_Premultiplied); + scrollBarImage.setDevicePixelRatio(scale); + scrollBarImage.fill(Qt::transparent); + QPainter scrollBarPainter(&scrollBarImage); + styleOption.rect = QRect(QPoint(0, 0), scrollBarSize); + style()->drawComplexControl(QStyle::CC_ScrollBar, &styleOption, &scrollBarPainter); + + // Draw vertical groove + painter->drawImage(QPoint(0, 0), scrollBarImage, targetImageRect); + + QPainterPath path; + path.moveTo(0, 0); + path.lineTo(0, grooveHeight); + path.lineTo(grooveWidth, grooveHeight); + path.closeSubpath(); + + QTransform transform; + transform.translate(grooveWidth, 0); + transform.rotate(90); + + painter->save(); + painter->setCompositionMode(QPainter::CompositionMode_Source); + painter->setClipPath(path); + painter->setTransform(transform); + // Draw horizontal groove, clipped to a triangle + painter->drawImage(QPoint(0, 0), scrollBarImage, targetImageRect); + painter->restore(); +} + +void QQuickStyleItemScrollViewCorner::initStyleOption(QStyleOptionSlider &styleOption) const +{ + initStyleOptionBase(styleOption); + + styleOption.subControls = QStyle::SC_ScrollBarGroove; + styleOption.activeSubControls = QStyle::SC_None; + styleOption.pageStep = 1000; + styleOption.minimum = 0; + styleOption.maximum = 1; + styleOption.sliderValue = 0; +} diff --git a/src/quicknativestyle/items/qquickstyleitemscrollviewcorner.h b/src/quicknativestyle/items/qquickstyleitemscrollviewcorner.h new file mode 100644 index 0000000000..637a8ea821 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemscrollviewcorner.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMSCROLLVIEWCORNER_H +#define QQUICKSTYLEITEMSCROLLVIEWCORNER_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickscrollbar_p.h> + +class QQuickStyleItemScrollViewCorner : public QQuickStyleItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(ScrollViewCorner) + +protected: + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionSlider &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMSCROLLVIEWCORNER_H diff --git a/src/quicknativestyle/items/qquickstyleitemslider.cpp b/src/quicknativestyle/items/qquickstyleitemslider.cpp new file mode 100644 index 0000000000..67161ad3da --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemslider.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemslider.h" + +QFont QQuickStyleItemSlider::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_ProgressBarLabel, controlSize(control)); +} + +void QQuickStyleItemSlider::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto slider = control<QQuickSlider>(); + connect(slider, &QQuickSlider::fromChanged, this, &QQuickStyleItem::markImageDirty); + connect(slider, &QQuickSlider::toChanged, this, &QQuickStyleItem::markImageDirty); + connect(slider, &QQuickSlider::positionChanged, this, &QQuickStyleItem::markImageDirty); + connect(slider, &QQuickSlider::valueChanged, this, &QQuickStyleItem::markImageDirty); + connect(slider, &QQuickSlider::stepSizeChanged, this, &QQuickStyleItem::markImageDirty); + connect(slider, &QQuickSlider::pressedChanged, this, &QQuickStyleItem::markImageDirty); + connect(slider, &QQuickSlider::orientationChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemSlider::calculateGeometry() +{ + QStyleOptionSlider styleOption; + initStyleOption(styleOption); + + StyleItemGeometry geometry; + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_Slider, &styleOption, QSize(0, 0)); + geometry.implicitSize = geometry.minimumSize; + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.layoutRect = style()->subElementRect(QStyle::SE_SliderLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CC_Slider, &styleOption, geometry.minimumSize); + geometry.focusFrameRadius = style()->pixelMetric(QStyle::PM_SliderFocusFrameRadius, &styleOption); + + return geometry; +} + +void QQuickStyleItemSlider::paintEvent(QPainter *painter) const +{ + QStyleOptionSlider styleOption; + initStyleOption(styleOption); + style()->drawComplexControl(QStyle::CC_Slider, &styleOption, painter); +} + +void QQuickStyleItemSlider::initStyleOption(QStyleOptionSlider &styleOption) const +{ + initStyleOptionBase(styleOption); + auto slider = control<QQuickSlider>(); + + styleOption.subControls = QStyle::SC_None; + if (m_subControl & Groove) + styleOption.subControls |= QStyle::SC_SliderGroove; + if (m_subControl & Handle) + styleOption.subControls |= QStyle::SC_SliderHandle; + styleOption.activeSubControls = QStyle::SC_None; + styleOption.orientation = slider->orientation(); + + if (slider->isPressed()) + styleOption.state |= QStyle::State_Sunken; + + qreal min = 0; + qreal max = 1; + if (!qFuzzyIsNull(slider->stepSize())) { + min = slider->from(); + max = slider->to(); + + // TODO: add proper API for tickmarks + const int index = slider->metaObject()->indexOfProperty("qqc2_style_tickPosition"); + if (index != -1) { + const int tickPosition = slider->metaObject()->property(index).read(slider).toInt(); + styleOption.tickPosition = QStyleOptionSlider::TickPosition(tickPosition); + if (styleOption.tickPosition != QStyleOptionSlider::NoTicks) + styleOption.subControls |= QStyle::SC_SliderTickmarks; + } + } + + // Since the [from, to] interval in QQuickSlider is floating point, users can + // specify very small ranges and step sizes, (e.g. [0.., 0.25], step size 0.05). + // Since the style operates on ints, we cannot pass these values directly to the style, + // so we normalize all values to the range [0, 10000] + static const qreal Scale = 10000; + const qreal normalizeMultiplier = Scale/(max - min); + styleOption.tickInterval = int(slider->stepSize() * normalizeMultiplier); + styleOption.minimum = 0; + styleOption.maximum = int(Scale); + styleOption.sliderValue = int((slider->value() - min) * normalizeMultiplier); + styleOption.sliderPosition = int(slider->position() * styleOption.maximum); +} diff --git a/src/quicknativestyle/items/qquickstyleitemslider.h b/src/quicknativestyle/items/qquickstyleitemslider.h new file mode 100644 index 0000000000..9a5142072b --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemslider.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMSLIDER_H +#define QQUICKSTYLEITEMSLIDER_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickslider_p.h> + +class QQuickStyleItemSlider : public QQuickStyleItem +{ + Q_OBJECT + + Q_PROPERTY(SubControl subControl MEMBER m_subControl) + + QML_NAMED_ELEMENT(Slider) + +public: + enum SubControl { + Groove = 1, + Handle, + }; + Q_ENUM(SubControl) + + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionSlider &styleOption) const; + +private: + SubControl m_subControl = Groove; +}; + +#endif // QQUICKSTYLEITEMSLIDER_H diff --git a/src/quicknativestyle/items/qquickstyleitemspinbox.cpp b/src/quicknativestyle/items/qquickstyleitemspinbox.cpp new file mode 100644 index 0000000000..2a232b8a39 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemspinbox.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemspinbox.h" +#include <QtQuickTemplates2/private/qquickindicatorbutton_p.h> + +QFont QQuickStyleItemSpinBox::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_ComboBoxLabel, controlSize(control)); +} + +void QQuickStyleItemSpinBox::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto spinbox = control<QQuickSpinBox>(); + connect(spinbox->up(), &QQuickIndicatorButton::pressedChanged, this, &QQuickStyleItem::markImageDirty); + connect(spinbox->down(), &QQuickIndicatorButton::pressedChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemSpinBox::calculateGeometry() +{ + QStyleOptionSpinBox styleOption; + initStyleOption(styleOption); + StyleItemGeometry geometry; + + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_SpinBox, &styleOption, QSize(0, 0)); + + if (styleOption.subControls == QStyle::SC_SpinBoxFrame) { + geometry.implicitSize = style()->sizeFromContents(QStyle::CT_SpinBox, &styleOption, contentSize()); + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.contentRect = style()->subControlRect(QStyle::CC_SpinBox, &styleOption, QStyle::SC_SpinBoxEditField); + geometry.layoutRect = style()->subElementRect(QStyle::SE_SpinBoxLayoutItem, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CC_SpinBox, &styleOption, geometry.minimumSize); + geometry.focusFrameRadius = style()->pixelMetric(QStyle::PM_SpinBoxFocusFrameRadius, &styleOption); + } else { + geometry.implicitSize = geometry.minimumSize; + } + + return geometry; +} + +void QQuickStyleItemSpinBox::paintEvent(QPainter *painter) const +{ + QStyleOptionSpinBox styleOption; + initStyleOption(styleOption); + style()->drawComplexControl(QStyle::CC_SpinBox, &styleOption, painter); +} + +void QQuickStyleItemSpinBox::initStyleOption(QStyleOptionSpinBox &styleOption) const +{ + initStyleOptionBase(styleOption); + auto spinbox = control<QQuickSpinBox>(); + + switch (m_subControl) { + case Frame: + styleOption.subControls = QStyle::SC_SpinBoxFrame; + styleOption.frame = true; + break; + case Up: + styleOption.subControls = (QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown); + break; + case Down: + styleOption.subControls = QStyle::SC_SpinBoxDown; + break; + } + + if (spinbox->up()->isPressed()) { + styleOption.activeSubControls = QStyle::SC_SpinBoxUp; + styleOption.state |= QStyle::State_Sunken; + } else if (spinbox->down()->isPressed()) { + styleOption.activeSubControls = QStyle::SC_SpinBoxDown; + styleOption.state |= QStyle::State_Sunken; + } + + styleOption.buttonSymbols = QStyleOptionSpinBox::UpDownArrows; + styleOption.stepEnabled = QStyleOptionSpinBox::StepEnabled; +} diff --git a/src/quicknativestyle/items/qquickstyleitemspinbox.h b/src/quicknativestyle/items/qquickstyleitemspinbox.h new file mode 100644 index 0000000000..d4b9f9fa6c --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemspinbox.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMSPINBOX_H +#define QQUICKSTYLEITEMSPINBOX_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquickspinbox_p.h> + +class QQuickStyleItemSpinBox : public QQuickStyleItem +{ + Q_OBJECT + + Q_PROPERTY(SubControl subControl MEMBER m_subControl) + + QML_NAMED_ELEMENT(SpinBox) + +public: + enum SubControl { + Frame = 1, + Up, + Down, + }; + Q_ENUM(SubControl) + + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionSpinBox &styleOption) const; + +private: + SubControl m_subControl = Frame; +}; + +#endif // QQUICKSTYLEITEMSPINBOX_H diff --git a/src/quicknativestyle/items/qquickstyleitemtextfield.cpp b/src/quicknativestyle/items/qquickstyleitemtextfield.cpp new file mode 100644 index 0000000000..cd7d35aa67 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemtextfield.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitemtextfield.h" + +QFont QQuickStyleItemTextField::styleFont(QQuickItem *control) const +{ + return style()->font(QStyle::CE_ComboBoxLabel, controlSize(control)); +} + +void QQuickStyleItemTextField::connectToControl() const +{ + QQuickStyleItem::connectToControl(); + auto textField = control<QQuickTextField>(); + connect(textField, &QQuickTextField::readOnlyChanged, this, &QQuickStyleItem::markImageDirty); + connect(textField, &QQuickTextField::focusChanged, this, &QQuickStyleItem::markImageDirty); +} + +StyleItemGeometry QQuickStyleItemTextField::calculateGeometry() +{ + QStyleOptionFrame styleOption; + initStyleOption(styleOption); + StyleItemGeometry geometry; + + geometry.minimumSize = style()->sizeFromContents(QStyle::CT_LineEdit, &styleOption, QSize(0, 0)); + geometry.implicitSize = style()->sizeFromContents(QStyle::CT_LineEdit, &styleOption, contentSize()); + styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize); + geometry.layoutRect = styleOption.rect; + geometry.contentRect = style()->subElementRect(QStyle::SE_LineEditContents, &styleOption); + geometry.ninePatchMargins = style()->ninePatchMargins(QStyle::CE_ShapedFrame, &styleOption, geometry.minimumSize); + geometry.focusFrameRadius = style()->pixelMetric(QStyle::PM_TextFieldFocusFrameRadius, &styleOption); + + return geometry; +} + +void QQuickStyleItemTextField::paintEvent(QPainter *painter) const +{ + QStyleOptionFrame styleOption; + initStyleOption(styleOption); + style()->drawPrimitive(QStyle::PE_PanelLineEdit, &styleOption, painter); +} + +void QQuickStyleItemTextField::initStyleOption(QStyleOptionFrame &styleOption) const +{ + initStyleOptionBase(styleOption); + auto textField = control<QQuickTextField>(); + + styleOption.lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &styleOption); + styleOption.midLineWidth = 0; + styleOption.state |= QStyle::State_Sunken; + if (textField->isReadOnly()) + styleOption.state |= QStyle::State_ReadOnly; +} diff --git a/src/quicknativestyle/items/qquickstyleitemtextfield.h b/src/quicknativestyle/items/qquickstyleitemtextfield.h new file mode 100644 index 0000000000..35aaf753b5 --- /dev/null +++ b/src/quicknativestyle/items/qquickstyleitemtextfield.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEMTEXTFIELD_H +#define QQUICKSTYLEITEMTEXTFIELD_H + +#include "qquickstyleitem.h" +#include <QtQuickTemplates2/private/qquicktextfield_p.h> + +class QQuickStyleItemTextField : public QQuickStyleItem +{ + Q_OBJECT + QML_NAMED_ELEMENT(TextField) + +public: + QFont styleFont(QQuickItem *control) const override; + +protected: + void connectToControl() const override; + void paintEvent(QPainter *painter) const override; + StyleItemGeometry calculateGeometry() override; + +private: + void initStyleOption(QStyleOptionFrame &styleOption) const; +}; + +#endif // QQUICKSTYLEITEMTEXTFIELD_H |