82 changes: 41 additions & 41 deletions doc/TRANSLATORS

Large diffs are not rendered by default.

3,272 changes: 2,218 additions & 1,054 deletions i18n/qgis_de.ts

Large diffs are not rendered by default.

2,482 changes: 1,808 additions & 674 deletions i18n/qgis_gl_ES.ts

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions images/images.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
<file>themes/default/mActionReshape.png</file>
<file>themes/default/mActionRollbackAllEdits.svg</file>
<file>themes/default/mActionRollbackEdits.svg</file>
<file>themes/default/mActionRotateFeature.png</file>
<file>themes/default/mActionRotateLabel.png</file>
<file>themes/default/mActionRotateLabel.svg</file>
<file>themes/default/mActionRotatePointSymbols.png</file>
Expand Down Expand Up @@ -188,6 +189,7 @@
<file>themes/default/mIconCollapse.png</file>
<file>themes/default/mIconConnect.png</file>
<file>themes/default/mIconClear.png</file>
<file>themes/default/mIconCritical.png</file>
<file>themes/default/mIconDbSchema.png</file>
<file>themes/default/mIconDelete.png</file>
<file>themes/default/mIconEditable.png</file>
Expand All @@ -196,12 +198,14 @@
<file>themes/default/mIconFavourites.png</file>
<file>themes/default/mIconFirst.png</file>
<file>themes/default/mIconGeometryLayer.png</file>
<file>themes/default/mIconInfo.png</file>
<file>themes/default/mIconLast.png</file>
<file>themes/default/mIconLayer.png</file>
<file>themes/default/mIconLineLayer.png</file>
<file>themes/default/mIconLock.png</file>
<file>themes/default/mIconNew.png</file>
<file>themes/default/mIconMssql.png</file>
<file>themes/default/mIconOracle.png</file>
<file>themes/default/mIconNext.png</file>
<file>themes/default/mIconNoPyramid.png</file>
<file>themes/default/mIconOws.png</file>
Expand Down Expand Up @@ -433,10 +437,12 @@
<file>themes/gis/mIconRaster.png</file>
<file>themes/gis/mIconPostgis.png</file>
<file>themes/gis/mIconMssql.png</file>
<file>themes/gis/mIconOracle.png</file>
<file>themes/gis/mIconConnect.png</file>
<file>themes/gis/mIconDbSchema.png</file>
<file>themes/gis/mActionTouch.png</file>
<file>themes/default/mActionAddMssqlLayer.png</file>
<file>themes/default/mActionAddOracleLayer.png</file>
<file>themes/default/mActionTouch.png</file>
<file>themes/default/mActionTouch2.png</file>
<file>themes/classic/mActionTouch.png</file>
Expand Down
Binary file added images/themes/default/mActionAddOracleLayer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/themes/default/mActionRotateFeature.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/themes/default/mIconCritical.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/themes/default/mIconInfo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/themes/default/mIconOracle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/themes/gis/mIconOracle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion ms-windows/osgeo4w/package-nightly.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ cmake -G "Visual Studio 9 2008" ^
-D WITH_ASTYLE=TRUE ^
-D WITH_GLOBE=TRUE ^
-D WITH_TOUCH=TRUE ^
-D WITH_ORACLE=TRUE ^
-D CMAKE_CONFIGURATION_TYPES=%BUILDCONF% ^
-D GEOS_LIBRARY=%O4W_ROOT%/lib/geos_c_i.lib ^
-D GEOS_LIBRARY=%O4W_ROOT%/lib/geos_c.lib ^
-D SQLITE3_LIBRARY=%O4W_ROOT%/lib/sqlite3_i.lib ^
-D SPATIALITE_LIBRARY=%O4W_ROOT%/lib/spatialite_i.lib ^
-D PYTHON_EXECUTABLE=%O4W_ROOT%/bin/python.exe ^
Expand Down Expand Up @@ -183,6 +184,7 @@ tar -C %OSGEO4W_ROOT% -cjf %PACKAGENAME%-%VERSION%-%PACKAGE%.tar.bz2 ^
bin/%PACKAGENAME%-browser.exe ^
bin/%PACKAGENAME%.bat.tmpl ^
bin/%PACKAGENAME%-browser.bat.tmpl ^
apps/qt4/plugins/sqldrivers/qsqlocispatial.dll ^
etc/postinstall/%PACKAGENAME%.bat ^
etc/preremove/%PACKAGENAME%.bat ^
>>%LOG% 2>&1
Expand Down
10 changes: 9 additions & 1 deletion ms-windows/osgeo4w/package.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,10 @@ cmake -G "Visual Studio 9 2008" ^
-D WITH_MAPSERVER=TRUE ^
-D WITH_GLOBE=TRUE ^
-D WITH_TOUCH=TRUE ^
-D WITH_ORACLE=TRUE ^
-D CMAKE_BUILD_TYPE=%BUILDCONF% ^
-D CMAKE_CONFIGURATION_TYPES=%BUILDCONF% ^
-D GEOS_LIBRARY=%O4W_ROOT%/lib/geos_c_i.lib ^
-D GEOS_LIBRARY=%O4W_ROOT%/lib/geos_c.lib ^
-D SQLITE3_LIBRARY=%O4W_ROOT%/lib/sqlite3_i.lib ^
-D SPATIALITE_LIBRARY=%O4W_ROOT%/lib/spatialite_i.lib ^
-D PYTHON_EXECUTABLE=%O4W_ROOT%/bin/python.exe ^
Expand Down Expand Up @@ -281,6 +282,12 @@ tar -C %OSGEO4W_ROOT% -cjf %PACKAGENAME%-globe-plugin-%VERSION%-%PACKAGE%.tar.bz
>>%LOG% 2>&1
if errorlevel 1 goto error

tar -C %OSGEO4W_ROOT% -cjf %PACKAGENAME%-oracle-provider-%VERSION%-%PACKAGE%.tar.bz2 ^
"apps/%PACKAGENAME%/plugins/oracleprovider.dll" ^
apps/qt4/plugins/sqldrivers/qsqlocispatial.dll ^
>>%LOG% 2>&1
if errorlevel 1 goto error

tar -C %OSGEO4W_ROOT% -cjf %PACKAGENAME%-devel-%VERSION%-%PACKAGE%.tar.bz2 ^
--exclude-from exclude ^
--exclude "*.pyc" ^
Expand All @@ -301,6 +308,7 @@ if exist %PACKAGENAME%-server-%VERSION%-%PACKAGE%.tar.bz2 del %PACKAGENAME%-serv
if exist %PACKAGENAME%-devel-%VERSION%-%PACKAGE%.tar.bz2 del %PACKAGENAME%-devel-%VERSION%-%PACKAGE%.tar.bz2
if exist %PACKAGENAME%-grass-plugin-%VERSION%-%PACKAGE%.tar.bz2 del %PACKAGENAME%-grass-plugin-%VERSION%-%PACKAGE%.tar.bz2
if exist %PACKAGENAME%-globe-plugin-%VERSION%-%PACKAGE%.tar.bz2 del %PACKAGENAME%-globe-plugin-%VERSION%-%PACKAGE%.tar.bz2
if exist %PACKAGENAME%-oracle-provider-%VERSION%-%PACKAGE%.tar.bz2 del %PACKAGENAME%-oracle-provider-%VERSION%-%PACKAGE%.tar.bz2

:end
echo FINISHED: %DATE% %TIME% >>%LOG% 2>&1
3 changes: 2 additions & 1 deletion python/console/console_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ def __init__(self, parent=None):
def insertInitText(self):
txtInit = QCoreApplication.translate("PythonConsole",
"## To access Quantum GIS environment from this console\n"
"## use qgis.utils.iface object (instance of QgisInterface class). Read help for more info.\n\n")
"## iface object (instance of QgisInterface class). \n"
"## Type help(iface) for more info and list of methods.\n\n")
initText = self.setText(txtInit)

def refreshLexerProperties(self):
Expand Down
3 changes: 2 additions & 1 deletion python/console/console_sci.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
import os
import code

_init_commands = ["from qgis.core import *", "import qgis.utils"]
_init_commands = ["from qgis.core import *", "import qgis.utils",
"from qgis.utils import iface"]
_historyFile = os.path.join(str(QDir.homePath()),".qgis","console_history.txt")

class PythonEdit(QsciScintilla, code.InteractiveInterpreter):
Expand Down
17 changes: 15 additions & 2 deletions python/gui/qgsmessagebar.sip
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,23 @@ class QgsMessageBar: QFrame
%End

public:
enum MessageLevel
{
INFO = 0,
WARNING = 1,
CRITICAL = 2
};

QgsMessageBar( QWidget *parent = 0 );
~QgsMessageBar();

/*! display a widget on the bar after hiding the currently visible one
* and putting it in a stack
* @param widget widget to add
* @param level is 0 for information, 1 for warning, 2 for critical
* @param level is QgsMessageBar::INFO, WARNING or CRITICAL
* @param duration timeout duration of message in seconds, 0 value indicates no timeout
*/
void pushWidget( QWidget *widget /Transfer/, int level = 0 );
void pushWidget( QWidget *widget /Transfer/, MessageLevel level = INFO, int duration = 0 );

/*! remove the passed widget from the bar (if previously added),
* then display the next one in the stack if any or hide the bar
Expand All @@ -31,6 +39,11 @@ class QgsMessageBar: QFrame
//! make out a widget containing icon, title and message to be displayed on the bar
static QWidget* createMessage( const QString &title, const QString &text, const QIcon &icon, QWidget *parent = 0 ) /Factory/;

//! convenience method for pushing a non-widget-based message to the bar
void pushMessage( const QString &text, MessageLevel level = INFO, int duration = 0 );
//! convenience method for pushing a non-widget-based message with title to the bar
void pushMessage( const QString &title, const QString &text, MessageLevel level = INFO, int duration = 0 );

signals:
//! emitted when a message widget is added to the bar
void widgetAdded( QWidget *widget );
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/sextante/grass/GrassAlgorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ def setSessionProjectionFromProject(self, commands):
if not GrassUtils.projectionSet:
from sextante.core.Sextante import Sextante
qgis = Sextante.getInterface()
proj4 = qgis.mapCanvas().mapRenderer().getDestinationCrs().toProj4()
proj4 = qgis.mapCanvas().mapRenderer().destinationCrs().toProj4()
command = "g.proj"
command +=" -c"
command +=" proj4=\""+proj4+"\""
Expand Down
11 changes: 10 additions & 1 deletion scripts/addcopyright.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,16 @@

set -e

for i in $(<files); do
if [ $# -gt 0 ]; then
FILES="$@"
elif [ -f files ]; then
FILES=$(<files)
else
echo no files
exit 1
fi

for i in $FILES; do
echo $i >&2
author=
authordate=
Expand Down
12 changes: 12 additions & 0 deletions scripts/licenses
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
: GPL \(v[23] or later\)$
: GPL \(v2 or later\) GENERATED FILE$
: \*No copyright\* LGPL \(v2\.1 or later\)$
: GPL LGPL$
: LGPL$
: Apache \(v2\.0\)$
: GPL \(v2\)$
: LGPL \(v2 or later\)$
: Apache \(v2.0\) GPL \(v2 or later\)$
: MIT\/X11 \(BSD like\)$
: MPL \(v1\.1\) GPL \(unversioned\/unknown version\)$
: LGPL \(v2\.1\)$
5 changes: 5 additions & 0 deletions scripts/prepare-commit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ if ! type -p colordiff >/dev/null; then
}
fi

if [ "$1" = "-c" ]; then
echo "Cleaning..."
find . \( -name "*.prepare" -o -name "*.astyle" -o -name "astyle.*.diff" -o -name "sha-*.diff" \) -print -delete
fi

set -e

# determine changed files
Expand Down
2 changes: 2 additions & 0 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ SET(QGIS_APP_SRCS
qgsmaptoolmovevertex.cpp
qgsmaptooloffsetcurve.cpp
qgsmaptoolreshape.cpp
qgsmaptoolrotatefeature.cpp
qgsmaptoolrotatelabel.cpp
qgsmaptoolrotatepointsymbols.cpp
qgsmaptoolselect.cpp
Expand Down Expand Up @@ -226,6 +227,7 @@ SET (QGIS_APP_MOC_HDRS
qgsmaptoolmovevertex.h
qgsmaptooloffsetcurve.h
qgsmaptoolreshape.h
qgsmaptoolrotatefeature.h
qgsmaptoolrotatelabel.h
qgsmaptoolrotatepointsymbols.h
qgsmaptoolselectfreehand.h
Expand Down
4 changes: 2 additions & 2 deletions src/app/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ void myMessageOutput( QtMsgType type, const char *msg )
case QtFatalMsg:
{
fprintf( stderr, "Fatal: %s\n", msg );
#if defined(linux) && ! defined(ANDROID)
fprintf( stderr, "Stacktrace (run through c++filt):\n" );
#if defined(linux) && !defined(ANDROID)
write( STDERR_FILENO, "Stacktrace (run through c++filt):\n", 34 );
void *buffer[256];
int nptrs = backtrace( buffer, sizeof( buffer ) / sizeof( *buffer ) );
backtrace_symbols_fd( buffer, nptrs, STDERR_FILENO );
Expand Down
108 changes: 82 additions & 26 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
#include "qgsmaptoolidentify.h"
#include "qgsmaptoolmeasureangle.h"
#include "qgsmaptoolmovefeature.h"
#include "qgsmaptoolrotatefeature.h"
#include "qgsmaptoolmovevertex.h"
#include "qgsmaptooloffsetcurve.h"
#include "qgsmaptoolpan.h"
Expand Down Expand Up @@ -382,9 +383,9 @@ void QgisApp::validateSrs( QgsCoordinateReferenceSystem &srs )
mySelector->setSelectedCrsId( defaultCrs.srsid() );
}

// why is this: it overrides the default cursor in the splitter in the dialog
// commenting it now till somebody tells us why it is necessary :-)
//QApplication::setOverrideCursor( Qt::ArrowCursor );
bool waiting = QApplication::overrideCursor() && QApplication::overrideCursor()->shape() == Qt::WaitCursor;
if ( waiting )
QApplication::setOverrideCursor( Qt::ArrowCursor );

if ( mySelector->exec() )
{
Expand All @@ -393,7 +394,8 @@ void QgisApp::validateSrs( QgsCoordinateReferenceSystem &srs )
srs.createFromOgcWmsCrs( mySelector->selectedAuthId() );
}

//QApplication::restoreOverrideCursor();
if ( waiting )
QApplication::restoreOverrideCursor();

delete mySelector;
}
Expand Down Expand Up @@ -514,6 +516,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
updateRecentProjectPaths();
updateProjectFromTemplates();
legendLayerSelectionChanged();
mSaveRollbackInProgress = false;
activateDeactivateLayerRelatedActions( NULL );

addDockWidget( Qt::LeftDockWidgetArea, mUndoWidget );
Expand Down Expand Up @@ -745,6 +748,7 @@ QgisApp::~QgisApp()
delete mMapTools.mPinLabels;
delete mMapTools.mShowHideLabels;
delete mMapTools.mMoveLabel;
delete mMapTools.mRotateFeature;
delete mMapTools.mRotateLabel;
delete mMapTools.mChangeLabelProperties;
delete mMapTools.mOffsetCurve;
Expand Down Expand Up @@ -881,6 +885,8 @@ void QgisApp::createActions()
connect( mActionPasteStyle, SIGNAL( triggered() ), this, SLOT( pasteStyle() ) );
connect( mActionAddFeature, SIGNAL( triggered() ), this, SLOT( addFeature() ) );
connect( mActionMoveFeature, SIGNAL( triggered() ), this, SLOT( moveFeature() ) );
connect( mActionRotateFeature, SIGNAL( triggered() ), this, SLOT( rotateFeature() ) );

connect( mActionReshapeFeatures, SIGNAL( triggered() ), this, SLOT( reshapeFeatures() ) );
connect( mActionSplitFeatures, SIGNAL( triggered() ), this, SLOT( splitFeatures() ) );
connect( mActionDeleteSelected, SIGNAL( triggered() ), this, SLOT( deleteSelected() ) );
Expand Down Expand Up @@ -944,6 +950,7 @@ void QgisApp::createActions()
connect( mActionAddPgLayer, SIGNAL( triggered() ), this, SLOT( addDatabaseLayer() ) );
connect( mActionAddSpatiaLiteLayer, SIGNAL( triggered() ), this, SLOT( addSpatiaLiteLayer() ) );
connect( mActionAddMssqlLayer, SIGNAL( triggered() ), this, SLOT( addMssqlLayer() ) );
connect( mActionAddOracleLayer, SIGNAL( triggered() ), this, SLOT( addOracleLayer() ) );
connect( mActionAddWmsLayer, SIGNAL( triggered() ), this, SLOT( addWmsLayer() ) );
connect( mActionAddWcsLayer, SIGNAL( triggered() ), this, SLOT( addWcsLayer() ) );
connect( mActionAddWfsLayer, SIGNAL( triggered() ), this, SLOT( addWfsLayer() ) );
Expand Down Expand Up @@ -1047,19 +1054,24 @@ void QgisApp::createActions()

#ifndef HAVE_SPATIALITE
delete mActionNewSpatialiteLayer;
mActionNewSpatialiteLayer = NULL;
mActionNewSpatialiteLayer = 0;
delete mActionAddSpatiaLiteLayer;
mActionAddSpatiaLiteLayer = NULL;
mActionAddSpatiaLiteLayer = 0;
#endif

#ifndef HAVE_POSTGRESQL
delete mActionAddPgLayer;
mActionAddPgLayer = NULL;
mActionAddPgLayer = 0;
#endif

#ifndef HAVE_MSSQL
delete mActionAddMssqlLayer;
mActionAddMssqlLayer = NULL;
mActionAddMssqlLayer = 0;
#endif

#ifndef HAVE_ORACLE
delete mActionAddOracleLayer;
mActionAddOracleLayer = 0;
#endif

}
Expand Down Expand Up @@ -1134,6 +1146,7 @@ void QgisApp::createActionGroups()
mMapToolGroup->addAction( mActionMeasureAngle );
mMapToolGroup->addAction( mActionAddFeature );
mMapToolGroup->addAction( mActionMoveFeature );
mMapToolGroup->addAction( mActionRotateFeature );
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
mMapToolGroup->addAction( mActionOffsetCurve );
Expand Down Expand Up @@ -1645,6 +1658,9 @@ void QgisApp::setTheme( QString theThemeName )
#endif
#ifdef HAVE_MSSQL
mActionAddMssqlLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddMssqlLayer.png" ) );
#endif
#ifdef HAVE_ORACLE
mActionAddOracleLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddOracleLayer.png" ) );
#endif
mActionRemoveLayer->setIcon( QgsApplication::getThemeIcon( "/mActionRemoveLayer.png" ) );
mActionDuplicateLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddMap.png" ) );
Expand Down Expand Up @@ -1685,6 +1701,7 @@ void QgisApp::setTheme( QString theThemeName )
mActionPasteFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionEditPaste.png" ) );
mActionAddFeature->setIcon( QgsApplication::getThemeIcon( "/mActionCapturePoint.png" ) );
mActionMoveFeature->setIcon( QgsApplication::getThemeIcon( "/mActionMoveFeature.png" ) );
mActionRotateFeature->setIcon( QgsApplication::getThemeIcon( "/mActionRotateFeature.png" ) );
mActionReshapeFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionReshape.png" ) );
mActionSplitFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionSplitFeatures.svg" ) );
mActionDeleteSelected->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteSelected.png" ) );
Expand Down Expand Up @@ -1874,6 +1891,8 @@ void QgisApp::createCanvasTools()
mMapTools.mAddFeature->setAction( mActionAddFeature );
mMapTools.mMoveFeature = new QgsMapToolMoveFeature( mMapCanvas );
mMapTools.mMoveFeature->setAction( mActionMoveFeature );
mMapTools.mRotateFeature = new QgsMapToolRotateFeature( mMapCanvas );
mMapTools.mRotateFeature->setAction( mActionRotateFeature );
//need at least geos 3.3 for OffsetCurve tool
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
Expand Down Expand Up @@ -1917,6 +1936,7 @@ void QgisApp::createCanvasTools()
mMapTools.mShowHideLabels->setAction( mActionShowHideLabels );
mMapTools.mMoveLabel = new QgsMapToolMoveLabel( mMapCanvas );
mMapTools.mMoveLabel->setAction( mActionMoveLabel );

mMapTools.mRotateLabel = new QgsMapToolRotateLabel( mMapCanvas );
mMapTools.mRotateLabel->setAction( mActionRotateLabel );
mMapTools.mChangeLabelProperties = new QgsMapToolChangeLabelProperties( mMapCanvas );
Expand Down Expand Up @@ -2826,11 +2846,9 @@ void QgisApp::loadOGRSublayers( QString layertype, QString uri, QStringList list
}
}

#ifndef HAVE_POSTGRESQL
void QgisApp::addDatabaseLayer() {}
#else
void QgisApp::addDatabaseLayer()
{
#ifdef HAVE_POSTGRESQL
if ( mMapCanvas && mMapCanvas->isDrawing() )
{
return;
Expand All @@ -2849,8 +2867,8 @@ void QgisApp::addDatabaseLayer()
this , SLOT( addDatabaseLayers( QStringList const &, QString const & ) ) );
pgs->exec();
delete pgs;
} // QgisApp::addDatabaseLayer()
#endif
} // QgisApp::addDatabaseLayer()

void QgisApp::addDatabaseLayers( QStringList const & layerPathList, QString const & providerKey )
{
Expand Down Expand Up @@ -2919,11 +2937,9 @@ void QgisApp::addDatabaseLayers( QStringList const & layerPathList, QString cons
}


#ifndef HAVE_SPATIALITE
void QgisApp::addSpatiaLiteLayer() {}
#else
void QgisApp::addSpatiaLiteLayer()
{
#ifdef HAVE_SPATIALITE
if ( mMapCanvas && mMapCanvas->isDrawing() )
{
return;
Expand All @@ -2940,15 +2956,12 @@ void QgisApp::addSpatiaLiteLayer()
this , SLOT( addDatabaseLayers( QStringList const &, QString const & ) ) );
dbs->exec();
delete dbs;

} // QgisApp::addSpatiaLiteLayer()
#endif
} // QgisApp::addSpatiaLiteLayer()

#ifndef HAVE_MSSQL
void QgisApp::addMssqlLayer() {}
#else
void QgisApp::addMssqlLayer()
{
#ifdef HAVE_MSSQL
if ( mMapCanvas && mMapCanvas->isDrawing() )
{
return;
Expand All @@ -2965,9 +2978,30 @@ void QgisApp::addMssqlLayer()
this , SLOT( addDatabaseLayers( QStringList const &, QString const & ) ) );
dbs->exec();
delete dbs;

#endif
} // QgisApp::addMssqlLayer()

void QgisApp::addOracleLayer()
{
#ifdef HAVE_ORACLE
if ( mMapCanvas && mMapCanvas->isDrawing() )
{
return;
}

// show the Oracle dialog
QDialog *dbs = dynamic_cast<QDialog*>( QgsProviderRegistry::instance()->selectWidget( QString( "oracle" ), this ) );
if ( !dbs )
{
QMessageBox::warning( this, tr( "Oracle" ), tr( "Cannot get Oracle select dialog from provider." ) );
return;
}
connect( dbs , SIGNAL( addDatabaseLayers( QStringList const &, QString const & ) ),
this , SLOT( addDatabaseLayers( QStringList const &, QString const & ) ) );
dbs->exec();
delete dbs;
#endif
} // QgisApp::addOracleLayer()

void QgisApp::addWmsLayer()
{
Expand Down Expand Up @@ -3388,7 +3422,7 @@ bool QgisApp::addProject( QString projectFile )
{
// create the notification widget for macros

QWidget *macroMsg = QgsMessageBar::createMessage( tr( "Security warning:" ),
QWidget *macroMsg = QgsMessageBar::createMessage( tr( "Security warning" ),
tr( "project macros have been disabled." ),
QgsApplication::getThemeIcon( "/mIconWarn.png" ),
mInfoBar );
Expand All @@ -3403,7 +3437,7 @@ bool QgisApp::addProject( QString projectFile )
macroMsg->layout()->addWidget( btnEnableMacros );

// display the macros notification widget
mInfoBar->pushWidget( macroMsg, 1 );
mInfoBar->pushWidget( macroMsg, QgsMessageBar::WARNING );
}
}
}
Expand Down Expand Up @@ -4005,7 +4039,10 @@ void QgisApp::labeling()
QgsMapLayer* layer = activeLayer();
if ( layer == NULL || layer->type() != QgsMapLayer::VectorLayer )
{
QMessageBox::warning( this, tr( "Labeling" ), tr( "Please select a vector layer first." ) );
messageBar()->pushMessage( tr( "Labeling Options" ),
tr( "Please select a vector layer first" ),
QgsMessageBar::INFO,
5 );
return;
}

Expand Down Expand Up @@ -4562,6 +4599,11 @@ void QgisApp::moveLabel()
mMapCanvas->setMapTool( mMapTools.mMoveLabel );
}

void QgisApp::rotateFeature()
{
mMapCanvas->setMapTool( mMapTools.mRotateFeature );
}

void QgisApp::rotateLabel()
{
mMapCanvas->setMapTool( mMapTools.mRotateLabel );
Expand Down Expand Up @@ -5224,8 +5266,12 @@ void QgisApp::saveEdits( QgsMapLayer *layer, bool leaveEditable )
if ( !vlayer || !vlayer->isEditable() || !vlayer->isModified() )
return;

if ( vlayer == activeLayer() )
mSaveRollbackInProgress = true;

if ( !vlayer->commitChanges() )
{
mSaveRollbackInProgress = false;
QMessageBox::information( 0,
tr( "Error" ),
tr( "Could not commit changes to layer %1\n\nErrors: %2\n" )
Expand All @@ -5246,8 +5292,12 @@ void QgisApp::cancelEdits( QgsMapLayer *layer, bool leaveEditable )
if ( !vlayer || !vlayer->isEditable() )
return;

if ( vlayer == activeLayer() && leaveEditable )
mSaveRollbackInProgress = true;

if ( !vlayer->rollBack() )
{
mSaveRollbackInProgress = false;
QMessageBox::information( 0,
tr( "Error" ),
tr( "Could not %1 changes to layer %2\n\nErrors: %3\n" )
Expand Down Expand Up @@ -5730,7 +5780,7 @@ void QgisApp::duplicateLayers( QList<QgsMapLayer *> lyrList )
// display errors in message bar after duplication of layers
foreach ( QWidget * msgBar, msgBars )
{
mInfoBar->pushWidget( msgBar, 1 );
mInfoBar->pushWidget( msgBar, QgsMessageBar::WARNING );
}

}
Expand Down Expand Up @@ -7285,6 +7335,7 @@ void QgisApp::layerEditStateChanged()
if ( layer && layer == activeLayer() )
{
activateDeactivateLayerRelatedActions( layer );
mSaveRollbackInProgress = false;
}
}

Expand Down Expand Up @@ -7357,6 +7408,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
mActionFeatureAction->setEnabled( false );
mActionAddFeature->setEnabled( false );
mActionMoveFeature->setEnabled( false );
mActionRotateFeature->setEnabled( false );
mActionOffsetCurve->setEnabled( false );
mActionNodeTool->setEnabled( false );
mActionDeleteSelected->setEnabled( false );
Expand Down Expand Up @@ -7425,7 +7477,8 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
mActionCopyFeatures->setEnabled( layerHasSelection );
mActionFeatureAction->setEnabled( layerHasActions );

if ( !vlayer->isEditable() && mMapCanvas->mapTool() && mMapCanvas->mapTool()->isEditTool() )
if ( !vlayer->isEditable() && mMapCanvas->mapTool()
&& mMapCanvas->mapTool()->isEditTool() && !mSaveRollbackInProgress )
{
mMapCanvas->setMapTool( mNonEditMapTool );
}
Expand Down Expand Up @@ -7498,13 +7551,15 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
mActionAddPart->setEnabled( true );
mActionDeletePart->setEnabled( true );
mActionMoveFeature->setEnabled( true );
mActionRotateFeature->setEnabled( true );
mActionNodeTool->setEnabled( true );
}
else
{
mActionAddPart->setEnabled( false );
mActionDeletePart->setEnabled( false );
mActionMoveFeature->setEnabled( false );
mActionRotateFeature->setEnabled( false );
mActionOffsetCurve->setEnabled( false );
mActionNodeTool->setEnabled( false );
}
Expand Down Expand Up @@ -7629,6 +7684,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
mActionAddPart->setEnabled( false );
mActionNodeTool->setEnabled( false );
mActionMoveFeature->setEnabled( false );
mActionRotateFeature->setEnabled( false );
mActionOffsetCurve->setEnabled( false );
mActionCopyFeatures->setEnabled( false );
mActionCutFeatures->setEnabled( false );
Expand Down
15 changes: 14 additions & 1 deletion src/app/qgisapp.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
QAction *actionDeleteSelected() { return mActionDeleteSelected; }
QAction *actionAddFeature() { return mActionAddFeature; }
QAction *actionMoveFeature() { return mActionMoveFeature; }
QAction *actionRotateFeature() { return mActionRotateFeature;}
QAction *actionSplitFeatures() { return mActionSplitFeatures; }
QAction *actionAddRing() { return mActionAddRing; }
QAction *actionAddPart() { return mActionAddPart; }
Expand Down Expand Up @@ -594,9 +595,13 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
void addSpatiaLiteLayer();
//#endif
//#ifdef HAVE_MSSQL
//! Add a SpatiaLite layer to the map
//! Add a MSSQL layer to the map
void addMssqlLayer();
//#endif
//#ifdef HAVE_ORACLE
//! Add a Oracle layer to the map
void addOracleLayer();
//#endif
/** toggles whether the current selected layer is in overview or not */
void isInOverview();
//! Slot to show the map coordinate position of the mouse cursor
Expand Down Expand Up @@ -960,6 +965,8 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
void showHideLabels();
//! Activates the move label tool
void moveLabel();
//! Activates rotate feature tool
void rotateFeature();
//! Activates rotate label tool
void rotateLabel();
//! Activates label property tool
Expand Down Expand Up @@ -1169,6 +1176,7 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
QgsMapTool* mPinLabels;
QgsMapTool* mShowHideLabels;
QgsMapTool* mMoveLabel;
QgsMapTool* mRotateFeature;
QgsMapTool* mRotateLabel;
QgsMapTool* mChangeLabelProperties;
} mMapTools;
Expand Down Expand Up @@ -1280,6 +1288,11 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
//!flag to indicate that the previous screen mode was 'maximised'
bool mPrevScreenModeMaximized;

/** Flag to indicate an edits save/rollback for active layer is in progress
* @note added in QGIS 1.9
*/
bool mSaveRollbackInProgress;

QgsPythonUtils* mPythonUtils;

static QgisApp *smInstance;
Expand Down
7 changes: 2 additions & 5 deletions src/app/qgsmaptooladdfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )

if ( !vlayer )
{
QMessageBox::information( 0, tr( "Not a vector layer" ),
tr( "The current layer is not a vector layer" ) );
notifyNotVectorLayer();
return;
}

Expand All @@ -72,9 +71,7 @@ void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )

if ( !vlayer->isEditable() )
{
QMessageBox::information( 0, tr( "Layer not editable" ),
tr( "Cannot edit the vector layer. Use 'Toggle Editing' to make it editable." )
);
notifyNotEditableLayer();
return;
}

Expand Down
9 changes: 2 additions & 7 deletions src/app/qgsmaptooladdpart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,13 @@ void QgsMapToolAddPart::canvasReleaseEvent( QMouseEvent * e )
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
if ( !vlayer )
{
QMessageBox::information( 0,
tr( "Not a vector layer" ),
tr( "The current layer is not a vector layer" ) );
notifyNotVectorLayer();
return;
}

if ( !vlayer->isEditable() )
{
QMessageBox::information( 0,
tr( "Layer not editable" ),
tr( "Cannot edit the vector layer. Use 'Toggle Editing' to make it editable." )
);
notifyNotEditableLayer();
return;
}

Expand Down
7 changes: 2 additions & 5 deletions src/app/qgsmaptooladdring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,13 @@ void QgsMapToolAddRing::canvasReleaseEvent( QMouseEvent * e )

if ( !vlayer )
{
QMessageBox::information( 0, tr( "Not a vector layer" ),
tr( "The current layer is not a vector layer" ) );
notifyNotVectorLayer();
return;
}

if ( !vlayer->isEditable() )
{
QMessageBox::information( 0, tr( "Layer not editable" ),
tr( "Cannot edit the vector layer. Use 'Toggle Editing' to make it editable." )
);
notifyNotEditableLayer();
return;
}

Expand Down
18 changes: 18 additions & 0 deletions src/app/qgsmaptooledit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
***************************************************************************/

#include "qgsmaptooledit.h"
#include "qgisapp.h"
#include "qgsmessagebar.h"
#include "qgsproject.h"
#include "qgsmapcanvas.h"
#include "qgsrubberband.h"
Expand Down Expand Up @@ -119,4 +121,20 @@ int QgsMapToolEdit::addTopologicalPoints( const QList<QgsPoint>& geom )
return 0;
}

void QgsMapToolEdit::notifyNotVectorLayer()
{
QgisApp::instance()->messageBar()->pushMessage(
tr( "No active vector layer" ),
tr( "Choose a vector layer in the legend" ),
QgsMessageBar::INFO,
5 );
}

void QgsMapToolEdit::notifyNotEditableLayer()
{
QgisApp::instance()->messageBar()->pushMessage(
tr( "Layer not editable" ),
tr( "Use 'Toggle Editing' to make it editable" ),
QgsMessageBar::INFO,
5 );
}
7 changes: 7 additions & 0 deletions src/app/qgsmaptooledit.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ class QgsMapToolEdit: public QgsMapTool
@return 0 in case of success*/
int addTopologicalPoints( const QList<QgsPoint>& geom );

/**Display a timed message bar noting the active layer is not vector.
@note added in QGIS 1.9*/
void notifyNotVectorLayer();
/**Display a timed message bar noting the active vector layer is not editable.
@note added in QGIS 1.9*/
void notifyNotEditableLayer();

};

#endif
5 changes: 2 additions & 3 deletions src/app/qgsmaptoolmovefeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,13 @@ void QgsMapToolMoveFeature::canvasPressEvent( QMouseEvent * e )
QgsVectorLayer* vlayer = currentVectorLayer();
if ( !vlayer )
{
notifyNotVectorLayer();
return;
}

if ( !vlayer->isEditable() )
{
QMessageBox::information( 0, tr( "Layer not editable" ),
tr( "Cannot edit the vector layer. Use 'Toggle Editing' to make it editable." )
);
notifyNotEditableLayer();
return;
}

Expand Down
8 changes: 7 additions & 1 deletion src/app/qgsmaptooloffsetcurve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,16 @@ void QgsMapToolOffsetCurve::canvasPressEvent( QMouseEvent* e )
mGeometryModified = false;
mForceCopy = false;

if ( !mCanvas )
{
return;
}

//get selected features or snap to nearest feature if no selection
QgsVectorLayer* layer = currentVectorLayer();
if ( !mCanvas || !layer )
if ( !layer )
{
notifyNotVectorLayer();
return;
}

Expand Down
7 changes: 2 additions & 5 deletions src/app/qgsmaptoolreshape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,13 @@ void QgsMapToolReshape::canvasReleaseEvent( QMouseEvent * e )

if ( !vlayer )
{
QMessageBox::information( 0, tr( "Not a vector layer" ),
tr( "The current layer is not a vector layer" ) );
notifyNotVectorLayer();
return;
}

if ( !vlayer->isEditable() )
{
QMessageBox::information( 0, tr( "Layer not editable" ),
tr( "Cannot edit the vector layer. Use 'Toggle Editing' to make it editable." )
);
notifyNotEditableLayer();
return;
}

Expand Down
343 changes: 343 additions & 0 deletions src/app/qgsmaptoolrotatefeature.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
/***************************************************************************
qgsmaptoolrotatefeature.cpp - map tool for rotating features by mouse drag
---------------------
begin : January 2012
copyright : (C) 2012 by Vinayan Parameswaran
email : vinayan123 at gmail dot com
***************************************************************************
* *
* 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 "qgsmaptoolrotatefeature.h"
#include "qgsgeometry.h"
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsrubberband.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
#include "qgstolerance.h"
#include <QMessageBox>
#include <QMouseEvent>
#include <QSettings>
#include <limits>
#include <math.h>
#include "qgsvertexmarker.h"

#define PI 3.14159265

QgsMapToolRotateFeature::QgsMapToolRotateFeature( QgsMapCanvas* canvas ): QgsMapToolEdit( canvas ), mRubberBand( 0 )
{
mRotation = 0;
mAnchorPoint = 0;
mCtrl = false;
}

QgsMapToolRotateFeature::~QgsMapToolRotateFeature()
{
delete mAnchorPoint;
delete mRubberBand;
}

void QgsMapToolRotateFeature::canvasMoveEvent( QMouseEvent * e )
{
if ( mCtrl == true )
{
if ( !mAnchorPoint )
{
return;
}
mAnchorPoint->setCenter( toMapCoordinates( e->pos() ) );
mStartPointMapCoords = toMapCoordinates( e->pos() );
mStPoint = e->pos();
return;


}
if ( mRubberBand )
{
double XDistance = mStPoint.x() - e->pos().x();
double YDistance = mStPoint.y() - e->pos().y();
mRotation = atan2( YDistance, XDistance ) * ( 180 / PI );

mStPoint = toCanvasCoordinates( mStartPointMapCoords );
double offsetX = mStPoint.x() - mRubberBand->x();
double offsetY = mStPoint.y() - mRubberBand->y();

mRubberBand->setTransform( QTransform().translate( offsetX, offsetY ).rotate( mRotation ).translate( -1 * offsetX, -1 * offsetY ) );
mRubberBand->update();
}
}

void QgsMapToolRotateFeature::canvasPressEvent( QMouseEvent * e )
{
mRotation = 0;
if ( mCtrl == true )
{
return;
}

delete mRubberBand;
mRubberBand = 0;

mInitialPos = e->pos();

QgsVectorLayer* vlayer = currentVectorLayer();
if ( !vlayer )
{
notifyNotVectorLayer();
return;
}

if ( !vlayer->isEditable() )
{
notifyNotEditableLayer();
return;
}

QgsPoint layerCoords = toLayerCoordinates( vlayer, e->pos() );
double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapRenderer() );
QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius,
layerCoords.x() + searchRadius, layerCoords.y() + searchRadius );

if ( vlayer->selectedFeatureCount() == 0 )
{
vlayer->select( QgsAttributeList(), selectRect, true );

//find the closest feature
QgsGeometry* pointGeometry = QgsGeometry::fromPoint( layerCoords );
if ( !pointGeometry )
{
return;
}

double minDistance = std::numeric_limits<double>::max();

QgsFeature cf;
QgsFeature f;
while ( vlayer->nextFeature( f ) )
{
if ( f.geometry() )
{
double currentDistance = pointGeometry->distance( *f.geometry() );
if ( currentDistance < minDistance )
{
minDistance = currentDistance;
cf = f;
}
}

}

delete pointGeometry;

if ( minDistance == std::numeric_limits<double>::max() )
{
return;
}

QgsRectangle bound = cf.geometry()->boundingBox();
mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() );

if ( !mAnchorPoint )
{
mAnchorPoint = new QgsVertexMarker( mCanvas );
}
mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS );
mAnchorPoint->setCenter( mStartPointMapCoords );

mStPoint = toCanvasCoordinates( mStartPointMapCoords );

mRotatedFeatures.clear();
mRotatedFeatures << cf.id(); //todo: take the closest feature, not the first one...

mRubberBand = createRubberBand();
mRubberBand->setToGeometry( cf.geometry(), vlayer );
}
else
{
mRotatedFeatures = vlayer->selectedFeaturesIds();

mRubberBand = createRubberBand();
for ( int i = 0; i < vlayer->selectedFeatureCount(); i++ )
{
mRubberBand->addGeometry( vlayer->selectedFeatures()[i].geometry(), vlayer );
}
}

mRubberBand->setColor( Qt::red );
mRubberBand->setWidth( 2 );
mRubberBand->show();

}

void QgsMapToolRotateFeature::canvasReleaseEvent( QMouseEvent * e )
{
Q_UNUSED( e );
if ( !mRubberBand )
{
return;
}

QgsVectorLayer* vlayer = currentVectorLayer();
if ( !vlayer )
{
return;
}

//calculations for affine transformation
double angle = -1 * mRotation * ( PI / 180 );
QgsPoint anchorPoint = toLayerCoordinates( vlayer, mStartPointMapCoords );
double a = cos( angle );
double b = -1 * sin( angle );
double c = anchorPoint.x() - cos( angle ) * anchorPoint.x() + sin( angle ) * anchorPoint.y();
double d = sin( angle );
double ee = cos( angle );
double f = anchorPoint.y() - sin( angle ) * anchorPoint.x() - cos( angle ) * anchorPoint.y();

vlayer->beginEditCommand( tr( "Features Rotated" ) );

int start;
if ( vlayer->geometryType() == 2 )
{
start = 1;
}
else
{
start = 0;
}

int i = 0;
foreach ( QgsFeatureId id, mRotatedFeatures )
{
QgsFeature feat;
vlayer->featureAtId( id, feat );
QgsGeometry* geom = feat.geometry();
i = start;

QgsPoint vertex = geom->vertexAt( i );
while ( vertex != QgsPoint( 0, 0 ) )
{
double newX = a * vertex.x() + b * vertex.y() + c;
double newY = d * vertex.x() + ee * vertex.y() + f;

vlayer->moveVertex( newX, newY, id, i );
i = i + 1;
vertex = geom->vertexAt( i );
}

}

double anchorX = a * anchorPoint.x() + b * anchorPoint.y() + c;
double anchorY = d * anchorPoint.x() + ee * anchorPoint.y() + f;

mAnchorPoint->setCenter( QgsPoint( anchorX, anchorY ) );

delete mRubberBand;
mRubberBand = 0;

mCanvas->refresh();
vlayer->endEditCommand();

}

void QgsMapToolRotateFeature::resetAnchor()
{
QgsVectorLayer* vlayer = currentVectorLayer();
if ( !vlayer )
{
return;
}

if ( vlayer->selectedFeatureCount() == 0 )
{
return;
}
else
{

QgsRectangle bound = vlayer->boundingBoxOfSelected();
mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() );

mAnchorPoint->setCenter( mStartPointMapCoords );

mStPoint = toCanvasCoordinates( mStartPointMapCoords );
}

}


void QgsMapToolRotateFeature::keyPressEvent( QKeyEvent* e )
{
if ( e->key() == Qt::Key_Control )
{
mCtrl = true;
mCanvas->viewport()->setMouseTracking( true );
return;
}

if ( e->key() == Qt::Key_Escape )
{
this->resetAnchor();
}
}

void QgsMapToolRotateFeature::keyReleaseEvent( QKeyEvent* e )
{
if ( e->key() == Qt::Key_Control )
{
mCtrl = false;
mCanvas->viewport()->setMouseTracking( false );

return;
}

}

void QgsMapToolRotateFeature::activate()
{

QgsVectorLayer* vlayer = currentVectorLayer();
if ( !vlayer )
{
return;
}

if ( !vlayer->isEditable() )
{
return;
}

if ( vlayer->selectedFeatureCount() == 0 )
{
return;
}
else
{

QgsRectangle bound = vlayer->boundingBoxOfSelected();
mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() );

mAnchorPoint = new QgsVertexMarker( mCanvas );
mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS );
mAnchorPoint->setCenter( mStartPointMapCoords );

mStPoint = toCanvasCoordinates( mStartPointMapCoords );

QgsMapTool::activate();
}
}

void QgsMapToolRotateFeature::deactivate()
{
delete mRubberBand;
delete mAnchorPoint;
mRubberBand = 0;
mAnchorPoint = 0;

QgsMapTool::deactivate();
}
74 changes: 74 additions & 0 deletions src/app/qgsmaptoolrotatefeature.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/***************************************************************************
qgsmaptoolrotatefeature.h - map tool for rotating features by mouse drag
---------------------
begin : January 2013
copyright : (C) 2013 by Vinayan Parameswaran
email : vinayan123 at gmail dot com
***************************************************************************
* *
* 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. *
* *
***************************************************************************/

#ifndef QGSMAPTOOLROTATEFEATURE_H
#define QGSMAPTOOLROTATEFEATURE_H

#include "qgsmaptooledit.h"
#include "qgsvectorlayer.h"

class QgsVertexMarker;

/**Map tool for translating feature position by mouse drag*/
class QgsMapToolRotateFeature: public QgsMapToolEdit
{
Q_OBJECT
public:
QgsMapToolRotateFeature( QgsMapCanvas* canvas );
virtual ~QgsMapToolRotateFeature();

virtual void canvasMoveEvent( QMouseEvent * e );

virtual void canvasPressEvent( QMouseEvent * e );

virtual void canvasReleaseEvent( QMouseEvent * e );

void keyPressEvent( QKeyEvent* e );

void keyReleaseEvent( QKeyEvent* e );


//! to reset the rotation anchor to selectionbound center
void resetAnchor();
//! called when map tool is being deactivated
void deactivate();

void activate();


private:

QgsGeometry rotateGeometry( QgsGeometry geom, QgsPoint point, double angle );
QgsPoint rotatePoint( QgsPoint point, double angle );

/**Start point of the move in map coordinates*/
QgsPoint mStartPointMapCoords;
QPointF mInitialPos;

/**Rubberband that shows the feature being moved*/
QgsRubberBand* mRubberBand;

/**Id of moved feature*/
QgsFeatureIds mRotatedFeatures;
double mRotation;

QPoint mStPoint;
QgsVertexMarker* mAnchorPoint;

/** flag if crtl is pressed */
bool mCtrl;
};

#endif
9 changes: 8 additions & 1 deletion src/app/qgsmaptoolrotatepointsymbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,17 @@ void QgsMapToolRotatePointSymbols::canvasPressEvent( QMouseEvent *e )
mActiveLayer = currentVectorLayer();
if ( !mActiveLayer )
{
notifyNotVectorLayer();
return;
}

if ( mActiveLayer->geometryType() != QGis::Point || !mActiveLayer->isEditable() )
if ( !mActiveLayer->isEditable() )
{
notifyNotEditableLayer();
return;
}

if ( mActiveLayer->geometryType() != QGis::Point )
{
return;
}
Expand Down
11 changes: 7 additions & 4 deletions src/app/qgsmaptoolselectutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ email : jpalmer at linz dot govt dot nz
#include <limits>

#include "qgsmaptoolselectutils.h"
#include "qgisapp.h"
#include "qgsmessagebar.h"
#include "qgsmapcanvas.h"
#include "qgsvectorlayer.h"
#include "qgsfeature.h"
Expand All @@ -35,10 +37,11 @@ QgsVectorLayer* QgsMapToolSelectUtils::getCurrentVectorLayer( QgsMapCanvas* canv
if ( !canvas->currentLayer()
|| ( vlayer = qobject_cast<QgsVectorLayer *>( canvas->currentLayer() ) ) == NULL )
{
QMessageBox::warning( canvas, QObject::tr( "No active vector layer" ),
QObject::tr( "To select features, you must choose a "
"vector layer by clicking on its name in the legend"
) );
QgisApp::instance()->messageBar()->pushMessage(
QObject::tr( "No active vector layer" ),
QObject::tr( "To select features, choose a vector layer in the legend" ),
QgsMessageBar::INFO,
5 );
}
return vlayer;
}
Expand Down
7 changes: 7 additions & 0 deletions src/app/qgsmaptoolsimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ bool QgsMapToolSimplify::calculateSliderBoudaries()
void QgsMapToolSimplify::canvasPressEvent( QMouseEvent * e )
{
QgsVectorLayer * vlayer = currentVectorLayer();

if ( !vlayer )
{
notifyNotVectorLayer();
return;
}

QgsPoint layerCoords = mCanvas->getCoordinateTransform()->toMapPoint( e->pos().x(), e->pos().y() );

double r = QgsTolerance::vertexSearchRadius( vlayer, mCanvas->mapRenderer() );
Expand Down
7 changes: 2 additions & 5 deletions src/app/qgsmaptoolsplitfeatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,13 @@ void QgsMapToolSplitFeatures::canvasReleaseEvent( QMouseEvent * e )

if ( !vlayer )
{
QMessageBox::information( 0, tr( "Not a vector layer" ),
tr( "The current layer is not a vector layer" ) );
notifyNotVectorLayer();
return;
}

if ( !vlayer->isEditable() )
{
QMessageBox::information( 0, tr( "Layer not editable" ),
tr( "Cannot edit the vector layer. Use 'Toggle Editing' to make it editable." )
);
notifyNotEditableLayer();
return;
}

Expand Down
1 change: 1 addition & 0 deletions src/app/qgsvectorlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ void QgsVectorLayerProperties::apply()
if ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::SetEncoding )
{
layer->dataProvider()->setEncoding( cboProviderEncoding->currentText() );
layer->updateFieldMap();
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/composer/qgscomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
bool widthConversionOk, heightConversionOk;
mPageWidth = compositionElem.attribute( "paperWidth" ).toDouble( &widthConversionOk );
mPageHeight = compositionElem.attribute( "paperHeight" ).toDouble( &heightConversionOk );
emit paperSizeChanged();
int numPages = compositionElem.attribute( "numPages", "1" ).toInt();

if ( widthConversionOk && heightConversionOk )
Expand Down Expand Up @@ -435,7 +436,6 @@ bool QgsComposition::loadFromTemplate( const QDomDocument& doc, QMap<QString, QS
// read atlas parameters
QDomElement atlasElem = importDoc.documentElement().firstChildElement( "Atlas" );
atlasComposition().readXML( atlasElem, importDoc );

return true;
}

Expand Down
45 changes: 22 additions & 23 deletions src/core/qgis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,32 +45,31 @@ const int QGis::QGIS_VERSION_INT = VERSION_INT;
const char* QGis::QGIS_RELEASE_NAME = RELEASE_NAME;

#if GDAL_VERSION_NUM >= 1800
const QString GEOPROJ4 = "+proj=longlat +datum=WGS84 +no_defs";
const CORE_EXPORT QString GEOPROJ4 = "+proj=longlat +datum=WGS84 +no_defs";
#else
const QString GEOPROJ4 = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
const CORE_EXPORT QString GEOPROJ4 = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
#endif

const char* QGis::qgisVectorGeometryType[] =
{
"Point",
"Line",
"Polygon",
"Unknown geometry",
"No geometry",
};

// description strings for feature types
const char* QGis::qgisFeatureTypes[] =
{
"Null",
"WKBPoint",
"WKBLineString",
"WKBPolygon",
"WKBMultiPoint",
"WKBMultiLineString",
"WKBMultiPolygon"
};

const CORE_EXPORT QString GEOWKT =
"GEOGCS[\"WGS 84\", "
" DATUM[\"WGS_1984\", "
" SPHEROID[\"WGS 84\",6378137,298.257223563, "
" AUTHORITY[\"EPSG\",7030]], "
" TOWGS84[0,0,0,0,0,0,0], "
" AUTHORITY[\"EPSG\",6326]], "
" PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]], "
" UNIT[\"DMSH\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]], "
" AXIS[\"Lat\",NORTH], "
" AXIS[\"Long\",EAST], "
" AUTHORITY[\"EPSG\",4326]]";

const CORE_EXPORT QString PROJECT_SCALES =
"1:1000000,1:500000,1:250000,1:100000,1:50000,1:25000,"
"1:10000,1:5000,1:2500,1:1000,1:500";

const CORE_EXPORT QString GEO_EPSG_CRS_AUTHID = "EPSG:4326";

const CORE_EXPORT QString GEO_NONE = "NONE";

const double QGis::DEFAULT_IDENTIFY_RADIUS = 0.5;

Expand Down
111 changes: 74 additions & 37 deletions src/core/qgis.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,47 @@ class CORE_EXPORT QGis
WKBMultiPolygon25D,
};

static WkbType singleType( WkbType type )
{
switch ( type )
{
case WKBMultiPoint: return WKBPoint;
case WKBMultiLineString: return WKBLineString;
case WKBMultiPolygon: return WKBPolygon;
case WKBMultiPoint25D: return WKBPoint25D;
case WKBMultiLineString25D: return WKBLineString25D;
case WKBMultiPolygon25D: return WKBPolygon25D;
default: return type;
}
}

static WkbType flatType( WkbType type )
{
switch ( type )
{
case WKBMultiPoint:
return WKBPoint;
case WKBMultiLineString:
return WKBLineString;
case WKBMultiPolygon:
return WKBPolygon;
case WKBMultiPoint25D:
return WKBPoint25D;
case WKBMultiLineString25D:
return WKBLineString25D;
case WKBMultiPolygon25D:
return WKBPolygon25D;
default:
return type;
case WKBPoint25D: return WKBPoint;
case WKBLineString25D: return WKBLineString;
case WKBPolygon25D: return WKBPolygon;
case WKBMultiPoint25D: return WKBMultiPoint;
case WKBMultiLineString25D: return WKBMultiLineString;
case WKBMultiPolygon25D: return WKBMultiPolygon;
default: return type;
}
}

static int wkbDimensions( WkbType type )
{
switch ( type )
{
case WKBUnknown: return 0;
case WKBNoGeometry: return 0;
case WKBPoint25D: return 3;
case WKBLineString25D: return 3;
case WKBPolygon25D: return 3;
case WKBMultiPoint25D: return 3;
case WKBMultiLineString25D: return 3;
case WKBMultiPolygon25D: return 3;
default: return 2;
}
}

Expand All @@ -97,13 +120,41 @@ class CORE_EXPORT QGis
NoGeometry
};

// String representation of geometry types (set in qgis.cpp)
//! @note not available in python bindings
static const char *qgisVectorGeometryType[];
//! description strings for geometry types
static const char *vectorGeometryType( GeometryType type )
{
switch ( type )
{
case Point: return "Point";
case Line: return "Line";
case Polygon: return "Polygon";
case UnknownGeometry: return "Unknown geometry";
case NoGeometry: return "No geometry";
default: return "Invalid type";
}
}

//! description strings for feature types
//! @note not available in python bindings
static const char *qgisFeatureTypes[];
static const char *featureType( WkbType type )
{
switch ( type )
{
case WKBUnknown: return "WKBUnknown";
case WKBPoint: return "WKBPoint";
case WKBLineString: return "WKBLineString";
case WKBPolygon: return "WKBPolygon";
case WKBMultiPoint: return "WKBMultiLineString";
case WKBMultiPolygon: return "WKBMultiPolygon";
case WKBNoGeometry: return "WKBNoGeometry";
case WKBPoint25D: return "WKBPoint25D";
case WKBLineString25D: return "WKBLineString25D";
case WKBPolygon25D: return "WKBPolygon25D";
case WKBMultiPoint25D: return "WKBMultiPoint25D";
case WKBMultiLineString25D: return "WKBMultiLineString25D";
case WKBMultiPolygon25D: return "WKBMultiPolygon25D";
default: return "invalid wkbtype";
}
}

/** Raster data types.
* This is modified and extended copy of GDALDataType.
Expand Down Expand Up @@ -245,22 +296,8 @@ void CORE_EXPORT QgsFree( void *ptr );
/** Wkt string that represents a geographic coord sys
* @note added in 1.8 to replace GEOWkt
*/
const QString GEOWKT =
"GEOGCS[\"WGS 84\", "
" DATUM[\"WGS_1984\", "
" SPHEROID[\"WGS 84\",6378137,298.257223563, "
" AUTHORITY[\"EPSG\",7030]], "
" TOWGS84[0,0,0,0,0,0,0], "
" AUTHORITY[\"EPSG\",6326]], "
" PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]], "
" UNIT[\"DMSH\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]], "
" AXIS[\"Lat\",NORTH], "
" AXIS[\"Long\",EAST], "
" AUTHORITY[\"EPSG\",4326]]";

const QString PROJECT_SCALES =
"1:1000000,1:500000,1:250000,1:100000,1:50000,1:25000,"
"1:10000,1:5000,1:2500,1:1000,1:500";
extern CORE_EXPORT const QString GEOWKT;
extern CORE_EXPORT const QString PROJECT_SCALES;

/** PROJ4 string that represents a geographic coord sys */
extern CORE_EXPORT const QString GEOPROJ4;
Expand All @@ -271,7 +308,7 @@ const long GEOCRS_ID = 3452;
/** Magic number for a geographic coord sys in EpsgCrsId ID format */
const long GEO_EPSG_CRS_ID = 4326;
/** Geographic coord sys from EPSG authority */
const QString GEO_EPSG_CRS_AUTHID = "EPSG:4326";
extern CORE_EXPORT const QString GEO_EPSG_CRS_AUTHID;
/** The length of the string "+proj=" */
const int PROJ_PREFIX_LEN = 6;
/** The length of the string "+ellps=" */
Expand All @@ -284,7 +321,7 @@ const int USER_CRS_START_ID = 100000;

//! Constant that holds the string representation for "No ellips/No CRS"
// Added in version 2.0
const QString GEO_NONE = "NONE";
extern CORE_EXPORT const QString GEO_NONE;

//
// Constants for point symbols
Expand Down
40 changes: 25 additions & 15 deletions src/core/qgsgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,6 @@ QgsGeometry* QgsGeometry::fromGML2( const QDomNode& geometryNode )
{
return 0;
}
return 0;
}

bool QgsGeometry::setFromGML2Point( const QDomElement& geometryElement )
Expand Down Expand Up @@ -1229,7 +1228,7 @@ GEOSGeometry* QgsGeometry::asGeos()
QGis::WkbType QgsGeometry::wkbType()
{
unsigned char *geom = asWkb(); // ensure that wkb representation exists
if ( geom )
if ( geom && wkbSize() >= 5 )
{
unsigned int wkbType;
memcpy( &wkbType, ( geom + 1 ), sizeof( wkbType ) );
Expand All @@ -1250,18 +1249,29 @@ QGis::GeometryType QgsGeometry::type()
exportGeosToWkb();
}

QGis::WkbType type = wkbType();
if ( type == QGis::WKBPoint || type == QGis::WKBPoint25D ||
type == QGis::WKBMultiPoint || type == QGis::WKBMultiPoint25D )
return QGis::Point;
if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D ||
type == QGis::WKBMultiLineString || type == QGis::WKBMultiLineString25D )
return QGis::Line;
if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D ||
type == QGis::WKBMultiPolygon || type == QGis::WKBMultiPolygon25D )
return QGis::Polygon;

return QGis::UnknownGeometry;
switch ( wkbType() )
{
case QGis::WKBPoint:
case QGis::WKBPoint25D:
case QGis::WKBMultiPoint:
case QGis::WKBMultiPoint25D:
return QGis::Point;

case QGis::WKBLineString:
case QGis::WKBLineString25D:
case QGis::WKBMultiLineString:
case QGis::WKBMultiLineString25D:
return QGis::Line;

case QGis::WKBPolygon:
case QGis::WKBPolygon25D:
case QGis::WKBMultiPolygon:
case QGis::WKBMultiPolygon25D:
return QGis::Polygon;

default:
return QGis::UnknownGeometry;
}
}

bool QgsGeometry::isMultipart()
Expand Down Expand Up @@ -4426,7 +4436,7 @@ QgsRectangle QgsGeometry::boundingBox()
}

default:
QgsDebugMsg( "Unknown WkbType ENCOUNTERED" );
QgsDebugMsg( QString( "Unknown WkbType %1 ENCOUNTERED" ).arg( wkbType ) );
return QgsRectangle( 0, 0, 0, 0 );
break;

Expand Down
3 changes: 0 additions & 3 deletions src/core/qgsgeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,9 +622,6 @@ class CORE_EXPORT QgsGeometry

/**Returns < 0 if point(x/y) is left of the line x1,y1 -> x1,y2*/
double leftOf( double x, double y, double& x1, double& y1, double& x2, double& y2 );


static int refcount;
}; // class QgsGeometry

#endif
6 changes: 3 additions & 3 deletions src/core/qgsproviderregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,10 @@ const QgsProviderMetadata* QgsProviderRegistry::providerMetadata( const QString&
}


/*
#if 0
QgsDataProvider *
QgsProviderRegistry::openVector( QString const & dataSource, QString const & providerKey )
{
return getProvider( providerKey, dataSource );
return getProvider( providerKey, dataSource );
} // QgsProviderRegistry::openVector
*/
#endif
2 changes: 1 addition & 1 deletion src/core/qgsvectorfilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ bool QgsVectorFileWriter::addFeature( QgsFeature& feature )
QgsGeometry *geom = feature.geometry();

// turn single geoemetry to multi geometry if needed
if ( geom && geom->wkbType() != mWkbType && geom->wkbType() == QGis::flatType( mWkbType ) )
if ( geom && geom->wkbType() != mWkbType && geom->wkbType() == QGis::singleType( mWkbType ) )
{
geom->convertToMultiType();
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3015,7 +3015,7 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
mapLayerNode.setAttribute( "type", "vector" );

// set the geometry type
mapLayerNode.setAttribute( "geometry", QGis::qgisVectorGeometryType[geometryType()] );
mapLayerNode.setAttribute( "geometry", QGis::vectorGeometryType( geometryType() ) );

// add provider node
if ( mDataProvider )
Expand Down Expand Up @@ -5799,7 +5799,7 @@ QString QgsVectorLayer::metadata()
}
else
{
QString typeString( QGis::qgisVectorGeometryType[geometryType()] );
QString typeString( QGis::vectorGeometryType( geometryType() ) );

myMetadata += "<tr><td>";
myMetadata += tr( "Geometry type of the features in this layer: %1" ).arg( typeString );
Expand Down
22 changes: 22 additions & 0 deletions src/core/qgsvectorlayerimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsvectorlayerimport.h"
#include "qgsproviderregistry.h"
#include "qgsdatasourceuri.h"

#include <QProgressDialog>

#include <QProgressDialog>

Expand Down Expand Up @@ -176,6 +179,17 @@ bool QgsVectorLayerImport::flushBuffer()
return true;
}

bool QgsVectorLayerImport::createSpatialIndex()
{
if ( mProvider && ( mProvider->capabilities() & QgsVectorDataProvider::CreateSpatialIndex ) != 0 )
{
return mProvider->createSpatialIndex();
}
else
{
return true;
}
}

QgsVectorLayerImport::ImportError
QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
Expand Down Expand Up @@ -384,6 +398,14 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
}
int errors = writer->errorCount();

if ( !writer->createSpatialIndex() )
{
if ( writer->hasError() && errorMessage )
{
*errorMessage += "\n" + writer->errorMessage();
}
}

delete writer;

if ( shallTransform )
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsvectorlayerimport.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class CORE_EXPORT QgsVectorLayerImport
/** flush the buffer writing the features to the new layer */
bool flushBuffer();

/** create index */
bool createSpatialIndex();

/** contains error value */
ImportError mError;
QString mErrorMessage;
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgsrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
break;

default:
QgsDebugMsg( "unsupported wkb type for rendering" );
QgsDebugMsg( QString( "unsupported wkb type 0x%1 for rendering" ).arg( geom->wkbType(), 0, 16 ) );
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/gui/attributetable/qgsattributetablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ bool QgsAttributeTableModel::removeRows( int row, int count, const QModelIndex &

void QgsAttributeTableModel::featureAdded( QgsFeatureId fid, bool newOperation )
{
QgsDebugMsgLevel( QString( "feature %1 added (%2, rows %3, ids %4)" ).arg( fid ).arg( newOperation ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 3 );
QgsDebugMsgLevel( QString( "feature %1 added (%2, rows %3, ids %4)" ).arg( fid ).arg( newOperation ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ), 4 );

int n = mRowIdMap.size();
if ( newOperation )
Expand Down
45 changes: 43 additions & 2 deletions src/gui/qgsattributeeditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,12 @@ QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *ed
case QgsVectorLayer::CheckBox:
{
QCheckBox *cb = 0;
QGroupBox *gb = 0;
if ( editor )
{
gb = qobject_cast<QGroupBox *>( editor );
cb = qobject_cast<QCheckBox*>( editor );
}
else
cb = new QCheckBox( parent );

Expand All @@ -427,6 +431,11 @@ QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *ed
myWidget = cb;
break;
}
else if ( gb )
{
myWidget = gb;
break;
}
}

// fall-through
Expand Down Expand Up @@ -560,6 +569,14 @@ QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *ed
case QgsVectorLayer::FileName:
case QgsVectorLayer::Calendar:
{
QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( editor );
if ( cw )
{
myWidget = cw;
break;
}


QPushButton *pb = 0;
QLineEdit *le = qobject_cast<QLineEdit *>( editor );
if ( le )
Expand Down Expand Up @@ -736,14 +753,23 @@ bool QgsAttributeEditor::retrieveValue( QWidget *widget, QgsVectorLayer *vl, int
text = ckb->isChecked() ? states.first : states.second;
}

QGroupBox *gb = qobject_cast<QGroupBox *>( widget );
if ( gb )
{
QPair<QString, QString> states = vl->checkedState( idx );
text = gb->isChecked() ? states.first : states.second;
}

QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( widget );
if ( cw )
{
text = cw->selectedDate().toString();
text = cw->selectedDate().toString( Qt::ISODate );
}

le = widget->findChild<QLineEdit *>();
if ( le )
// QCalendarWidget and QGroupBox have an internal QLineEdit which returns the year
// part of the date so we need to skip this if we have a QCalendarWidget
if ( !cw && !gb && le )
{
text = le->text();
}
Expand Down Expand Up @@ -888,6 +914,14 @@ bool QgsAttributeEditor::setValue( QWidget *editor, QgsVectorLayer *vl, int idx,

case QgsVectorLayer::CheckBox:
{
QGroupBox *gb = qobject_cast<QGroupBox *>( editor );
if ( gb )
{
QPair<QString, QString> states = vl->checkedState( idx );
gb->setChecked( value == states.first );
break;
}

QCheckBox *cb = qobject_cast<QCheckBox *>( editor );
if ( cb )
{
Expand Down Expand Up @@ -941,6 +975,13 @@ bool QgsAttributeEditor::setValue( QWidget *editor, QgsVectorLayer *vl, int idx,
case QgsVectorLayer::FileName:
case QgsVectorLayer::Calendar:
{
QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( editor );
if ( cw )
{
cw->setSelectedDate( value.toDate() );
break;
}

QLineEdit* le = qobject_cast<QLineEdit*>( editor );
if ( !le )
{
Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsfieldvalidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ QValidator::State QgsFieldValidator::validate( QString &s, int &i ) const
}
else
{
QgsDebugMsg( "unsupported type for validation" );
QgsDebugMsg( QString( "unsupported type %1 for validation" ).arg( mField.type() ) );
return Invalid;
}

Expand Down
145 changes: 144 additions & 1 deletion src/gui/qgsmanageconnectionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ void QgsManageConnectionsDialog::doExportImport()
case WCS:
doc = saveOWSConnections( items, "WCS" );
break;
case Oracle:
doc = saveOracleConnections( items );
break;
}

QFile file( mFileName );
Expand Down Expand Up @@ -173,6 +176,9 @@ void QgsManageConnectionsDialog::doExportImport()
case WCS:
loadOWSConnections( doc, items, "WCS" );
break;
case Oracle:
loadOracleConnections( doc, items );
break;
}
// clear connections list and close window
listConnections->clear();
Expand Down Expand Up @@ -205,6 +211,9 @@ bool QgsManageConnectionsDialog::populateConnections()
case MSSQL:
settings.beginGroup( "/MSSQL/connections" );
break;
case Oracle:
settings.beginGroup( "/Oracle/connections" );
break;
}
QStringList keys = settings.childGroups();
QStringList::Iterator it = keys.begin();
Expand Down Expand Up @@ -292,6 +301,14 @@ bool QgsManageConnectionsDialog::populateConnections()
return false;
}
break;
case Oracle:
if ( root.tagName() != "qgsOracleConnections" )
{
QMessageBox::information( this, tr( "Loading connections" ),
tr( "The file is not an Oracle connections exchange file." ) );
return false;
}
break;
}

QDomElement child = root.firstChildElement();
Expand Down Expand Up @@ -446,6 +463,48 @@ QDomDocument QgsManageConnectionsDialog::saveMssqlConnections( const QStringList
return doc;
}

QDomDocument QgsManageConnectionsDialog::saveOracleConnections( const QStringList &connections )
{
QDomDocument doc( "connections" );
QDomElement root = doc.createElement( "qgsOracleConnections" );
root.setAttribute( "version", "1.0" );
doc.appendChild( root );

QSettings settings;
QString path;
for ( int i = 0; i < connections.count(); ++i )
{
path = "/Oracle/connections/" + connections[ i ];
QDomElement el = doc.createElement( "oracle" );
el.setAttribute( "name", connections[ i ] );
el.setAttribute( "host", settings.value( path + "/host", "" ).toString() );
el.setAttribute( "port", settings.value( path + "/port", "" ).toString() );
el.setAttribute( "database", settings.value( path + "/database", "" ).toString() );
el.setAttribute( "estimatedMetadata", settings.value( path + "/estimatedMetadata", "0" ).toString() );
el.setAttribute( "userTablesOnly", settings.value( path + "/userTablesOnly", "0" ).toString() );
el.setAttribute( "geometryColumnsOnly", settings.value( path + "/geometryColumnsOnly", "0" ).toString() );
el.setAttribute( "allowGeometrylessTables", settings.value( path + "/allowGeometrylessTables", "0" ).toString() );

el.setAttribute( "saveUsername", settings.value( path + "/saveUsername", "false" ).toString() );

if ( settings.value( path + "/saveUsername", "false" ).toString() == "true" )
{
el.setAttribute( "username", settings.value( path + "/username", "" ).toString() );
}

el.setAttribute( "savePassword", settings.value( path + "/savePassword", "false" ).toString() );

if ( settings.value( path + "/savePassword", "false" ).toString() == "true" )
{
el.setAttribute( "password", settings.value( path + "/password", "" ).toString() );
}

root.appendChild( el );
}

return doc;
}

void QgsManageConnectionsDialog::loadOWSConnections( const QDomDocument &doc, const QStringList &items, const QString &service )
{
QDomElement root = doc.documentElement();
Expand Down Expand Up @@ -708,7 +767,7 @@ void QgsManageConnectionsDialog::loadMssqlConnections( const QDomDocument &doc,
{
QMessageBox::information( this,
tr( "Loading connections" ),
tr( "The file is not an PostGIS connections exchange file." ) );
tr( "The file is not an MSSQL connections exchange file." ) );
return;
}

Expand Down Expand Up @@ -791,6 +850,90 @@ void QgsManageConnectionsDialog::loadMssqlConnections( const QDomDocument &doc,
}
}

void QgsManageConnectionsDialog::loadOracleConnections( const QDomDocument &doc, const QStringList &items )
{
QDomElement root = doc.documentElement();
if ( root.tagName() != "qgsOracleConnections" )
{
QMessageBox::information( this,
tr( "Loading connections" ),
tr( "The file is not an Oracle connections exchange file." ) );
return;
}

QString connectionName;
QSettings settings;
settings.beginGroup( "/Oracle/connections" );
QStringList keys = settings.childGroups();
settings.endGroup();
QDomElement child = root.firstChildElement();
bool prompt = true;
bool overwrite = true;

while ( !child.isNull() )
{
connectionName = child.attribute( "name" );
if ( !items.contains( connectionName ) )
{
child = child.nextSiblingElement();
continue;
}

// check for duplicates
if ( keys.contains( connectionName ) && prompt )
{
int res = QMessageBox::warning( this,
tr( "Loading connections" ),
tr( "Connection with name '%1' already exists. Overwrite?" )
.arg( connectionName ),
QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
switch ( res )
{
case QMessageBox::Cancel:
return;
case QMessageBox::No:
child = child.nextSiblingElement();
continue;
case QMessageBox::Yes:
overwrite = true;
break;
case QMessageBox::YesToAll:
prompt = false;
overwrite = true;
break;
case QMessageBox::NoToAll:
prompt = false;
overwrite = false;
break;
}
}

if ( keys.contains( connectionName ) && !overwrite )
{
child = child.nextSiblingElement();
continue;
}

//no dups detected or overwrite is allowed
settings.beginGroup( "/Oracle/connections/" + connectionName );

settings.setValue( "/host", child.attribute( "host" ) );
settings.setValue( "/port", child.attribute( "port" ) );
settings.setValue( "/database", child.attribute( "database" ) );
settings.setValue( "/estimatedMetadata", child.attribute( "estimatedMetadata" ) );
settings.setValue( "/userTablesOnly", child.attribute( "userTablesOnly" ) );
settings.setValue( "/geometryColumnsOnly", child.attribute( "geometryColumnsOnly" ) );
settings.setValue( "/allowGeometrylessTables", child.attribute( "allowGeometrylessTables" ) );
settings.setValue( "/saveUsername", child.attribute( "saveUsername" ) );
settings.setValue( "/username", child.attribute( "username" ) );
settings.setValue( "/savePassword", child.attribute( "savePassword" ) );
settings.setValue( "/password", child.attribute( "password" ) );
settings.endGroup();

child = child.nextSiblingElement();
}
}

void QgsManageConnectionsDialog::selectAll()
{
listConnections->selectAll();
Expand Down
7 changes: 6 additions & 1 deletion src/gui/qgsmanageconnectionsdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan
PostGIS,
WFS,
MSSQL,
WCS
WCS,
Oracle,
};

// constructor
Expand All @@ -54,14 +55,18 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan

private:
bool populateConnections();

QDomDocument saveOWSConnections( const QStringList &connections, const QString &service );
QDomDocument saveWFSConnections( const QStringList &connections );
QDomDocument savePgConnections( const QStringList & connections );
QDomDocument saveMssqlConnections( const QStringList & connections );
QDomDocument saveOracleConnections( const QStringList & connections );

void loadOWSConnections( const QDomDocument &doc, const QStringList &items, const QString &service );
void loadWFSConnections( const QDomDocument &doc, const QStringList &items );
void loadPgConnections( const QDomDocument &doc, const QStringList &items );
void loadMssqlConnections( const QDomDocument &doc, const QStringList &items );
void loadOracleConnections( const QDomDocument &doc, const QStringList &items );

QString mFileName;
Mode mDialogMode;
Expand Down
106 changes: 95 additions & 11 deletions src/gui/qgsmessagebar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
#include <QPalette>
#include <QStackedWidget>
#include <QLabel>
#include <QProgressBar>
#include <QToolButton>
#include <QTimer>
#include <QGridLayout>
#include <QMenu>

Expand All @@ -41,11 +43,28 @@ QgsMessageBar::QgsMessageBar( QWidget *parent )
mLayout->setContentsMargins( 9, 1, 9, 1 );
setLayout( mLayout );

mCountProgress = new QProgressBar( this );

mCountProgress->setStyleSheet( "QProgressBar { border: 1px solid rgba(0, 0, 0, 75%);"
" border-radius: 2px; background: rgba(0, 0, 0, 0); }"
"QProgressBar::chunk { background-color: rgba(0, 0, 0, 50%); width: 5px; }" );
mCountProgress->setObjectName( "mCountdown" );
mCountProgress->setToolTip( tr( "Countdown" ) );
mCountProgress->setMinimumWidth( 25 );
mCountProgress->setMaximumWidth( 25 );
mCountProgress->setMinimumHeight( 10 );
mCountProgress->setMaximumHeight( 10 );
mCountProgress->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
mCountProgress->setTextVisible( false );
mCountProgress->setRange( 0, 5 );
mCountProgress->setHidden( true );
mLayout->addWidget( mCountProgress, 0, 0, 1, 1 );

mItemCount = new QLabel( this );
mItemCount->setObjectName( "mItemCount" );
mItemCount->setToolTip( tr( "Remaining messages" ) );
mItemCount->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
mLayout->addWidget( mItemCount, 0, 1, 1, 1 );
mLayout->addWidget( mItemCount, 0, 2, 1, 1 );

mCloseMenu = new QMenu( this );
mCloseMenu->setObjectName( "mCloseMenu" );
Expand All @@ -64,7 +83,11 @@ QgsMessageBar::QgsMessageBar( QWidget *parent )
mCloseBtn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
mCloseBtn->setMenu( mCloseMenu );
connect( mCloseBtn, SIGNAL( clicked() ), this, SLOT( popWidget() ) );
mLayout->addWidget( mCloseBtn, 0, 2, 1, 1 );
mLayout->addWidget( mCloseBtn, 0, 3, 1, 1 );

mCountdownTimer = new QTimer( this );
mCountdownTimer->setInterval( 1000 );
connect( mCountdownTimer, SIGNAL( timeout() ), this, SLOT( updateCountdown() ) );

connect( this, SIGNAL( widgetAdded( QWidget* ) ), this, SLOT( updateItemCount() ) );
connect( this, SIGNAL( widgetRemoved( QWidget* ) ), this, SLOT( updateItemCount() ) );
Expand Down Expand Up @@ -148,6 +171,8 @@ bool QgsMessageBar::popWidget()
if ( !mCurrentItem )
return false;

resetCountdown();

QgsMessageBarItem *item = mCurrentItem;
popItem( item );

Expand Down Expand Up @@ -186,47 +211,57 @@ void QgsMessageBar::pushItem( QgsMessageBarItem *item )
}

mCurrentItem = item;
mLayout->addWidget( item->widget(), 0, 0, 1, 1 );
mLayout->addWidget( item->widget(), 0, 1, 1, 1 );
mCurrentItem->widget()->show();

if ( item->duration() > 0 )
{
mCountProgress->setRange( 0, item->duration() );
mCountProgress->setValue( item->duration() );
mCountProgress->setVisible( true );
mCountdownTimer->start();
}

setStyleSheet( item->styleSheet() );
show();

emit widgetAdded( item->widget() );
}

void QgsMessageBar::pushWidget( QWidget *widget, int level )
void QgsMessageBar::pushWidget( QWidget *widget, MessageLevel level, int duration )
{
resetCountdown();

QString stylesheet;
if ( level >= 2 )
if ( level >= CRITICAL )
{
stylesheet = "QgsMessageBar { background-color: #d65253; border: 1px solid #9b3d3d; } "
"QLabel { color: white; } ";
}
else if ( level == 1 )
else if ( level == WARNING )
{
stylesheet = "QgsMessageBar { background-color: #ffc800; border: 1px solid #e0aa00; } "
"QLabel { color: black; } ";
}
else if ( level <= 0 )
else if ( level <= INFO )
{
stylesheet = "QgsMessageBar { background-color: #e7f5fe; border: 1px solid #b9cfe4; } "
"QLabel { color: #2554a1; } ";
}
stylesheet += "QLabel#mMsgTitle { font-weight: bold; } "
"QLabel#mItemCount { font-style: italic; }";
pushWidget( widget, stylesheet );
pushWidget( widget, stylesheet, duration );
}

void QgsMessageBar::pushWidget( QWidget *widget, const QString &styleSheet )
void QgsMessageBar::pushWidget( QWidget *widget, const QString &styleSheet, int duration )
{
if ( !widget )
return;

// avoid duplicated widget
popWidget( widget );

pushItem( new QgsMessageBarItem( widget, styleSheet ) );
pushItem( new QgsMessageBarItem( widget, styleSheet, duration ) );
}

QWidget* QgsMessageBar::createMessage( const QString &title, const QString &text, const QIcon &icon, QWidget *parent )
Expand All @@ -245,7 +280,12 @@ QWidget* QgsMessageBar::createMessage( const QString &title, const QString &text

if ( !title.isEmpty() )
{
QLabel *lblTitle = new QLabel( title, widget );
// add ':' to end of title
QString t = title.trimmed();
if ( !t.endsWith( ":" ) )
t += ":";

QLabel *lblTitle = new QLabel( t, widget );
lblTitle->setObjectName( "mMsgTitle" );
layout->addWidget( lblTitle );
}
Expand All @@ -259,6 +299,50 @@ QWidget* QgsMessageBar::createMessage( const QString &title, const QString &text
return widget;
}

void QgsMessageBar::pushMessage( const QString &title, const QString &text, MessageLevel level, int duration )
{
QString msgIcon( "/mIconInfo.png" );
switch ( level )
{
case QgsMessageBar::CRITICAL:
msgIcon = QString( "/mIconCritical.png" );
break;
case QgsMessageBar::WARNING:
msgIcon = QString( "/mIconWarn.png" );
break;
default:
break;
}

QWidget *msg = QgsMessageBar::createMessage( title, text, QgsApplication::getThemeIcon( msgIcon ), this );
pushWidget( msg, level, duration );
}

void QgsMessageBar::updateCountdown()
{
if ( !mCountdownTimer->isActive() )
{
resetCountdown();
return;
}
if ( mCountProgress->value() < 2 )
{
popWidget();
}
else
{
mCountProgress->setValue( mCountProgress->value() - 1 );
}
}

void QgsMessageBar::resetCountdown()
{
if ( mCountdownTimer->isActive() )
mCountdownTimer->stop();

mCountProgress->setVisible( false );
}

void QgsMessageBar::updateItemCount()
{
mItemCount->setText( mList.count() > 0 ? QString::number( mList.count() ) + QString( " " ) + tr( "more" ) : QString( "" ) );
Expand Down
34 changes: 28 additions & 6 deletions src/gui/qgsmessagebar.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
class QWidget;
class QGridLayout;
class QMenu;
class QProgressBar;
class QToolButton;
class QLabel;
class QAction;
class QTimer;

/** \ingroup gui
* A bar for displaying non-blocking messages to the user.
Expand All @@ -41,15 +43,23 @@ class GUI_EXPORT QgsMessageBar: public QFrame
Q_OBJECT

public:
enum MessageLevel
{
INFO = 0,
WARNING = 1,
CRITICAL = 2
};

QgsMessageBar( QWidget *parent = 0 );
~QgsMessageBar();

/*! display a widget on the bar after hiding the currently visible one
* and putting it in a stack
* @param widget widget to add
* @param level is 0 for information, 1 for warning, 2 for critical
* @param level is QgsMessageBar::INFO, WARNING or CRITICAL
* @param duration timeout duration of message in seconds, 0 value indicates no timeout
*/
void pushWidget( QWidget *widget, int level = 0 );
void pushWidget( QWidget *widget, MessageLevel level = INFO, int duration = 0 );

/*! remove the passed widget from the bar (if previously added),
* then display the next one in the stack if any or hide the bar
Expand All @@ -67,6 +77,11 @@ class GUI_EXPORT QgsMessageBar: public QFrame
//! make out a widget containing icon, title and message to be displayed on the bar
static QWidget* createMessage( const QString &title, const QString &text, const QIcon &icon, QWidget *parent = 0 );

//! convenience method for pushing a non-widget-based message to the bar
void pushMessage( const QString &text, MessageLevel level = INFO, int duration = 0 ) { pushMessage( QString::null, text, level, duration ); }
//! convenience method for pushing a non-widget-based message with title to the bar
void pushMessage( const QString &title, const QString &text, MessageLevel level = INFO, int duration = 0 );

signals:
//! emitted when a message widget is added to the bar
void widgetAdded( QWidget *widget );
Expand All @@ -90,20 +105,21 @@ class GUI_EXPORT QgsMessageBar: public QFrame
class QgsMessageBarItem
{
public:
QgsMessageBarItem( QWidget *widget, const QString &styleSheet ):
mWidget( widget ), mStyleSheet( styleSheet ) {}
QgsMessageBarItem( QWidget *widget, const QString &styleSheet, int duration = 0 ):
mWidget( widget ), mStyleSheet( styleSheet ), mDuration( duration ) {}
~QgsMessageBarItem() {}

QWidget* widget() const { return mWidget; }
QString styleSheet() const { return mStyleSheet; }
int duration() const { return mDuration; }

private:
QWidget *mWidget;
QString mStyleSheet;
int mDuration; // 0 value indicates no timeout duration
};

//! display a widget on the bar
void pushWidget( QWidget *widget, const QString &styleSheet );
void pushWidget( QWidget *widget, const QString &styleSheet, int duration = 0 );

void popItem( QgsMessageBarItem *item );
void pushItem( QgsMessageBarItem *item );
Expand All @@ -115,10 +131,16 @@ class GUI_EXPORT QgsMessageBar: public QFrame
QGridLayout *mLayout;
QLabel *mItemCount;
QAction *mActionCloseAll;
QTimer *mCountdownTimer;
QProgressBar *mCountProgress;

private slots:
//! updates count of items in widget list
void updateItemCount();

//! updates the countdown for widgets that have a timeout duration
void updateCountdown();
void resetCountdown();
};

#endif
2 changes: 1 addition & 1 deletion src/plugins/grass/qgsgrassmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ QgsGrassModuleStandardOptions::QgsGrassModuleStandardOptions(
bool ok = false;
QDomDocument gDoc( "task" );
QString err;
int line, column;
int line = -1, column = -1;

if ( codec )
{
Expand Down
1 change: 0 additions & 1 deletion src/plugins/grass/qgsgrassmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ class QgsGrassModule: public QDialog, private Ui::QgsGrassModuleBase
Description(): direct( true ) {}
Description( QString lab, bool dir = false ): label( lab ), direct( dir ) { }
Description( const Description & desc ) { label = desc.label; direct = desc.direct; }
Description( Description & desc ) { label = desc.label; direct = desc.direct; }
};

//! Constructor
Expand Down
4 changes: 4 additions & 0 deletions src/providers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ ADD_SUBDIRECTORY(wcs)
ADD_SUBDIRECTORY(gpx)
ADD_SUBDIRECTORY(wfs)

IF (WITH_ORACLE)
ADD_SUBDIRECTORY(oracle)
ENDIF(WITH_ORACLE)

IF (POSTGRES_FOUND)
ADD_SUBDIRECTORY(postgres)
ENDIF (POSTGRES_FOUND)
Expand Down
1 change: 0 additions & 1 deletion src/providers/mssql/qgsmssqlsourceselect.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class QPushButton;
class QStringList;
class QgsGeomColumnTypeThread;
class QgisApp;
class QgsPgSourceSelect;

class QgsMssqlSourceSelectDelegate : public QItemDelegate
{
Expand Down
54 changes: 54 additions & 0 deletions src/providers/oracle/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
########################################################
# Files

ADD_SUBDIRECTORY(ocispatial)

SET(ORACLE_SRCS
qgsoracleprovider.cpp
qgsoracleconn.cpp
qgsoracledataitems.cpp
qgsoraclesourceselect.cpp
qgsoraclenewconnection.cpp
qgsoracletablemodel.cpp
qgsoraclecolumntypethread.cpp
)

SET(ORACLE_MOC_HDRS
qgsoracleprovider.h
qgsoracleconn.h
qgsoracledataitems.h
qgsoraclesourceselect.h
qgsoraclenewconnection.h
qgsoracletablemodel.h
qgsoraclecolumntypethread.h
)


########################################################
# Build

QT4_WRAP_CPP(ORACLE_MOC_SRCS ${ORACLE_MOC_HDRS})

INCLUDE_DIRECTORIES(
../../core
../../gui
${GEOS_INCLUDE_DIR}
${CMAKE_CURRENT_BINARY_DIR}/../../ui
${QT_QTSQL_INCLUDEDIR}
)

ADD_LIBRARY (oracleprovider MODULE ${ORACLE_SRCS} ${ORACLE_MOC_SRCS})

TARGET_LINK_LIBRARIES (oracleprovider
qgis_core
qgis_gui
${QT_QTSQL_LIBRARY}
)


########################################################
# Install

INSTALL(TARGETS oracleprovider
RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})
32 changes: 32 additions & 0 deletions src/providers/oracle/ocispatial/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/${QGIS_PLUGIN_SUBDIR}/sqldrivers)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/${QGIS_PLUGIN_SUBDIR}/sqldrivers)

FIND_PACKAGE(OCI)

ADD_DEFINITIONS(${QT_DEFINITIONS})
ADD_DEFINITIONS(-DQT_PLUGIN)
ADD_DEFINITIONS(-DQT_NO_DEBUG)
ADD_DEFINITIONS(-DQT_SHARED)

INCLUDE_DIRECTORIES(${OCI_INCLUDE_DIR})

SET(QSQLOCISPATIAL_SRC qsql_ocispatial.cpp main.cpp)
QT4_WRAP_CPP(QSQLOCISPATIAL_SRC qsql_ocispatial.h)

ADD_LIBRARY(qsqlocispatial SHARED ${QSQLOCISPATIAL_SRC})

TARGET_LINK_LIBRARIES(qsqlocispatial
${QT_QTCORE_LIBRARY}
${QT_QTSQL_LIBRARY}
${OCI_LIBRARY}
)

IF(MSVC)
TARGET_LINK_LIBRARIES(qsqlocispatial wsock32)
ENDIF(MSVC)

INSTALL(TARGETS qsqlocispatial
RUNTIME DESTINATION ${QT_PLUGINS_DIR}/sqldrivers
LIBRARY DESTINATION ${QT_PLUGINS_DIR}/sqldrivers
)
7 changes: 7 additions & 0 deletions src/providers/oracle/ocispatial/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
QOCISPATIAL driver derived from QOCI driver.

You will need the Oracle development headers and libraries installed
before compiling this plugin.

See the Qt SQL documentation for more information on compiling Qt SQL
driver plugins (sql-driver.html).
45 changes: 45 additions & 0 deletions src/providers/oracle/ocispatial/cmake/FindOCI.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# ~~~~~~~~~~
# Copyright (c) 2012, Juergen E. Fischer <jef at norbit dot de>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
# CMake module to search for OCI library
#
# If it's found it sets OCI_FOUND to TRUE
# and following variables are set:
# OCI_INCLUDE_DIR
# OCI_LIBRARY

FIND_PATH(OCI_INCLUDE_DIR oci.h
PATHS
/usr/include/oracle/11.2/client64
$ENV{OSGEO4W_ROOT}/include
$ENV{ORACLE_HOME}/rdbms/public
)

FIND_LIBRARY(OCI_LIBRARY clntsh oci
PATHS
/usr/lib/oracle/11.2/client64/lib/
$ENV{OSGEO4W_ROOT}/lib
$ENV{ORACLE_HOME}/lib
)

IF (OCI_INCLUDE_DIR)
SET(OCI_FOUND TRUE)
ELSE (OCI_INCLUDE_DIR)
SET(OCI_FOUND FALSE)
ENDIF(OCI_INCLUDE_DIR)

IF (OCI_FOUND)
IF (NOT OCI_FIND_QUIETLY)
MESSAGE(STATUS "Found OCI: ${OCI_LIBRARY}")
ENDIF (NOT OCI_FIND_QUIETLY)
ELSE (OCI_FOUND)
IF (OCI_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find OCI")
ELSE (OCI_FIND_REQUIRED)
IF (NOT OCI_FIND_QUIETLY)
MESSAGE(STATUS "Could not find OCI")
ENDIF (NOT OCI_FIND_QUIETLY)
ENDIF (OCI_FIND_REQUIRED)
ENDIF (OCI_FOUND)
85 changes: 85 additions & 0 deletions src/providers/oracle/ocispatial/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
** Oracle Spatial Support: (C) 2012-2013 Juergen E. Fischer < jef at norbit dot de >, norBIT GmbH
**
****************************************************************************/

#include <qsqldriverplugin.h>
#include <qstringlist.h>
#include "qsql_ocispatial.h"

QT_BEGIN_NAMESPACE

class QOCISpatialDriverPlugin : public QSqlDriverPlugin
{
public:
QOCISpatialDriverPlugin();

QSqlDriver* create( const QString & );
QStringList keys() const;
};

QOCISpatialDriverPlugin::QOCISpatialDriverPlugin()
: QSqlDriverPlugin()
{
}

QSqlDriver* QOCISpatialDriverPlugin::create( const QString &name )
{
if ( name == QLatin1String( "QOCISPATIAL" ) || name == QLatin1String( "QOCISPATIAL8" ) )
{
QOCISpatialDriver* driver = new QOCISpatialDriver();
return driver;
}
return 0;
}

QStringList QOCISpatialDriverPlugin::keys() const
{
QStringList l;
l.append( QLatin1String( "QOCISPATIAL8" ) );
l.append( QLatin1String( "QOCISPATIAL" ) );
return l;
}

Q_EXPORT_STATIC_PLUGIN( QOCISpatialDriverPlugin )
Q_EXPORT_PLUGIN2( qsqloci, QOCISpatialDriverPlugin )

QT_END_NAMESPACE
3,983 changes: 3,983 additions & 0 deletions src/providers/oracle/ocispatial/qsql_ocispatial.cpp

Large diffs are not rendered by default.

130 changes: 130 additions & 0 deletions src/providers/oracle/ocispatial/qsql_ocispatial.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSql module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef QSQL_OCISPATIAL_H
#define QSQL_OCISPATIAL_H

#include <QtSql/qsqlresult.h>
#include <QtSql/qsqldriver.h>
#include "qsqlcachedresult_p.h"

#ifdef QT_PLUGIN
#define Q_EXPORT_SQLDRIVER_OCISPATIAL
#else
#define Q_EXPORT_SQLDRIVER_OCISPATIAL Q_SQL_EXPORT
#endif

QT_BEGIN_HEADER

typedef struct OCIEnv OCIEnv;
typedef struct OCISvcCtx OCISvcCtx;

QT_BEGIN_NAMESPACE

class QOCISpatialDriver;
class QOCISpatialCols;
struct QOCISpatialDriverPrivate;
struct QOCISpatialResultPrivate;

class Q_EXPORT_SQLDRIVER_OCISPATIAL QOCISpatialResult : public QSqlCachedResult
{
friend class QOCISpatialDriver;
friend struct QOCISpatialResultPrivate;
friend class QOCISpatialCols;
public:
QOCISpatialResult( const QOCISpatialDriver * db, const QOCISpatialDriverPrivate* p );
~QOCISpatialResult();
bool prepare( const QString& query );
bool exec();
QVariant handle() const;

protected:
bool gotoNext( ValueCache &values, int index );
bool reset( const QString& query );
int size();
int numRowsAffected();
QSqlRecord record() const;
QVariant lastInsertId() const;
void virtual_hook( int id, void *data );

private:
QOCISpatialResultPrivate *d;
};

class Q_EXPORT_SQLDRIVER_OCISPATIAL QOCISpatialDriver : public QSqlDriver
{
Q_OBJECT
friend struct QOCISpatialResultPrivate;
friend class QOCISpatialPrivate;
public:
explicit QOCISpatialDriver( QObject* parent = 0 );
QOCISpatialDriver( OCIEnv* env, OCISvcCtx* ctx, QObject* parent = 0 );
~QOCISpatialDriver();
bool hasFeature( DriverFeature f ) const;
bool open( const QString & db,
const QString & user,
const QString & password,
const QString & host,
int port,
const QString& connOpts );
void close();
QSqlResult *createResult() const;
QStringList tables( QSql::TableType ) const;
QSqlRecord record( const QString& tablename ) const;
QSqlIndex primaryIndex( const QString& tablename ) const;
QString formatValue( const QSqlField &field,
bool trimStrings ) const;
QVariant handle() const;
QString escapeIdentifier( const QString &identifier, IdentifierType ) const;

protected:
bool beginTransaction();
bool commitTransaction();
bool rollbackTransaction();
private:
QOCISpatialDriverPrivate *d;
};

QT_END_NAMESPACE

QT_END_HEADER

#endif // QSQL_OCISPATIAL_H
100 changes: 100 additions & 0 deletions src/providers/oracle/ocispatial/qsqlcachedresult_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSql module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef QSQLCACHEDRESULT_P_H
#define QSQLCACHEDRESULT_P_H

//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include "QtSql/qsqlresult.h"

QT_BEGIN_NAMESPACE

class QVariant;
template <typename T> class QVector;

class QSqlCachedResultPrivate;

class Q_SQL_EXPORT QSqlCachedResult: public QSqlResult
{
public:
virtual ~QSqlCachedResult();

typedef QVector<QVariant> ValueCache;

protected:
QSqlCachedResult( const QSqlDriver * db );

void init( int colCount );
void cleanup();
void clearValues();

virtual bool gotoNext( ValueCache &values, int index ) = 0;

QVariant data( int i );
bool isNull( int i );
bool fetch( int i );
bool fetchNext();
bool fetchPrevious();
bool fetchFirst();
bool fetchLast();

int colCount() const;
ValueCache &cache();

void virtual_hook( int id, void *data );
private:
bool cacheNext();
QSqlCachedResultPrivate *d;
};

QT_END_NAMESPACE

#endif // QSQLCACHEDRESULT_P_H
66 changes: 66 additions & 0 deletions src/providers/oracle/ocispatial/wkbptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/***************************************************************************
wkbptr.h
---------------------
begin : Dezember 2012
copyright : (C) 2012 by Juergen E. Fischer
email : jef at norbit dot de
***************************************************************************
* *
* This file may be used under the terms of the GNU Lesser *
* General Public License version 2.1 as published by the Free Software *
* Foundation and appearing in the file LICENSE.LGPL included in the *
* packaging of this file. Please review the following information to *
* ensure the GNU Lesser General Public License version 2.1 requirements *
* will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. *
* *
***************************************************************************/
#ifndef WKBPTR_H
#define WKBPTR_H

#include <QSharedData>

union wkbPtr
{
void *vPtr;
double *dPtr;
int *iPtr;
unsigned char *ucPtr;
char *cPtr;

};

const int SDO_ARRAY_SIZE = 1024;

#define SDO_GTYPE_D(g) (g/1000%10)
#define SDO_GTYPE_L(g) (g/100%10)
#define SDO_GTYPE_TT(g) (g%100)
#define SDO_GTYPE(g,tt) (g*1000+tt)

enum SDO_GTYPE_TT
{
gtUnknown = 0,
gtPoint = 1,
gtLine = 2,
gtPolygon = 3,
gtCollection = 4,
gtMultiPoint = 5,
gtMultiLine = 6,
gtMultiPolygon = 7,
};


class QOCISpatialGeometry : public QSharedData
{
public:
bool isNull;
int gtype;
int srid;
double x, y, z;

QVector<int> eleminfo;
QVector<double> ordinates;
};

Q_DECLARE_METATYPE( QOCISpatialGeometry );

#endif // WKBPTR_H
66 changes: 66 additions & 0 deletions src/providers/oracle/qgsoraclecolumntypethread.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/***************************************************************************
qgscolumntypethread.cpp - lookup oracle geometry type and srid in a thread
-------------------
begin : 3.1.2012
copyright : (C) 2012 by Juergen E. Fischer
email : jef at norbit dot de
***************************************************************************/

/***************************************************************************
* *
* 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 "qgsoraclecolumntypethread.h"

#include <QMetaType>

QgsOracleColumnTypeThread::QgsOracleColumnTypeThread( QgsOracleConn *conn, bool useEstimatedMetaData )
: QThread()
, mConn( conn )
, mUseEstimatedMetadata( useEstimatedMetaData )
{
qRegisterMetaType<QgsOracleLayerProperty>( "QgsOracleLayerProperty" );
}

void QgsOracleColumnTypeThread::addGeometryColumn( QgsOracleLayerProperty layerProperty )
{
layerProperties << layerProperty;
}

void QgsOracleColumnTypeThread::stop()
{
mStopped = true;
}

void QgsOracleColumnTypeThread::run()
{
if ( !mConn )
return;

mStopped = false;

foreach ( QgsOracleLayerProperty layerProperty, layerProperties )
{
if ( !mStopped )
{
mConn->retrieveLayerTypes( layerProperty, mUseEstimatedMetadata );
}

if ( mStopped )
{
layerProperty.types.clear();
layerProperty.srids.clear();
}

// Now tell the layer list dialog box...
emit setLayerType( layerProperty );
}

mConn->disconnect();
mConn = 0;
}
Loading