From 226f67a1e84017796c6422acd45bbf86c392cdb1 Mon Sep 17 00:00:00 2001 From: Furgo <148809153+furgo16@users.noreply.github.com> Date: Mon, 17 Feb 2025 17:18:35 +0100 Subject: [PATCH] Start: add optional custom folder view (#19473) * Start: add optional additional folder view * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added logic to migrate ShowCustomFolder parameter * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Rename Additional to Custom folder * Change Start page text to sentence case for consistency * Fix breakage created by pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Rearrange migration logic to make it more explicit * Revert "Change Start page text to sentence case for consistency" This reverts commit 8a31a1238c0380ddbe13e6e5838a3be6b13400a5. * Make parameterGroup local * Apply suggestions and linter improvements * Adapted suggestion to simplify migration logic * Start: Warning -> Message for rename of ShowCustomFolder --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Chris Hennes --- src/Mod/Start/App/CMakeLists.txt | 2 + src/Mod/Start/App/CustomFolderModel.cpp | 61 +++++++++++++++++++++++++ src/Mod/Start/App/CustomFolderModel.h | 53 +++++++++++++++++++++ src/Mod/Start/Gui/StartView.cpp | 44 ++++++++++++++++++ src/Mod/Start/Gui/StartView.h | 4 ++ 5 files changed, 164 insertions(+) create mode 100644 src/Mod/Start/App/CustomFolderModel.cpp create mode 100644 src/Mod/Start/App/CustomFolderModel.h diff --git a/src/Mod/Start/App/CMakeLists.txt b/src/Mod/Start/App/CMakeLists.txt index 992fad97de..ad27072f24 100644 --- a/src/Mod/Start/App/CMakeLists.txt +++ b/src/Mod/Start/App/CMakeLists.txt @@ -37,6 +37,8 @@ SET(Start_SRCS DisplayedFilesModel.h ExamplesModel.cpp ExamplesModel.h + CustomFolderModel.cpp + CustomFolderModel.h PreCompiled.cpp PreCompiled.h RecentFilesModel.cpp diff --git a/src/Mod/Start/App/CustomFolderModel.cpp b/src/Mod/Start/App/CustomFolderModel.cpp new file mode 100644 index 0000000000..bd7036e2e1 --- /dev/null +++ b/src/Mod/Start/App/CustomFolderModel.cpp @@ -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 * + * . * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + +#include "CustomFolderModel.h" +#include + +using namespace Start; + + +CustomFolderModel::CustomFolderModel(QObject* parent) + : DisplayedFilesModel(parent) +{ + + Base::Reference parameterGroup = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Start"); + + _customFolderDirectory = + QDir(QString::fromStdString(parameterGroup->GetASCII("CustomFolder", ""))); +} + +void CustomFolderModel::loadCustomFolder() +{ + beginResetModel(); + clear(); + if (!_customFolderDirectory.isReadable()) { + Base::Console().Warning( + "BaseApp/Preferences/Mod/Start/CustomFolder: cannot read custom folder %s\n", + _customFolderDirectory.absolutePath().toStdString().c_str()); + } + auto entries = _customFolderDirectory.entryList(QDir::Filter::Files | QDir::Filter::Readable, + QDir::SortFlag::Name); + for (const auto& entry : entries) { + addFile(_customFolderDirectory.filePath(entry)); + } + endResetModel(); +} diff --git a/src/Mod/Start/App/CustomFolderModel.h b/src/Mod/Start/App/CustomFolderModel.h new file mode 100644 index 0000000000..d4c132708d --- /dev/null +++ b/src/Mod/Start/App/CustomFolderModel.h @@ -0,0 +1,53 @@ +// 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 * + * . * + * * + ***************************************************************************/ + +#ifndef FREECAD_START_CUSTOMFOLDERMODEL_H +#define FREECAD_START_CUSTOMFOLDERMODEL_H + +#include +#include +#include + +#include "DisplayedFilesModel.h" +#include "../StartGlobal.h" + +namespace Start +{ + +/// A model for displaying a list of files including a thumbnail or icon, plus various file +/// statistics. +class StartExport CustomFolderModel: public DisplayedFilesModel +{ + Q_OBJECT +public: + explicit CustomFolderModel(QObject* parent = nullptr); + + void loadCustomFolder(); + +private: + QDir _customFolderDirectory; +}; + +} // namespace Start + +#endif // FREECAD_START_CUSTOMFOLDERMODEL_H diff --git a/src/Mod/Start/Gui/StartView.cpp b/src/Mod/Start/Gui/StartView.cpp index 0942ea80a2..e398c142ae 100644 --- a/src/Mod/Start/Gui/StartView.cpp +++ b/src/Mod/Start/Gui/StartView.cpp @@ -185,6 +185,7 @@ StartView::StartView(QWidget* parent) , _newFileLabel {nullptr} , _examplesLabel {nullptr} , _recentFilesLabel {nullptr} + , _customFolderLabel {nullptr} , _showOnStartupCheckBox {nullptr} { setObjectName(QLatin1String("StartView")); @@ -193,6 +194,30 @@ StartView::StartView(QWidget* parent) auto cardSpacing = hGrp->GetInt("FileCardSpacing", 15); // NOLINT auto showExamples = hGrp->GetBool("ShowExamples", true); // NOLINT + // Migrate legacy property, can be removed in later releases + std::string legacyCustomFolder(hGrp->GetASCII("ShowCustomFolder", "")); + if (!legacyCustomFolder.empty()) { + hGrp->SetASCII("CustomFolder", legacyCustomFolder); + hGrp->RemoveASCII("ShowCustomFolder"); + Base::Console().Message("v1.1: renamed ShowCustomFolder parameter to CustomFolder\n"); + } + // End of migration code + + // Verify that the folder specified in preferences is available before showing it + std::string customFolder(hGrp->GetASCII("CustomFolder", "")); + bool showCustomFolder = false; + if (!customFolder.empty()) { + auto customFolderDirectory = QDir(QString::fromStdString(customFolder)); + if (customFolderDirectory.exists()) { + showCustomFolder = true; + } + else { + Base::Console().Warning( + "BaseApp/Preferences/Mod/Start/CustomFolder: '%s' does not exist\n", + customFolderDirectory.absolutePath().toStdString().c_str()); + } + } + // First start page auto firstStartScrollArea = gsl::owner(new QScrollArea()); auto firstStartScrollWidget = gsl::owner(new QWidget(firstStartScrollArea)); @@ -245,6 +270,15 @@ StartView::StartView(QWidget* parent) connect(recentFilesListWidget, &QListView::clicked, this, &StartView::fileCardSelected); documentsContentLayout->addWidget(recentFilesListWidget); + auto customFolderListWidget = gsl::owner(new FileCardView(_contents)); + customFolderListWidget->setVisible(showCustomFolder); + _customFolderLabel = gsl::owner(new QLabel()); + _customFolderLabel->setVisible(showCustomFolder); + documentsContentLayout->addWidget(_customFolderLabel); + + connect(customFolderListWidget, &QListView::clicked, this, &StartView::fileCardSelected); + documentsContentLayout->addWidget(customFolderListWidget); + auto examplesListWidget = gsl::owner(new FileCardView(_contents)); examplesListWidget->setVisible(showExamples); _examplesLabel = gsl::owner(new QLabel()); @@ -281,6 +315,7 @@ StartView::StartView(QWidget* parent) // Set startup widget according to the first start parameter auto firstStart = hGrp->GetBool("FirstStart2024", true); // NOLINT _contents->setCurrentWidget(firstStart ? firstStartScrollArea : documentsWidget); + configureCustomFolderListWidget(customFolderListWidget); configureExamplesListWidget(examplesListWidget); configureRecentFilesListWidget(recentFilesListWidget, _recentFilesLabel); @@ -370,6 +405,14 @@ void StartView::configureExamplesListWidget(QListView* examplesListWidget) } +void StartView::configureCustomFolderListWidget(QListView* customFolderListWidget) +{ + _customFolderModel.loadCustomFolder(); + customFolderListWidget->setModel(&_customFolderModel); + configureFileCardWidget(customFolderListWidget); +} + + void StartView::newEmptyFile() const { Gui::Application::Instance->commandManager().runCommandByName("Std_New"); @@ -529,6 +572,7 @@ void StartView::retranslateUi() _newFileLabel->setText(h1Start + tr("New File") + h1End); _examplesLabel->setText(h1Start + tr("Examples") + h1End); _recentFilesLabel->setText(h1Start + tr("Recent Files") + h1End); + _customFolderLabel->setText(h1Start + tr("Custom Folder") + h1End); QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str()); _openFirstStart->setText(tr("Open first start setup")); diff --git a/src/Mod/Start/Gui/StartView.h b/src/Mod/Start/Gui/StartView.h index 04f89c23c7..3530a5435b 100644 --- a/src/Mod/Start/Gui/StartView.h +++ b/src/Mod/Start/Gui/StartView.h @@ -31,6 +31,7 @@ #include "../App/DisplayedFilesModel.h" #include "../App/RecentFilesModel.h" #include "../App/ExamplesModel.h" +#include "../App/CustomFolderModel.h" class QCheckBox; class QEvent; @@ -86,6 +87,7 @@ protected: static void configureFileCardWidget(QListView* fileCardWidget); void configureRecentFilesListWidget(QListView* recentFilesListWidget, QLabel* recentFilesLabel); void configureExamplesListWidget(QListView* examplesListWidget); + void configureCustomFolderListWidget(QListView* customFolderListWidget); void postStart(PostStartBehavior behavior) const; @@ -101,9 +103,11 @@ private: QStackedWidget* _contents = nullptr; Start::RecentFilesModel _recentFilesModel; Start::ExamplesModel _examplesModel; + Start::CustomFolderModel _customFolderModel; QLabel* _newFileLabel; QLabel* _examplesLabel; QLabel* _recentFilesLabel; + QLabel* _customFolderLabel; QPushButton* _openFirstStart; QCheckBox* _showOnStartupCheckBox;