QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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#include "qgsuserprofile.h"
18#include "qgsapplication.h"
19#include "qgslogger.h"
20#include "qgssettings.h"
21
22#include <QFile>
23#include <QDir>
24#include <QTextStream>
25#include <QProcess>
26#include <QStandardPaths>
27
28
29QgsUserProfileManager::QgsUserProfileManager( const QString &rootLocation, QObject *parent )
30 : QObject( parent )
31{
33}
34
35QString QgsUserProfileManager::resolveProfilesFolder( const QString &basePath )
36{
37 return basePath + QDir::separator() + "profiles";
38}
39
40QgsUserProfile *QgsUserProfileManager::getProfile( const QString &defaultProfile, bool createNew, bool initSettings )
41{
42 const QString profileName = defaultProfile.isEmpty() ? defaultProfileName() : defaultProfile;
43
44 if ( createNew && !profileExists( defaultProfile ) )
45 {
46 createUserProfile( profileName );
47 }
48
49 QgsUserProfile *profile = profileForName( profileName );
50 if ( initSettings )
51 profile->initSettings();
52
53 return profile;
54}
55
56void QgsUserProfileManager::setRootLocation( const QString &rootProfileLocation )
57{
58 mRootProfilePath = rootProfileLocation;
59
60 //updates (or removes) profile file watcher for new root location
61 setNewProfileNotificationEnabled( mWatchProfiles );
62
63 mSettings.reset( new QSettings( settingsFile(), QSettings::IniFormat ) );
64}
65
67{
68 mWatchProfiles = enabled;
69 if ( mWatchProfiles && !mRootProfilePath.isEmpty() && QDir( mRootProfilePath ).exists() )
70 {
71 mWatcher.reset( new QFileSystemWatcher() );
72 mWatcher->addPath( mRootProfilePath );
73 connect( mWatcher.get(), &QFileSystemWatcher::directoryChanged, this, [this]
74 {
75 emit profilesChanged();
76 } );
77 }
78 else
79 {
80 mWatcher.reset();
81 }
82}
83
85{
86 return static_cast< bool >( mWatcher.get() );
87}
88
90{
91 return !mRootProfilePath.isEmpty();
92}
93
95{
96 const QString defaultName = QStringLiteral( "default" );
97 // If the profiles.ini doesn't have the default profile we grab it from
98 // global settings as it might be set by the admin.
99 // If the overrideProfile flag is set then no matter what the profiles.ini says we always take the
100 // global profile.
101 const QgsSettings globalSettings;
102 if ( !mSettings->contains( QStringLiteral( "/core/defaultProfile" ) ) || globalSettings.value( QStringLiteral( "overrideLocalProfile" ), false, QgsSettings::Core ).toBool() )
103 {
104 return globalSettings.value( QStringLiteral( "defaultProfile" ), defaultName, QgsSettings::Core ).toString();
105 }
106 return mSettings->value( QStringLiteral( "/core/defaultProfile" ), defaultName ).toString();
107}
108
110{
111 mSettings->setValue( QStringLiteral( "/core/defaultProfile" ), name );
112 mSettings->sync();
113}
114
116{
118}
119
121{
122 return mSettings->value( QStringLiteral( "/core/lastProfile" ), QString() ).toString();
123}
124
126{
127 mSettings->setValue( QStringLiteral( "/core/lastProfile" ), userProfile()->name() );
128 mSettings->sync();
129}
130
132{
133 return static_cast< Qgis::UserProfileSelectionPolicy >( mSettings->value( QStringLiteral( "/core/selectionPolicy" ), 0 ).toInt() );
134}
135
137{
138 mSettings->setValue( QStringLiteral( "/core/selectionPolicy" ), static_cast< int >( policy ) );
139 mSettings->sync();
140}
141
143{
144 return QDir( mRootProfilePath ).entryList( QDir::Dirs | QDir::NoDotAndDotDot );
145}
146
147bool QgsUserProfileManager::profileExists( const QString &name ) const
148{
149 return allProfiles().contains( name );
150}
151
153{
154 const QString profilePath = mRootProfilePath + QDir::separator() + name;
155 return new QgsUserProfile( profilePath );
156}
157
159{
160 QgsError error;
161
162 // TODO Replace with safe folder name
163
164 const QDir folder( mRootProfilePath + QDir::separator() + name );
165 if ( !folder.exists() )
166 {
167 if ( !QDir().mkpath( folder.absolutePath() ) )
168 {
169 error.append( tr( "Cannot write '%1'" ).arg( folder.absolutePath() ) );
170 return error;
171 }
172 }
173
174 QFile qgisPrivateDbFile( folder.absolutePath() + QDir::separator() + "qgis.db" );
175
176 // first we look for ~/.qgis/qgis.db
177 if ( !qgisPrivateDbFile.exists() )
178 {
179 // if it doesn't exist we copy it from the global resources dir
180 const QString qgisMasterDbFileName = QgsApplication::qgisMasterDatabaseFilePath();
181 QFile masterFile( qgisMasterDbFileName );
182
183 //now copy the master file into the users .qgis dir
184 masterFile.copy( qgisPrivateDbFile.fileName() );
185
186 // In some packaging systems, the master can be read-only. Make sure to make
187 // the copy user writable.
188 const QFile::Permissions perms = QFile( qgisPrivateDbFile.fileName() ).permissions();
189 if ( !( perms & QFile::WriteOwner ) )
190 {
191 if ( !qgisPrivateDbFile.setPermissions( perms | QFile::WriteOwner ) )
192 {
193 error.append( tr( "Can not make '%1' user writable" ).arg( qgisPrivateDbFile.fileName() ) );
194 }
195 }
196 }
197
198 if ( error.isEmpty() )
199 {
200 emit profilesChanged();
201 }
202
203 return error;
204}
205
207{
208 QgsError error;
209 QDir folder( mRootProfilePath + QDir::separator() + name );
210
211 // This might have to be changed to something better.
212 const bool deleted = folder.removeRecursively();
213 if ( !deleted )
214 {
215 error.append( ( tr( "Unable to fully delete user profile folder" ) ) );
216 }
217 else
218 {
219 emit profilesChanged();
220 }
221 return error;
222}
223
224QString QgsUserProfileManager::settingsFile() const
225{
226 return mRootProfilePath + QDir::separator() + "profiles.ini";
227}
228
230{
231 return mSettings.get();
232}
233
235{
236 return mUserProfile.get();
237}
238
239void QgsUserProfileManager::loadUserProfile( const QString &name )
240{
241#if QT_CONFIG(process)
242 const QString path = QDir::toNativeSeparators( QCoreApplication::applicationFilePath() );
243 QStringList arguments;
244 arguments << QCoreApplication::arguments();
245 // The first is the path to the application
246 // on Windows this might not be case so we need to handle that
247 // http://doc.qt.io/qt-5/qcoreapplication.html#arguments
248 arguments.removeFirst();
249 arguments << QStringLiteral( "--profile" ) << name;
250 QgsDebugMsgLevel( QStringLiteral( "Starting instance from %1 with %2" ).arg( path ).arg( arguments.join( " " ) ), 2 );
251 QProcess::startDetached( path, arguments, QDir::toNativeSeparators( QCoreApplication::applicationDirPath() ) );
252#else
253 Q_UNUSED( name )
254 Q_ASSERT( "Starting the user profile is not supported on the platform" );
255#endif //QT_CONFIG(process)
256}
257
259{
260 if ( ! mUserProfile.get() )
261 {
262 mUserProfile.reset( profileForName( profile ) );
263 }
264}
UserProfileSelectionPolicy
User profile selection policy.
Definition: qgis.h:4369
static QString qgisMasterDatabaseFilePath()
Returns the path to the master qgis.db file.
QgsError is container for error messages (report).
Definition: qgserror.h:81
bool isEmpty() const
Test if any error is set.
Definition: qgserror.h:111
void append(const QString &message, const QString &tag)
Append new error message.
Definition: qgserror.cpp:39
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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.
QString rootLocation()
Returns the path to the root profiles location.
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.
QgsUserProfile * profileForName(const QString &name) const
Returns the profile found for a given name.
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.
void initSettings() const
Init the settings from the user folder.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39