From be08a2fd45042dfc841662bfda44577c0fcaffd7 Mon Sep 17 00:00:00 2001 From: Alfredo Monclus Date: Wed, 26 Feb 2025 13:50:35 -0300 Subject: [PATCH 1/4] start: fix visibility by removing hardcoded styling from newfile buttons this allows the new file buttons to change from light to dark dynamically --- src/Mod/Start/Gui/StartView.cpp | 74 ++------------------------------- 1 file changed, 4 insertions(+), 70 deletions(-) diff --git a/src/Mod/Start/Gui/StartView.cpp b/src/Mod/Start/Gui/StartView.cpp index bcc51ba28a..fea28b0b7b 100644 --- a/src/Mod/Start/Gui/StartView.cpp +++ b/src/Mod/Start/Gui/StartView.cpp @@ -72,7 +72,7 @@ class NewFileButton: public QPushButton { public: - NewFileButton(const NewButton& newButton) + explicit NewFileButton(const NewButton& newButton) { auto hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Start"); @@ -92,7 +92,9 @@ public: auto textLayout = gsl::owner(new QVBoxLayout); auto textLabelLine1 = gsl::owner(new QLabel(this)); textLabelLine1->setText(newButton.heading); - textLabelLine1->setStyleSheet(QLatin1String("font-weight: bold;")); + QFont font = textLabelLine1->font(); + font.setWeight(QFont::Bold); + textLabelLine1->setFont(font); auto textLabelLine2 = gsl::owner(new QLabel(this)); textLabelLine2->setText(newButton.description); textLabelLine2->setWordWrap(true); @@ -105,75 +107,7 @@ public: this->setMinimumHeight(newFileIconSize + cardSpacing); this->setMinimumWidth(newFileIconSize + cardLabelWith); - - updateStyle(); } - - void updateStyle() - { - QString style = QStringLiteral(""); - if (qApp->styleSheet().isEmpty()) { - style = fileCardStyle(); - } - setStyleSheet(style); // This will trigger a changeEvent - } - - void changeEvent(QEvent* event) override - { - if (!changeInProgress && event->type() == QEvent::StyleChange) { - changeInProgress = true; // Block recursive calls. - updateStyle(); - changeInProgress = false; - } - - QPushButton::changeEvent(event); - } - - - QString fileCardStyle() const - { - auto hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Start"); - - auto getUserColor = [&hGrp](QColor color, const char* parameter) { - uint32_t packed = Base::Color::asPackedRGB(color); - packed = hGrp->GetUnsigned(parameter, packed); - color = Base::Color::fromPackedRGB(packed); - return color; - }; - - QColor background(221, 221, 221); // NOLINT - background = getUserColor(background, "FileCardBackgroundColor"); - - QColor hovered(98, 160, 234); // NOLINT - hovered = getUserColor(hovered, "FileCardBorderColor"); - - QColor pressed(38, 162, 105); // NOLINT - pressed = getUserColor(pressed, "FileCardSelectionColor"); - - return QStringLiteral("QPushButton {" - " background-color: rgb(%1, %2, %3);" - " border-radius: 8px;" - "}" - "QPushButton:hover {" - " border: 2px solid rgb(%4, %5, %6);" - "}" - "QPushButton:pressed {" - " border: 2px solid rgb(%7, %8, %9);" - "}") - .arg(background.red()) - .arg(background.green()) - .arg(background.blue()) - .arg(hovered.red()) - .arg(hovered.green()) - .arg(hovered.blue()) - .arg(pressed.red()) - .arg(pressed.green()) - .arg(pressed.blue()); - } - -private: - bool changeInProgress = false; }; } // namespace From e4a14871f512994f0ae70d630ad13220f152d670 Mon Sep 17 00:00:00 2001 From: Alfredo Monclus Date: Wed, 26 Feb 2025 14:52:08 -0300 Subject: [PATCH 2/4] start: fix new file button layout size fixes #15758 --- src/Mod/Start/Gui/StartView.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Mod/Start/Gui/StartView.cpp b/src/Mod/Start/Gui/StartView.cpp index fea28b0b7b..b07286bbc1 100644 --- a/src/Mod/Start/Gui/StartView.cpp +++ b/src/Mod/Start/Gui/StartView.cpp @@ -83,6 +83,7 @@ public: static_cast(hGrp->GetInt("FileCardLabelWith", 180)); // NOLINT auto mainLayout = gsl::owner(new QHBoxLayout(this)); + mainLayout->setAlignment(Qt::AlignVCenter); auto iconLabel = gsl::owner(new QLabel(this)); mainLayout->addWidget(iconLabel); QIcon baseIcon(newButton.iconPath); @@ -105,8 +106,16 @@ public: mainLayout->addStretch(); - this->setMinimumHeight(newFileIconSize + cardSpacing); - this->setMinimumWidth(newFileIconSize + cardLabelWith); + textLabelLine1->adjustSize(); + textLabelLine2->adjustSize(); + int textHeight = + textLabelLine1->height() + textLabelLine2->height() + textLayout->spacing(); + + int minWidth = newFileIconSize + cardLabelWith + cardSpacing; + int minHeight = std::max(newFileIconSize, textHeight) + cardSpacing; + + this->setMinimumHeight(minHeight); + this->setMinimumWidth(minWidth); } }; From eae8aec93dddddc436a1ee135671d4e4aa3c36ee Mon Sep 17 00:00:00 2001 From: Alfredo Monclus Date: Wed, 26 Feb 2025 15:17:46 -0300 Subject: [PATCH 3/4] start: fix filecard text visibility on classic theme also fixes hover and pressed states --- src/Gui/Stylesheets/FreeCAD Dark.qss | 8 +- src/Gui/Stylesheets/FreeCAD Light.qss | 8 +- src/Mod/Start/Gui/FileCardDelegate.cpp | 171 +++++++++---------------- src/Mod/Start/Gui/FileCardDelegate.h | 11 +- 4 files changed, 71 insertions(+), 127 deletions(-) diff --git a/src/Gui/Stylesheets/FreeCAD Dark.qss b/src/Gui/Stylesheets/FreeCAD Dark.qss index 0326a321b7..0b10fa8325 100644 --- a/src/Gui/Stylesheets/FreeCAD Dark.qss +++ b/src/Gui/Stylesheets/FreeCAD Dark.qss @@ -2860,17 +2860,17 @@ QTreeView::branch#groupsTreeView:has-siblings:!adjoins-item { /*================================================================================================== Start page ==================================================================================================*/ -QWidget#thumbnailWidget { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #252525); +#thumbnailWidget { + background-color: #2f2f2f; border-radius: 8px; border: 1px solid #020202; } -QWidget#thumbnailWidget[state="hovered"] { +#thumbnailWidget:hover { border: 1px solid @ThemeAccentColor1; } -QWidget#thumbnailWidget[state="pressed"] { +#thumbnailWidget:pressed { border: 1px solid @ThemeAccentColor1; } diff --git a/src/Gui/Stylesheets/FreeCAD Light.qss b/src/Gui/Stylesheets/FreeCAD Light.qss index 9cafa1cb2a..77bc028e28 100644 --- a/src/Gui/Stylesheets/FreeCAD Light.qss +++ b/src/Gui/Stylesheets/FreeCAD Light.qss @@ -2865,17 +2865,17 @@ QTreeView::branch#groupsTreeView:has-siblings:!adjoins-item { /*================================================================================================== Start page ==================================================================================================*/ -QWidget#thumbnailWidget { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f0f0f0, stop:1 #fdfdfd); +#thumbnailWidget { + background-color: #ededed; border-radius: 8px; border: 1px solid #ababab; } -QWidget#thumbnailWidget[state="hovered"] { +#thumbnailWidget:hover { border: 1px solid @ThemeAccentColor1; } -QWidget#thumbnailWidget[state="pressed"] { +#thumbnailWidget:pressed { border: 1px solid @ThemeAccentColor1; } diff --git a/src/Mod/Start/Gui/FileCardDelegate.cpp b/src/Mod/Start/Gui/FileCardDelegate.cpp index 9fef0b800d..a7cd323842 100644 --- a/src/Mod/Start/Gui/FileCardDelegate.cpp +++ b/src/Mod/Start/Gui/FileCardDelegate.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #endif #include "FileCardDelegate.h" @@ -44,152 +45,98 @@ using namespace Start; FileCardDelegate::FileCardDelegate(QObject* parent) - : QAbstractItemDelegate(parent) + : QStyledItemDelegate(parent) { _parameterGroup = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Start"); - _widget = std::make_unique(); + _widget = std::make_unique(); _widget->setObjectName(QLatin1String("thumbnailWidget")); auto layout = gsl::owner(new QVBoxLayout()); layout->setSpacing(0); _widget->setLayout(layout); } -QColor FileCardDelegate::getBorderColor() const -{ - QColor color(98, 160, 234); // NOLINT - uint32_t packed = Base::Color::asPackedRGB(color); - packed = _parameterGroup->GetUnsigned("FileThumbnailBorderColor", packed); - color = Base::Color::fromPackedRGB(packed); - return color; -} - -QColor FileCardDelegate::getBackgroundColor() const -{ - QColor color(221, 221, 221); // NOLINT - uint32_t packed = Base::Color::asPackedRGB(color); - packed = _parameterGroup->GetUnsigned("FileThumbnailBackgroundColor", packed); - color = Base::Color::fromPackedRGB(packed); - return color; -} - -QColor FileCardDelegate::getSelectionColor() const -{ - QColor color(38, 162, 105); // NOLINT - uint32_t packed = Base::Color::asPackedRGB(color); - packed = _parameterGroup->GetUnsigned("FileThumbnailSelectionColor", packed); - color = Base::Color::fromPackedRGB(packed); - return color; -} - void FileCardDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + painter->save(); + + // Step 1: Styling + QStyleOptionButton buttonOption; + buttonOption.initFrom(_widget.get()); + buttonOption.rect = option.rect; + buttonOption.state = QStyle::State_Enabled; + + if ((option.state & QStyle::State_MouseOver) != 0) { + buttonOption.state |= QStyle::State_MouseOver; + } + if ((option.state & QStyle::State_Selected) != 0) { + buttonOption.state |= QStyle::State_On; + } + if ((option.state & QStyle::State_Sunken) != 0) { + buttonOption.state |= QStyle::State_Sunken; + } + + QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter); + + // Step 2: Fetch required data auto thumbnailSize = static_cast(_parameterGroup->GetInt("FileThumbnailIconsSize", 128)); // NOLINT - auto cardWidth = thumbnailSize; auto baseName = index.data(static_cast(DisplayedFilesModelRoles::baseName)).toString(); + auto elidedName = painter->fontMetrics().elidedText(baseName, Qt::ElideRight, thumbnailSize); auto size = index.data(static_cast(DisplayedFilesModelRoles::size)).toString(); auto image = index.data(static_cast(DisplayedFilesModelRoles::image)).toByteArray(); auto path = index.data(static_cast(DisplayedFilesModelRoles::path)).toString(); - painter->save(); - auto thumbnail = std::make_unique(); - auto pixmap = std::make_unique(); - auto layout = qobject_cast(_widget->layout()); + + QPixmap pixmap; if (!image.isEmpty()) { - pixmap->loadFromData(image); - if (!pixmap->isNull()) { - auto scaled = pixmap->scaled(QSize(thumbnailSize, thumbnailSize), - Qt::AspectRatioMode::KeepAspectRatio, - Qt::TransformationMode::SmoothTransformation); - thumbnail->setPixmap(scaled); - } + pixmap.loadFromData(image); } else { - thumbnail->setPixmap(generateThumbnail(path)); - } - thumbnail->setFixedSize(thumbnailSize, thumbnailSize); - thumbnail->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); - - QString style = QStringLiteral(""); - - _widget->setProperty("state", QStringLiteral("")); - if (option.state & QStyle::State_Selected) { - _widget->setProperty("state", QStringLiteral("pressed")); - if (qApp->styleSheet().isEmpty()) { - QColor color = getSelectionColor(); - style = QStringLiteral("QWidget#thumbnailWidget {" - " border: 2px solid rgb(%1, %2, %3);" - " border-radius: 4px;" - " padding: 2px;" - "}") - .arg(color.red()) - .arg(color.green()) - .arg(color.blue()); - } - } - else if (option.state & QStyle::State_MouseOver) { - _widget->setProperty("state", QStringLiteral("hovered")); - if (qApp->styleSheet().isEmpty()) { - QColor color = getBorderColor(); - style = QStringLiteral("QWidget#thumbnailWidget {" - " border: 2px solid rgb(%1, %2, %3);" - " border-radius: 4px;" - " padding: 2px;" - "}") - .arg(color.red()) - .arg(color.green()) - .arg(color.blue()); - } - } - else if (qApp->styleSheet().isEmpty()) { - QColor color = getBackgroundColor(); - style = QStringLiteral("QWidget#thumbnailWidget {" - " background-color: rgb(%1, %2, %3);" - " border-radius: 8px;" - "}") - .arg(color.red()) - .arg(color.green()) - .arg(color.blue()); + pixmap = generateThumbnail(path); } - _widget->setStyleSheet(style); + QPixmap scaledPixmap = pixmap.scaled(QSize(thumbnailSize, thumbnailSize), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); - auto elided = - painter->fontMetrics().elidedText(baseName, Qt::TextElideMode::ElideRight, cardWidth); - auto name = std::make_unique(elided); - layout->addWidget(thumbnail.get()); // Temp. ownership transfer - layout->addWidget(name.get()); // Temp. ownership transfer - auto sizeLabel = std::make_unique(size); - layout->addWidget(sizeLabel.get()); // Temp. ownership transfer - layout->addStretch(); - _widget->resize(option.rect.size()); - painter->translate(option.rect.topLeft()); - _widget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren); + // Step 4: Positioning + QRect thumbnailRect(option.rect.x() + margin, + option.rect.y() + margin, + thumbnailSize, + thumbnailSize); + QRect textRect(option.rect.x() + margin, + thumbnailRect.bottom() + margin, + thumbnailSize, + painter->fontMetrics().lineSpacing()); + + QRect sizeRect(option.rect.x() + margin, + textRect.bottom() + textspacing, + thumbnailSize, + painter->fontMetrics().lineSpacing() + margin); + + // Step 5: Draw + painter->drawPixmap(thumbnailRect, scaledPixmap); + painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, elidedName); + painter->drawText(sizeRect, Qt::AlignLeft | Qt::AlignTop, size); painter->restore(); - layout->removeWidget(sizeLabel.get()); - layout->removeWidget(thumbnail.get()); - layout->removeWidget(name.get()); } QSize FileCardDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { - Q_UNUSED(option) - Q_UNUSED(index) + Q_UNUSED(option); + Q_UNUSED(index); + auto thumbnailSize = _parameterGroup->GetInt("FileThumbnailIconsSize", 128); // NOLINT - auto cardMargin = _widget->layout()->contentsMargins(); - auto cardWidth = thumbnailSize + cardMargin.left() + cardMargin.right(); - auto spacing = _widget->layout()->spacing(); - auto font = QGuiApplication::font(); - auto qfm = QFontMetrics(font); - auto textHeight = 2 * qfm.lineSpacing(); - auto cardHeight = - thumbnailSize + textHeight + 2 * spacing + cardMargin.top() + cardMargin.bottom(); + QFontMetrics qfm(QGuiApplication::font()); + int textHeight = textspacing + qfm.lineSpacing() * 2; // name + size + int cardWidth = static_cast(thumbnailSize) + 2 * margin; + int cardHeight = static_cast(thumbnailSize) + textHeight + 3 * margin; - return {static_cast(cardWidth), static_cast(cardHeight)}; + return {cardWidth, cardHeight}; } namespace diff --git a/src/Mod/Start/Gui/FileCardDelegate.h b/src/Mod/Start/Gui/FileCardDelegate.h index 35e74c79ba..78ba3f80b4 100644 --- a/src/Mod/Start/Gui/FileCardDelegate.h +++ b/src/Mod/Start/Gui/FileCardDelegate.h @@ -27,9 +27,9 @@ #include #include -#include +#include -class FileCardDelegate: public QAbstractItemDelegate +class FileCardDelegate: public QStyledItemDelegate { public: @@ -44,14 +44,11 @@ public: protected: QPixmap generateThumbnail(const QString& path) const; -private: - QColor getBorderColor() const; - QColor getBackgroundColor() const; - QColor getSelectionColor() const; - private: Base::Reference _parameterGroup; std::unique_ptr _widget; + const int margin = 11; + const int textspacing = 2; }; From 48adc418178967723c17240c89282a2abf3cba72 Mon Sep 17 00:00:00 2001 From: Alfredo Monclus Date: Wed, 5 Mar 2025 10:16:30 -0300 Subject: [PATCH 4/4] start: simplify cardspacing --- src/Mod/Start/Gui/FileCardView.cpp | 24 +++++++++++------------- src/Mod/Start/Gui/FileCardView.h | 3 +++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Mod/Start/Gui/FileCardView.cpp b/src/Mod/Start/Gui/FileCardView.cpp index 343a644d9c..62bf6561d5 100644 --- a/src/Mod/Start/Gui/FileCardView.cpp +++ b/src/Mod/Start/Gui/FileCardView.cpp @@ -30,7 +30,6 @@ namespace StartGui { - FileCardView::FileCardView(QWidget* parent) : QListView(parent) { @@ -45,7 +44,12 @@ FileCardView::FileCardView(QWidget* parent) setResizeMode(QListView::ResizeMode::Adjust); setUniformItemSizes(true); setMouseTracking(true); - setSpacing(20); + + auto hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Start"); + m_cardSpacing = static_cast(hGrp->GetInt("FileCardSpacing", 16)); // NOLINT + + setSpacing(m_cardSpacing); } int FileCardView::heightForWidth(int width) const @@ -61,28 +65,22 @@ int FileCardView::heightForWidth(int width) const int numRows = static_cast(ceil(static_cast(numCards) / static_cast(cardsPerRow))); int neededHeight = numRows * cardSize.height(); - auto hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Start"); - int cardSpacing = static_cast(hGrp->GetInt("FileCardSpacing", 20)); // NOLINT - return neededHeight + cardSpacing * (numRows - 1) + 2 * cardSpacing; + + return neededHeight + m_cardSpacing * (numRows - 1) + 2 * m_cardSpacing; } QSize FileCardView::sizeHint() const { - auto hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Start"); - int cardSpacing = static_cast(hGrp->GetInt("FileCardSpacing", 20)); // NOLINT - auto model = this->model(); auto delegate = this->itemDelegate(); if (!model || !delegate) { // The model and/or delegate have not been set yet, this was an early startup call - return {cardSpacing, cardSpacing}; + return {m_cardSpacing, m_cardSpacing}; } int numCards = model->rowCount(); auto cardSize = delegate->sizeHint(QStyleOptionViewItem(), model->index(0, 0)); - return {(cardSize.width() + cardSpacing) * numCards + cardSpacing, - cardSize.height() + 2 * cardSpacing}; + return {(cardSize.width() + m_cardSpacing) * numCards + m_cardSpacing, + cardSize.height() + 2 * m_cardSpacing}; } } // namespace StartGui diff --git a/src/Mod/Start/Gui/FileCardView.h b/src/Mod/Start/Gui/FileCardView.h index 9ccd720f6d..febeedd7a9 100644 --- a/src/Mod/Start/Gui/FileCardView.h +++ b/src/Mod/Start/Gui/FileCardView.h @@ -39,6 +39,9 @@ public: int heightForWidth(int width) const override; QSize sizeHint() const override; + +private: + int m_cardSpacing; }; } // namespace StartGui