QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
16 #include "qgsuserprofilemanager.h"
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 
29 QgsUserProfileManager::QgsUserProfileManager( const QString &rootLocation, QObject *parent )
30  : QObject( parent )
31 {
33 }
34 
35 QString QgsUserProfileManager::resolveProfilesFolder( const QString &basePath )
36 {
37  return basePath + QDir::separator() + "profiles";
38 }
39 
40 QgsUserProfile *QgsUserProfileManager::getProfile( const QString &defaultProfile, bool createNew, bool initSettings )
41 {
42  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 
56 void 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  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  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 {
117  setDefaultProfileName( userProfile()->name() );
118 }
119 
121 {
122  return QDir( mRootProfilePath ).entryList( QDir::Dirs | QDir::NoDotAndDotDot );
123 }
124 
125 bool QgsUserProfileManager::profileExists( const QString &name ) const
126 {
127  return allProfiles().contains( name );
128 }
129 
131 {
132  QString profilePath = mRootProfilePath + QDir::separator() + name;
133  return new QgsUserProfile( profilePath );
134 }
135 
137 {
138  QgsError error;
139 
140  // TODO Replace with safe folder name
141 
142  QDir folder( mRootProfilePath + QDir::separator() + name );
143  if ( !folder.exists() )
144  {
145  QDir().mkpath( folder.absolutePath() );
146  }
147 
148  QFile qgisPrivateDbFile( folder.absolutePath() + QDir::separator() + "qgis.db" );
149 
150  // first we look for ~/.qgis/qgis.db
151  if ( !qgisPrivateDbFile.exists() )
152  {
153  // if it doesn't exist we copy it from the global resources dir
154  QString qgisMasterDbFileName = QgsApplication::qgisMasterDatabaseFilePath();
155  QFile masterFile( qgisMasterDbFileName );
156 
157  //now copy the master file into the users .qgis dir
158  masterFile.copy( qgisPrivateDbFile.fileName() );
159 
160  // In some packaging systems, the master can be read-only. Make sure to make
161  // the copy user writable.
162  const QFile::Permissions perms = QFile( qgisPrivateDbFile.fileName() ).permissions();
163  if ( !( perms & QFile::WriteOwner ) )
164  {
165  if ( !qgisPrivateDbFile.setPermissions( perms | QFile::WriteOwner ) )
166  {
167  error.append( tr( "Can not make '%1' user writable" ).arg( qgisPrivateDbFile.fileName() ) );
168  }
169  }
170  }
171 
172  if ( error.isEmpty() )
173  {
174  emit profilesChanged();
175  }
176 
177  return error;
178 }
179 
181 {
182  QgsError error;
183  QDir folder( mRootProfilePath + QDir::separator() + name );
184 
185  // This might have to be changed to something better.
186  bool deleted = folder.removeRecursively();
187  if ( !deleted )
188  {
189  error.append( ( tr( "Unable to fully delete user profile folder" ) ) );
190  }
191  else
192  {
193  emit profilesChanged();
194  }
195  return error;
196 }
197 
198 QString QgsUserProfileManager::settingsFile() const
199 {
200  return mRootProfilePath + QDir::separator() + "profiles.ini";
201 }
202 
204 {
205  return mUserProfile.get();
206 }
207 
208 void QgsUserProfileManager::loadUserProfile( const QString &name )
209 {
210 #if QT_CONFIG(process)
211  QString path = QDir::toNativeSeparators( QCoreApplication::applicationFilePath() );
212  QStringList arguments;
213  arguments << QCoreApplication::arguments();
214  // The first is the path to the application
215  // on Windows this might not be case so we need to handle that
216  // http://doc.qt.io/qt-5/qcoreapplication.html#arguments
217  arguments.removeFirst();
218  arguments << QStringLiteral( "--profile" ) << name;
219  QgsDebugMsg( QStringLiteral( "Starting instance from %1 with %2" ).arg( path ).arg( arguments.join( " " ) ) );
220  QProcess::startDetached( path, arguments, QDir::toNativeSeparators( QCoreApplication::applicationDirPath() ) );
221 #else
222  Q_UNUSED( name )
223  Q_ASSERT( "Starting the user profile is not supported on the platform" );
224 #endif //QT_CONFIG(process)
225 }
226 
227 void QgsUserProfileManager::setActiveUserProfile( const QString &profile )
228 {
229  if ( ! mUserProfile.get() )
230  {
231  mUserProfile.reset( profileForName( profile ) );
232  }
233 }
QgsUserProfileManager::setActiveUserProfile
void setActiveUserProfile(const QString &profile)
Sets the active profile in the manager.
Definition: qgsuserprofilemanager.cpp:227
QgsUserProfileManager::setDefaultProfileName
void setDefaultProfileName(const QString &name)
Sets the default profile name.
Definition: qgsuserprofilemanager.cpp:109
QgsUserProfileManager::QgsUserProfileManager
QgsUserProfileManager(const QString &rootLocation=QString(), QObject *parent=nullptr)
User profile manager used to manage user profiles for the instance of QGIS.
Definition: qgsuserprofilemanager.cpp:29
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:174
QgsUserProfileManager::allProfiles
QStringList allProfiles() const
Returns a list of all found profile names.
Definition: qgsuserprofilemanager.cpp:120
QgsSettings::Core
@ Core
Definition: qgssettings.h:70
qgsuserprofile.h
QgsUserProfileManager::resolveProfilesFolder
static QString resolveProfilesFolder(const QString &basePath=QString())
Resolves the profiles folder for the given path.
Definition: qgsuserprofilemanager.cpp:35
QgsError
QgsError is container for error messages (report).
Definition: qgserror.h:81
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsError::append
void append(const QString &message, const QString &tag)
Append new error message.
Definition: qgserror.cpp:39
QgsUserProfileManager::deleteProfile
QgsError deleteProfile(const QString &name)
Deletes a profile from the root profiles folder.
Definition: qgsuserprofilemanager.cpp:180
QgsUserProfileManager::setRootLocation
void setRootLocation(const QString &rootProfileLocation)
Set the root profile location for the profile manager.
Definition: qgsuserprofilemanager.cpp:56
qgsapplication.h
QgsUserProfileManager::getProfile
QgsUserProfile * getProfile(const QString &defaultProfile="default", bool createNew=true, bool initSettings=true)
Returns the profile from the given root profile location.
Definition: qgsuserprofilemanager.cpp:40
QgsApplication::qgisMasterDatabaseFilePath
static QString qgisMasterDatabaseFilePath()
Returns the path to the master qgis.db file.
Definition: qgsapplication.cpp:988
QgsUserProfileManager::createUserProfile
QgsError createUserProfile(const QString &name)
Create a user profile given by the name.
Definition: qgsuserprofilemanager.cpp:136
QgsUserProfileManager::userProfile
QgsUserProfile * userProfile()
The currently active user profile.
Definition: qgsuserprofilemanager.cpp:203
QgsError::isEmpty
bool isEmpty() const
Test if any error is set.
Definition: qgserror.h:111
QgsUserProfileManager::setNewProfileNotificationEnabled
void setNewProfileNotificationEnabled(bool enabled)
Sets whether the manager should watch for the creation of new user profiles and emit the profilesChan...
Definition: qgsuserprofilemanager.cpp:66
QgsUserProfile::initSettings
void initSettings() const
Init the settings from the user folder.
Definition: qgsuserprofile.cpp:51
QgsUserProfileManager::defaultProfileName
QString defaultProfileName() const
Returns the name of the default profile that has been set in .default.
Definition: qgsuserprofilemanager.cpp:94
QgsUserProfileManager::profileForName
QgsUserProfile * profileForName(const QString &name) const
Returns the profile found for a given name.
Definition: qgsuserprofilemanager.cpp:130
qgsuserprofilemanager.h
QgsUserProfileManager::setDefaultFromActive
void setDefaultFromActive()
Set the default profile name from the current active profile.
Definition: qgsuserprofilemanager.cpp:115
QgsUserProfileManager::isNewProfileNotificationEnabled
bool isNewProfileNotificationEnabled() const
Returns whether the manager is watching for the creation of new user profiles and emitting the profil...
Definition: qgsuserprofilemanager.cpp:84
qgssettings.h
QgsUserProfile
User profile contains information about the user profile folders on the machine.
Definition: qgsuserprofile.h:35
QgsUserProfileManager::profileExists
bool profileExists(const QString &name) const
Check if a profile exists.
Definition: qgsuserprofilemanager.cpp:125
QgsUserProfileManager::profilesChanged
void profilesChanged()
Emitted when the list of profiles is changed.
QgsUserProfileManager::rootLocationIsSet
bool rootLocationIsSet() const
Check if the root location has been set for the manager.
Definition: qgsuserprofilemanager.cpp:89
qgslogger.h
QgsUserProfileManager::loadUserProfile
void loadUserProfile(const QString &name)
Starts a new instance of QGIS for the given profile.
Definition: qgsuserprofilemanager.cpp:208
QgsUserProfileManager::rootLocation
QString rootLocation()
Returns the path to the root profiles location.
Definition: qgsuserprofilemanager.h:83