Start: Create 'First Start' screen

This commit is contained in:
Chris Hennes
2024-04-22 17:58:59 -05:00
parent 2aad8ab334
commit 3a9547c235
15 changed files with 785 additions and 36 deletions

View File

@@ -53,14 +53,20 @@ SET(StartGui_SRCS
FileCardDelegate.h
FileCardView.cpp
FileCardView.h
FirstStartWidget.cpp
FirstStartWidget.h
FlowLayout.cpp
FlowLayout.h
GeneralSettingsWidget.cpp
GeneralSettingsWidget.h
Manipulator.cpp
Manipulator.h
PreCompiled.cpp
PreCompiled.h
StartView.cpp
StartView.h
ThemeSelectorWidget.cpp
ThemeSelectorWidget.h
)
SET(StartGuiIcon_SVG
@@ -68,6 +74,12 @@ SET(StartGuiIcon_SVG
Resources/icons/PartDesignWorkbench.svg
)
SET(StartGuiThumbnail_PNG
Resources/thumbnails/Classic512.png
Resources/thumbnails/OpenDark512.png
Resources/thumbnails/OpenLight512.png
)
# TODO: Evaluate PCH use with Qt6/QtQuick/Qml
if (FREECAD_USE_PCH)
add_definitions(-D_PreComp_)
@@ -75,7 +87,7 @@ if (FREECAD_USE_PCH)
ADD_MSVC_PRECOMPILED_HEADER(StartGui PreCompiled.h PreCompiled.cpp PCH_SRCS)
endif (FREECAD_USE_PCH)
add_library(StartGui SHARED ${StartGui_SRCS} ${StartGuiIcon_SVG})
add_library(StartGui SHARED ${StartGui_SRCS} ${StartGuiIcon_SVG} ${StartGuiThumbnail_PNG})
# target_link_libraries(StartGui ${StartGui_LIBS} Qt::Quick Qt::Qml Qt::QuickWidgets)
target_link_libraries(StartGui ${StartGui_LIBS})

View File

@@ -0,0 +1,108 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 The FreeCAD Project Association AISBL *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QGuiApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QResizeEvent>
#include <QVBoxLayout>
#include <QWidget>
#endif
#include "FirstStartWidget.h"
#include "ThemeSelectorWidget.h"
#include "GeneralSettingsWidget.h"
#include <App/Application.h>
#include <gsl/pointers>
using namespace StartGui;
FirstStartWidget::FirstStartWidget(QWidget* parent)
: QGroupBox(parent)
, _themeSelectorWidget {nullptr}
, _generalSettingsWidget {nullptr}
, _welcomeLabel {nullptr}
, _descriptionLabel {nullptr}
, _doneButton {nullptr}
{
setObjectName(QLatin1String("FirstStartWidget"));
setupUi();
qApp->installEventFilter(this);
}
void FirstStartWidget::setupUi()
{
auto outerLayout = gsl::owner<QVBoxLayout*>(new QVBoxLayout(this));
QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str());
_welcomeLabel = gsl::owner<QLabel*>(new QLabel);
outerLayout->addWidget(_welcomeLabel);
_descriptionLabel = gsl::owner<QLabel*>(new QLabel);
outerLayout->addWidget(_descriptionLabel);
_themeSelectorWidget = gsl::owner<ThemeSelectorWidget*>(new ThemeSelectorWidget(this));
_generalSettingsWidget = gsl::owner<GeneralSettingsWidget*>(new GeneralSettingsWidget(this));
outerLayout->addWidget(_generalSettingsWidget);
outerLayout->addWidget(_themeSelectorWidget);
_doneButton = gsl::owner<QPushButton*>(new QPushButton);
auto buttonBar = gsl::owner<QHBoxLayout*>(new QHBoxLayout);
buttonBar->addStretch();
buttonBar->addWidget(_doneButton);
outerLayout->addLayout(buttonBar);
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) {
this->retranslateUi();
}
return QWidget::eventFilter(object, event);
}
void FirstStartWidget::retranslateUi()
{
_doneButton->setText(tr("Done"));
QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str());
_welcomeLabel->setText(QLatin1String("<h1>") + tr("Welcome to %1").arg(application)
+ QLatin1String("</h1>"));
_descriptionLabel->setText(
tr("To get started, set your basic configuration options below.") + QLatin1String(" ")
+ tr("These options (and many more) can be changed later in Preferences."));
}

View File

@@ -0,0 +1,61 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 The FreeCAD Project Association AISBL *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#ifndef FREECAD_FIRSTSTARTWIDGET_H
#define FREECAD_FIRSTSTARTWIDGET_H
#include <QWidget>
#include <QGroupBox>
class QLabel;
class QPushButton;
namespace StartGui
{
class ThemeSelectorWidget;
class GeneralSettingsWidget;
class FirstStartWidget: public QGroupBox
{
Q_OBJECT
public:
explicit FirstStartWidget(QWidget* parent = nullptr);
bool eventFilter(QObject* object, QEvent* event) override;
private:
void retranslateUi();
void setupUi();
void doneClicked();
ThemeSelectorWidget* _themeSelectorWidget;
GeneralSettingsWidget* _generalSettingsWidget;
QLabel* _welcomeLabel;
QLabel* _descriptionLabel;
QPushButton* _doneButton;
};
} // namespace StartGui
#endif // FREECAD_FIRSTSTARTWIDGET_H

View File

@@ -0,0 +1,238 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 The FreeCAD Project Association AISBL *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QApplication>
#include <QComboBox>
#include <QGridLayout>
#include <QLabel>
#include <QLayout>
#include <QToolButton>
#include <QVBoxLayout>
#include <QWidget>
#endif
#include "GeneralSettingsWidget.h"
#include <gsl/pointers>
#include <App/Application.h>
#include <Base/Parameter.h>
#include <Base/UnitsApi.h>
#include <Gui/Language/Translator.h>
#include <Gui/NavigationStyle.h>
using namespace StartGui;
GeneralSettingsWidget::GeneralSettingsWidget(QWidget* parent)
: QWidget(parent)
, _languageLabel {nullptr}
, _unitSystemLabel {nullptr}
, _navigationStyleLabel {nullptr}
, _languageComboBox {nullptr}
, _unitSystemComboBox {nullptr}
, _navigationStyleComboBox {nullptr}
{
setObjectName(QLatin1String("GeneralSettingsWidget"));
setupUi();
qApp->installEventFilter(this);
}
void GeneralSettingsWidget::setupUi()
{
if (layout()) {
qDeleteAll(findChildren<QWidget*>(QString(), Qt::FindDirectChildrenOnly));
delete layout();
}
_languageLabel = gsl::owner<QLabel*>(new QLabel);
_navigationStyleLabel = gsl::owner<QLabel*>(new QLabel);
_unitSystemLabel = gsl::owner<QLabel*>(new QLabel);
createLanguageComboBox();
createUnitSystemComboBox();
createNavigationStyleComboBox();
createHorizontalUi();
retranslateUi();
}
void GeneralSettingsWidget::createHorizontalUi()
{
auto mainLayout = gsl::owner<QHBoxLayout*>(new QHBoxLayout(this));
const int extraSpace {36};
mainLayout->addWidget(_languageLabel);
mainLayout->addWidget(_languageComboBox);
mainLayout->addSpacing(extraSpace);
mainLayout->addWidget(_unitSystemLabel);
mainLayout->addWidget(_unitSystemComboBox);
mainLayout->addSpacing(extraSpace);
mainLayout->addWidget(_navigationStyleLabel);
mainLayout->addWidget(_navigationStyleComboBox);
}
QString GeneralSettingsWidget::createLabelText(const QString& translatedText) const
{
static const auto h2Start = QLatin1String("<h2>");
static const auto h2End = QLatin1String("</h2>");
return h2Start + translatedText + h2End;
}
gsl::owner<QComboBox*> GeneralSettingsWidget::createLanguageComboBox()
{
ParameterGrp::handle hGrp =
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General");
auto langToStr = Gui::Translator::instance()->activeLanguage();
QByteArray language = hGrp->GetASCII("Language", langToStr.c_str()).c_str();
auto comboBox = gsl::owner<QComboBox*>(new QComboBox);
comboBox->addItem(QString::fromLatin1("English"), QByteArray("English"));
Gui::TStringMap list = Gui::Translator::instance()->supportedLocales();
int index {0};
for (auto it = list.begin(); it != list.end(); ++it, ++index) {
QByteArray lang = it->first.c_str();
QString langname = QString::fromLatin1(lang.constData());
if (it->second == "sr-CS") {
// Qt does not treat sr-CS (Serbian, Latin) as a Latin-script variant by default: this
// forces it to do so.
it->second = "sr_Latn";
}
QLocale locale(QString::fromLatin1(it->second.c_str()));
QString native = locale.nativeLanguageName();
if (!native.isEmpty()) {
if (native[0].isLetter()) {
native[0] = native[0].toUpper();
}
langname = native;
}
comboBox->addItem(langname, lang);
if (language == lang) {
comboBox->setCurrentIndex(index);
}
}
_languageComboBox = comboBox;
connect(_languageComboBox,
qOverload<int>(&QComboBox::currentIndexChanged),
this,
&GeneralSettingsWidget::onLanguageChanged);
return comboBox;
}
gsl::owner<QComboBox*> GeneralSettingsWidget::createUnitSystemComboBox()
{
// Contents are created in retranslateUi()
auto comboBox = gsl::owner<QComboBox*>(new QComboBox);
_unitSystemComboBox = comboBox;
connect(_unitSystemComboBox,
qOverload<int>(&QComboBox::currentIndexChanged),
this,
&GeneralSettingsWidget::onUnitSystemChanged);
return comboBox;
}
gsl::owner<QComboBox*> GeneralSettingsWidget::createNavigationStyleComboBox()
{
// Contents are created in retranslateUi()
auto comboBox = gsl::owner<QComboBox*>(new QComboBox);
_navigationStyleComboBox = comboBox;
connect(_navigationStyleComboBox,
qOverload<int>(&QComboBox::currentIndexChanged),
this,
&GeneralSettingsWidget::onNavigationStyleChanged);
return comboBox;
}
void GeneralSettingsWidget::onLanguageChanged(int index)
{
if (index < 0) {
return; // happens when clearing the combo box in retranslateUi()
}
Gui::Translator::instance()->activateLanguage(
_languageComboBox->itemData(index).toByteArray().data());
ParameterGrp::handle hGrp =
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General");
auto langToStr = Gui::Translator::instance()->activeLanguage();
hGrp->SetASCII("Language", langToStr.c_str());
}
void GeneralSettingsWidget::onUnitSystemChanged(int index)
{
if (index < 0) {
return; // happens when clearing the combo box in retranslateUi()
}
Base::UnitsApi::setSchema(static_cast<Base::UnitSystem>(index));
ParameterGrp::handle hGrp =
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units");
hGrp->SetInt("UserSchema", index);
}
void GeneralSettingsWidget::onNavigationStyleChanged(int index)
{
if (index < 0) {
return; // happens when clearing the combo box in retranslateUi()
}
auto navStyleName = _navigationStyleComboBox->itemData(index).toByteArray().data();
ParameterGrp::handle hGrp =
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
hGrp->SetASCII("NavigationStyle", navStyleName);
}
bool GeneralSettingsWidget::eventFilter(QObject* object, QEvent* event)
{
if (object == this && event->type() == QEvent::LanguageChange) {
this->retranslateUi();
}
return QWidget::eventFilter(object, event);
}
void GeneralSettingsWidget::retranslateUi()
{
_languageLabel->setText(createLabelText(tr("Language")));
_unitSystemLabel->setText(createLabelText(tr("Unit System")));
_unitSystemComboBox->clear();
ParameterGrp::handle hGrpUnits =
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units");
auto userSchema = hGrpUnits->GetInt("UserSchema", 0);
int num = static_cast<int>(Base::UnitSystem::NumUnitSystemTypes);
for (int i = 0; i < num; i++) {
QString item = Base::UnitsApi::getDescription(static_cast<Base::UnitSystem>(i));
_unitSystemComboBox->addItem(item, i);
}
_unitSystemComboBox->setCurrentIndex(userSchema);
_navigationStyleLabel->setText(createLabelText(tr("Navigation Style")));
_navigationStyleComboBox->clear();
ParameterGrp::handle hGrpNav =
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
auto navStyleName =
hGrpNav->GetASCII("NavigationStyle", Gui::CADNavigationStyle::getClassTypeId().getName());
std::map<Base::Type, std::string> styles = Gui::UserNavigationStyle::getUserFriendlyNames();
for (const auto& style : styles) {
QByteArray data(style.first.getName());
QString name = QApplication::translate(style.first.getName(), style.second.c_str());
_navigationStyleComboBox->addItem(name, data);
if (navStyleName == style.first.getName()) {
_navigationStyleComboBox->setCurrentIndex(_navigationStyleComboBox->count() - 1);
}
}
}

View File

@@ -0,0 +1,72 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 The FreeCAD Project Association AISBL *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#ifndef FREECAD_START_GENERALSETTINGSWIDGET_H
#define FREECAD_START_GENERALSETTINGSWIDGET_H
#include <QWidget>
#include <3rdParty/GSL/include/gsl/pointers>
class QLabel;
class QComboBox;
namespace StartGui
{
class GeneralSettingsWidget: public QWidget
{
Q_OBJECT
public:
explicit GeneralSettingsWidget(QWidget* parent = nullptr);
bool eventFilter(QObject* object, QEvent* event) override;
private:
void retranslateUi();
void setupUi();
void createHorizontalUi();
QString createLabelText(const QString& translatedText) const;
gsl::owner<QComboBox*> createLanguageComboBox();
gsl::owner<QComboBox*> createUnitSystemComboBox();
gsl::owner<QComboBox*> createNavigationStyleComboBox();
void onLanguageChanged(int index);
void onUnitSystemChanged(int index);
void onNavigationStyleChanged(int index);
Qt::Orientation _orientation;
// Non-owning pointers to things that need to be re-translated when the language changes
QLabel* _languageLabel;
QLabel* _unitSystemLabel;
QLabel* _navigationStyleLabel;
QComboBox* _languageComboBox;
QComboBox* _unitSystemComboBox;
QComboBox* _navigationStyleComboBox;
};
} // namespace StartGui
#endif // FREECAD_START_GENERALSETTINGSWIDGET_H

View File

@@ -44,22 +44,28 @@
// Qt
#include <QApplication>
#include <QBoxLayout>
#include <QCheckBox>
#include <QComboBox>
#include <QCoreApplication>
#include <QFile>
#include <QFileIconProvider>
#include <QGridLayout>
#include <QGuiApplication>
#include <QHBoxLayout>
#include <QImageReader>
#include <QLabel>
#include <QListView>
#include <QModelIndex>
#include <QPainter>
#include <QPushButton>
#include <QResizeEvent>
#include <QScrollArea>
#include <QSpacerItem>
#include <QString>
#include <QStyleOptionViewItem>
#include <QTimer>
#include <QToolButton>
#include <QUrl>
#include <QVBoxLayout>
#include <QWidget>

View File

@@ -2,5 +2,8 @@
<qresource prefix="/">
<file>icons/StartCommandIcon.svg</file>
<file>icons/PartDesignWorkbench.svg</file>
<file>thumbnails/Classic512.png</file>
<file>thumbnails/OpenLight512.png</file>
<file>thumbnails/OpenDark512.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -37,6 +37,7 @@
#include "StartView.h"
#include "FileCardDelegate.h"
#include "FileCardView.h"
#include "FirstStartWidget.h"
#include "FlowLayout.h"
#include "Gui/Workbench.h"
#include <Gui/Document.h>
@@ -99,6 +100,11 @@ gsl::owner<QPushButton*> createNewButton(const NewButton& newButton)
StartView::StartView(Gui::Document* pcDocument, QWidget* parent)
: Gui::MDIView(pcDocument, parent)
, _contents(new QScrollArea(parent))
, _newFileLabel {nullptr}
, _examplesLabel {nullptr}
, _recentFilesLabel {nullptr}
, _showOnStartupCheckBox {nullptr}
, _rewriteLabel {nullptr}
{
setObjectName(QLatin1String("StartView"));
auto hGrp = App::GetApplication().GetParameterGroupByPath(
@@ -114,44 +120,42 @@ StartView::StartView(Gui::Document* pcDocument, QWidget* parent)
layout->setSizeConstraint(QLayout::SizeConstraint::SetMinAndMaxSize);
// New WB notice: temporary to explain why all your setting disappeared
auto newStartWBNotice = gsl::owner<QLabel*>(
new QLabel(tr("NOTE: The Start Workbench has been completely rewritten to remove all "
"network access, and to remove its dependency on Chromium. This is still a "
"work-in-progress, and not all settings from the previous version of Start "
"have been migrated yet.")));
newStartWBNotice->setWordWrap(true);
layout->addWidget(newStartWBNotice);
_rewriteLabel = gsl::owner<QLabel*>(new QLabel());
_rewriteLabel->setWordWrap(true);
layout->addWidget(_rewriteLabel);
// Launch start automatically?
QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str());
auto launchAutomaticallyCheckbox =
gsl::owner<QCheckBox*>(new QCheckBox(tr("Show Start when starting %1").arg(application)));
_showOnStartupCheckBox = gsl::owner<QCheckBox*>(new QCheckBox());
bool showOnStartup = hGrp->GetBool("ShowOnStartup", true);
launchAutomaticallyCheckbox->setCheckState(showOnStartup ? Qt::CheckState::Checked
: Qt::CheckState::Unchecked);
connect(launchAutomaticallyCheckbox,
&QCheckBox::toggled,
this,
&StartView::showOnStartupChanged);
layout->addWidget(launchAutomaticallyCheckbox);
_showOnStartupCheckBox->setCheckState(showOnStartup ? Qt::CheckState::Checked
: Qt::CheckState::Unchecked);
connect(_showOnStartupCheckBox, &QCheckBox::toggled, this, &StartView::showOnStartupChanged);
layout->addWidget(_showOnStartupCheckBox);
const QLatin1String h1Start("<h1>");
const QLatin1String h1End("</h1>");
auto firstStart = hGrp->GetBool("FirstStart2024", true); // NOLINT
if (firstStart) {
auto firstStartRegion = gsl::owner<QHBoxLayout*>(new QHBoxLayout);
firstStartRegion->addStretch();
auto firstStartWidget = gsl::owner<FirstStartWidget*>(new FirstStartWidget(this));
firstStartRegion->addWidget(firstStartWidget);
firstStartRegion->addStretch();
layout->addLayout(firstStartRegion);
}
auto newFileLabel = gsl::owner<QLabel*>(new QLabel(h1Start + tr("New File") + h1End));
layout->addWidget(newFileLabel);
_newFileLabel = gsl::owner<QLabel*>(new QLabel());
layout->addWidget(_newFileLabel);
auto flowLayout = gsl::owner<FlowLayout*>(new FlowLayout);
layout->addLayout(flowLayout);
configureNewFileButtons(flowLayout);
auto recentFilesLabel = gsl::owner<QLabel*>(new QLabel(h1Start + tr("Recent Files") + h1End));
layout->addWidget(recentFilesLabel);
_recentFilesLabel = gsl::owner<QLabel*>(new QLabel());
layout->addWidget(_recentFilesLabel);
auto recentFilesListWidget = gsl::owner<FileCardView*>(new FileCardView(_contents));
connect(recentFilesListWidget, &QListView::clicked, this, &StartView::fileCardSelected);
layout->addWidget(recentFilesListWidget);
auto examplesLabel = gsl::owner<QLabel*>(new QLabel(h1Start + tr("Examples") + h1End));
layout->addWidget(examplesLabel);
_examplesLabel = gsl::owner<QLabel*>(new QLabel());
layout->addWidget(_examplesLabel);
auto examplesListWidget = gsl::owner<FileCardView*>(new FileCardView(_contents));
connect(examplesListWidget, &QListView::clicked, this, &StartView::fileCardSelected);
layout->addWidget(examplesListWidget);
@@ -161,11 +165,10 @@ StartView::StartView(Gui::Document* pcDocument, QWidget* parent)
setCentralWidget(_contents);
QString title = QCoreApplication::translate("Workbench", "Start");
setWindowTitle(title);
configureExamplesListWidget(examplesListWidget);
configureRecentFilesListWidget(recentFilesListWidget, recentFilesLabel);
configureRecentFilesListWidget(recentFilesListWidget, _recentFilesLabel);
retranslateUi();
}
void StartView::configureNewFileButtons(QLayout* layout) const
@@ -202,7 +205,6 @@ void StartView::configureNewFileButtons(QLayout* layout) const
}
// TODO: Ensure all of the required WBs are actually available
// TODO: Make this layout more flexible (e.g. use a single line if possible)
layout->addWidget(partDesign);
layout->addWidget(assembly);
layout->addWidget(draft);
@@ -406,3 +408,33 @@ void StartView::showOnStartupChanged(bool checked)
"User parameter:BaseApp/Preferences/Mod/Start");
hGrp->SetBool("ShowOnStartup", checked);
}
void StartView::changeEvent(QEvent* event)
{
if (event->type() == QEvent::LanguageChange) {
this->retranslateUi();
}
Gui::MDIView::changeEvent(event);
}
void StartView::retranslateUi()
{
QString title = QCoreApplication::translate("Workbench", "Start");
setWindowTitle(title);
const QLatin1String h1Start("<h1>");
const QLatin1String h1End("</h1>");
_newFileLabel->setText(h1Start + tr("New File") + h1End);
_examplesLabel->setText(h1Start + tr("Examples") + h1End);
_recentFilesLabel->setText(h1Start + tr("Recent Files") + h1End);
QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str());
_showOnStartupCheckBox->setText(tr("Show this view when starting %1").arg(application));
_rewriteLabel->setText(
tr("NOTE: The Start Workbench has been completely rewritten to remove all "
"network access, and to remove its dependency on Chromium. This is still a "
"work-in-progress, and not all settings from the previous version of Start "
"have been migrated yet."));
}

View File

@@ -32,10 +32,11 @@
#include "../App/RecentFilesModel.h"
#include "../App/ExamplesModel.h"
class QCheckBox;
class QEvent;
class QGridLayout;
class QLabel;
class QListView;
class QGridLayout;
class QScrollArea;
namespace Gui
@@ -75,6 +76,8 @@ public:
};
protected:
void changeEvent(QEvent* e) override;
void configureNewFileButtons(QLayout* layout) const;
static void configureFileCardWidget(QListView* fileCardWidget);
void configureRecentFilesListWidget(QListView* recentFilesListWidget, QLabel* recentFilesLabel);
@@ -88,10 +91,18 @@ protected:
QString fileCardStyle() const;
private:
void retranslateUi();
QScrollArea* _contents = nullptr;
Start::RecentFilesModel _recentFilesModel;
Start::ExamplesModel _examplesModel;
QLabel* _newFileLabel;
QLabel* _examplesLabel;
QLabel* _recentFilesLabel;
QCheckBox* _showOnStartupCheckBox;
QLabel* _rewriteLabel;
}; // namespace StartGui

View File

@@ -0,0 +1,142 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 The FreeCAD Project Association AISBL *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QGuiApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QString>
#include <QToolButton>
#endif
#include "ThemeSelectorWidget.h"
#include <3rdParty/GSL/include/gsl/pointers>
#include <App/Application.h>
#include <Gui/Application.h>
#include <Gui/PreferencePackManager.h>
using namespace StartGui;
ThemeSelectorWidget::ThemeSelectorWidget(QWidget* parent)
: QWidget(parent)
, _titleLabel {nullptr}
, _descriptionLabel {nullptr}
, _buttons {nullptr, nullptr, nullptr}
{
setObjectName(QLatin1String("ThemeSelectorWidget"));
setupUi();
qApp->installEventFilter(this);
}
void ThemeSelectorWidget::setupButtons(QBoxLayout* layout)
{
if (!layout) {
return;
}
std::map<Theme, QString> themeMap {{Theme::Classic, tr("Classic")},
{Theme::Light, tr("Light")},
{Theme::Dark, tr("Dark")}};
std::map<Theme, QIcon> iconMap {
{Theme::Classic, QIcon(QLatin1String(":/thumbnails/Classic512.png"))},
{Theme::Light, QIcon(QLatin1String(":/thumbnails/OpenLight512.png"))},
{Theme::Dark, QIcon(QLatin1String(":/thumbnails/OpenDark512.png"))}};
auto hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/MainWindow");
auto styleSheetName = QString::fromStdString(hGrp->GetASCII("StyleSheet"));
for (const auto& theme : themeMap) {
auto button = gsl::owner<QToolButton*>(new QToolButton());
button->setCheckable(true);
button->setAutoExclusive(true);
button->setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonTextUnderIcon);
button->setText(theme.second);
button->setIcon(iconMap[theme.first]);
button->setIconSize(iconMap[theme.first].actualSize(QSize(256, 256)));
if (theme.first == Theme::Classic && styleSheetName.isEmpty()) {
button->setChecked(true);
}
else if (theme.first == Theme::Light
&& styleSheetName.contains(QLatin1String("light"),
Qt::CaseSensitivity::CaseInsensitive)) {
button->setChecked(true);
}
else if (theme.first == Theme::Dark
&& styleSheetName.contains(QLatin1String("dark"),
Qt::CaseSensitivity::CaseInsensitive)) {
button->setChecked(true);
}
connect(button, &QToolButton::clicked, this, [this, theme] {
themeChanged(theme.first);
});
layout->addWidget(button);
_buttons[static_cast<int>(theme.first)] = button;
}
}
void ThemeSelectorWidget::setupUi()
{
auto* outerLayout = gsl::owner<QVBoxLayout*>(new QVBoxLayout(this));
auto* buttonLayout = gsl::owner<QHBoxLayout*>(new QHBoxLayout);
_titleLabel = gsl::owner<QLabel*>(new QLabel);
_descriptionLabel = gsl::owner<QLabel*>(new QLabel);
outerLayout->addWidget(_titleLabel);
outerLayout->addWidget(_descriptionLabel);
outerLayout->addLayout(buttonLayout);
setupButtons(buttonLayout);
retranslateUi();
}
void ThemeSelectorWidget::themeChanged(Theme newTheme)
{
// Run the appropriate preference pack:
auto prefPackManager = Gui::Application::Instance->prefPackManager();
switch (newTheme) {
case Theme::Classic:
prefPackManager->apply("Classic");
break;
case Theme::Dark:
prefPackManager->apply("Dark");
break;
case Theme::Light:
prefPackManager->apply("Light");
break;
}
}
bool ThemeSelectorWidget::eventFilter(QObject* object, QEvent* event)
{
if (object == this && event->type() == QEvent::LanguageChange) {
this->retranslateUi();
}
return QWidget::eventFilter(object, event);
}
void ThemeSelectorWidget::retranslateUi()
{
_titleLabel->setText(QLatin1String("<h2>") + tr("Theme") + QLatin1String("</h2>"));
_descriptionLabel->setText(tr("More themes are available online using the Addon Manager"));
_buttons[static_cast<int>(Theme::Classic)]->setText(tr("Classic", "Visual theme name"));
_buttons[static_cast<int>(Theme::Light)]->setText(tr("Light", "Visual theme name"));
_buttons[static_cast<int>(Theme::Dark)]->setText(tr("Dark", "Visual theme name"));
}

View File

@@ -0,0 +1,67 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 The FreeCAD Project Association AISBL *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#ifndef FREECAD_START_THEMESELECTORWIDGET_H
#define FREECAD_START_THEMESELECTORWIDGET_H
#include <QWidget>
#include <array>
class QBoxLayout;
class QLabel;
class QToolButton;
namespace StartGui
{
enum class Theme
{
Classic,
Light,
Dark
};
/// A widget to allow selection of the UI theme (color scheme).
class ThemeSelectorWidget: public QWidget
{
Q_OBJECT
public:
explicit ThemeSelectorWidget(QWidget* parent = nullptr);
bool eventFilter(QObject* object, QEvent* event) override;
protected:
void themeChanged(Theme newTheme);
private:
void retranslateUi();
void setupUi();
void setupButtons(QBoxLayout* layout);
QLabel* _titleLabel;
QLabel* _descriptionLabel;
std::array<QToolButton*, 3> _buttons;
};
} // namespace StartGui
#endif // FREECAD_START_THEMESELECTORWIDGET_H

View File

@@ -1,8 +1,5 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#ifdef WIN32
#define _USE_MATH_DEFINES
#endif
#include <cmath>
#include "gtest/gtest.h"