QGIS API Documentation 3.43.0-Master (58029bba303)
qgsdbqueryhistoryprovider.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsdbqueryhistoryprovider.cpp
3 --------------------------
4 begin : April 2023
5 copyright : (C) 2023 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18#include "moc_qgsdbqueryhistoryprovider.cpp"
19#include "qgscodeeditorsql.h"
20#include "qgshistoryentry.h"
21#include "qgsprovidermetadata.h"
22#include "qgsproviderregistry.h"
23#include "qgsapplication.h"
25
26#include <QIcon>
27#include <QAction>
28#include <QMenu>
29#include <QMimeData>
30#include <QClipboard>
31
33
34class DatabaseQueryHistoryNode : public QgsHistoryEntryGroup
35{
36 public:
37 DatabaseQueryHistoryNode( const QgsHistoryEntry &entry, QgsDatabaseQueryHistoryProvider *provider )
39 , mEntry( entry )
40 , mProvider( provider )
41 {
42 }
43
44 protected:
45 QgsHistoryEntry mEntry;
46 QgsDatabaseQueryHistoryProvider *mProvider = nullptr;
47};
48
49class DatabaseQueryValueNode : public DatabaseQueryHistoryNode
50{
51 public:
52 DatabaseQueryValueNode( const QgsHistoryEntry &entry, QgsDatabaseQueryHistoryProvider *provider, const QString &value )
53 : DatabaseQueryHistoryNode( entry, provider )
54 , mValue( value )
55 {}
56
57 QVariant data( int role = Qt::DisplayRole ) const override
58 {
59 switch ( role )
60 {
61 case Qt::DisplayRole:
62 case Qt::ToolTipRole:
63 return mValue;
64
65 default:
66 return QVariant();
67 }
68 }
69
70 QString html( const QgsHistoryWidgetContext & ) const override
71 {
72 return mValue;
73 }
74
75 private:
76 QString mValue;
77};
78
79class DatabaseQueryRootNode : public DatabaseQueryHistoryNode
80{
81 public:
82 DatabaseQueryRootNode( const QgsHistoryEntry &entry, QgsDatabaseQueryHistoryProvider *provider )
83 : DatabaseQueryHistoryNode( entry, provider )
84 {
85 setEntry( entry );
86
87 mProviderKey = mEntry.entry.value( QStringLiteral( "provider" ) ).toString();
88 }
89
90 QVariant data( int role = Qt::DisplayRole ) const override
91 {
92 switch ( role )
93 {
94 case Qt::DisplayRole:
95 case Qt::ToolTipRole:
96 return mEntry.entry.value( QStringLiteral( "query" ) );
97
98 case Qt::DecorationRole:
99 {
100 if ( !mProviderIcon.isNull() )
101 return mProviderIcon;
102
103 if ( QgsProviderMetadata *md = QgsProviderRegistry::instance()->providerMetadata( mProviderKey ) )
104 {
105 mProviderIcon = md->icon();
106 }
107 return mProviderIcon;
108 }
109
110 default:
111 break;
112 }
113 return QVariant();
114 }
115
116 void setEntry( const QgsHistoryEntry &entry )
117 {
118 if ( !mConnectionNode )
119 {
120 mConnectionNode = new DatabaseQueryValueNode( mEntry, mProvider, QObject::tr( "Connection: %1" ).arg( entry.entry.value( QStringLiteral( "connection" ) ).toString() ) );
121 addChild( mConnectionNode );
122 }
123 if ( entry.entry.contains( QStringLiteral( "rows" ) ) )
124 {
125 if ( !mRowsNode )
126 {
127 mRowsNode = new DatabaseQueryValueNode( mEntry, mProvider, QObject::tr( "Row count: %1" ).arg( entry.entry.value( QStringLiteral( "rows" ) ).toString() ) );
128 addChild( mRowsNode );
129 }
130 }
131 if ( entry.entry.contains( QStringLiteral( "time" ) ) )
132 {
133 if ( !mTimeNode )
134 {
135 mTimeNode = new DatabaseQueryValueNode( mEntry, mProvider, QObject::tr( "Execution time: %1 ms" ).arg( entry.entry.value( QStringLiteral( "time" ) ).toString() ) );
136 addChild( mTimeNode );
137 }
138 }
139 }
140
141 QWidget *createWidget( const QgsHistoryWidgetContext & ) override
142 {
143 QgsCodeEditorSQL *editor = new QgsCodeEditorSQL();
144 editor->setText( mEntry.entry.value( QStringLiteral( "query" ) ).toString() );
145 editor->setReadOnly( true );
146 editor->setCaretLineVisible( false );
147 editor->setLineNumbersVisible( false );
148 editor->setFoldingVisible( false );
149 editor->setEdgeMode( QsciScintilla::EdgeNone );
150 editor->setWrapMode( QsciScintilla::WrapMode::WrapWord );
151 return editor;
152 }
153
154 bool doubleClicked( const QgsHistoryWidgetContext &context ) override
155 {
156 if ( QgsDatabaseQueryHistoryWidget *queryHistoryWidget = qobject_cast< QgsDatabaseQueryHistoryWidget * >( context.historyWidget() ) )
157 {
158 queryHistoryWidget->emitSqlTriggered( mEntry.entry.value( QStringLiteral( "connection" ) ).toString(), mEntry.entry.value( QStringLiteral( "provider" ) ).toString(), mEntry.entry.value( QStringLiteral( "query" ) ).toString() );
159 }
160 return true;
161 }
162
163 void populateContextMenu( QMenu *menu, const QgsHistoryWidgetContext &context ) override
164 {
165 if ( QgsDatabaseQueryHistoryWidget *queryHistoryWidget = qobject_cast< QgsDatabaseQueryHistoryWidget * >( context.historyWidget() ) )
166 {
167 QAction *executeAction = new QAction(
168 QObject::tr( "Execute SQL Command…" ), menu
169 );
170 QObject::connect( executeAction, &QAction::triggered, menu, [=] {
171 queryHistoryWidget->emitSqlTriggered( mEntry.entry.value( QStringLiteral( "connection" ) ).toString(), mEntry.entry.value( QStringLiteral( "provider" ) ).toString(), mEntry.entry.value( QStringLiteral( "query" ) ).toString() );
172 } );
173 menu->addAction( executeAction );
174 }
175
176 QAction *copyAction = new QAction(
177 QObject::tr( "Copy SQL Command" ), menu
178 );
179 copyAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionEditCopy.svg" ) ) );
180 QObject::connect( copyAction, &QAction::triggered, menu, [=] {
181 QMimeData *m = new QMimeData();
182 m->setText( mEntry.entry.value( QStringLiteral( "query" ) ).toString() );
183 QApplication::clipboard()->setMimeData( m );
184 } );
185 menu->addAction( copyAction );
186 }
187
188 private:
189 QString mProviderKey;
190 mutable QIcon mProviderIcon;
191 DatabaseQueryValueNode *mConnectionNode = nullptr;
192 DatabaseQueryValueNode *mRowsNode = nullptr;
193 DatabaseQueryValueNode *mTimeNode = nullptr;
194};
195
197
198
202
204{
205 return QStringLiteral( "dbquery" );
206}
207
209{
210 return new DatabaseQueryRootNode( entry, this );
211}
212
214{
215 if ( DatabaseQueryRootNode *dbNode = dynamic_cast<DatabaseQueryRootNode *>( node ) )
216 {
217 dbNode->setEntry( entry );
218 }
219}
220
221//
222// QgsDatabaseQueryHistoryWidget
223//
224
226 : QgsHistoryWidget( QStringLiteral( "dbquery" ), backends, registry, context, parent )
227{
228}
229
230void QgsDatabaseQueryHistoryWidget::emitSqlTriggered( const QString &connectionUri, const QString &provider, const QString &sql )
231{
232 emit sqlTriggered( connectionUri, provider, sql );
233}
QFlags< HistoryProviderBackend > HistoryProviderBackends
Definition qgis.h:3376
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
A SQL editor based on QScintilla2.
void setText(const QString &text) override
void setFoldingVisible(bool folding)
Set whether the folding controls are visible in the editor.
void setLineNumbersVisible(bool visible)
Sets whether line numbers should be visible in the editor.
History provider for operations database queries.
void updateNodeForEntry(QgsHistoryEntryNode *node, const QgsHistoryEntry &entry, const QgsHistoryWidgetContext &context) override
Updates an existing history node for the given entry.
QString id() const override
Returns the provider's unique id, which is used to associate existing history entries with the provid...
QgsHistoryEntryNode * createNodeForEntry(const QgsHistoryEntry &entry, const QgsHistoryWidgetContext &context) override
Creates a new history node for the given entry.
Custom QgsHistoryWidget for use with the database query provider.
QgsDatabaseQueryHistoryWidget(Qgis::HistoryProviderBackends backends=Qgis::HistoryProviderBackend::LocalProfile, QgsHistoryProviderRegistry *registry=nullptr, const QgsHistoryWidgetContext &context=QgsHistoryWidgetContext(), QWidget *parent=nullptr)
Constructor for QgsDatabaseQueryHistoryWidget, with the specified parent widget.
void sqlTriggered(const QString &connectionUri, const QString &provider, const QString &sql)
Emitted when the user has triggered a previously executed SQL statement in the widget.
void emitSqlTriggered(const QString &connectionUri, const QString &provider, const QString &sql)
Causes the widget to emit the sqlTriggered() signal.
Base class for history entry "group" nodes, which contain children of their own.
Base class for nodes representing a QgsHistoryEntry.
Encapsulates a history entry.
QVariantMap entry
Entry details.
A registry for objects which track user history (i.e.
Contains settings which reflect the context in which a history widget is shown, e....
QgsHistoryWidget * historyWidget() const
Returns the parent history widget.
A widget showing entries from a QgsHistoryProviderRegistry.
Holds data provider key, description, and associated shared library file or function pointer informat...
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.