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