QGIS API Documentation  3.0.2-Girona (307d082)
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 {
32  setRootLocation( rootLocation );
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().mkdir( 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 
161  if ( error.isEmpty() )
162  {
163  emit profilesChanged();
164  }
165 
166  return error;
167 }
168 
170 {
171  QgsError error;
172  QDir folder( mRootProfilePath + QDir::separator() + name );
173 
174  // This might have to be changed to something better.
175  bool deleted = folder.removeRecursively();
176  if ( !deleted )
177  {
178  error.append( ( tr( "Unable to fully delete user profile folder" ) ) );
179  }
180  else
181  {
182  emit profilesChanged();
183  }
184  return error;
185 }
186 
187 QString QgsUserProfileManager::settingsFile() const
188 {
189  return mRootProfilePath + QDir::separator() + "profiles.ini";
190 }
191 
193 {
194  return mUserProfile.get();
195 }
196 
197 void QgsUserProfileManager::loadUserProfile( const QString &name )
198 {
199  QString path = QDir::toNativeSeparators( QCoreApplication::applicationFilePath() );
200  QStringList arguments;
201  arguments << QCoreApplication::arguments();
202  // The first is the path to the application
203  // on Windows this might not be case so we need to handle that
204  // http://doc.qt.io/qt-5/qcoreapplication.html#arguments
205  arguments.removeFirst();
206 
207  arguments << QStringLiteral( "--profile" ) << name;
208  QgsDebugMsg( QString( "Starting instance from %1 with %2" ).arg( path ).arg( arguments.join( " " ) ) );
209  QProcess::startDetached( path, arguments, QDir::toNativeSeparators( QCoreApplication::applicationDirPath() ) );
210 }
211 
212 void QgsUserProfileManager::setActiveUserProfile( const QString &profile )
213 {
214  if ( ! mUserProfile.get() )
215  {
216  mUserProfile.reset( profileForName( profile ) );
217  }
218 }
static QString resolveProfilesFolder(const QString &basePath=QString())
Resolves the profiles folder for the given path.
void profilesChanged()
Emitted when the list of profiles is changed.
static QString qgisMasterDatabaseFilePath()
Returns the path to the master qgis.db file.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:57
QgsUserProfile * userProfile()
The currently active user profile.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
User profile contains information about the user profile folders on the machine.
QgsError createUserProfile(const QString &name)
Create a user profile given by the name.
QStringList allProfiles() const
A list of all found profile names.
QgsUserProfile * profileForName(const QString &name) const
Return the profile found for a given name.
void setDefaultFromActive()
Set the default profile name from the current active profile.
bool isEmpty() const
Test if any error is set.
Definition: qgserror.h:111
QString defaultProfileName() const
Returns the name of the default profile that has been set in .default.
bool rootLocationIsSet() const
Check if the root location has been set for the manager.
bool profileExists(const QString &name) const
Check if a profile exists.
void append(const QString &message, const QString &tag)
Append new error message.
Definition: qgserror.cpp:39
void setNewProfileNotificationEnabled(bool enabled)
Sets whether the manager should watch for the creation of new user profiles and emit the profilesChan...
void setRootLocation(const QString &rootProfileLocation)
Set the root profile location for the profile manager.
void loadUserProfile(const QString &name)
Starts a new instance of QGIS for the given profile.
QgsError is container for error messages (report).
Definition: qgserror.h:80
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
QgsUserProfile * getProfile(const QString &defaultProfile="default", bool createNew=true, bool initSettings=true)
Return the profile from the given root profile location.
void setActiveUserProfile(const QString &profile)
Sets the active profile in the manager.
void setDefaultProfileName(const QString &name)
Sets the default profile name.
QgsUserProfileManager(const QString &rootLocation=QString(), QObject *parent=nullptr)
User profile manager used to manage user profiles for the instance of QGIS.
bool isNewProfileNotificationEnabled() const
Returns whether the manager is watching for the creation of new user profiles and emitting the profil...
QgsError deleteProfile(const QString &name)
Deletes a profile from the root profiles folder.
void initSettings() const
Init the settings from the user folder.