Skip to content

Commit

Permalink
[Gui] Fix 100% CPU usage due to StartView (FreeCAD#17565)
Browse files Browse the repository at this point in the history
* [Gui] Fix 100% CPU usage due to StartView

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
benj5378 and pre-commit-ci[bot] authored Nov 6, 2024
1 parent e0cf31b commit fd71fc3
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 110 deletions.
239 changes: 131 additions & 108 deletions src/Mod/Start/Gui/StartView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,43 +68,117 @@ struct NewButton
QString iconPath;
};

gsl::owner<QPushButton*> createNewButton(const NewButton& newButton)
class NewFileButton: public QPushButton
{
auto hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Start");
const auto cardSpacing = static_cast<int>(hGrp->GetInt("FileCardSpacing", 25)); // NOLINT
const auto newFileIconSize = static_cast<int>(hGrp->GetInt("NewFileIconSize", 48)); // NOLINT
const auto cardLabelWith = static_cast<int>(hGrp->GetInt("FileCardLabelWith", 180)); // NOLINT

auto button = gsl::owner<QPushButton*>(new QPushButton());
auto mainLayout = gsl::owner<QHBoxLayout*>(new QHBoxLayout(button));
auto iconLabel = gsl::owner<QLabel*>(new QLabel(button));
mainLayout->addWidget(iconLabel);
QIcon baseIcon(newButton.iconPath);
iconLabel->setPixmap(baseIcon.pixmap(newFileIconSize, newFileIconSize));
iconLabel->setPixmap(baseIcon.pixmap(newFileIconSize, newFileIconSize));

auto textLayout = gsl::owner<QVBoxLayout*>(new QVBoxLayout);
auto textLabelLine1 = gsl::owner<QLabel*>(new QLabel(button));
textLabelLine1->setText(newButton.heading);
textLabelLine1->setStyleSheet(QLatin1String("font-weight: bold;"));
auto textLabelLine2 = gsl::owner<QLabel*>(new QLabel(button));
textLabelLine2->setText(newButton.description);
textLabelLine2->setWordWrap(true);
textLayout->addWidget(textLabelLine1);
textLayout->addWidget(textLabelLine2);
textLayout->setSpacing(0);
mainLayout->addItem(textLayout);

mainLayout->addStretch();

button->setMinimumHeight(newFileIconSize + cardSpacing);
button->setMinimumWidth(newFileIconSize + cardLabelWith);
return button;
}

public:
NewFileButton(const NewButton& newButton)
{
auto hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Start");
const auto cardSpacing = static_cast<int>(hGrp->GetInt("FileCardSpacing", 25)); // NOLINT
const auto newFileIconSize =
static_cast<int>(hGrp->GetInt("NewFileIconSize", 48)); // NOLINT
const auto cardLabelWith =
static_cast<int>(hGrp->GetInt("FileCardLabelWith", 180)); // NOLINT

auto mainLayout = gsl::owner<QHBoxLayout*>(new QHBoxLayout(this));
auto iconLabel = gsl::owner<QLabel*>(new QLabel(this));
mainLayout->addWidget(iconLabel);
QIcon baseIcon(newButton.iconPath);
iconLabel->setPixmap(baseIcon.pixmap(newFileIconSize, newFileIconSize));
iconLabel->setPixmap(baseIcon.pixmap(newFileIconSize, newFileIconSize));

auto textLayout = gsl::owner<QVBoxLayout*>(new QVBoxLayout);
auto textLabelLine1 = gsl::owner<QLabel*>(new QLabel(this));
textLabelLine1->setText(newButton.heading);
textLabelLine1->setStyleSheet(QLatin1String("font-weight: bold;"));
auto textLabelLine2 = gsl::owner<QLabel*>(new QLabel(this));
textLabelLine2->setText(newButton.description);
textLabelLine2->setWordWrap(true);
textLayout->addWidget(textLabelLine1);
textLayout->addWidget(textLabelLine2);
textLayout->setSpacing(0);
mainLayout->addItem(textLayout);

mainLayout->addStretch();

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 = App::Color::asPackedRGB<QColor>(color);
packed = hGrp->GetUnsigned(parameter, packed);
color = App::Color::fromPackedRGB<QColor>(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 QString::fromLatin1("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


StartView::StartView(QWidget* parent)
: Gui::MDIView(nullptr, parent)
, _contents(new QStackedWidget(parent))
Expand Down Expand Up @@ -211,24 +285,30 @@ StartView::StartView(QWidget* parent)

void StartView::configureNewFileButtons(QLayout* layout) const
{
auto newEmptyFile = createNewButton({tr("Empty file"),
tr("Create a new empty FreeCAD file"),
QLatin1String(":/icons/document-new.svg")});
auto openFile = createNewButton({tr("Open File"),
tr("Open an existing CAD file or 3D model"),
QLatin1String(":/icons/document-open.svg")});
auto partDesign = createNewButton({tr("Parametric Part"),
tr("Create a part with the Part Design workbench"),
QLatin1String(":/icons/PartDesignWorkbench.svg")});
auto assembly = createNewButton({tr("Assembly"),
tr("Create an assembly project"),
QLatin1String(":/icons/AssemblyWorkbench.svg")});
auto draft = createNewButton({tr("2D Draft"),
tr("Create a 2D Draft with the Draft workbench"),
QLatin1String(":/icons/DraftWorkbench.svg")});
auto arch = createNewButton({tr("BIM/Architecture"),
tr("Create an architectural project"),
QLatin1String(":/icons/BIMWorkbench.svg")});
auto newEmptyFile =
gsl::owner<NewFileButton*>(new NewFileButton({tr("Empty file"),
tr("Create a new empty FreeCAD file"),
QLatin1String(":/icons/document-new.svg")}));
auto openFile =
gsl::owner<NewFileButton*>(new NewFileButton({tr("Open File"),
tr("Open an existing CAD file or 3D model"),
QLatin1String(":/icons/document-open.svg")}));
auto partDesign = gsl::owner<NewFileButton*>(
new NewFileButton({tr("Parametric Part"),
tr("Create a part with the Part Design workbench"),
QLatin1String(":/icons/PartDesignWorkbench.svg")}));
auto assembly = gsl::owner<NewFileButton*>(
new NewFileButton({tr("Assembly"),
tr("Create an assembly project"),
QLatin1String(":/icons/AssemblyWorkbench.svg")}));
auto draft = gsl::owner<NewFileButton*>(
new NewFileButton({tr("2D Draft"),
tr("Create a 2D Draft with the Draft workbench"),
QLatin1String(":/icons/DraftWorkbench.svg")}));
auto arch =
gsl::owner<NewFileButton*>(new NewFileButton({tr("BIM/Architecture"),
tr("Create an architectural project"),
QLatin1String(":/icons/BIMWorkbench.svg")}));

// TODO: Ensure all of the required WBs are actually available
layout->addWidget(partDesign);
Expand All @@ -246,63 +326,6 @@ void StartView::configureNewFileButtons(QLayout* layout) const
connect(arch, &QPushButton::clicked, this, &StartView::newArchFile);
}

void StartView::paintEvent(QPaintEvent* event)
{
QString style = QStringLiteral("");
if (qApp->styleSheet().isEmpty()) {
style = fileCardStyle();
}
setStyleSheet(style);

Gui::MDIView::paintEvent(event);
}

QString StartView::fileCardStyle() const
{
if (!qApp->styleSheet().isEmpty()) {
return {};
}

auto hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Start");

auto getUserColor = [&hGrp](QColor color, const char* parameter) {
uint32_t packed = App::Color::asPackedRGB<QColor>(color);
packed = hGrp->GetUnsigned(parameter, packed);
color = App::Color::fromPackedRGB<QColor>(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 QString::fromLatin1("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());
}

void StartView::configureFileCardWidget(QListView* fileCardWidget)
{
auto delegate = gsl::owner<FileCardDelegate*>(new FileCardDelegate(fileCardWidget));
Expand Down
2 changes: 0 additions & 2 deletions src/Mod/Start/Gui/StartView.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ class StartGuiExport StartView: public Gui::MDIView

QString fileCardStyle() const;

void paintEvent(QPaintEvent* event) override;

private:
void retranslateUi();

Expand Down

0 comments on commit fd71fc3

Please sign in to comment.