Skip to content

Commit d212ca7

Browse files
committedMar 23, 2012
Adding the native MSSQL provider
1 parent a2ee769 commit d212ca7

25 files changed

+5411
-1
lines changed
 

‎CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ IF (SPATIALITE_FOUND)
191191
SET (HAVE_SPATIALITE TRUE)
192192
ENDIF (SPATIALITE_FOUND)
193193

194+
# following variable is used in qgsconfig.h
195+
SET (HAVE_MSSQL TRUE)
196+
194197
#############################################################
195198
# search for Qt4
196199
SET(QT_MIN_VERSION 4.4.0)

‎cmake_templates/qgsconfig.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232
#cmakedefine HAVE_SPATIALITE
3333

34+
#cmakedefine HAVE_MSSQL
35+
3436
#cmakedefine HAVE_PYTHON
3537

3638
#endif

‎doc/CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Richard Kostecky
4949
Robert Szczepanek
5050
Stefanie Tellex
5151
Steven Mizuno
52+
Tamas Szekeres
5253
Tom Russo
5354
Tyler Mitchell
5455
Vita Cizek

‎images/images.qrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,10 @@
363363
<file>themes/gis/mIconSpatialite.png</file>
364364
<file>themes/gis/mIconRaster.png</file>
365365
<file>themes/gis/mIconPostgis.png</file>
366+
<file>themes/gis/mIconMssql.png</file>
366367
<file>themes/gis/mIconConnect.png</file>
367368
<file>themes/gis/mIconDbSchema.png</file>
369+
<file>themes/default/mActionAddMssqlLayer.png</file>
368370
</qresource>
369371
<qresource prefix="/images/tips">
370372
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
4.12 KB
Loading

‎images/themes/gis/mIconMssql.png

3.24 KB
Loading

‎src/app/qgisapp.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ void QgisApp::createActions()
860860
connect( mActionAddRasterLayer, SIGNAL( triggered() ), this, SLOT( addRasterLayer() ) );
861861
connect( mActionAddPgLayer, SIGNAL( triggered() ), this, SLOT( addDatabaseLayer() ) );
862862
connect( mActionAddSpatiaLiteLayer, SIGNAL( triggered() ), this, SLOT( addSpatiaLiteLayer() ) );
863+
connect( mActionAddMssqlLayer, SIGNAL( triggered() ), this, SLOT( addMssqlLayer() ) );
863864
connect( mActionAddWmsLayer, SIGNAL( triggered() ), this, SLOT( addWmsLayer() ) );
864865
connect( mActionAddWfsLayer, SIGNAL( triggered() ), this, SLOT( addWfsLayer() ) );
865866
connect( mActionOpenTable, SIGNAL( triggered() ), this, SLOT( attributeTable() ) );
@@ -950,6 +951,11 @@ void QgisApp::createActions()
950951
mActionAddPgLayer = NULL;
951952
#endif
952953

954+
#ifndef HAVE_MSSQL
955+
delete mActionAddMssqlLayer;
956+
mActionAddMssqlLayer = NULL;
957+
#endif
958+
953959
}
954960

955961
#include "qgsstylev2.h"
@@ -1471,6 +1477,9 @@ void QgisApp::setTheme( QString theThemeName )
14711477
#ifdef HAVE_SPATIALITE
14721478
mActionNewSpatialiteLayer->setIcon( getThemeIcon( "/mActionNewVectorLayer.png" ) );
14731479
mActionAddSpatiaLiteLayer->setIcon( getThemeIcon( "/mActionAddSpatiaLiteLayer.png" ) );
1480+
#endif
1481+
#ifdef HAVE_MSSQL
1482+
mActionAddMssqlLayer->setIcon( getThemeIcon( "/mActionAddMssqlLayer.png" ) );
14741483
#endif
14751484
mActionRemoveLayer->setIcon( getThemeIcon( "/mActionRemoveLayer.png" ) );
14761485
mActionSetLayerCRS->setIcon( getThemeIcon( "/mActionSetLayerCRS.png" ) );
@@ -2515,6 +2524,31 @@ void QgisApp::addSpatiaLiteLayer()
25152524
} // QgisApp::addSpatiaLiteLayer()
25162525
#endif
25172526

2527+
#ifndef HAVE_MSSQL
2528+
void QgisApp::addMssqlLayer() {}
2529+
#else
2530+
void QgisApp::addMssqlLayer()
2531+
{
2532+
if ( mMapCanvas && mMapCanvas->isDrawing() )
2533+
{
2534+
return;
2535+
}
2536+
2537+
// show the MS SQL dialog
2538+
QDialog *dbs = dynamic_cast<QDialog*>( QgsProviderRegistry::instance()->selectWidget( QString( "mssql" ), this ) );
2539+
if ( !dbs )
2540+
{
2541+
QMessageBox::warning( this, tr( "MSSQL" ), tr( "Cannot get MS SQL select dialog from provider." ) );
2542+
return;
2543+
}
2544+
connect( dbs , SIGNAL( addDatabaseLayers( QStringList const &, QString const & ) ),
2545+
this , SLOT( addDatabaseLayers( QStringList const &, QString const & ) ) );
2546+
dbs->exec();
2547+
delete dbs;
2548+
2549+
} // QgisApp::addMssqlLayer()
2550+
#endif
2551+
25182552
void QgisApp::addWmsLayer()
25192553
{
25202554
if ( mMapCanvas && mMapCanvas->isDrawing() )

‎src/app/qgisapp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,10 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
502502
//! Add a SpatiaLite layer to the map
503503
void addSpatiaLiteLayer();
504504
//#endif
505+
//#ifdef HAVE_MSSQL
506+
//! Add a SpatiaLite layer to the map
507+
void addMssqlLayer();
508+
//#endif
505509
/** toggles whether the current selected layer is in overview or not */
506510
void isInOverview();
507511
//! Slot to show the map coordinate position of the mouse cursor

‎src/gui/qgsmanageconnectionsdialog.cpp

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ void QgsManageConnectionsDialog::doExportImport()
108108
case PostGIS:
109109
doc = savePgConnections( items );
110110
break;
111+
case MSSQL:
112+
doc = saveMssqlConnections( items );
113+
break;
111114
}
112115

113116
QFile file( mFileName );
@@ -161,6 +164,9 @@ void QgsManageConnectionsDialog::doExportImport()
161164
case PostGIS:
162165
loadPgConnections( doc, items );
163166
break;
167+
case MSSQL:
168+
loadMssqlConnections( doc, items );
169+
break;
164170
}
165171
// clear connections list and close window
166172
listConnections->clear();
@@ -187,6 +193,9 @@ bool QgsManageConnectionsDialog::populateConnections()
187193
case PostGIS:
188194
settings.beginGroup( "/PostgreSQL/connections" );
189195
break;
196+
case MSSQL:
197+
settings.beginGroup( "/MSSQL/connections" );
198+
break;
190199
}
191200
QStringList keys = settings.childGroups();
192201
QStringList::Iterator it = keys.begin();
@@ -256,6 +265,15 @@ bool QgsManageConnectionsDialog::populateConnections()
256265
return false;
257266
}
258267
break;
268+
269+
case MSSQL:
270+
if ( root.tagName() != "qgsMssqlConnections" )
271+
{
272+
QMessageBox::information( this, tr( "Loading connections" ),
273+
tr( "The file is not an MSSQL connections exchange file." ) );
274+
return false;
275+
}
276+
break;
259277
}
260278

261279
QDomElement child = root.firstChildElement();
@@ -363,6 +381,47 @@ QDomDocument QgsManageConnectionsDialog::savePgConnections( const QStringList &c
363381
return doc;
364382
}
365383

384+
QDomDocument QgsManageConnectionsDialog::saveMssqlConnections( const QStringList &connections )
385+
{
386+
QDomDocument doc( "connections" );
387+
QDomElement root = doc.createElement( "qgsMssqlConnections" );
388+
root.setAttribute( "version", "1.0" );
389+
doc.appendChild( root );
390+
391+
QSettings settings;
392+
QString path;
393+
for ( int i = 0; i < connections.count(); ++i )
394+
{
395+
path = "/MSSQL/connections/" + connections[ i ];
396+
QDomElement el = doc.createElement( "mssql" );
397+
el.setAttribute( "name", connections[ i ] );
398+
el.setAttribute( "host", settings.value( path + "/host", "" ).toString() );
399+
el.setAttribute( "port", settings.value( path + "/port", "" ).toString() );
400+
el.setAttribute( "database", settings.value( path + "/database", "" ).toString() );
401+
el.setAttribute( "service", settings.value( path + "/service", "" ).toString() );
402+
el.setAttribute( "sslmode", settings.value( path + "/sslmode", "1" ).toString() );
403+
el.setAttribute( "estimatedMetadata", settings.value( path + "/estimatedMetadata", "0" ).toString() );
404+
405+
el.setAttribute( "saveUsername", settings.value( path + "/saveUsername", "false" ).toString() );
406+
407+
if ( settings.value( path + "/saveUsername", "false" ).toString() == "true" )
408+
{
409+
el.setAttribute( "username", settings.value( path + "/username", "" ).toString() );
410+
}
411+
412+
el.setAttribute( "savePassword", settings.value( path + "/savePassword", "false" ).toString() );
413+
414+
if ( settings.value( path + "/savePassword", "false" ).toString() == "true" )
415+
{
416+
el.setAttribute( "password", settings.value( path + "/password", "" ).toString() );
417+
}
418+
419+
root.appendChild( el );
420+
}
421+
422+
return doc;
423+
}
424+
366425
void QgsManageConnectionsDialog::loadWMSConnections( const QDomDocument &doc, const QStringList &items )
367426
{
368427
QDomElement root = doc.documentElement();
@@ -616,6 +675,96 @@ void QgsManageConnectionsDialog::loadPgConnections( const QDomDocument &doc, con
616675
}
617676
}
618677

678+
void QgsManageConnectionsDialog::loadMssqlConnections( const QDomDocument &doc, const QStringList &items )
679+
{
680+
QDomElement root = doc.documentElement();
681+
if ( root.tagName() != "qgsMssqlConnections" )
682+
{
683+
QMessageBox::information( this,
684+
tr( "Loading connections" ),
685+
tr( "The file is not an PostGIS connections exchange file." ) );
686+
return;
687+
}
688+
689+
QString connectionName;
690+
QSettings settings;
691+
settings.beginGroup( "/MSSQL/connections" );
692+
QStringList keys = settings.childGroups();
693+
settings.endGroup();
694+
QDomElement child = root.firstChildElement();
695+
bool prompt = true;
696+
bool overwrite = true;
697+
698+
while ( !child.isNull() )
699+
{
700+
connectionName = child.attribute( "name" );
701+
if ( !items.contains( connectionName ) )
702+
{
703+
child = child.nextSiblingElement();
704+
continue;
705+
}
706+
707+
// check for duplicates
708+
if ( keys.contains( connectionName ) && prompt )
709+
{
710+
int res = QMessageBox::warning( this,
711+
tr( "Loading connections" ),
712+
tr( "Connection with name '%1' already exists. Overwrite?" )
713+
.arg( connectionName ),
714+
QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
715+
switch ( res )
716+
{
717+
case QMessageBox::Cancel:
718+
return;
719+
case QMessageBox::No:
720+
child = child.nextSiblingElement();
721+
continue;
722+
case QMessageBox::Yes:
723+
overwrite = true;
724+
break;
725+
case QMessageBox::YesToAll:
726+
prompt = false;
727+
overwrite = true;
728+
break;
729+
case QMessageBox::NoToAll:
730+
prompt = false;
731+
overwrite = false;
732+
break;
733+
}
734+
}
735+
736+
if ( keys.contains( connectionName ) && !overwrite )
737+
{
738+
child = child.nextSiblingElement();
739+
continue;
740+
}
741+
742+
//no dups detected or overwrite is allowed
743+
settings.beginGroup( "/MSSQL/connections/" + connectionName );
744+
745+
settings.setValue( "/host", child.attribute( "host" ) );
746+
settings.setValue( "/port", child.attribute( "port" ) );
747+
settings.setValue( "/database", child.attribute( "database" ) );
748+
if ( child.hasAttribute( "service" ) )
749+
{
750+
settings.setValue( "/service", child.attribute( "service" ) );
751+
}
752+
else
753+
{
754+
settings.setValue( "/service", "" );
755+
}
756+
settings.setValue( "/sslmode", child.attribute( "sslmode" ) );
757+
settings.setValue( "/estimatedMetadata", child.attribute( "estimatedMetadata" ) );
758+
settings.setValue( "/saveUsername", child.attribute( "saveUsername" ) );
759+
settings.setValue( "/username", child.attribute( "username" ) );
760+
settings.setValue( "/savePassword", child.attribute( "savePassword" ) );
761+
settings.setValue( "/password", child.attribute( "password" ) );
762+
settings.endGroup();
763+
764+
child = child.nextSiblingElement();
765+
}
766+
}
767+
619768
void QgsManageConnectionsDialog::selectAll()
620769
{
621770
listConnections->selectAll();

‎src/gui/qgsmanageconnectionsdialog.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan
3838
WMS,
3939
PostGIS,
4040
WFS,
41+
MSSQL,
4142
};
4243

4344
// constructor
@@ -55,9 +56,11 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan
5556
QDomDocument saveWMSConnections( const QStringList &connections );
5657
QDomDocument saveWFSConnections( const QStringList &connections );
5758
QDomDocument savePgConnections( const QStringList & connections );
59+
QDomDocument saveMssqlConnections( const QStringList & connections );
5860
void loadWMSConnections( const QDomDocument &doc, const QStringList &items );
5961
void loadWFSConnections( const QDomDocument &doc, const QStringList &items );
6062
void loadPgConnections( const QDomDocument &doc, const QStringList &items );
63+
void loadMssqlConnections( const QDomDocument &doc, const QStringList &items );
6164

6265
QString mFileName;
6366
Mode mDialogMode;

‎src/providers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ ADD_SUBDIRECTORY(delimitedtext)
99
ADD_SUBDIRECTORY(osm)
1010
ADD_SUBDIRECTORY(sqlanywhere)
1111
ADD_SUBDIRECTORY(gdal)
12+
ADD_SUBDIRECTORY(mssql)
1213

1314
IF (POSTGRES_FOUND)
1415
ADD_SUBDIRECTORY(postgres)

‎src/providers/mssql/CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
SET (MSSQL_SRCS qgsmssqlprovider.cpp qgsmssqlgeometryparser.cpp qgsmssqlsourceselect.cpp qgsmssqltablemodel.cpp qgsmssqlnewconnection.cpp qgsmssqldataitems.cpp)
3+
4+
SET (MSSQL_MOC_HDRS qgsmssqlprovider.h qgsmssqlsourceselect.h qgsmssqltablemodel.h qgsmssqlnewconnection.h qgsmssqldataitems.h)
5+
6+
########################################################
7+
# Build
8+
9+
QT4_WRAP_CPP(MSSQL_MOC_SRCS ${MSSQL_MOC_HDRS})
10+
11+
INCLUDE_DIRECTORIES(
12+
.
13+
../../core
14+
${GDAL_INCLUDE_DIR}
15+
${GEOS_INCLUDE_DIR}
16+
${QT_INCLUDE_DIR}
17+
../../gui
18+
${CMAKE_CURRENT_BINARY_DIR}/../../ui
19+
)
20+
21+
22+
ADD_LIBRARY(mssqlprovider MODULE ${MSSQL_SRCS} ${MSSQL_MOC_SRCS})
23+
24+
TARGET_LINK_LIBRARIES(mssqlprovider
25+
qgis_core
26+
qgis_gui
27+
${QT_QTSQL_LIBRARY}
28+
)
29+
########################################################
30+
# Install
31+
32+
INSTALL (TARGETS mssqlprovider
33+
RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
34+
LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})
35+

‎src/providers/mssql/qgsmssqldataitems.cpp

Lines changed: 555 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/***************************************************************************
2+
qgsmssqldataitems.h - description
3+
-------------------
4+
begin : 2011-10-08
5+
copyright : (C) 2011 by Tamas Szekeres
6+
email : szekerest at gmail.com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
19+
20+
#ifndef QGSMSSQLDATAITEMS_H
21+
#define QGSMSSQLDATAITEMS_H
22+
23+
#include "qgsdataitem.h"
24+
25+
#include "qgsmssqlsourceselect.h"
26+
27+
class QgsMssqlRootItem;
28+
class QgsMssqlConnectionItem;
29+
class QgsMssqlSchemaItem;
30+
class QgsMssqlLayerItem;
31+
32+
class QgsMssqlRootItem : public QgsDataCollectionItem
33+
{
34+
Q_OBJECT
35+
public:
36+
QgsMssqlRootItem( QgsDataItem* parent, QString name, QString path );
37+
~QgsMssqlRootItem();
38+
39+
QVector<QgsDataItem*> createChildren();
40+
41+
virtual QWidget * paramWidget();
42+
43+
virtual QList<QAction*> actions();
44+
45+
public slots:
46+
void connectionsChanged();
47+
void newConnection();
48+
};
49+
50+
class QgsMssqlConnectionItem : public QgsDataCollectionItem
51+
{
52+
Q_OBJECT
53+
public:
54+
QgsMssqlConnectionItem( QgsDataItem* parent, QString name, QString path );
55+
~QgsMssqlConnectionItem();
56+
57+
QVector<QgsDataItem*> createChildren();
58+
virtual bool equal( const QgsDataItem *other );
59+
virtual QList<QAction*> actions();
60+
61+
virtual bool acceptDrop() { return true; }
62+
virtual bool handleDrop( const QMimeData * data, Qt::DropAction action );
63+
void refresh();
64+
65+
QString connInfo() const { return mConnInfo; };
66+
67+
signals:
68+
void addGeometryColumn( QgsMssqlLayerProperty );
69+
70+
public slots:
71+
void editConnection();
72+
void deleteConnection();
73+
74+
void setLayerType( QgsMssqlLayerProperty layerProperty );
75+
76+
private:
77+
QString mConnInfo;
78+
QString mService;
79+
QString mHost;
80+
QString mDatabase;
81+
QString mUsername;
82+
QString mPassword;
83+
bool mUseGeometryColumns;
84+
};
85+
86+
class QgsMssqlSchemaItem : public QgsDataCollectionItem
87+
{
88+
Q_OBJECT
89+
public:
90+
QgsMssqlSchemaItem( QgsDataItem* parent, QString name, QString path );
91+
~QgsMssqlSchemaItem();
92+
93+
QVector<QgsDataItem*> createChildren();
94+
95+
QgsMssqlLayerItem* addLayer( QgsMssqlLayerProperty layerProperty, bool refresh );
96+
void refresh() {}; // do not refresh directly
97+
void addLayers(QgsDataItem* newLayers);
98+
};
99+
100+
class QgsMssqlLayerItem : public QgsLayerItem
101+
{
102+
Q_OBJECT
103+
104+
public:
105+
QgsMssqlLayerItem( QgsDataItem* parent, QString name, QString path, QgsLayerItem::LayerType layerType, QgsMssqlLayerProperty layerProperties );
106+
~QgsMssqlLayerItem();
107+
108+
QString createUri();
109+
110+
QgsMssqlLayerItem* createClone();
111+
bool Used;
112+
113+
private:
114+
QgsMssqlLayerProperty mLayerProperty;
115+
};
116+
117+
#endif // QGSMSSQLDATAITEMS_H

‎src/providers/mssql/qgsmssqlgeometryparser.cpp

Lines changed: 562 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/***************************************************************************
2+
qgsmssqlnewconnection.cpp - description
3+
-------------------
4+
begin : 2011-10-08
5+
copyright : (C) 2011 by Tamas Szekeres
6+
email : szekerest at gmail.com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include <QSettings>
19+
#include <QMessageBox>
20+
#include <QInputDialog>
21+
22+
#include <QtSql/QSqlDatabase>
23+
#include <QtSql/QSqlError>
24+
25+
#include "qgsmssqlnewconnection.h"
26+
#include "qgsmssqlprovider.h"
27+
#include "qgscontexthelp.h"
28+
29+
QgsMssqlNewConnection::QgsMssqlNewConnection( QWidget *parent, const QString& connName, Qt::WFlags fl )
30+
: QDialog( parent, fl ), mOriginalConnName( connName )
31+
{
32+
setupUi( this );
33+
34+
if ( !connName.isEmpty() )
35+
{
36+
// populate the dialog with the information stored for the connection
37+
// populate the fields with the stored setting parameters
38+
QSettings settings;
39+
40+
QString key = "/MSSQL/connections/" + connName;
41+
txtService->setText( settings.value( key + "/service" ).toString() );
42+
txtHost->setText( settings.value( key + "/host" ).toString() );
43+
txtDatabase->setText( settings.value( key + "/database" ).toString() );
44+
cb_geometryColumns->setChecked( settings.value( key + "/geometryColumns", true ).toBool() );
45+
cb_allowGeometrylessTables->setChecked( settings.value( key + "/allowGeometrylessTables", true ).toBool() );
46+
cb_useEstimatedMetadata->setChecked( settings.value( key + "/estimatedMetadata", false ).toBool() );
47+
48+
if ( settings.value( key + "/saveUsername" ).toString() == "true" )
49+
{
50+
txtUsername->setText( settings.value( key + "/username" ).toString() );
51+
chkStoreUsername->setChecked( true );
52+
}
53+
54+
if ( settings.value( key + "/savePassword" ).toString() == "true" )
55+
{
56+
txtPassword->setText( settings.value( key + "/password" ).toString() );
57+
chkStorePassword->setChecked( true );
58+
}
59+
60+
// Old save setting
61+
if ( settings.contains( key + "/save" ) )
62+
{
63+
txtUsername->setText( settings.value( key + "/username" ).toString() );
64+
chkStoreUsername->setChecked( !txtUsername->text().isEmpty() );
65+
66+
if ( settings.value( key + "/save" ).toString() == "true" )
67+
txtPassword->setText( settings.value( key + "/password" ).toString() );
68+
69+
chkStorePassword->setChecked( true );
70+
}
71+
72+
txtName->setText( connName );
73+
}
74+
}
75+
/** Autoconnected SLOTS **/
76+
void QgsMssqlNewConnection::accept()
77+
{
78+
QSettings settings;
79+
QString baseKey = "/MSSQL/connections/";
80+
settings.setValue( baseKey + "selected", txtName->text() );
81+
82+
if ( chkStorePassword->isChecked() &&
83+
QMessageBox::question( this,
84+
tr( "Saving passwords" ),
85+
tr( "WARNING: You have opted to save your password. It will be stored in plain text in your project files and in your home directory on Unix-like systems, or in your user profile on Windows. If you do not want this to happen, please press the Cancel button.\n" ),
86+
QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Cancel )
87+
{
88+
return;
89+
}
90+
91+
// warn if entry was renamed to an existing connection
92+
if (( mOriginalConnName.isNull() || mOriginalConnName != txtName->text() ) &&
93+
( settings.contains( baseKey + txtName->text() + "/service" ) ||
94+
settings.contains( baseKey + txtName->text() + "/host" ) ) &&
95+
QMessageBox::question( this,
96+
tr( "Save connection" ),
97+
tr( "Should the existing connection %1 be overwritten?" ).arg( txtName->text() ),
98+
QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Cancel )
99+
{
100+
return;
101+
}
102+
103+
// on rename delete the original entry first
104+
if ( !mOriginalConnName.isNull() && mOriginalConnName != txtName->text() )
105+
{
106+
107+
settings.remove( baseKey + mOriginalConnName );
108+
}
109+
110+
baseKey += txtName->text();
111+
settings.setValue( baseKey + "/service", txtService->text() );
112+
settings.setValue( baseKey + "/host", txtHost->text() );
113+
settings.setValue( baseKey + "/database", txtDatabase->text() );
114+
settings.setValue( baseKey + "/username", chkStoreUsername->isChecked() ? txtUsername->text() : "" );
115+
settings.setValue( baseKey + "/password", chkStorePassword->isChecked() ? txtPassword->text() : "" );
116+
settings.setValue( baseKey + "/saveUsername", chkStoreUsername->isChecked() ? "true" : "false" );
117+
settings.setValue( baseKey + "/savePassword", chkStorePassword->isChecked() ? "true" : "false" );
118+
settings.setValue( baseKey + "/geometryColumns", cb_geometryColumns->isChecked() );
119+
settings.setValue( baseKey + "/allowGeometrylessTables", cb_allowGeometrylessTables->isChecked() );
120+
settings.setValue( baseKey + "/estimatedMetadata", cb_useEstimatedMetadata->isChecked() );
121+
122+
QDialog::accept();
123+
}
124+
125+
void QgsMssqlNewConnection::on_btnConnect_clicked()
126+
{
127+
testConnection();
128+
}
129+
130+
/** end Autoconnected SLOTS **/
131+
132+
QgsMssqlNewConnection::~QgsMssqlNewConnection()
133+
{
134+
}
135+
136+
void QgsMssqlNewConnection::testConnection()
137+
{
138+
if (txtService->text().isEmpty())
139+
{
140+
if (txtHost->text().isEmpty())
141+
{
142+
QMessageBox::information( this,
143+
tr( "Test connection" ),
144+
tr( "Connection failed - Host name hasn't been specified.\n\n" ) );
145+
return;
146+
}
147+
148+
if (txtDatabase->text().isEmpty())
149+
{
150+
QMessageBox::information( this,
151+
tr( "Test connection" ),
152+
tr( "Connection failed - Database name hasn't been specified.\n\n" ) );
153+
return;
154+
}
155+
}
156+
157+
QSqlDatabase db = QgsMssqlProvider::GetDatabase( txtService->text().trimmed(),
158+
txtHost->text().trimmed(), txtDatabase->text().trimmed(),
159+
txtUsername->text().trimmed(), txtPassword->text().trimmed() );
160+
161+
if ( db.isOpen() )
162+
db.close();
163+
164+
if ( !db.open() )
165+
{
166+
QMessageBox::information( this,
167+
tr( "Test connection" ),
168+
db.lastError( ).text( ) );
169+
}
170+
else
171+
{
172+
QMessageBox::information( this,
173+
tr( "Test connection" ),
174+
tr( "Connection to %1 was successful" ).arg( txtDatabase->text() ) );
175+
}
176+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/***************************************************************************
2+
qgsmssqlnewconnection.h - description
3+
-------------------
4+
begin : 2011-10-08
5+
copyright : (C) 2011 by Tamas Szekeres
6+
email : szekerest at gmail.com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
#ifndef QGSMSSQLNEWCONNECTION_H
18+
#define QGSMSSQLNEWCONNECTION_H
19+
#include "ui_qgsmssqlnewconnectionbase.h"
20+
#include "qgisgui.h"
21+
#include "qgscontexthelp.h"
22+
23+
/*! \class QgsMssqlNewConnection
24+
* \brief Dialog to allow the user to configure and save connection
25+
* information for an MSSQL database
26+
*/
27+
class QgsMssqlNewConnection : public QDialog, private Ui::QgsMssqlNewConnectionBase
28+
{
29+
Q_OBJECT
30+
public:
31+
//! Constructor
32+
QgsMssqlNewConnection( QWidget *parent = 0, const QString& connName = QString::null, Qt::WFlags fl = QgisGui::ModalDialogFlags );
33+
//! Destructor
34+
~QgsMssqlNewConnection();
35+
//! Tests the connection using the parameters supplied
36+
void testConnection();
37+
public slots:
38+
void accept();
39+
void on_btnConnect_clicked();
40+
void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
41+
private:
42+
QString mOriginalConnName; //store initial name to delete entry in case of rename
43+
};
44+
45+
#endif // QGSMSSQLNEWCONNECTION_H

‎src/providers/mssql/qgsmssqlprovider.cpp

Lines changed: 1541 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
/***************************************************************************
2+
qgsmssqlprovider.h - Data provider for mssql server
3+
-------------------
4+
begin : 2011-10-08
5+
copyright : (C) 2011 by Tamas Szekeres
6+
email : szekerest at gmail.com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
19+
#include "qgsvectordataprovider.h"
20+
#include "qgscoordinatereferencesystem.h"
21+
#include "qgsvectorlayerimport.h"
22+
23+
#include <QStringList>
24+
#include <QFile>
25+
#include <QtSql/QSqlDatabase>
26+
#include <QtSql/QSqlQuery>
27+
#include <QtSql/QSqlError>
28+
29+
class QgsFeature;
30+
class QgsField;
31+
class QFile;
32+
class QTextStream;
33+
34+
#include "qgsdatasourceuri.h"
35+
#include "qgsgeometry.h"
36+
37+
38+
/**
39+
\class QgsMssqlGeometryParser
40+
\brief Geometry parser for SqlGeometry/SqlGeography.
41+
*
42+
*/
43+
44+
class QgsMssqlGeometryParser
45+
{
46+
47+
protected:
48+
unsigned char* pszData;
49+
unsigned char* pszWkb;
50+
int nWkbLen;
51+
int nWkbMaxLen;
52+
/* byte order */
53+
char chByteOrder;
54+
/* serialization properties */
55+
char chProps;
56+
/* point array */
57+
int nPointSize;
58+
int nPointPos;
59+
int nNumPoints;
60+
/* figure array */
61+
int nFigurePos;
62+
int nNumFigures;
63+
/* shape array */
64+
int nShapePos;
65+
int nNumShapes;
66+
int nSRSId;
67+
68+
protected:
69+
void CopyBytes(void* src, int len);
70+
void CopyPoint(int iPoint);
71+
void ReadPoint(int iShape);
72+
void ReadMultiPoint(int iShape);
73+
void ReadLineString(int iShape);
74+
void ReadMultiLineString(int iShape);
75+
void ReadPolygon(int iShape);
76+
void ReadMultiPolygon(int iShape);
77+
void ReadGeometryCollection(int iShape);
78+
79+
public:
80+
QgsMssqlGeometryParser();
81+
unsigned char* ParseSqlGeometry(unsigned char* pszInput, int nLen);
82+
int GetSRSId() { return nSRSId; };
83+
int GetWkbLen() { return nWkbLen; };
84+
void DumpMemoryToLog(char* pszMsg, unsigned char* pszInput, int nLen);
85+
};
86+
87+
88+
/**
89+
\class QgsMssqlProvider
90+
\brief Data provider for mssql server.
91+
*
92+
*/
93+
class QgsMssqlProvider : public QgsVectorDataProvider
94+
{
95+
Q_OBJECT
96+
97+
public:
98+
99+
QgsMssqlProvider( QString uri = QString() );
100+
101+
virtual ~QgsMssqlProvider();
102+
103+
static QSqlDatabase GetDatabase(QString driver, QString host, QString database, QString username, QString password);
104+
static bool OpenDatabase(QSqlDatabase db);
105+
106+
/* Implementation of functions from QgsVectorDataProvider */
107+
108+
/**
109+
* Returns the permanent storage type for this layer as a friendly name.
110+
*/
111+
virtual QString storageType() const;
112+
113+
/**
114+
* Sub-layers handled by this provider, in order from bottom to top
115+
*
116+
* Sub-layers are used when the provider's source can combine layers
117+
* it knows about in some way before it hands them off to the provider.
118+
*/
119+
virtual QStringList subLayers() const;
120+
121+
/** Select features based on a bounding rectangle. Features can be retrieved with calls to nextFeature.
122+
* @param fetchAttributes list of attributes which should be fetched
123+
* @param rect spatial filter
124+
* @param fetchGeometry true if the feature geometry should be fetched
125+
* @param useIntersect true if an accurate intersection test should be used,
126+
* false if a test based on bounding box is sufficient
127+
*/
128+
virtual void select( QgsAttributeList fetchAttributes = QgsAttributeList(),
129+
QgsRectangle rect = QgsRectangle(),
130+
bool fetchGeometry = true,
131+
bool useIntersect = false );
132+
133+
/**
134+
* Get the next feature resulting from a select operation.
135+
* @param feature feature which will receive data from the provider
136+
* @return true when there was a feature to fetch, false when end was hit
137+
*
138+
* mFile should be open with the file pointer at the record of the next
139+
* feature, or EOF. The feature found on the current line is parsed.
140+
*/
141+
virtual bool nextFeature( QgsFeature& feature );
142+
143+
/**
144+
* Gets the feature at the given feature ID.
145+
* @param featureId id of the feature
146+
* @param feature feature which will receive the data
147+
* @param fetchGeoemtry if true, geometry will be fetched from the provider
148+
* @param fetchAttributes a list containing the indexes of the attribute fields to copy
149+
* @return True when feature was found, otherwise false
150+
*/
151+
virtual bool featureAtId( QgsFeatureId featureId,
152+
QgsFeature& feature,
153+
bool fetchGeometry = true,
154+
QgsAttributeList fetchAttributes = QgsAttributeList() );
155+
156+
/**
157+
* Get feature type.
158+
* @return int representing the feature type
159+
*/
160+
virtual QGis::WkbType geometryType() const;
161+
162+
/**
163+
* Number of features in the layer
164+
* @return long containing number of features
165+
*/
166+
virtual long featureCount() const;
167+
168+
/**
169+
* Number of attribute fields for a feature in the layer
170+
*/
171+
virtual uint fieldCount() const;
172+
173+
/** update the extent, feature count, wkb type and srid for this layer */
174+
void UpdateStatistics();
175+
176+
/**
177+
* Return a map of indexes with field names for this layer
178+
* @return map of fields
179+
*/
180+
virtual const QgsFieldMap & fields() const;
181+
182+
/** Restart reading features from previous select operation */
183+
virtual void rewind();
184+
185+
/** Returns a bitmask containing the supported capabilities
186+
Note, some capabilities may change depending on whether
187+
a spatial filter is active on this provider, so it may
188+
be prudent to check this value per intended operation.
189+
*/
190+
virtual int capabilities() const;
191+
192+
193+
/* Implementation of functions from QgsDataProvider */
194+
195+
/** return a provider name
196+
197+
Essentially just returns the provider key. Should be used to build file
198+
dialogs so that providers can be shown with their supported types. Thus
199+
if more than one provider supports a given format, the user is able to
200+
select a specific provider to open that file.
201+
202+
@note
203+
204+
Instead of being pure virtual, might be better to generalize this
205+
behavior and presume that none of the sub-classes are going to do
206+
anything strange with regards to their name or description?
207+
*/
208+
QString name() const;
209+
210+
/** return description
211+
212+
Return a terse string describing what the provider is.
213+
214+
@note
215+
216+
Instead of being pure virtual, might be better to generalize this
217+
behavior and presume that none of the sub-classes are going to do
218+
anything strange with regards to their name or description?
219+
*/
220+
QString description() const;
221+
222+
/**
223+
* Return the extent for this data layer
224+
*/
225+
virtual QgsRectangle extent();
226+
227+
/**
228+
* Returns true if this is a valid data source
229+
*/
230+
bool isValid();
231+
232+
/**Writes a list of features to the database*/
233+
virtual bool addFeatures( QgsFeatureList & flist );
234+
235+
/**Deletes a feature*/
236+
virtual bool deleteFeatures( const QgsFeatureIds & id );
237+
238+
/**
239+
* Adds new attributes
240+
* @param attributes list of new attributes
241+
* @return true in case of success and false in case of failure
242+
* @note added in 1.2
243+
*/
244+
virtual bool addAttributes( const QList<QgsField> &attributes );
245+
246+
/**
247+
* Deletes existing attributes
248+
* @param attributes a set containing names of attributes
249+
* @return true in case of success and false in case of failure
250+
*/
251+
virtual bool deleteAttributes( const QgsAttributeIds &attributes );
252+
253+
/**Changes attribute values of existing features */
254+
virtual bool changeAttributeValues( const QgsChangedAttributesMap & attr_map );
255+
256+
/**Changes existing geometries*/
257+
virtual bool changeGeometryValues( QgsGeometryMap & geometry_map );
258+
259+
/**
260+
* Create a spatial index for the current layer
261+
*/
262+
virtual bool createSpatialIndex();
263+
264+
/**Create an attribute index on the datasource*/
265+
virtual bool createAttributeIndex( int field );
266+
267+
/** convert a QgsField to work with MSSQL */
268+
static bool convertField( QgsField &field );
269+
270+
/** Import a vector layer into the database */
271+
static QgsVectorLayerImport::ImportError createEmptyLayer(
272+
const QString& uri,
273+
const QgsFieldMap &fields,
274+
QGis::WkbType wkbType,
275+
const QgsCoordinateReferenceSystem *srs,
276+
bool overwrite,
277+
QMap<int, int> *oldToNewAttrIdxMap,
278+
QString *errorMessage = 0,
279+
const QMap<QString, QVariant> *options = 0
280+
);
281+
282+
virtual QgsCoordinateReferenceSystem crs();
283+
284+
protected:
285+
/** loads fields from input file to member attributeFields */
286+
QVariant::Type DecodeODBCType(int sqltype);
287+
void loadFields();
288+
void loadMetadata();
289+
290+
private:
291+
292+
//! Fields
293+
QgsFieldMap mAttributeFields;
294+
295+
QgsMssqlGeometryParser parser;
296+
297+
int mFieldCount; // Note: this includes field count for wkt field
298+
299+
//! Layer extent
300+
QgsRectangle mExtent;
301+
302+
bool mValid;
303+
304+
bool mUseWkb;
305+
bool mSkipFailures;
306+
307+
int mGeomType;
308+
309+
long mNumberFeatures;
310+
long mFidCol;
311+
QString mFidColName;
312+
long mSRId;
313+
long mGeometryCol;
314+
QString mGeometryColName;
315+
QString mGeometryColType;
316+
317+
// QString containing the last reported error message
318+
QString mLastError;
319+
320+
// Coordinate reference sytem
321+
QgsCoordinateReferenceSystem mCrs;
322+
323+
QGis::WkbType mWkbType;
324+
325+
// The database object
326+
QSqlDatabase mDatabase;
327+
328+
// The current sql query
329+
QSqlQuery mQuery;
330+
331+
// The current sql statement
332+
QString mStatement;
333+
334+
// current layer name
335+
QString mSchemaName;
336+
QString mTableName;
337+
// available tables
338+
QStringList mTables;
339+
340+
// Sets the error messages
341+
void setLastError( QString error )
342+
{
343+
mLastError = error;
344+
}
345+
346+
static void mssqlWkbTypeAndDimension( QGis::WkbType wkbType, QString &geometryType, int &dim );
347+
static QGis::WkbType getWkbType( QString geometryType, int dim );
348+
};

‎src/providers/mssql/qgsmssqlsourceselect.cpp

Lines changed: 814 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/***************************************************************************
2+
qgmssqlsourceselect.h - description
3+
-------------------
4+
begin : 2011-10-08
5+
copyright : (C) 2011 by Tamas Szekeres
6+
email : szekerest at gmail.com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
#ifndef QGSMSSQLSOURCESELECT_H
18+
#define QGSMSSQLSOURCESELECT_H
19+
20+
#include "ui_qgsdbsourceselectbase.h"
21+
#include "qgisgui.h"
22+
#include "qgsdbfilterproxymodel.h"
23+
#include "qgsmssqltablemodel.h"
24+
#include "qgscontexthelp.h"
25+
26+
#include <QMap>
27+
#include <QPair>
28+
#include <QIcon>
29+
#include <QItemDelegate>
30+
#include <QThread>
31+
32+
class QPushButton;
33+
class QStringList;
34+
class QgsGeomColumnTypeThread;
35+
class QgisApp;
36+
class QgsPgSourceSelect;
37+
38+
class QgsMssqlSourceSelectDelegate : public QItemDelegate
39+
{
40+
Q_OBJECT;
41+
42+
public:
43+
QgsMssqlSourceSelectDelegate( QObject *parent = NULL )
44+
: QItemDelegate( parent )
45+
{}
46+
47+
QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
48+
void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const;
49+
};
50+
51+
// A class that determines the geometry type of a given database
52+
// schema.table.column, with the option of doing so in a separate
53+
// thread.
54+
55+
class QgsMssqlGeomColumnTypeThread : public QThread
56+
{
57+
Q_OBJECT
58+
public:
59+
QgsMssqlGeomColumnTypeThread( QString connectionName, bool useEstimatedMetadata );
60+
61+
// These functions get the layer types and pass that information out
62+
// by emitting the setLayerType() signal.
63+
virtual void run();
64+
65+
signals:
66+
void setLayerType( QgsMssqlLayerProperty layerProperty );
67+
68+
public slots:
69+
void addGeometryColumn( QgsMssqlLayerProperty layerProperty );
70+
void stop();
71+
72+
private:
73+
QgsMssqlGeomColumnTypeThread() {}
74+
75+
QString mConnectionName;
76+
bool mUseEstimatedMetadata;
77+
bool mStopped;
78+
QList<QgsMssqlLayerProperty> layerProperties;
79+
};
80+
81+
82+
/*! \class QgsMssqlSourceSelect
83+
* \brief Dialog to create connections and add tables from MS SQL.
84+
*
85+
* This dialog allows the user to define and save connection information
86+
* for MS SQL databases. The user can then connect and add
87+
* tables from the database to the map canvas.
88+
*/
89+
class QgsMssqlSourceSelect : public QDialog, private Ui::QgsDbSourceSelectBase
90+
{
91+
Q_OBJECT
92+
93+
public:
94+
95+
//! static function to delete a connection
96+
static void deleteConnection( QString key );
97+
98+
//! Constructor
99+
QgsMssqlSourceSelect( QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags, bool managerMode = false, bool embeddedMode = false );
100+
//! Destructor
101+
~QgsMssqlSourceSelect();
102+
//! Populate the connection list combo box
103+
void populateConnectionList();
104+
//! String list containing the selected tables
105+
QStringList selectedTables();
106+
//! Connection info (database, host, user, password)
107+
QString connectionInfo();
108+
109+
signals:
110+
void addDatabaseLayers( QStringList const & layerPathList, QString const & providerKey );
111+
void connectionsChanged();
112+
void addGeometryColumn( QgsMssqlLayerProperty );
113+
114+
public slots:
115+
//! Determines the tables the user selected and closes the dialog
116+
void addTables();
117+
void buildQuery();
118+
119+
/*! Connects to the database using the stored connection parameters.
120+
* Once connected, available layers are displayed.
121+
*/
122+
void on_btnConnect_clicked();
123+
void on_cbxAllowGeometrylessTables_stateChanged( int );
124+
//! Opens the create connection dialog to build a new connection
125+
void on_btnNew_clicked();
126+
//! Opens a dialog to edit an existing connection
127+
void on_btnEdit_clicked();
128+
//! Deletes the selected connection
129+
void on_btnDelete_clicked();
130+
//! Saves the selected connections to file
131+
void on_btnSave_clicked();
132+
//! Loads the selected connections from file
133+
void on_btnLoad_clicked();
134+
void on_mSearchTableEdit_textChanged( const QString & text );
135+
void on_mSearchColumnComboBox_currentIndexChanged( const QString & text );
136+
void on_mSearchModeComboBox_currentIndexChanged( const QString & text );
137+
void setSql( const QModelIndex& index );
138+
//! Store the selected database
139+
void on_cmbConnections_activated( int );
140+
void setLayerType( QgsMssqlLayerProperty layerProperty );
141+
void on_mTablesTreeView_clicked( const QModelIndex &index );
142+
void on_mTablesTreeView_doubleClicked( const QModelIndex &index );
143+
//!Sets a new regular expression to the model
144+
void setSearchExpression( const QString& regexp );
145+
146+
void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
147+
148+
void columnThreadFinished();
149+
150+
private:
151+
typedef QPair<QString, QString> geomPair;
152+
typedef QList<geomPair> geomCol;
153+
154+
//! Connections manager mode
155+
bool mManagerMode;
156+
157+
//! Embedded mode, without 'Close'
158+
bool mEmbeddedMode;
159+
160+
// queue another query for the thread
161+
void addSearchGeometryColumn( QString connectionName, QgsMssqlLayerProperty layerProperty );
162+
163+
// Set the position of the database connection list to the last
164+
// used one.
165+
void setConnectionListPosition();
166+
// Combine the schema, table and column data into a single string
167+
// useful for display to the user
168+
QString fullDescription( QString schema, QString table, QString column, QString type );
169+
// The column labels
170+
QStringList mColumnLabels;
171+
// Our thread for doing long running queries
172+
QgsMssqlGeomColumnTypeThread* mColumnTypeThread;
173+
QString mConnInfo;
174+
QStringList mSelectedTables;
175+
bool mUseEstimatedMetadata;
176+
// Storage for the range of layer type icons
177+
QMap<QString, QPair<QString, QIcon> > mLayerIcons;
178+
179+
//! Model that acts as datasource for mTableTreeWidget
180+
QgsMssqlTableModel mTableModel;
181+
QgsDbFilterProxyModel mProxyModel;
182+
183+
QPushButton *mBuildQueryButton;
184+
QPushButton *mAddButton;
185+
186+
void finishList();
187+
};
188+
189+
#endif // QGSMSSQLSOURCESELECT_H

‎src/providers/mssql/qgsmssqltablemodel.cpp

Lines changed: 431 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/***************************************************************************
2+
qgsmssqltablemodel.h - description
3+
-------------------
4+
begin : 2011-10-08
5+
copyright : (C) 2011 by Tamas Szekeres
6+
email : szekerest at gmail.com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include <QStandardItemModel>
19+
20+
#include "qgis.h"
21+
22+
/** Layer Property structure */
23+
struct QgsMssqlLayerProperty
24+
{
25+
// MSSQL layer properties
26+
QString type;
27+
QString schemaName;
28+
QString tableName;
29+
QString geometryColName;
30+
QStringList pkCols;
31+
QString srid;
32+
bool isGeography;
33+
QString sql;
34+
};
35+
36+
37+
class QIcon;
38+
39+
/**A model that holds the tables of a database in a hierarchy where the
40+
schemas are the root elements that contain the individual tables as children.
41+
The tables have the following columns: Type, Schema, Tablename, Geometry Column, Sql*/
42+
class QgsMssqlTableModel : public QStandardItemModel
43+
{
44+
Q_OBJECT
45+
public:
46+
QgsMssqlTableModel();
47+
~QgsMssqlTableModel();
48+
49+
/**Adds entry for one database table to the model*/
50+
void addTableEntry( QgsMssqlLayerProperty property );
51+
52+
/**Sets an sql statement that belongs to a cell specified by a model index*/
53+
void setSql( const QModelIndex& index, const QString& sql );
54+
55+
/**Sets one or more geometry types to a row. In case of several types, additional rows are inserted.
56+
This is for tables where the type is dectected later by thread*/
57+
void setGeometryTypesForTable( QgsMssqlLayerProperty layerProperty );
58+
59+
/**Returns the number of tables in the model*/
60+
int tableCount() const { return mTableCount; }
61+
62+
enum columns
63+
{
64+
dbtmSchema = 0,
65+
dbtmTable,
66+
dbtmType,
67+
dbtmGeomCol,
68+
dbtmSrid,
69+
dbtmPkCol,
70+
dbtmSelectAtId,
71+
dbtmSql,
72+
dbtmColumns
73+
};
74+
75+
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole );
76+
77+
QString layerURI( const QModelIndex &index, QString connInfo, bool useEstimatedMetadata );
78+
79+
static QIcon iconForGeomType( QGis::GeometryType type );
80+
81+
static QGis::GeometryType geomTypeFromMssql( QString dbType );
82+
83+
static QString displayStringForGeomType( QGis::GeometryType type );
84+
85+
private:
86+
/**Number of tables in the model*/
87+
int mTableCount;
88+
};
89+

‎src/ui/qgisapp.ui

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<x>0</x>
1818
<y>0</y>
1919
<width>1052</width>
20-
<height>20</height>
20+
<height>21</height>
2121
</rect>
2222
</property>
2323
<widget class="QMenu" name="mEditMenu">
@@ -147,6 +147,7 @@
147147
<addaction name="mActionAddRasterLayer"/>
148148
<addaction name="mActionAddPgLayer"/>
149149
<addaction name="mActionAddSpatiaLiteLayer"/>
150+
<addaction name="mActionAddMssqlLayer"/>
150151
<addaction name="mActionAddWmsLayer"/>
151152
<addaction name="mActionAddLayerSeparator"/>
152153
<addaction name="mActionAddWfsLayer"/>
@@ -250,6 +251,7 @@
250251
<addaction name="mActionAddRasterLayer"/>
251252
<addaction name="mActionAddPgLayer"/>
252253
<addaction name="mActionAddSpatiaLiteLayer"/>
254+
<addaction name="mActionAddMssqlLayer"/>
253255
<addaction name="mActionAddWmsLayer"/>
254256
<addaction name="mActionAddWfsLayer"/>
255257
<addaction name="mActionNewVectorLayer"/>
@@ -1146,6 +1148,18 @@
11461148
<string>Ctrl+Shift+L</string>
11471149
</property>
11481150
</action>
1151+
<action name="mActionAddMssqlLayer">
1152+
<property name="icon">
1153+
<iconset resource="../../images/images.qrc">
1154+
<normaloff>:/images/themes/default/mActionAddMssqlLayer.png</normaloff>:/images/themes/default/mActionAddMssqlLayer.png</iconset>
1155+
</property>
1156+
<property name="text">
1157+
<string>Add MSSQL Spatial Layer...</string>
1158+
</property>
1159+
<property name="shortcut">
1160+
<string>Ctrl+Shift+M</string>
1161+
</property>
1162+
</action>
11491163
<action name="mActionAddWmsLayer">
11501164
<property name="icon">
11511165
<iconset resource="../../images/images.qrc">

‎src/ui/qgsmssqlnewconnectionbase.ui

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>QgsMssqlNewConnectionBase</class>
4+
<widget class="QDialog" name="QgsMssqlNewConnectionBase">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>311</width>
10+
<height>352</height>
11+
</rect>
12+
</property>
13+
<property name="sizePolicy">
14+
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
15+
<horstretch>0</horstretch>
16+
<verstretch>0</verstretch>
17+
</sizepolicy>
18+
</property>
19+
<property name="windowTitle">
20+
<string>Create a New MS SQL connection</string>
21+
</property>
22+
<property name="sizeGripEnabled">
23+
<bool>true</bool>
24+
</property>
25+
<property name="modal">
26+
<bool>true</bool>
27+
</property>
28+
<layout class="QGridLayout">
29+
<property name="margin">
30+
<number>9</number>
31+
</property>
32+
<property name="spacing">
33+
<number>6</number>
34+
</property>
35+
<item row="0" column="0">
36+
<widget class="QGroupBox" name="GroupBox1">
37+
<property name="title">
38+
<string>Connection Information</string>
39+
</property>
40+
<layout class="QGridLayout">
41+
<property name="margin">
42+
<number>0</number>
43+
</property>
44+
<property name="spacing">
45+
<number>5</number>
46+
</property>
47+
<item row="0" column="0">
48+
<layout class="QHBoxLayout">
49+
<property name="spacing">
50+
<number>6</number>
51+
</property>
52+
<property name="margin">
53+
<number>0</number>
54+
</property>
55+
<item>
56+
<layout class="QVBoxLayout">
57+
<property name="spacing">
58+
<number>6</number>
59+
</property>
60+
<property name="margin">
61+
<number>0</number>
62+
</property>
63+
<item>
64+
<widget class="QLabel" name="TextLabel1_2">
65+
<property name="text">
66+
<string>Name</string>
67+
</property>
68+
<property name="buddy">
69+
<cstring>txtName</cstring>
70+
</property>
71+
</widget>
72+
</item>
73+
<item>
74+
<widget class="QLabel" name="label">
75+
<property name="text">
76+
<string>Provider/DSN</string>
77+
</property>
78+
<property name="buddy">
79+
<cstring>txtService</cstring>
80+
</property>
81+
</widget>
82+
</item>
83+
<item>
84+
<widget class="QLabel" name="TextLabel1">
85+
<property name="text">
86+
<string>Host</string>
87+
</property>
88+
<property name="buddy">
89+
<cstring>txtHost</cstring>
90+
</property>
91+
</widget>
92+
</item>
93+
<item>
94+
<widget class="QLabel" name="TextLabel2">
95+
<property name="text">
96+
<string>Database</string>
97+
</property>
98+
<property name="buddy">
99+
<cstring>txtDatabase</cstring>
100+
</property>
101+
</widget>
102+
</item>
103+
<item>
104+
<widget class="QLabel" name="label_2">
105+
<property name="text">
106+
<string/>
107+
</property>
108+
</widget>
109+
</item>
110+
<item>
111+
<widget class="QLabel" name="TextLabel3">
112+
<property name="text">
113+
<string>Username</string>
114+
</property>
115+
<property name="buddy">
116+
<cstring>txtUsername</cstring>
117+
</property>
118+
</widget>
119+
</item>
120+
<item>
121+
<widget class="QLabel" name="TextLabel3_2">
122+
<property name="text">
123+
<string>Password</string>
124+
</property>
125+
<property name="buddy">
126+
<cstring>txtPassword</cstring>
127+
</property>
128+
</widget>
129+
</item>
130+
</layout>
131+
</item>
132+
<item>
133+
<layout class="QVBoxLayout">
134+
<property name="spacing">
135+
<number>6</number>
136+
</property>
137+
<property name="margin">
138+
<number>0</number>
139+
</property>
140+
<item>
141+
<widget class="QLineEdit" name="txtName">
142+
<property name="toolTip">
143+
<string>Name of the new connection</string>
144+
</property>
145+
</widget>
146+
</item>
147+
<item>
148+
<widget class="QLineEdit" name="txtService"/>
149+
</item>
150+
<item>
151+
<widget class="QLineEdit" name="txtHost"/>
152+
</item>
153+
<item>
154+
<widget class="QLineEdit" name="txtDatabase"/>
155+
</item>
156+
<item>
157+
<widget class="QCheckBox" name="cb_trustedConnection">
158+
<property name="text">
159+
<string>Trusted Connection</string>
160+
</property>
161+
<property name="checked">
162+
<bool>true</bool>
163+
</property>
164+
</widget>
165+
</item>
166+
<item>
167+
<widget class="QLineEdit" name="txtUsername"/>
168+
</item>
169+
<item>
170+
<widget class="QLineEdit" name="txtPassword">
171+
<property name="echoMode">
172+
<enum>QLineEdit::Password</enum>
173+
</property>
174+
</widget>
175+
</item>
176+
</layout>
177+
</item>
178+
</layout>
179+
</item>
180+
<item row="1" column="0">
181+
<layout class="QGridLayout" name="gridLayout_1">
182+
<property name="margin">
183+
<number>0</number>
184+
</property>
185+
<item row="0" column="0">
186+
<widget class="QCheckBox" name="chkStoreUsername">
187+
<property name="text">
188+
<string>Save Username</string>
189+
</property>
190+
</widget>
191+
</item>
192+
<item row="0" column="1" rowspan="2">
193+
<widget class="QPushButton" name="btnConnect">
194+
<property name="text">
195+
<string>&amp;Test Connect</string>
196+
</property>
197+
</widget>
198+
</item>
199+
<item row="1" column="0">
200+
<widget class="QCheckBox" name="chkStorePassword">
201+
<property name="text">
202+
<string>Save Password</string>
203+
</property>
204+
</widget>
205+
</item>
206+
</layout>
207+
</item>
208+
<item row="2" column="0">
209+
<widget class="QCheckBox" name="cb_geometryColumns">
210+
<property name="text">
211+
<string>Only look in the geometry_columns metadata table</string>
212+
</property>
213+
<property name="checked">
214+
<bool>true</bool>
215+
</property>
216+
</widget>
217+
</item>
218+
<item row="3" column="0">
219+
<widget class="QCheckBox" name="cb_allowGeometrylessTables">
220+
<property name="text">
221+
<string>Also list tables with no geometry</string>
222+
</property>
223+
</widget>
224+
</item>
225+
<item row="4" column="0">
226+
<widget class="QCheckBox" name="cb_useEstimatedMetadata">
227+
<property name="text">
228+
<string>Use estimated table parameters</string>
229+
</property>
230+
<property name="checked">
231+
<bool>true</bool>
232+
</property>
233+
</widget>
234+
</item>
235+
</layout>
236+
</widget>
237+
</item>
238+
<item row="1" column="0">
239+
<widget class="QDialogButtonBox" name="buttonBox">
240+
<property name="standardButtons">
241+
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
242+
</property>
243+
</widget>
244+
</item>
245+
</layout>
246+
</widget>
247+
<layoutdefault spacing="6" margin="11"/>
248+
<tabstops>
249+
<tabstop>txtName</tabstop>
250+
<tabstop>txtService</tabstop>
251+
<tabstop>txtHost</tabstop>
252+
<tabstop>txtDatabase</tabstop>
253+
<tabstop>txtUsername</tabstop>
254+
<tabstop>txtPassword</tabstop>
255+
<tabstop>chkStoreUsername</tabstop>
256+
<tabstop>chkStorePassword</tabstop>
257+
<tabstop>btnConnect</tabstop>
258+
<tabstop>buttonBox</tabstop>
259+
</tabstops>
260+
<resources/>
261+
<connections>
262+
<connection>
263+
<sender>buttonBox</sender>
264+
<signal>rejected()</signal>
265+
<receiver>QgsMssqlNewConnectionBase</receiver>
266+
<slot>reject()</slot>
267+
<hints>
268+
<hint type="sourcelabel">
269+
<x>313</x>
270+
<y>501</y>
271+
</hint>
272+
<hint type="destinationlabel">
273+
<x>451</x>
274+
<y>312</y>
275+
</hint>
276+
</hints>
277+
</connection>
278+
<connection>
279+
<sender>buttonBox</sender>
280+
<signal>accepted()</signal>
281+
<receiver>QgsMssqlNewConnectionBase</receiver>
282+
<slot>accept()</slot>
283+
<hints>
284+
<hint type="sourcelabel">
285+
<x>395</x>
286+
<y>501</y>
287+
</hint>
288+
<hint type="destinationlabel">
289+
<x>450</x>
290+
<y>287</y>
291+
</hint>
292+
</hints>
293+
</connection>
294+
</connections>
295+
</ui>

0 commit comments

Comments
 (0)
Please sign in to comment.