Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
QgsQueryResultWidget
- Loading branch information
Showing
10 changed files
with
299 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ui version="4.0"> | ||
<class>QgsQueryResultWidgetBase</class> | ||
<widget class="QWidget" name="QgsQueryResultWidgetBase"> | ||
<property name="geometry"> | ||
<rect> | ||
<x>0</x> | ||
<y>0</y> | ||
<width>662</width> | ||
<height>483</height> | ||
</rect> | ||
</property> | ||
<property name="windowTitle"> | ||
<string notr="true">Dialog</string> | ||
</property> | ||
<layout class="QVBoxLayout" name="verticalLayout"> | ||
<item> | ||
<widget class="QgsCodeEditorSQL" name="mCodeEditor" native="true"/> | ||
</item> | ||
<item> | ||
<layout class="QHBoxLayout" name="horizontalLayout"> | ||
<item> | ||
<spacer name="horizontalSpacer"> | ||
<property name="orientation"> | ||
<enum>Qt::Horizontal</enum> | ||
</property> | ||
<property name="sizeHint" stdset="0"> | ||
<size> | ||
<width>40</width> | ||
<height>20</height> | ||
</size> | ||
</property> | ||
</spacer> | ||
</item> | ||
<item> | ||
<widget class="QPushButton" name="mExecuteButton"> | ||
<property name="enabled"> | ||
<bool>false</bool> | ||
</property> | ||
<property name="text"> | ||
<string>Execute</string> | ||
</property> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QPushButton" name="mStopButton"> | ||
<property name="enabled"> | ||
<bool>false</bool> | ||
</property> | ||
<property name="text"> | ||
<string>Stop</string> | ||
</property> | ||
</widget> | ||
</item> | ||
</layout> | ||
</item> | ||
<item> | ||
<widget class="QTableView" name="mQueryResultsTableView"/> | ||
</item> | ||
<item> | ||
<widget class="QLabel" name="mStatusLabel"> | ||
<property name="text"> | ||
<string>Status and errors goes here.</string> | ||
</property> | ||
</widget> | ||
</item> | ||
</layout> | ||
</widget> | ||
<customwidgets> | ||
<customwidget> | ||
<class>QgsCodeEditorSQL</class> | ||
<extends>QWidget</extends> | ||
<header>qgscodeeditorsql.h</header> | ||
<container>1</container> | ||
</customwidget> | ||
</customwidgets> | ||
<resources/> | ||
<connections/> | ||
</ui> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/*************************************************************************** | ||
testqgsqueryresultwidget.cpp | ||
---------------------- | ||
Date : Jan 2021 | ||
Copyright : (C) 2021 Alessandro Pasotti | ||
Email : elpaso at itopen dot it | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
|
||
#include "qgstest.h" | ||
|
||
#include "qgsqueryresultwidget.h" | ||
#include "qgsqueryresultmodel.h" | ||
#include "qgsproviderregistry.h" | ||
#include "qgsprovidermetadata.h" | ||
#include "qgsabstractdatabaseproviderconnection.h" | ||
#include <QApplication> | ||
#include <QAction> | ||
#include <QDialog> | ||
#include <QVBoxLayout> | ||
|
||
class TestQgsQueryResultWidget: public QObject | ||
{ | ||
Q_OBJECT | ||
private slots: | ||
void initTestCase(); // will be called before the first testfunction is executed. | ||
void cleanupTestCase(); // will be called after the last testfunction was executed. | ||
void init(); // will be called before each testfunction is executed. | ||
void cleanup(); // will be called after every testfunction. | ||
|
||
void testWidgetCrash(); | ||
void testWidget(); | ||
|
||
private: | ||
|
||
std::unique_ptr<QgsAbstractDatabaseProviderConnection> mConn; | ||
|
||
}; | ||
|
||
void TestQgsQueryResultWidget::initTestCase() | ||
{ | ||
QgsApplication::initQgis(); | ||
auto conn { QgsProviderRegistry::instance( )->providerMetadata( QStringLiteral( "postgres" ) )->createConnection( qgetenv( "QGIS_PGTEST_DB" ), QVariantMap() ) }; | ||
mConn.reset( static_cast<QgsAbstractDatabaseProviderConnection *>( conn ) ); | ||
// Prepare data for fetching test | ||
mConn->execSql( QStringLiteral( "DROP TABLE IF EXISTS qgis_test.random_big_data" ) ); | ||
mConn->execSql( QStringLiteral( "SELECT * INTO qgis_test.random_big_data FROM generate_series(1,1000000) AS id, md5(random()::text) AS descr" ) ); | ||
} | ||
|
||
void TestQgsQueryResultWidget::cleanupTestCase() | ||
{ | ||
} | ||
|
||
void TestQgsQueryResultWidget::init() | ||
{ | ||
} | ||
|
||
void TestQgsQueryResultWidget::cleanup() | ||
{ | ||
} | ||
|
||
// Test do not crash when deleting the result while the model fetcher is running | ||
void TestQgsQueryResultWidget::testWidgetCrash() | ||
{ | ||
// Make a copy | ||
auto res = new QgsAbstractDatabaseProviderConnection::QueryResult( mConn->execSql( QStringLiteral( "SELECT * FROM qgis_test.random_big_data" ) ) ); | ||
auto model = new QgsQueryResultModel( *res ); | ||
bool exited { false }; | ||
QTimer::singleShot( 0, model, [ & ] { delete res; } ); | ||
QTimer::singleShot( 1, model, [ & ] { exited = true; } ); | ||
while ( ! exited ) | ||
QgsApplication::processEvents(); | ||
const auto rowCount { model->rowCount( model->index( -1, -1 ) ) }; | ||
QVERIFY( rowCount > 0 && rowCount < 1000000 ); | ||
delete model; | ||
} | ||
|
||
|
||
void TestQgsQueryResultWidget::testWidget() | ||
{ | ||
auto d = qgis::make_unique<QDialog>( ); | ||
auto l = new QVBoxLayout(); | ||
auto w = new QgsQueryResultWidget( d.get(), mConn.release() ); | ||
w->setQuery( QStringLiteral( "SELECT * FROM qgis_test.random_big_data" ) ); | ||
l->addWidget( w ); | ||
d->setLayout( l ); | ||
// For interactive testing | ||
//d->exec(); | ||
w->executeQuery(); | ||
QTimer::singleShot( 0, d.get(), [ = ] | ||
{ | ||
QTest::mousePress( w->mStopButton, Qt::MouseButton::LeftButton ); | ||
} ); | ||
QgsApplication::processEvents(); | ||
const auto rowCount { w->mModel->rowCount( w->mModel->index( -1, -1 ) ) }; | ||
QVERIFY( rowCount > 0 && rowCount < 1000000 ); | ||
} | ||
|
||
QGSTEST_MAIN( TestQgsQueryResultWidget ) | ||
#include "testqgsqueryresultwidget.moc" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# -*- coding: utf-8 -*- | ||
"""QGIS Unit tests for QgsQueryResultWidget. | ||
.. note:: This program is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2 of the License, or | ||
(at your option) any later version. | ||
""" | ||
__author__ = 'Alessandro Pasotti' | ||
__date__ = '2021-01' | ||
__copyright__ = 'Copyright 2021, The QGIS Project' | ||
|
||
import os | ||
|
||
import qgis # NOQA | ||
from qgis.core import QgsProviderRegistry, QgsQueryResultModel | ||
from qgis.gui import QgsQueryResultWidget | ||
from qgis.PyQt.QtCore import QCoreApplication | ||
from qgis.PyQt.QtWidgets import QDialog, QLabel, QListView, QVBoxLayout | ||
from qgis.testing import start_app, unittest | ||
from utilities import getTestFont | ||
|
||
start_app() | ||
|
||
|
||
class PyQgsQueryResultWidget(unittest.TestCase): | ||
|
||
NUM_RECORDS = 1000000 | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
"""Run before all tests""" | ||
|
||
QCoreApplication.setOrganizationName("QGIS_Test") | ||
QCoreApplication.setOrganizationDomain(cls.__name__) | ||
QCoreApplication.setApplicationName(cls.__name__) | ||
start_app() | ||
cls.postgres_conn = "service='qgis_test'" | ||
if 'QGIS_PGTEST_DB' in os.environ: | ||
cls.postgres_conn = os.environ['QGIS_PGTEST_DB'] | ||
cls.uri = cls.postgres_conn + ' sslmode=disable' | ||
|
||
# Prepare data for threaded test | ||
cls._deleteBigData() | ||
md = QgsProviderRegistry.instance().providerMetadata('postgres') | ||
conn = md.createConnection(cls.uri, {}) | ||
conn.executeSql('DROP TABLE IF EXISTS qgis_test.random_big_data') | ||
conn.executeSql('SELECT * INTO qgis_test.random_big_data FROM generate_series(1,%s) AS id, md5(random()::text) AS descr' % cls.NUM_RECORDS) | ||
|
||
@classmethod | ||
def tearDownClass(cls): | ||
|
||
cls._deleteBigData() | ||
|
||
@classmethod | ||
def _deleteBigData(cls): | ||
|
||
try: | ||
md = QgsProviderRegistry.instance().providerMetadata('postgres') | ||
conn = md.createConnection(cls.uri, {}) | ||
conn.dropVectorTable('qgis_test', 'random_big_data') | ||
except: | ||
pass | ||
|
||
def test_widget(self): | ||
|
||
md = QgsProviderRegistry.instance().providerMetadata('postgres') | ||
conn = md.createConnection(self.uri, {}) | ||
widget = QgsQueryResultWidget(None, conn) | ||
widget.setQuery("SELECT * FROM qgis_test.random_big_data") | ||
d = QDialog() | ||
l = QVBoxLayout(d) | ||
d.setLayout(l) | ||
l.addWidget(widget) | ||
|
||
d.exec_() | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |