QGIS API Documentation 3.99.0-Master (8e76e220402)
Loading...
Searching...
No Matches
qgsuserprofilemanager.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsuserprofilemanager.cpp
3 --------------------------------------
4 Date : Jul-2017
5 Copyright : (C) 2017 by Nathan Woodrow
6 Email : woodrow.nathan 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
17
18#include <memory>
19
20#include "qgsapplication.h"
21#include "qgslogger.h"
22#include "qgssettings.h"
23#include "qgsuserprofile.h"
24
25#include <QDir>
26#include <QFile>
27#include <QProcess>
28#include <QStandardPaths>
29#include <QString>
30#include <QTextStream>
31
32#include "moc_qgsuserprofilemanager.cpp"
33
34using namespace Qt::StringLiterals;
35
37 : QObject( parent )
38{
40}
41
42QString QgsUserProfileManager::resolveProfilesFolder( const QString &basePath )
43{
44 return basePath + QDir::separator() + "profiles";
45}
46
47std::unique_ptr< QgsUserProfile > QgsUserProfileManager::getProfile( const QString &defaultProfile, bool createNew, bool initSettings )
48{
49 const QString profileName = defaultProfile.isEmpty() ? defaultProfileName() : defaultProfile;
50
51 if ( createNew && !profileExists( defaultProfile ) )
52 {
53 createUserProfile( profileName );
54 }
55
56 std::unique_ptr< QgsUserProfile > profile = profileForName( profileName );
57 if ( initSettings )
58 profile->initSettings();
59
60 return profile;
61}
62
63void QgsUserProfileManager::setRootLocation( const QString &rootProfileLocation )
64{
65 mRootProfilePath = rootProfileLocation;
66
67 //updates (or removes) profile file watcher for new root location
68 setNewProfileNotificationEnabled( mWatchProfiles );
69
70 mSettings = std::make_unique<QSettings>( settingsFile(), QSettings::IniFormat );
71}
72
74{
75 mWatchProfiles = enabled;
76 if ( mWatchProfiles && !mRootProfilePath.isEmpty() && QDir( mRootProfilePath ).exists() )
77 {
78 mWatcher = std::make_unique<QFileSystemWatcher>( );
79 mWatcher->addPath( mRootProfilePath );
80 connect( mWatcher.get(), &QFileSystemWatcher::directoryChanged, this, [this]
81 {
82 emit profilesChanged();
83 } );
84 }
85 else
86 {
87 mWatcher.reset();
88 }
89}
90
92{
93 return static_cast< bool >( mWatcher.get() );
94}
95
97{
98 return !mRootProfilePath.isEmpty();
99}
100
102{
103 const QString defaultName = u"default"_s;
104 // If the profiles.ini doesn't have the default profile we grab it from
105 // global settings as it might be set by the admin.
106 // If the overrideProfile flag is set then no matter what the profiles.ini says we always take the
107 // global profile.
108 const QgsSettings globalSettings;
109 if ( !mSettings->contains( u"/core/defaultProfile"_s ) || globalSettings.value( u"overrideLocalProfile"_s, false, QgsSettings::Core ).toBool() )
110 {
111 return globalSettings.value( u"defaultProfile"_s, defaultName, QgsSettings::Core ).toString();
112 }
113 return mSettings->value( u"/core/defaultProfile"_s, defaultName ).toString();
114}
115
117{
118 mSettings->setValue( u"/core/defaultProfile"_s, name );
119 mSettings->sync();
120}
121
126
128{
129 return mSettings->value( u"/core/lastProfile"_s, QString() ).toString();
130}
131
133{
134 mSettings->setValue( u"/core/lastProfile"_s, userProfile()->name() );
135 mSettings->sync();
136}
137
139{
140 return static_cast< Qgis::UserProfileSelectionPolicy >( mSettings->value( u"/core/selectionPolicy"_s, 0 ).toInt() );
141}
142
144{
145 mSettings->setValue( u"/core/selectionPolicy"_s, static_cast< int >( policy ) );
146 mSettings->sync();
147}
148
150{
151 return QDir( mRootProfilePath ).entryList( QDir::Dirs | QDir::NoDotAndDotDot );
152}
153
154bool QgsUserProfileManager::profileExists( const QString &name ) const
155{
156 return allProfiles().contains( name );
157}
158
159std::unique_ptr< QgsUserProfile > QgsUserProfileManager::profileForName( const QString &name ) const
160{
161 const QString profilePath = mRootProfilePath + QDir::separator() + name;
162 return std::make_unique< QgsUserProfile >( profilePath );
163}
164
166{
167 QgsError error;
168
169 // TODO Replace with safe folder name
170
171 const QDir folder( mRootProfilePath + QDir::separator() + name );
172 if ( !folder.exists() )
173 {
174 if ( !QDir().mkpath( folder.absolutePath() ) )
175 {
176 error.append( tr( "Cannot write '%1'" ).arg( folder.absolutePath() ) );
177 return error;
178 }
179 }
180
181 QFile qgisPrivateDbFile( folder.absolutePath() + QDir::separator() + "qgis.db" );
182
183 // first we look for ~/.qgis/qgis.db
184 if ( !qgisPrivateDbFile.exists() )
185 {
186 // if it doesn't exist we copy it from the global resources dir
187 const QString qgisMasterDbFileName = QgsApplication::qgisMasterDatabaseFilePath();
188 QFile masterFile( qgisMasterDbFileName );
189
190 //now copy the master file into the users .qgis dir
191 if ( !masterFile.copy( qgisPrivateDbFile.fileName() ) )
192 {
193 error.append( tr( "Could not copy master database to %1" ).arg( qgisPrivateDbFile.fileName() ) );
194 }
195 else
196 {
197 // In some packaging systems, the master can be read-only. Make sure to make
198 // the copy user writable.
199 const QFile::Permissions perms = QFile( qgisPrivateDbFile.fileName() ).permissions();
200 if ( !( perms & QFile::WriteOwner ) )
201 {
202 if ( !qgisPrivateDbFile.setPermissions( perms | QFile::WriteOwner ) )
203 {
204 error.append( tr( "Can not make '%1' user writable" ).arg( qgisPrivateDbFile.fileName() ) );
205 }
206 }
207 }
208 }
209
210 if ( error.isEmpty() )
211 {
212 emit profilesChanged();
213 }
214
215 return error;
216}
217
219{
220 QgsError error;
221 QDir folder( mRootProfilePath + QDir::separator() + name );
222
223 // This might have to be changed to something better.
224 const bool deleted = folder.removeRecursively();
225 if ( !deleted )
226 {
227 error.append( ( tr( "Unable to fully delete user profile folder" ) ) );
228 }
229 else
230 {
231 emit profilesChanged();
232 }
233 return error;
234}
235
236QString QgsUserProfileManager::settingsFile() const
237{
238 return mRootProfilePath + QDir::separator() + "profiles.ini";
239}
240
242{
243 return mSettings.get();
244}
245
247{
248 return mUserProfile.get();
249}
250
251void QgsUserProfileManager::loadUserProfile( const QString &name )
252{
253#if QT_CONFIG(process)
254 const QString path = QDir::toNativeSeparators( QCoreApplication::applicationFilePath() );
255 QStringList arguments;
256 arguments << QCoreApplication::arguments();
257 // The first is the path to the application
258 // on Windows this might not be case so we need to handle that
259 // http://doc.qt.io/qt-5/qcoreapplication.html#arguments
260 arguments.removeFirst();
261 arguments << u"--profile"_s << name;
262 QgsDebugMsgLevel( u"Starting instance from %1 with %2"_s.arg( path ).arg( arguments.join( " " ) ), 2 );
263 QProcess::startDetached( path, arguments, QDir::toNativeSeparators( QCoreApplication::applicationDirPath() ) );
264#else
265 Q_UNUSED( name )
266 Q_ASSERT( "Starting the user profile is not supported on the platform" );
267#endif //QT_CONFIG(process)
268}
269
271{
272 if ( ! mUserProfile )
273 {
274 mUserProfile = profileForName( profile );
275 }
276}
UserProfileSelectionPolicy
User profile selection policy.
Definition qgis.h:5737
static QString qgisMasterDatabaseFilePath()
Returns the path to the master qgis.db file.
A container for error messages.
Definition qgserror.h:83
bool isEmpty() const
Test if no error is set.
Definition qgserror.h:112
void append(const QString &message, const QString &tag)
Append new error message.
Definition qgserror.cpp:43
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
std::unique_ptr< QgsUserProfile > profileForName(const QString &name) const
Returns the profile found for a given name.
std::unique_ptr< QgsUserProfile > getProfile(const QString &defaultProfile="default", bool createNew=true, bool initSettings=true)
Returns the profile from the given root profile location.
void setRootLocation(const QString &rootProfileLocation)
Set the root profile location for the profile manager.
QgsError createUserProfile(const QString &name)
Create a user profile given by the name.
void setActiveUserProfile(const QString &profile)
Sets the active profile in the manager.
bool profileExists(const QString &name) const
Check if a profile exists.
QgsUserProfile * userProfile()
The currently active user profile.
void setDefaultProfileName(const QString &name)
Sets the default profile name.
void setDefaultFromActive()
Set the default profile name from the current active profile.
QStringList allProfiles() const
Returns a list of all found profile names.
bool rootLocationIsSet() const
Check if the root location has been set for the manager.
QgsError deleteProfile(const QString &name)
Deletes a profile from the root profiles folder.
QSettings * settings()
Returns the settings for the profile manager.
static QString resolveProfilesFolder(const QString &basePath=QString())
Resolves the profiles folder for the given path.
void setUserProfileSelectionPolicy(Qgis::UserProfileSelectionPolicy policy)
Sets the user profile selection policy.
void setNewProfileNotificationEnabled(bool enabled)
Sets whether the manager should watch for the creation of new user profiles and emit the profilesChan...
QString defaultProfileName() const
Returns the name of the default profile that has been set in .default.
QgsUserProfileManager(const QString &rootLocation=QString(), QObject *parent=nullptr)
User profile manager used to manage user profiles for the instance of QGIS.
Qgis::UserProfileSelectionPolicy userProfileSelectionPolicy() const
Returns the user profile selection policy.
void profilesChanged()
Emitted when the list of profiles is changed.
QString lastProfileName() const
Returns the name of the most recently closed profile.
void updateLastProfileName()
Updates the last closed profile name.
QString rootLocation() const
Returns the path to the root profiles location.
void loadUserProfile(const QString &name)
Starts a new instance of QGIS for the given profile.
bool isNewProfileNotificationEnabled() const
Returns whether the manager is watching for the creation of new user profiles and emitting the profil...
User profile contains information about the user profile folders on the machine.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63