Skip to content

Commit aa4701e

Browse files
YoannQDQnyalldawson
authored andcommittedApr 24, 2023
Add User Selection Dialog
1 parent 7b5f745 commit aa4701e

File tree

6 files changed

+443
-15
lines changed

6 files changed

+443
-15
lines changed
 

‎src/app/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ set(QGIS_APP_SRCS
261261
options/qgsrenderingoptions.cpp
262262
options/qgsvectorrenderingoptions.cpp
263263
options/qgsuserprofilesettingsdialog.cpp
264+
options/qgsuserprofileselectiondialog.cpp
264265

265266
gps/qgsappgpsconnection.cpp
266267
gps/qgsappgpsdigitizing.cpp

‎src/app/main.cpp

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ typedef SInt32 SRefCon;
105105
#include "qgsuserprofilemanager.h"
106106
#include "qgsuserprofile.h"
107107
#include "layers/qgsapplayerhandling.h"
108+
#include "options/qgsuserprofileselectiondialog.h"
108109

109110
#ifdef HAVE_OPENCL
110111
#include "qgsopenclutils.h"
@@ -1083,18 +1084,53 @@ int main( int argc, char *argv[] )
10831084
// If profile name was not explicitly set, use the policy to determine which profile to use
10841085
if ( profileName.isEmpty() )
10851086
{
1086-
switch ( manager.userProfileSelectionPolicy() )
1087+
1088+
// If no profiles exist, use the default profile
1089+
if ( manager.allProfiles().isEmpty() )
10871090
{
1088-
case QgsUserProfileManager::UserProfileSelectionPolicy::LastProfile:
1089-
profileName = manager.lastProfileName();
1090-
break;
1091-
// case QgsUserProfileManager::UserProfileSelectionPolicy::AskUser:
1092-
// profileName = manager.askUserToChooseProfile();
1093-
// break;
1094-
case QgsUserProfileManager::UserProfileSelectionPolicy::DefaultProfile:
1095-
default:
1096-
profileName = manager.defaultProfileName();
1097-
break;
1091+
profileName = manager.defaultProfileName();
1092+
}
1093+
else
1094+
{
1095+
switch ( manager.userProfileSelectionPolicy() )
1096+
{
1097+
// Use the last closed profile (default behavior prior to QGIS 3.32)
1098+
case QgsUserProfileManager::UserProfileSelectionPolicy::LastProfile:
1099+
profileName = manager.lastProfileName();
1100+
// If last used profile no longer exists, use the default profile
1101+
if ( !manager.profileExists( profileName ) )
1102+
{
1103+
profileName = manager.defaultProfileName();
1104+
}
1105+
break;
1106+
1107+
// Ask the user to select a profile (if more than one exists)
1108+
case QgsUserProfileManager::UserProfileSelectionPolicy::AskUser:
1109+
{
1110+
if ( manager.allProfiles().size() == 1 )
1111+
{
1112+
profileName = manager.allProfiles()[0];
1113+
break;
1114+
}
1115+
QgsUserProfileSelectionDialog dlg( &manager );
1116+
if ( dlg.exec() == QDialog::Accepted )
1117+
{
1118+
profileName = dlg.selectedProfileName();
1119+
}
1120+
else
1121+
{
1122+
// Exit QGIS if the user cancels the profile selection dialog
1123+
return 0;
1124+
}
1125+
break;
1126+
}
1127+
1128+
// Use the default profile
1129+
case QgsUserProfileManager::UserProfileSelectionPolicy::DefaultProfile:
1130+
default:
1131+
profileName = manager.defaultProfileName();
1132+
break;
1133+
}
10981134
}
10991135
}
11001136

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/***************************************************************************
2+
qgsuserprofileselectiondialog.cpp
3+
--------------------------------------
4+
Date : February 2023
5+
Copyright : (C) 2023 by Yoann Quenach de Quivillic
6+
Email : yoann dot quenach at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include <QListWidgetItem>
17+
#include <QMessageBox>
18+
19+
#include "qgisapp.h"
20+
#include "qgsapplication.h"
21+
#include "qgsuserprofilemanager.h"
22+
#include "qgsnewnamedialog.h"
23+
24+
#include "qgsuserprofileselectiondialog.h"
25+
26+
QgsUserProfileSelectionDialog::QgsUserProfileSelectionDialog( QgsUserProfileManager *manager, QWidget *parent )
27+
: QDialog( parent ), mManager( manager )
28+
29+
{
30+
setupUi( this );
31+
setWindowIcon( QIcon( QgsApplication::appIconPath() ) );
32+
33+
// Select user profile on double click
34+
connect( mProfileListWidget, &QListWidget::itemDoubleClicked, this, &QgsUserProfileSelectionDialog::accept );
35+
36+
// Add a new profile on button click
37+
connect( mAddProfileButton, &QPushButton::clicked, this, &QgsUserProfileSelectionDialog::onAddProfile );
38+
39+
// Fill the list of profiles
40+
mProfileListWidget->clear(); // Clear bogus profiles in the Ui form
41+
for ( auto profile : mManager->allProfiles() )
42+
{
43+
auto item = new QListWidgetItem( mManager->profileForName( profile )->icon(), profile );
44+
mProfileListWidget->addItem( item );
45+
46+
// If the profile is the last used one, select it
47+
if ( profile == mManager->lastProfileName() )
48+
{
49+
mProfileListWidget->setCurrentItem( item );
50+
item->setSelected( true );
51+
}
52+
}
53+
}
54+
55+
QString QgsUserProfileSelectionDialog::selectedProfileName() const
56+
{
57+
return mProfileListWidget->currentItem()->text();
58+
}
59+
60+
void QgsUserProfileSelectionDialog::accept()
61+
{
62+
// Accept only if an item is selected
63+
if ( mProfileListWidget->currentItem() != nullptr && mProfileListWidget->currentItem()->isSelected() )
64+
{
65+
QDialog::accept();
66+
}
67+
}
68+
69+
void QgsUserProfileSelectionDialog::onAddProfile()
70+
{
71+
// Ask for a new profile name
72+
QgsNewNameDialog dlg( QString(), QString(), QStringList(), mManager->allProfiles(), Qt::CaseInsensitive, this );
73+
dlg.setConflictingNameWarning( tr( "A profile with this name already exists" ) );
74+
dlg.setOverwriteEnabled( false );
75+
dlg.setHintString( tr( "New profile name" ) );
76+
dlg.setWindowTitle( tr( "New profile name" ) );
77+
78+
// Prevent from entering slashes and backslashes
79+
dlg.setRegularExpression( "[^/\\\\]+" );
80+
81+
if ( dlg.exec() != QDialog::Accepted )
82+
return;
83+
84+
// Try to create the profile folder
85+
QString profileName = dlg.name();
86+
QgsError error = mManager->createUserProfile( profileName );
87+
if ( error.isEmpty() )
88+
{
89+
auto item = new QListWidgetItem( QgsApplication::getThemeIcon( "user.svg" ), profileName );
90+
mProfileListWidget->addItem( item );
91+
mProfileListWidget->setCurrentItem( item );
92+
item->setSelected( true );
93+
// Automatically accept the dialog
94+
accept();
95+
}
96+
else
97+
{
98+
QMessageBox::warning( this, tr( "New Profile" ), tr( "Cannot create folder '%1'" ).arg( profileName ) );
99+
return;
100+
}
101+
}
102+
103+
QgsUserProfileSelectionDialog::~QgsUserProfileSelectionDialog() {}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/***************************************************************************
2+
qgsuserprofileselectiondialog.h
3+
--------------------------------------
4+
Date : February 2023
5+
Copyright : (C) 2023 by Yoann Quenach de Quivillic
6+
Email : yoann dot quenach at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSUSERPROFILESELECTIONDIALOG_H
17+
#define QGSUSERPROFILESELECTIONDIALOG_H
18+
19+
#include <QDialog>
20+
21+
#include "ui_qgsuserprofileselectiondialog.h"
22+
23+
24+
// Forward declarations
25+
class QgsUserProfileManager;
26+
class QEvent;
27+
28+
/**
29+
* \class QgsUserProfileSelectionDialog
30+
* \brief A dialog shown at startup to select the user profile
31+
* \since QGIS 3.32
32+
*/
33+
class GUI_EXPORT QgsUserProfileSelectionDialog : public QDialog, private Ui::QgsUserProfileSelectionDialog
34+
{
35+
Q_OBJECT
36+
37+
public:
38+
39+
/**
40+
* Constructor for QgsUserProfileSelectionDialog.
41+
* \param manager QgsUserProfileManager manager that will be used to fill the list of profiles
42+
* \param parent parent widget
43+
*/
44+
explicit QgsUserProfileSelectionDialog( QgsUserProfileManager *manager, QWidget *parent = nullptr );
45+
virtual ~QgsUserProfileSelectionDialog();
46+
47+
48+
/* Return the selected profile name */
49+
QString selectedProfileName() const;
50+
51+
public slots:
52+
void accept() override;
53+
54+
private slots:
55+
void onAddProfile();
56+
57+
private:
58+
QgsUserProfileManager *mManager = nullptr;
59+
60+
61+
};
62+
63+
#endif // QGSUSERPROFILESELECTIONDIALOG_H

‎src/app/options/qgsuserprofilesettingsdialog.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@
1818

1919
#include "qgsuserprofilesettingsdialog.h"
2020

21-
2221
QgsUserProfileSettingsDialog::QgsUserProfileSettingsDialog( QWidget *parent )
2322
: QDialog( parent )
2423

2524
{
2625
setupUi( this );
27-
connect( mDefaultProfile, &QRadioButton::toggled, mDefaultProfileComboBox, &QComboBox::setEnabled );
2826
connect( mButtonBox, &QDialogButtonBox::accepted, this, &QgsUserProfileSettingsDialog::apply );
2927

28+
// Disable combobox if default profile is not selected
29+
mDefaultProfileComboBox->setEnabled( false );
30+
connect( mDefaultProfile, &QRadioButton::toggled, mDefaultProfileComboBox, &QComboBox::setEnabled );
31+
3032
// Init radio buttons
3133
auto manager = QgisApp::instance()->userProfileManager();
3234
if ( manager->userProfileSelectionPolicy() == QgsUserProfileManager::UserProfileSelectionPolicy::LastProfile )
@@ -46,7 +48,6 @@ QgsUserProfileSettingsDialog::QgsUserProfileSettingsDialog( QWidget *parent )
4648
mDefaultProfileComboBox->clear();
4749
mDefaultProfileComboBox->addItems( manager->allProfiles() );
4850
mDefaultProfileComboBox->setCurrentText( manager->defaultProfileName() );
49-
5051
}
5152

5253
void QgsUserProfileSettingsDialog::apply()
@@ -66,4 +67,3 @@ void QgsUserProfileSettingsDialog::apply()
6667
manager->setDefaultProfileName( mDefaultProfileComboBox->currentText() );
6768
}
6869
}
69-
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>QgsUserProfileSelectionDialog</class>
4+
<widget class="QDialog" name="QgsUserProfileSelectionDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>313</width>
10+
<height>417</height>
11+
</rect>
12+
</property>
13+
<property name="palette">
14+
<palette>
15+
<active>
16+
<colorrole role="Base">
17+
<brush brushstyle="SolidPattern">
18+
<color alpha="255">
19+
<red>255</red>
20+
<green>255</green>
21+
<blue>255</blue>
22+
</color>
23+
</brush>
24+
</colorrole>
25+
<colorrole role="Window">
26+
<brush brushstyle="SolidPattern">
27+
<color alpha="255">
28+
<red>255</red>
29+
<green>255</green>
30+
<blue>255</blue>
31+
</color>
32+
</brush>
33+
</colorrole>
34+
</active>
35+
<inactive>
36+
<colorrole role="Base">
37+
<brush brushstyle="SolidPattern">
38+
<color alpha="255">
39+
<red>255</red>
40+
<green>255</green>
41+
<blue>255</blue>
42+
</color>
43+
</brush>
44+
</colorrole>
45+
<colorrole role="Window">
46+
<brush brushstyle="SolidPattern">
47+
<color alpha="255">
48+
<red>255</red>
49+
<green>255</green>
50+
<blue>255</blue>
51+
</color>
52+
</brush>
53+
</colorrole>
54+
</inactive>
55+
<disabled>
56+
<colorrole role="Base">
57+
<brush brushstyle="SolidPattern">
58+
<color alpha="255">
59+
<red>255</red>
60+
<green>255</green>
61+
<blue>255</blue>
62+
</color>
63+
</brush>
64+
</colorrole>
65+
<colorrole role="Window">
66+
<brush brushstyle="SolidPattern">
67+
<color alpha="255">
68+
<red>255</red>
69+
<green>255</green>
70+
<blue>255</blue>
71+
</color>
72+
</brush>
73+
</colorrole>
74+
</disabled>
75+
</palette>
76+
</property>
77+
<property name="windowTitle">
78+
<string>Profiles</string>
79+
</property>
80+
<layout class="QVBoxLayout" name="verticalLayout">
81+
<item>
82+
<widget class="QLabel" name="label_2">
83+
<property name="text">
84+
<string/>
85+
</property>
86+
<property name="pixmap">
87+
<pixmap resource="../../images/images.qrc">:/images/icons/qgis-icon-60x60.png</pixmap>
88+
</property>
89+
<property name="scaledContents">
90+
<bool>false</bool>
91+
</property>
92+
<property name="alignment">
93+
<set>Qt::AlignCenter</set>
94+
</property>
95+
</widget>
96+
</item>
97+
<item>
98+
<widget class="QLabel" name="label">
99+
<property name="font">
100+
<font>
101+
<pointsize>20</pointsize>
102+
</font>
103+
</property>
104+
<property name="text">
105+
<string>Choose a profile</string>
106+
</property>
107+
<property name="alignment">
108+
<set>Qt::AlignCenter</set>
109+
</property>
110+
</widget>
111+
</item>
112+
<item>
113+
<widget class="QListWidget" name="mProfileListWidget">
114+
<property name="frameShape">
115+
<enum>QFrame::NoFrame</enum>
116+
</property>
117+
<property name="uniformItemSizes">
118+
<bool>true</bool>
119+
</property>
120+
<item>
121+
<property name="text">
122+
<string>default</string>
123+
</property>
124+
<property name="icon">
125+
<iconset resource="../../images/images.qrc">
126+
<normaloff>:/images/themes/default/user.svg</normaloff>:/images/themes/default/user.svg</iconset>
127+
</property>
128+
</item>
129+
<item>
130+
<property name="text">
131+
<string>New User</string>
132+
</property>
133+
<property name="icon">
134+
<iconset resource="../../images/images.qrc">
135+
<normaloff>:/images/themes/default/user.svg</normaloff>:/images/themes/default/user.svg</iconset>
136+
</property>
137+
</item>
138+
</widget>
139+
</item>
140+
<item>
141+
<layout class="QHBoxLayout" name="horizontalLayout">
142+
<item>
143+
<widget class="QToolButton" name="mAddProfileButton">
144+
<property name="text">
145+
<string>Add new profile</string>
146+
</property>
147+
<property name="icon">
148+
<iconset resource="../../images/images.qrc">
149+
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
150+
</property>
151+
<property name="iconSize">
152+
<size>
153+
<width>24</width>
154+
<height>24</height>
155+
</size>
156+
</property>
157+
<property name="toolButtonStyle">
158+
<enum>Qt::ToolButtonTextBesideIcon</enum>
159+
</property>
160+
<property name="autoRaise">
161+
<bool>true</bool>
162+
</property>
163+
</widget>
164+
</item>
165+
<item>
166+
<spacer name="horizontalSpacer">
167+
<property name="orientation">
168+
<enum>Qt::Horizontal</enum>
169+
</property>
170+
<property name="sizeHint" stdset="0">
171+
<size>
172+
<width>40</width>
173+
<height>20</height>
174+
</size>
175+
</property>
176+
</spacer>
177+
</item>
178+
<item>
179+
<widget class="QToolButton" name="mOkButton">
180+
<property name="text">
181+
<string>Ok</string>
182+
</property>
183+
<property name="iconSize">
184+
<size>
185+
<width>24</width>
186+
<height>24</height>
187+
</size>
188+
</property>
189+
<property name="shortcut">
190+
<string>Return</string>
191+
</property>
192+
<property name="toolButtonStyle">
193+
<enum>Qt::ToolButtonTextBesideIcon</enum>
194+
</property>
195+
<property name="autoRaise">
196+
<bool>true</bool>
197+
</property>
198+
</widget>
199+
</item>
200+
</layout>
201+
</item>
202+
</layout>
203+
</widget>
204+
<resources>
205+
<include location="../../images/images.qrc"/>
206+
</resources>
207+
<connections>
208+
<connection>
209+
<sender>mOkButton</sender>
210+
<signal>clicked()</signal>
211+
<receiver>QgsUserProfileSelectionDialog</receiver>
212+
<slot>accept()</slot>
213+
<hints>
214+
<hint type="sourcelabel">
215+
<x>285</x>
216+
<y>390</y>
217+
</hint>
218+
<hint type="destinationlabel">
219+
<x>156</x>
220+
<y>208</y>
221+
</hint>
222+
</hints>
223+
</connection>
224+
</connections>
225+
</ui>

0 commit comments

Comments
 (0)
Please sign in to comment.