From 16f7652717c6587fb9013ca1bb0aef9c74f1fa27 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 14 Sep 2023 10:55:56 +0200 Subject: [PATCH] Utils: Add AspectList::addToLayout Added a new, clean IconButton that mimiks the ToolButton with the compact/relaxed background. Change-Id: I582c6aac404724af5459bab2ca9023aa63171f93 Reviewed-by: hjk --- src/libs/utils/CMakeLists.txt | 1 + src/libs/utils/aspects.cpp | 81 ++++++++++++++++++++++++++++++ src/libs/utils/aspects.h | 1 + src/libs/utils/fancylineedit.cpp | 19 +++---- src/libs/utils/fancylineedit.h | 4 +- src/libs/utils/iconbutton.cpp | 62 +++++++++++++++++++++++ src/libs/utils/iconbutton.h | 27 ++++++++++ src/libs/utils/utils.qbs | 2 + src/libs/utils/variablechooser.cpp | 4 +- 9 files changed, 188 insertions(+), 13 deletions(-) create mode 100644 src/libs/utils/iconbutton.cpp create mode 100644 src/libs/utils/iconbutton.h diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index b7f956f968f..2467f6dfbc5 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -75,6 +75,7 @@ add_qtc_library(Utils hostosinfo.cpp hostosinfo.h htmldocextractor.cpp htmldocextractor.h icon.cpp icon.h + iconbutton.cpp iconbutton.h id.cpp id.h indexedcontainerproxyconstiterator.h infobar.cpp infobar.h diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index b5669908486..42bd40badf3 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -7,6 +7,7 @@ #include "checkablemessagebox.h" #include "environment.h" #include "fancylineedit.h" +#include "iconbutton.h" #include "layoutbuilder.h" #include "passworddialog.h" #include "pathchooser.h" @@ -14,6 +15,7 @@ #include "qtcassert.h" #include "qtcolorbutton.h" #include "qtcsettings.h" +#include "utilsicons.h" #include "utilstr.h" #include "variablechooser.h" @@ -26,9 +28,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include #include @@ -3155,5 +3160,81 @@ bool AspectList::isDirty() return false; } +class ColoredRow : public QWidget +{ +public: + ColoredRow(int idx, QWidget *parent = nullptr) + : QWidget(parent) + , m_index(idx) + {} + void paintEvent(QPaintEvent *event) + { + QPainter p(this); + QPalette pal = palette(); + if (m_index % 2 == 0) + p.fillRect(event->rect(), pal.base()); + else + p.fillRect(event->rect(), pal.alternateBase()); + } + +private: + int m_index; +}; + +void AspectList::addToLayout(Layouting::LayoutItem &parent) +{ + using namespace Layouting; + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidgetResizable(true); + scrollArea->setMaximumHeight(100); + scrollArea->setMinimumHeight(100); + scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + auto fill = [this, scrollArea]() mutable { + if (scrollArea->widget()) + delete scrollArea->takeWidget(); + + auto add = new QPushButton(Tr::tr("Add")); + QObject::connect(add, &QPushButton::clicked, scrollArea, [this] { + addItem(d->createItem()); + }); + + Column column{noMargin()}; + + forEachItem([&column, this](const std::shared_ptr &item, int idx) { + auto removeBtn = new IconButton; + removeBtn->setIcon(Utils::Icons::EDIT_CLEAR.icon()); + removeBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + QObject::connect(removeBtn, &QPushButton::clicked, removeBtn, [this, item] { + removeItem(item); + }); + ColoredRow *rowWdgt = new ColoredRow(idx); + // clang-format off + auto row = Row { + *item, + removeBtn, + spacing(5), + }; + // clang-format on + row.attachTo(rowWdgt); + column.addItem(rowWdgt); + }); + + ColoredRow *rowWdgt = new ColoredRow(size()); + Row{st, add}.attachTo(rowWdgt); + column.addItem(rowWdgt); + + QWidget *contentWidget = column.emerge(); + contentWidget->layout()->setSpacing(1); + + scrollArea->setWidget(contentWidget); + }; + + fill(); + QObject::connect(this, &AspectList::volatileValueChanged, scrollArea, fill); + + parent.addItem(scrollArea); +} } // namespace Utils diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h index d07be7bcb77..fb1945b156e 100644 --- a/src/libs/utils/aspects.h +++ b/src/libs/utils/aspects.h @@ -1062,6 +1062,7 @@ public: QVariant volatileVariantValue() const override { return {}; } + void addToLayout(Layouting::LayoutItem &parent) override; private: std::unique_ptr d; diff --git a/src/libs/utils/fancylineedit.cpp b/src/libs/utils/fancylineedit.cpp index 09fe9380197..f30fa4bd841 100644 --- a/src/libs/utils/fancylineedit.cpp +++ b/src/libs/utils/fancylineedit.cpp @@ -102,7 +102,7 @@ public: bool eventFilter(QObject *obj, QEvent *event) override; FancyLineEdit *m_lineEdit; - IconButton *m_iconbutton[2]; + FancyIconButton *m_iconbutton[2]; HistoryCompleter *m_historyCompleter = nullptr; QShortcut m_completionShortcut; FancyLineEdit::ValidationFunction m_validationFunction = &FancyLineEdit::validateWithValidator; @@ -151,7 +151,7 @@ FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) &m_completionShortcut, &QShortcut::setKey); for (int i = 0; i < 2; ++i) { - m_iconbutton[i] = new IconButton(parent); + m_iconbutton[i] = new FancyIconButton(parent); m_iconbutton[i]->installEventFilter(this); m_iconbutton[i]->hide(); m_iconbutton[i]->setAutoHide(false); @@ -619,14 +619,15 @@ QString FancyLineEdit::fixInputString(const QString &string) // IconButton - helper class to represent a clickable icon // -IconButton::IconButton(QWidget *parent) - : QAbstractButton(parent), m_autoHide(false) +FancyIconButton::FancyIconButton(QWidget *parent) + : QAbstractButton(parent) + , m_autoHide(false) { setCursor(Qt::ArrowCursor); setFocusPolicy(Qt::NoFocus); } -void IconButton::paintEvent(QPaintEvent *) +void FancyIconButton::paintEvent(QPaintEvent *) { const qreal pixelRatio = window()->windowHandle()->devicePixelRatio(); const QPixmap iconPixmap = icon().pixmap(sizeHint(), pixelRatio, @@ -653,7 +654,7 @@ void IconButton::paintEvent(QPaintEvent *) } } -void IconButton::animateShow(bool visible) +void FancyIconButton::animateShow(bool visible) { QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity"); animation->setDuration(FADE_TIME); @@ -661,13 +662,13 @@ void IconButton::animateShow(bool visible) animation->start(QAbstractAnimation::DeleteWhenStopped); } -QSize IconButton::sizeHint() const +QSize FancyIconButton::sizeHint() const { QWindow *window = this->window()->windowHandle(); return icon().actualSize(window, QSize(32, 16)); // Find flags icon can be wider than 16px } -void IconButton::keyPressEvent(QKeyEvent *ke) +void FancyIconButton::keyPressEvent(QKeyEvent *ke) { QAbstractButton::keyPressEvent(ke); if (!ke->modifiers() && (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)) @@ -676,7 +677,7 @@ void IconButton::keyPressEvent(QKeyEvent *ke) ke->accept(); } -void IconButton::keyReleaseEvent(QKeyEvent *ke) +void FancyIconButton::keyReleaseEvent(QKeyEvent *ke) { QAbstractButton::keyReleaseEvent(ke); // do not forward to line edit diff --git a/src/libs/utils/fancylineedit.h b/src/libs/utils/fancylineedit.h index c5212aa6392..1b9cf4d5e52 100644 --- a/src/libs/utils/fancylineedit.h +++ b/src/libs/utils/fancylineedit.h @@ -23,13 +23,13 @@ namespace Utils { class FancyLineEditPrivate; -class QTCREATOR_UTILS_EXPORT IconButton: public QAbstractButton +class QTCREATOR_UTILS_EXPORT FancyIconButton : public QAbstractButton { Q_OBJECT Q_PROPERTY(float iconOpacity READ iconOpacity WRITE setIconOpacity) Q_PROPERTY(bool autoHide READ hasAutoHide WRITE setAutoHide) public: - explicit IconButton(QWidget *parent = nullptr); + explicit FancyIconButton(QWidget *parent = nullptr); void paintEvent(QPaintEvent *event) override; float iconOpacity() { return m_iconOpacity; } void setIconOpacity(float value) { m_iconOpacity = value; update(); } diff --git a/src/libs/utils/iconbutton.cpp b/src/libs/utils/iconbutton.cpp new file mode 100644 index 00000000000..746cf0ecb1c --- /dev/null +++ b/src/libs/utils/iconbutton.cpp @@ -0,0 +1,62 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "iconbutton.h" + +#include "stylehelper.h" +#include "theme/theme.h" + +#include +#include +#include + +namespace Utils { + +IconButton::IconButton(QWidget *parent) + : QAbstractButton(parent) +{ + setAttribute(Qt::WA_Hover); +} + +void IconButton::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e); + + QPainter p(this); + QRect r(QPoint(), size()); + + if (m_containsMouse && isEnabled()) { + QColor c = creatorTheme()->color(Theme::TextColorDisabled); + c.setAlphaF(c.alphaF() * .5); + StyleHelper::drawPanelBgRect(&p, r, c); + } + + icon().paint(&p, r, Qt::AlignCenter); +} + +void IconButton::enterEvent(QEnterEvent *e) +{ + m_containsMouse = true; + e->accept(); + update(); +} + +void IconButton::leaveEvent(QEvent *e) +{ + m_containsMouse = false; + e->accept(); + update(); +} + +QSize IconButton::sizeHint() const +{ + QWindow *window = this->window()->windowHandle(); + QSize s = icon().actualSize(window, QSize(32, 16)) + QSize(8, 8); + + if (StyleHelper::toolbarStyle() == StyleHelper::ToolbarStyleRelaxed) + s += QSize(5, 5); + + return s; +} + +} // namespace Utils diff --git a/src/libs/utils/iconbutton.h b/src/libs/utils/iconbutton.h new file mode 100644 index 00000000000..db615eefb11 --- /dev/null +++ b/src/libs/utils/iconbutton.h @@ -0,0 +1,27 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "utils_global.h" + +#include + +namespace Utils { + +class QTCREATOR_UTILS_EXPORT IconButton : public QAbstractButton +{ +public: + IconButton(QWidget *parent = nullptr); + + void paintEvent(QPaintEvent *e) override; + void enterEvent(QEnterEvent *e) override; + void leaveEvent(QEvent *e) override; + + QSize sizeHint() const override; + +private: + bool m_containsMouse{false}; +}; + +} // namespace Utils diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index 40a75de69e1..0c74fedc443 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -157,6 +157,8 @@ QtcLibrary { "htmldocextractor.h", "icon.cpp", "icon.h", + "iconbutton.cpp", + "iconbutton.h", "id.cpp", "id.h", "indexedcontainerproxyconstiterator.h", diff --git a/src/libs/utils/variablechooser.cpp b/src/libs/utils/variablechooser.cpp index 07348b64894..22513d4bb45 100644 --- a/src/libs/utils/variablechooser.cpp +++ b/src/libs/utils/variablechooser.cpp @@ -81,7 +81,7 @@ public: void createIconButton() { - m_iconButton = new IconButton; + m_iconButton = new FancyIconButton; m_iconButton->setIcon(Icons::REPLACE.icon()); m_iconButton->setToolTip(Tr::tr("Insert Variable")); m_iconButton->hide(); @@ -108,7 +108,7 @@ public: QPointer m_lineEdit; QPointer m_textEdit; QPointer m_plainTextEdit; - QPointer m_iconButton; + QPointer m_iconButton; FancyLineEdit *m_variableFilter; VariableTreeView *m_variableTree;