QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgsstoredquerymanager.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsstoredquerymanager.cpp
3 ------------------------------------
4 Date : February 2025
5 Copyright : (C) 2025 Nyall Dawson
6 Email : nyall dot dawson 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 "qgsproject.h"
20
21#include <QCryptographicHash>
22
23#include "moc_qgsstoredquerymanager.cpp"
24
26const QgsSettingsEntryString *QgsStoredQueryManager::settingQueryName = new QgsSettingsEntryString( QStringLiteral( "name" ), sTreeStoredQueries );
27const QgsSettingsEntryString *QgsStoredQueryManager::settingQueryDefinition = new QgsSettingsEntryString( QStringLiteral( "query" ), sTreeStoredQueries );
29
31 : QObject( parent )
32{
33}
34
35void QgsStoredQueryManager::storeQuery( const QString &name, const QString &query, Qgis::QueryStorageBackend backend )
36{
37 if ( query.isEmpty() || name.isEmpty() )
38 return;
39
40 bool wasAdded = false;
41 bool wasUpdated = false;
42
43 // Yes, this looks odd! It's this way for compatibility with DB Manager stored queries...
44 const QString hash = getQueryHash( name );
45
46 switch ( backend )
47 {
49 {
50 const bool isExisting = sTreeStoredQueries->items().contains( hash );
51 wasAdded = !isExisting;
52 wasUpdated = isExisting;
53 settingQueryName->setValue( name, hash );
54 settingQueryDefinition->setValue( query, hash );
55 break;
56 }
57
59 {
60 const bool isExisting = QgsProject::instance()->subkeyList( QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries" ) ).contains( hash );
61 wasAdded = !isExisting;
62 wasUpdated = isExisting;
63 QgsProject::instance()->writeEntry( QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries/%1/name" ).arg( hash ), name );
64 QgsProject::instance()->writeEntry( QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries/%1/query" ).arg( hash ), query );
65 break;
66 }
67 }
68
69 if ( wasAdded )
70 emit queryAdded( name, backend );
71 else if ( wasUpdated )
72 emit queryChanged( name, backend );
73}
74
76{
77 if ( name.isEmpty() )
78 return;
79
80 bool wasDeleted = false;
81 // Yes, this looks odd! It's this way for compatibility with DB Manager stored queries...
82 const QString hash = getQueryHash( name );
83
84 switch ( backend )
85 {
87 {
88 wasDeleted = sTreeStoredQueries->items().contains( hash );
89 sTreeStoredQueries->deleteItem( hash );
90 break;
91 }
92
94 {
95 wasDeleted = QgsProject::instance()->subkeyList( QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries" ) ).contains( hash );
97 "DBManager", QStringLiteral( "savedQueries/%1" ).arg( hash )
98 );
99 break;
100 }
101 }
102
103 if ( wasDeleted )
104 emit queryRemoved( name, backend );
105}
106
108{
109 QStringList names;
110 switch ( backend )
111 {
113 {
114 const QStringList hashes = sTreeStoredQueries->items();
115 names.reserve( hashes.size() );
116 for ( const QString &hash : hashes )
117 {
118 names.append( settingQueryName->value( hash ) );
119 }
120 break;
121 }
122
124 {
125 const QStringList hashes = QgsProject::instance()->subkeyList( QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries" ) );
126 names.reserve( hashes.size() );
127 for ( const QString &hash : hashes )
128 {
129 names.append( QgsProject::instance()->readEntry(
130 QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries/%1/name" ).arg( hash )
131 ) );
132 }
133 break;
134 }
135 }
136 return names;
137}
138
139QString QgsStoredQueryManager::query( const QString &name, Qgis::QueryStorageBackend backend ) const
140{
141 // Yes, this looks odd! It's this way for compatibility with DB Manager stored queries...
142 const QString hash = getQueryHash( name );
143
144 switch ( backend )
145 {
147 {
148 return settingQueryDefinition->value( hash );
149 }
150
152 {
153 return QgsProject::instance()->readEntry( QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries/%1/query" ).arg( hash ) );
154 }
155 }
157}
158
159QList<QgsStoredQueryManager::QueryDetails> QgsStoredQueryManager::allQueries() const
160{
161 QList<QgsStoredQueryManager::QueryDetails> res;
162
163 const QStringList localProfileHashes = sTreeStoredQueries->items();
164 const QStringList projectHashes = QgsProject::instance()->subkeyList( QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries" ) );
165 res.reserve( localProfileHashes.size() + projectHashes.size() );
166
167 for ( const QString &hash : localProfileHashes )
168 {
169 QueryDetails details;
170 details.name = settingQueryName->value( hash );
171 details.definition = settingQueryDefinition->value( hash );
173 res.append( details );
174 }
175
176 for ( const QString &hash : projectHashes )
177 {
178 QueryDetails details;
180 QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries/%1/name" ).arg( hash )
181 );
183 QStringLiteral( "DBManager" ), QStringLiteral( "savedQueries/%1/query" ).arg( hash )
184 );
186 res.append( details );
187 }
188
189 std::sort( res.begin(), res.end(), []( const QueryDetails &a, const QueryDetails &b ) {
190 if ( a.name == b.name )
191 {
192 if ( a.backend == b.backend )
193 return false;
194 else
195 return a.backend == Qgis::QueryStorageBackend::CurrentProject;
196 }
197
198 return QString::localeAwareCompare( a.name, b.name ) < 0;
199 } );
200
201 return res;
202}
203
204QString QgsStoredQueryManager::getQueryHash( const QString &name )
205{
206 // for compatibility with DB manager stored queries!
207 QByteArray nameUtf8 = name.toUtf8();
208 QByteArray hash = QCryptographicHash::hash( nameUtf8, QCryptographicHash::Md5 ).toHex();
209 return QStringLiteral( "q%1" ).arg( QString::fromUtf8( hash ) );
210}
QueryStorageBackend
Stored query storage backends.
Definition qgis.h:3517
@ CurrentProject
Current QGIS project.
Definition qgis.h:3519
@ LocalProfile
Local user profile.
Definition qgis.h:3518
static QgsProject * instance()
Returns the QgsProject singleton instance.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Reads a string from the specified scope and key.
bool writeEntry(const QString &scope, const QString &key, bool value)
Write a boolean value to the project file.
QStringList subkeyList(const QString &scope, const QString &key) const
Returns a list of child keys which contain other keys that exist within the the specified scope and k...
bool removeEntry(const QString &scope, const QString &key)
Remove the given key from the specified scope.
A string settings entry.
Contains details about a stored query.
Qgis::QueryStorageBackend backend
Storage backend.
QList< QgsStoredQueryManager::QueryDetails > allQueries() const
Returns details of all queries stored in the manager.
QStringList allQueryNames(Qgis::QueryStorageBackend backend=Qgis::QueryStorageBackend::LocalProfile) const
Returns a list of the names of all stored queries for the specified backend.
void queryRemoved(const QString &name, Qgis::QueryStorageBackend backend)
Emitted when a query is removed from the manager.
void queryChanged(const QString &name, Qgis::QueryStorageBackend backend)
Emitted when an existing query is changed in the manager.
void queryAdded(const QString &name, Qgis::QueryStorageBackend backend)
Emitted when a query is added to the manager.
QgsStoredQueryManager(QObject *parent=nullptr)
Constructor for QgsStoredQueryManager, with the specified parent object.
QString query(const QString &name, Qgis::QueryStorageBackend backend=Qgis::QueryStorageBackend::LocalProfile) const
Returns the query definition with matching name, from the specified backend.
void removeQuery(const QString &name, Qgis::QueryStorageBackend backend=Qgis::QueryStorageBackend::LocalProfile)
Removes the stored query with matching name.
void storeQuery(const QString &name, const QString &query, Qgis::QueryStorageBackend backend=Qgis::QueryStorageBackend::LocalProfile)
Saves a query to the manager.
#define BUILTIN_UNREACHABLE
Definition qgis.h:7208