From 14ed708e0206726c78410fb01aca752836f7b212 Mon Sep 17 00:00:00 2001 From: qewer33 Date: Mon, 5 Aug 2024 12:09:15 +0300 Subject: [PATCH 1/4] Make start page use QStackedWidget + other fixes closes #14039, closes #14694, closes #14817, closes #15113 --- src/Mod/Start/Gui/FirstStartWidget.cpp | 19 +--- src/Mod/Start/Gui/FirstStartWidget.h | 3 +- src/Mod/Start/Gui/StartView.cpp | 146 +++++++++++++++---------- src/Mod/Start/Gui/StartView.h | 7 +- 4 files changed, 101 insertions(+), 74 deletions(-) diff --git a/src/Mod/Start/Gui/FirstStartWidget.cpp b/src/Mod/Start/Gui/FirstStartWidget.cpp index b506b382e7..16050e1358 100644 --- a/src/Mod/Start/Gui/FirstStartWidget.cpp +++ b/src/Mod/Start/Gui/FirstStartWidget.cpp @@ -48,7 +48,7 @@ FirstStartWidget::FirstStartWidget(QWidget* parent) , _generalSettingsWidget {nullptr} , _welcomeLabel {nullptr} , _descriptionLabel {nullptr} - , _doneButton {nullptr} + , doneButton {nullptr} { setObjectName(QLatin1String("FirstStartWidget")); setupUi(); @@ -58,6 +58,7 @@ FirstStartWidget::FirstStartWidget(QWidget* parent) void FirstStartWidget::setupUi() { auto outerLayout = gsl::owner(new QVBoxLayout(this)); + outerLayout->addStretch(); QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str()); _welcomeLabel = gsl::owner(new QLabel); outerLayout->addWidget(_welcomeLabel); @@ -70,24 +71,16 @@ void FirstStartWidget::setupUi() outerLayout->addWidget(_generalSettingsWidget); outerLayout->addWidget(_themeSelectorWidget); - _doneButton = gsl::owner(new QPushButton); + doneButton = gsl::owner(new QPushButton); auto buttonBar = gsl::owner(new QHBoxLayout); buttonBar->addStretch(); - buttonBar->addWidget(_doneButton); + buttonBar->addWidget(doneButton); outerLayout->addLayout(buttonBar); + outerLayout->addStretch(); - connect(_doneButton, &QPushButton::clicked, this, &FirstStartWidget::doneClicked); retranslateUi(); } -void FirstStartWidget::doneClicked() -{ - auto hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Start"); - hGrp->SetBool("FirstStart2024", false); - this->hide(); -} - bool FirstStartWidget::eventFilter(QObject* object, QEvent* event) { if (object == this && event->type() == QEvent::LanguageChange) { @@ -98,7 +91,7 @@ bool FirstStartWidget::eventFilter(QObject* object, QEvent* event) void FirstStartWidget::retranslateUi() { - _doneButton->setText(tr("Done")); + doneButton->setText(tr("Done")); QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str()); _welcomeLabel->setText(QLatin1String("

") + tr("Welcome to %1").arg(application) + QLatin1String("

")); diff --git a/src/Mod/Start/Gui/FirstStartWidget.h b/src/Mod/Start/Gui/FirstStartWidget.h index 0965d80424..7cc4031e91 100644 --- a/src/Mod/Start/Gui/FirstStartWidget.h +++ b/src/Mod/Start/Gui/FirstStartWidget.h @@ -42,18 +42,17 @@ class FirstStartWidget: public QGroupBox public: explicit FirstStartWidget(QWidget* parent = nullptr); bool eventFilter(QObject* object, QEvent* event) override; + QPushButton* doneButton; private: void retranslateUi(); void setupUi(); - void doneClicked(); ThemeSelectorWidget* _themeSelectorWidget; GeneralSettingsWidget* _generalSettingsWidget; QLabel* _welcomeLabel; QLabel* _descriptionLabel; - QPushButton* _doneButton; }; } // namespace StartGui diff --git a/src/Mod/Start/Gui/StartView.cpp b/src/Mod/Start/Gui/StartView.cpp index fc245fc65a..e4d14404e5 100644 --- a/src/Mod/Start/Gui/StartView.cpp +++ b/src/Mod/Start/Gui/StartView.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #endif #include "StartView.h" @@ -68,7 +69,7 @@ gsl::owner createNewButton(const NewButton& newButton) { auto hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Start"); - const auto cardSpacing = static_cast(hGrp->GetInt("FileCardSpacing", 20)); // NOLINT + const auto cardSpacing = static_cast(hGrp->GetInt("FileCardSpacing", 25)); // NOLINT const auto newFileIconSize = static_cast(hGrp->GetInt("NewFileIconSize", 48)); // NOLINT const auto cardLabelWith = static_cast(hGrp->GetInt("FileCardLabelWith", 180)); // NOLINT @@ -82,7 +83,8 @@ gsl::owner createNewButton(const NewButton& newButton) auto textLayout = gsl::owner(new QVBoxLayout); auto textLabelLine1 = gsl::owner(new QLabel(button)); - textLabelLine1->setText(QLatin1String("") + newButton.heading + QLatin1String("")); + textLabelLine1->setText(newButton.heading); + textLabelLine1->setStyleSheet(QLatin1String("font-weight: bold;")); auto textLabelLine2 = gsl::owner(new QLabel(button)); textLabelLine2->setText(newButton.description); textLabelLine2->setWordWrap(true); @@ -102,7 +104,7 @@ gsl::owner createNewButton(const NewButton& newButton) StartView::StartView(QWidget* parent) : Gui::MDIView(nullptr, parent) - , _contents(new QScrollArea(parent)) + , _contents(new QStackedWidget(parent)) , _newFileLabel {nullptr} , _examplesLabel {nullptr} , _recentFilesLabel {nullptr} @@ -111,73 +113,90 @@ StartView::StartView(QWidget* parent) setObjectName(QLatin1String("StartView")); auto hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Start"); - auto cardSpacing = hGrp->GetInt("FileCardSpacing", 30); // NOLINT + auto cardSpacing = hGrp->GetInt("FileCardSpacing", 15); // NOLINT - auto scrolledWidget = gsl::owner(new QWidget(this)); - _contents->setWidget(scrolledWidget); - _contents->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - _contents->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - _contents->setWidgetResizable(true); - auto layout = gsl::owner(new QVBoxLayout(scrolledWidget)); - layout->setSizeConstraint(QLayout::SizeConstraint::SetMinAndMaxSize); + // First start page + auto firstStartScrollArea = gsl::owner(new QScrollArea(_contents)); + auto firstStartRegion = gsl::owner(new QHBoxLayout(firstStartScrollArea)); + firstStartRegion->addStretch(); + auto firstStartWidget = gsl::owner(new FirstStartWidget(this)); + connect(firstStartWidget->doneButton, + &QPushButton::clicked, + this, + &StartView::firstStartWidgetDoneClicked); + firstStartRegion->addWidget(firstStartWidget); + firstStartRegion->addStretch(); + _contents->addWidget(firstStartScrollArea); - auto firstStart = hGrp->GetBool("FirstStart2024", true); // NOLINT - if (firstStart) { - auto firstStartRegion = gsl::owner(new QHBoxLayout); - firstStartRegion->addStretch(); - auto firstStartWidget = gsl::owner(new FirstStartWidget(this)); - firstStartRegion->addWidget(firstStartWidget); - firstStartRegion->addStretch(); - layout->addLayout(firstStartRegion); + // Documents page + auto documentsWidget = gsl::owner(new QWidget()); + _contents->addWidget(documentsWidget); + auto documentsMainLayout = gsl::owner(new QVBoxLayout()); + documentsWidget->setLayout(documentsMainLayout); + auto documentsScrollArea = gsl::owner(new QScrollArea()); + documentsScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + documentsMainLayout->addWidget(documentsScrollArea); + auto documentsScrollWidget = gsl::owner(new QWidget(documentsScrollArea)); + documentsScrollArea->setWidget(documentsScrollWidget); + documentsScrollArea->setWidgetResizable(true); + auto documentsContentLayout = gsl::owner(new QVBoxLayout(documentsScrollWidget)); + documentsContentLayout->setSizeConstraint(QLayout::SizeConstraint::SetMinAndMaxSize); - // Try to further differentiate the checkbox below, when the First Start box is shown - auto line = new QFrame(); - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - layout->addWidget(line); - } + _newFileLabel = gsl::owner(new QLabel()); + documentsContentLayout->addWidget(_newFileLabel); + + auto createNewRow = gsl::owner(new QWidget); + auto flowLayout = gsl::owner(new FlowLayout); + + // Reset margins of layout to provide consistent spacing + flowLayout->setContentsMargins({}); + + // This allows new file widgets to be targeted via QSS + createNewRow->setObjectName(QStringLiteral("CreateNewRow")); + createNewRow->setLayout(flowLayout); + + documentsContentLayout->addWidget(createNewRow); + configureNewFileButtons(flowLayout); + + _recentFilesLabel = gsl::owner(new QLabel()); + documentsContentLayout->addWidget(_recentFilesLabel); + auto recentFilesListWidget = gsl::owner(new FileCardView(_contents)); + connect(recentFilesListWidget, &QListView::clicked, this, &StartView::fileCardSelected); + documentsContentLayout->addWidget(recentFilesListWidget); + + _examplesLabel = gsl::owner(new QLabel()); + documentsContentLayout->addWidget(_examplesLabel); + auto examplesListWidget = gsl::owner(new FileCardView(_contents)); + connect(examplesListWidget, &QListView::clicked, this, &StartView::fileCardSelected); + documentsContentLayout->addWidget(examplesListWidget); + + documentsContentLayout->setSpacing(static_cast(cardSpacing)); + documentsContentLayout->addStretch(); + + // Documents page footer + auto footerLayout = gsl::owner(new QHBoxLayout(_contents)); + documentsMainLayout->addLayout(footerLayout); + + auto _openFirstStart = gsl::owner(new QPushButton(tr("Open first start setup"))); + _openFirstStart->setIcon(QIcon(QLatin1String(":/icons/preferences-general.svg"))); + connect(_openFirstStart, &QPushButton::clicked, this, &StartView::openFirstStartClicked); - // Launch start automatically? _showOnStartupCheckBox = gsl::owner(new QCheckBox()); bool showOnStartup = hGrp->GetBool("ShowOnStartup", true); _showOnStartupCheckBox->setCheckState(showOnStartup ? Qt::CheckState::Unchecked : Qt::CheckState::Checked); connect(_showOnStartupCheckBox, &QCheckBox::toggled, this, &StartView::showOnStartupChanged); - layout->addWidget(_showOnStartupCheckBox); - _newFileLabel = gsl::owner(new QLabel()); - layout->addWidget(_newFileLabel); - - auto createNewRow = gsl::owner(new QWidget); - auto flowLayout = gsl::owner(new FlowLayout); - - // reset margins of layout to provide consistent spacing - flowLayout->setContentsMargins({}); - - // this allows new file widgets to be targeted via QSS - createNewRow->setObjectName(QStringLiteral("CreateNewRow")); - createNewRow->setLayout(flowLayout); - - layout->addWidget(createNewRow); - configureNewFileButtons(flowLayout); - - _recentFilesLabel = gsl::owner(new QLabel()); - layout->addWidget(_recentFilesLabel); - auto recentFilesListWidget = gsl::owner(new FileCardView(_contents)); - connect(recentFilesListWidget, &QListView::clicked, this, &StartView::fileCardSelected); - layout->addWidget(recentFilesListWidget); - - _examplesLabel = gsl::owner(new QLabel()); - layout->addWidget(_examplesLabel); - auto examplesListWidget = gsl::owner(new FileCardView(_contents)); - connect(examplesListWidget, &QListView::clicked, this, &StartView::fileCardSelected); - layout->addWidget(examplesListWidget); - - layout->setSpacing(static_cast(cardSpacing)); - layout->addStretch(); + footerLayout->addWidget(_openFirstStart); + footerLayout->addStretch(); + footerLayout->addWidget(_showOnStartupCheckBox); setCentralWidget(_contents); + // Set startup widget according to the first start parameter + auto firstStart = hGrp->GetBool("FirstStart2024", true); // NOLINT + _contents->setCurrentWidget(firstStart ? firstStartScrollArea : documentsWidget); + configureExamplesListWidget(examplesListWidget); configureRecentFilesListWidget(recentFilesListWidget, _recentFilesLabel); @@ -428,6 +447,19 @@ void StartView::showOnStartupChanged(bool checked) // original sense, so is stored inverted. } +void StartView::openFirstStartClicked() +{ + _contents->setCurrentIndex(0); +} + +void StartView::firstStartWidgetDoneClicked() +{ + auto hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Start"); + hGrp->SetBool("FirstStart2024", false); + _contents->setCurrentIndex(1); +} + void StartView::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { diff --git a/src/Mod/Start/Gui/StartView.h b/src/Mod/Start/Gui/StartView.h index fe2d33167c..c0b7da3e61 100644 --- a/src/Mod/Start/Gui/StartView.h +++ b/src/Mod/Start/Gui/StartView.h @@ -38,6 +38,7 @@ class QGridLayout; class QLabel; class QListView; class QScrollArea; +class QStackedWidget; namespace Gui { @@ -86,14 +87,16 @@ protected: void postStart(PostStartBehavior behavior) const; void fileCardSelected(const QModelIndex& index); - void showOnStartupChanged(bool checked); + void openFirstStartClicked(); + void firstStartWidgetDoneClicked(); + QString fileCardStyle() const; private: void retranslateUi(); - QScrollArea* _contents = nullptr; + QStackedWidget* _contents = nullptr; Start::RecentFilesModel _recentFilesModel; Start::ExamplesModel _examplesModel; From 001cb880b2fcacdeb6d95dec2ae429a214853b35 Mon Sep 17 00:00:00 2001 From: qewer33 Date: Mon, 5 Aug 2024 13:23:39 +0300 Subject: [PATCH 2/4] Fix QStackedWidget layout warning --- src/Mod/Start/Gui/StartView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Start/Gui/StartView.cpp b/src/Mod/Start/Gui/StartView.cpp index e4d14404e5..28e84a35e8 100644 --- a/src/Mod/Start/Gui/StartView.cpp +++ b/src/Mod/Start/Gui/StartView.cpp @@ -116,7 +116,7 @@ StartView::StartView(QWidget* parent) auto cardSpacing = hGrp->GetInt("FileCardSpacing", 15); // NOLINT // First start page - auto firstStartScrollArea = gsl::owner(new QScrollArea(_contents)); + auto firstStartScrollArea = gsl::owner(new QScrollArea()); auto firstStartRegion = gsl::owner(new QHBoxLayout(firstStartScrollArea)); firstStartRegion->addStretch(); auto firstStartWidget = gsl::owner(new FirstStartWidget(this)); @@ -174,7 +174,7 @@ StartView::StartView(QWidget* parent) documentsContentLayout->addStretch(); // Documents page footer - auto footerLayout = gsl::owner(new QHBoxLayout(_contents)); + auto footerLayout = gsl::owner(new QHBoxLayout()); documentsMainLayout->addLayout(footerLayout); auto _openFirstStart = gsl::owner(new QPushButton(tr("Open first start setup"))); From ab79cf0b94c5ecd7745a5ea6930b84d5784a3143 Mon Sep 17 00:00:00 2001 From: qewer33 Date: Mon, 5 Aug 2024 13:36:39 +0300 Subject: [PATCH 3/4] Fix open first start button translation --- src/Mod/Start/Gui/StartView.cpp | 3 ++- src/Mod/Start/Gui/StartView.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Mod/Start/Gui/StartView.cpp b/src/Mod/Start/Gui/StartView.cpp index 28e84a35e8..b10d2d7887 100644 --- a/src/Mod/Start/Gui/StartView.cpp +++ b/src/Mod/Start/Gui/StartView.cpp @@ -177,7 +177,7 @@ StartView::StartView(QWidget* parent) auto footerLayout = gsl::owner(new QHBoxLayout()); documentsMainLayout->addLayout(footerLayout); - auto _openFirstStart = gsl::owner(new QPushButton(tr("Open first start setup"))); + _openFirstStart = gsl::owner(new QPushButton()); _openFirstStart->setIcon(QIcon(QLatin1String(":/icons/preferences-general.svg"))); connect(_openFirstStart, &QPushButton::clicked, this, &StartView::openFirstStartClicked); @@ -481,6 +481,7 @@ void StartView::retranslateUi() _recentFilesLabel->setText(h1Start + tr("Recent Files") + h1End); QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str()); + _openFirstStart->setText(tr("Open first start setup")); _showOnStartupCheckBox->setText( tr("Don't show this Start page again (start with blank screen)")); } diff --git a/src/Mod/Start/Gui/StartView.h b/src/Mod/Start/Gui/StartView.h index c0b7da3e61..ebe5d87ee3 100644 --- a/src/Mod/Start/Gui/StartView.h +++ b/src/Mod/Start/Gui/StartView.h @@ -39,6 +39,7 @@ class QLabel; class QListView; class QScrollArea; class QStackedWidget; +class QPushButton; namespace Gui { @@ -103,6 +104,7 @@ private: QLabel* _newFileLabel; QLabel* _examplesLabel; QLabel* _recentFilesLabel; + QPushButton* _openFirstStart; QCheckBox* _showOnStartupCheckBox; From ab1872fdbf5d91753933b831fb34cea901f4598c Mon Sep 17 00:00:00 2001 From: qewer33 Date: Mon, 5 Aug 2024 18:45:31 +0300 Subject: [PATCH 4/4] Fix FirstStartWidget dismiss signal handling --- src/Mod/Start/Gui/FirstStartWidget.cpp | 9 +++++---- src/Mod/Start/Gui/FirstStartWidget.h | 3 ++- src/Mod/Start/Gui/StartView.cpp | 8 ++++---- src/Mod/Start/Gui/StartView.h | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Mod/Start/Gui/FirstStartWidget.cpp b/src/Mod/Start/Gui/FirstStartWidget.cpp index 16050e1358..9a00acfbcc 100644 --- a/src/Mod/Start/Gui/FirstStartWidget.cpp +++ b/src/Mod/Start/Gui/FirstStartWidget.cpp @@ -48,7 +48,7 @@ FirstStartWidget::FirstStartWidget(QWidget* parent) , _generalSettingsWidget {nullptr} , _welcomeLabel {nullptr} , _descriptionLabel {nullptr} - , doneButton {nullptr} + , _doneButton {nullptr} { setObjectName(QLatin1String("FirstStartWidget")); setupUi(); @@ -71,10 +71,11 @@ void FirstStartWidget::setupUi() outerLayout->addWidget(_generalSettingsWidget); outerLayout->addWidget(_themeSelectorWidget); - doneButton = gsl::owner(new QPushButton); + _doneButton = gsl::owner(new QPushButton); + connect(_doneButton, &QPushButton::clicked, this, &FirstStartWidget::dismissed); auto buttonBar = gsl::owner(new QHBoxLayout); buttonBar->addStretch(); - buttonBar->addWidget(doneButton); + buttonBar->addWidget(_doneButton); outerLayout->addLayout(buttonBar); outerLayout->addStretch(); @@ -91,7 +92,7 @@ bool FirstStartWidget::eventFilter(QObject* object, QEvent* event) void FirstStartWidget::retranslateUi() { - doneButton->setText(tr("Done")); + _doneButton->setText(tr("Done")); QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str()); _welcomeLabel->setText(QLatin1String("

") + tr("Welcome to %1").arg(application) + QLatin1String("

")); diff --git a/src/Mod/Start/Gui/FirstStartWidget.h b/src/Mod/Start/Gui/FirstStartWidget.h index 7cc4031e91..7a5b4505c6 100644 --- a/src/Mod/Start/Gui/FirstStartWidget.h +++ b/src/Mod/Start/Gui/FirstStartWidget.h @@ -42,7 +42,7 @@ class FirstStartWidget: public QGroupBox public: explicit FirstStartWidget(QWidget* parent = nullptr); bool eventFilter(QObject* object, QEvent* event) override; - QPushButton* doneButton; + Q_SIGNAL void dismissed(); private: void retranslateUi(); @@ -53,6 +53,7 @@ private: QLabel* _welcomeLabel; QLabel* _descriptionLabel; + QPushButton* _doneButton; }; } // namespace StartGui diff --git a/src/Mod/Start/Gui/StartView.cpp b/src/Mod/Start/Gui/StartView.cpp index b10d2d7887..481e142398 100644 --- a/src/Mod/Start/Gui/StartView.cpp +++ b/src/Mod/Start/Gui/StartView.cpp @@ -120,10 +120,10 @@ StartView::StartView(QWidget* parent) auto firstStartRegion = gsl::owner(new QHBoxLayout(firstStartScrollArea)); firstStartRegion->addStretch(); auto firstStartWidget = gsl::owner(new FirstStartWidget(this)); - connect(firstStartWidget->doneButton, - &QPushButton::clicked, + connect(firstStartWidget, + &FirstStartWidget::dismissed, this, - &StartView::firstStartWidgetDoneClicked); + &StartView::firstStartWidgetDismissed); firstStartRegion->addWidget(firstStartWidget); firstStartRegion->addStretch(); _contents->addWidget(firstStartScrollArea); @@ -452,7 +452,7 @@ void StartView::openFirstStartClicked() _contents->setCurrentIndex(0); } -void StartView::firstStartWidgetDoneClicked() +void StartView::firstStartWidgetDismissed() { auto hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Start"); diff --git a/src/Mod/Start/Gui/StartView.h b/src/Mod/Start/Gui/StartView.h index ebe5d87ee3..1c4f589551 100644 --- a/src/Mod/Start/Gui/StartView.h +++ b/src/Mod/Start/Gui/StartView.h @@ -90,7 +90,7 @@ protected: void fileCardSelected(const QModelIndex& index); void showOnStartupChanged(bool checked); void openFirstStartClicked(); - void firstStartWidgetDoneClicked(); + void firstStartWidgetDismissed(); QString fileCardStyle() const;