Skip to content

Handle multi-directories for project templates - #67476

Open
Djedouas wants to merge 1 commit into
qgis:masterfrom
Djedouas:multi_dirs_project_templates
Open

Djedouas wants to merge 1 commit into
qgis:masterfrom
Djedouas:multi_dirs_project_templates

Conversation

@Djedouas

@Djedouas Djedouas commented Sep 17, 2026

Copy link
Copy Markdown
Member

Description

This PR adds the feature to have multiple directories for the project templates.

The need behind it is for instance having a team with its set of project templates, plus some templates coming from another centralized directory from an organization.

To clean the menu UI, the sub-menu for creating a project from a template is only available if there is at least one project template in one template directory.

A toolbar button has been added to be coherent with the menu.

A new icon for project templates is proposed: image

The welcome screen has been adapted to show the directories as sections.

See screencast below:

Enregistrement.d.ecran_20260917_160105.webm

AI tool usage

  • AI tool(s) (Copilot, Claude, or something similar) supported my development of this PR. See our policy about AI tool use. Use of AI tools must be indicated. Failure to be honest might result in banning.

Claude Fable 5.1 used

  • to create the widget to save a project as a template (src/app/qgssaveprojecttemplatedialog.[cpp/h])
  • to adapt the qml welcome screen file

@github-actions github-actions Bot added this to the 4.4.0 milestone Sep 17, 2026
@github-actions github-actions Bot added the GUI/UX Related to QGIS application GUI or User Experience label Sep 17, 2026
@Djedouas Djedouas added Feature and removed GUI/UX Related to QGIS application GUI or User Experience labels Sep 17, 2026
@Djedouas
Djedouas force-pushed the multi_dirs_project_templates branch from becd36e to 1c10666 Compare September 17, 2026 13:24
@github-actions github-actions Bot added the GUI/UX Related to QGIS application GUI or User Experience label Sep 17, 2026
@Djedouas

Copy link
Copy Markdown
Member Author

I tried to split the PR in multiple commits, but couldn't find a logic to make more atomic commits, so I submit the feature in one commit only.

@troopa81

Copy link
Copy Markdown
Contributor

We don't see the menu in the video it seems

@Djedouas

Copy link
Copy Markdown
Member Author

We don't see the menu in the video it seems

Oops, screencast updated

@troopa81

Copy link
Copy Markdown
Contributor

To clean the menu UI, the sub-menu for creating a project from a template is only available if there is at least one project template in one template directory.

That's not the actual behavior where there is an empty menu if there is no template. IMHO, I think it's better to see an empty menu than not seeing a menu at all. It can confuse the user who would not understand why the menu is not there.

@Djedouas

Copy link
Copy Markdown
Member Author

Related to #66024

@troopa81

Copy link
Copy Markdown
Contributor

I like the proposed UI, but I would like to have @nirvn opinion, especially on the template look on welcoming page

@Djedouas

Copy link
Copy Markdown
Member Author

That's not the actual behavior where there is an empty menu if there is no template. IMHO, I think it's better to see an empty menu than not seeing a menu at all. It can confuse the user who would not understand why the menu is not there.

Yes, we could gray them (menu + toolbar button) out with setEnabled(False).

But it's also arguable to lighten the UI I think.


// The default template directory depends on the active profile, which is not known now, so we use an empty default,
// and it will be handled later on by the getter QgsApplication::projectTemplatePaths.
const QgsSettingsEntryStringList *QgsApplication::settingsProjectTemplatePaths = new QgsSettingsEntryStringList( u"projectTemplatePaths"_s, QgsSettingsTree::sTreeQgis, QStringList() );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we not add this settings to sTreeProject instead ?

Comment thread src/core/qgsapplication.h
/**
* Returns the paths to project template directories.
*
* Defaults to the template directory of the active user profile when no path

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happen if the user destroy the default path from the qgsoptions widget ? It would reappear next opening no? It seems it was the existing behavior but maybe we can do better here

Comment on lines +2249 to +2255
// Dialog that shows QGIS projects inside the current directory, but only directories are selectable.
QFileDialog dialog( this, tr( "Choose a directory" ), QDir::toNativeSeparators( QDir::homePath() ) );
dialog.setFileMode( QFileDialog::Directory );
dialog.setOption( QFileDialog::DontUseNativeDialog ); // to have the desired behavior on most platforms
dialog.setNameFilter( tr( "QGIS project files (*.qgs *.qgz)" ) );
if ( dialog.exec() != QDialog::Accepted || dialog.selectedFiles().isEmpty() )
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot we not replace all this with QFileDialog::getExistingDirectory like it was done before ?

Comment on lines +2261 to +2264
for ( int i = 0; i < mListProjectTemplatePaths->count(); ++i )
{
if ( mListProjectTemplatePaths->item( i )->text() == myDir )
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may I suggest to use std::find_if here to be more consise ?

void QgsOptions::moveProjectTemplatePathUp()
{
QList<QListWidgetItem *> selectedItems = mListProjectTemplatePaths->selectedItems();
QList<QListWidgetItem *>::iterator itemIt = selectedItems.begin();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we autorize the use of auto for iterator

Comment thread src/app/qgisapp.cpp
if ( templateFiles.count() > 0 )
{
const QString label = directoryNameCount.value( templateDir.dirName() ) > 1 ? QDir::toNativeSeparators( templateDirName ) : templateDir.dirName();
QMenu *dirMenu = mProjectFromTemplateMenu->addMenu( fontMetrics.elidedText( label, Qt::ElideLeft, maxLabelWidth ) );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add the tooltip with the non-elided text

Comment thread src/app/qgisapp.cpp
mProjectFromTemplateMenu->addAction( tr( "< Blank >" ) );
mProjectFromTemplateMenu->addAction( tr( "< Blank >" ), [this]() { fileNewBlank(); } );

mProjectFromTemplateMenu->menuAction()->setVisible( !mProjectFromTemplateMenu->isEmpty() );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I said, I prefer an empty menu, or a disabled one

}
}

const QStringList watchedDirectories = mFileSystemWatcher.directories();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code is very much alike than the one in QgisApp. Can we put somewhere and reuse it?


const QStringList watchedDirectories = mFileSystemWatcher.directories();
if ( !watchedDirectories.isEmpty() )
mFileSystemWatcher.removePaths( watchedDirectories );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be cool to avoid to have 2 QFileSystemWatcher because it is ressource consuming, and move it elwere (QgsApplication maybe?). But it was already this way, so non blocking

QHash<int, QByteArray> roleNames() const override;

private slots:
/**

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to reload if we have the file watcher ? Maybe it would be interesting to centralize all in QgsApplication maybe with a signal templatePathsChanged() ?

@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

🪟 Windows Qt6 builds

Download Windows Qt6 builds of this PR for testing.
To execute locally, unzip the downloaded zip file and run bin\qgis-bin.exe in the extracted directory.
You might be prompted by Windows Defender click "Run anyway"
(Built from commit 1c10666)

🍎 MacOS Qt6 builds

Download MacOS Qt6 builds of this PR for testing.
This app is not notarized, run sudo xattr -d com.apple.quarantine /Applications/QGIS*.app to avoid the warning
(Built from commit 1c10666)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature GUI/UX Related to QGIS application GUI or User Experience

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants