Skip to content

Commit

Permalink
copy/paste as test unit
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Sep 5, 2013
1 parent fa66803 commit 250df51
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 19 deletions.
3 changes: 3 additions & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -456,6 +456,9 @@ ELSE (ANDROID)
ADD_EXECUTABLE(${QGIS_APP_NAME} MACOSX_BUNDLE WIN32 ${QGIS_APP_SRCS} ${QGIS_APP_MOC_SRCS} ${IMAGE_RCC_SRCS} ${TEST_RCC_SRCS})
ENDIF (ANDROID)

# shared library used by tests - TODO: use it also for qgis executable?
ADD_LIBRARY(qgis_app SHARED ${QGIS_APP_SRCS} ${QGIS_APP_MOC_SRCS} ${QGIS_APP_HDRS} ${QGIS_APP_MOC_HDRS} ${IMAGE_RCC_SRCS})

TARGET_LINK_LIBRARIES(${QGIS_APP_NAME}
${QWT_LIBRARY}
${QT_QTSQL_LIBRARY}
Expand Down
69 changes: 53 additions & 16 deletions src/app/qgisapp.cpp
Expand Up @@ -738,7 +738,24 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,

} // QgisApp ctor


QgisApp::QgisApp( )
: QMainWindow( 0, 0 )
, mOverviewMapCursor( 0 )
, mQgisInterface( 0 )
, mInternalClipboard( 0 )
, mpMaptip( 0 )
, mPythonUtils( 0 )
, mpGpsWidget( 0 )
{
smInstance = this;
setupUi( this );
mInternalClipboard = new QgsClipboard;
mMapCanvas = new QgsMapCanvas();
mMapCanvas->freeze();
mMapLegend = new QgsLegend( mMapCanvas );
mUndoWidget = new QgsUndoWidget( NULL, mMapCanvas );
// More tests may need more members to be initialized
}

QgisApp::~QgisApp()
{
Expand Down Expand Up @@ -5564,24 +5581,29 @@ void QgisApp::pasteAsNewVector()
delete layer;
}

void QgisApp::pasteAsNewMemoryVector()
QgsVectorLayer * QgisApp::pasteAsNewMemoryVector( const QString & theLayerName )
{
if ( mMapCanvas && mMapCanvas->isDrawing() ) return;
if ( mMapCanvas && mMapCanvas->isDrawing() ) return 0;

bool ok;
QString defaultName = tr( "Pasted" );
QString layerName = QInputDialog::getText( this, tr( "New memory layer name" ),
tr( "Layer name" ), QLineEdit::Normal,
defaultName, &ok );
if ( !ok ) return;
QString layerName = theLayerName;

if ( layerName.isEmpty() )
{
layerName = defaultName;
bool ok;
QString defaultName = tr( "Pasted" );
layerName = QInputDialog::getText( this, tr( "New memory layer name" ),
tr( "Layer name" ), QLineEdit::Normal,
defaultName, &ok );
if ( !ok ) return 0;

if ( layerName.isEmpty() )
{
layerName = defaultName;
}
}

QgsVectorLayer * layer = pasteToNewMemoryVector();
if ( !layer ) return;
if ( !layer ) return 0;

layer->setLayerName( layerName );

Expand All @@ -5593,6 +5615,8 @@ void QgisApp::pasteAsNewMemoryVector()
mMapCanvas->refresh();

qApp->processEvents();

return layer;
}

QgsVectorLayer * QgisApp::pasteToNewMemoryVector()
Expand Down Expand Up @@ -5634,6 +5658,8 @@ QgsVectorLayer * QgisApp::pasteToNewMemoryVector()

QString typeName = QString( QGis::featureType( wkbType ) ).replace( "WKB", "" );

QgsDebugMsg( QString( "output wkbType = %1 typeName = %2" ).arg( wkbType ).arg( typeName ) );

QString message;

if ( features.size() == 0 )
Expand Down Expand Up @@ -5668,7 +5694,14 @@ QgsVectorLayer * QgisApp::pasteToNewMemoryVector()

foreach ( QgsField f, clipboard()->fields().toList() )
{
layer->addAttribute( f );
if ( !layer->addAttribute( f ) )
{
QMessageBox::warning( this, tr( "Warning" ),
tr( "Cannot create field %1 (%2,%3)" ).arg( f.name() ).arg( f.typeName() ).arg( QVariant::typeToName( f.type() ) ),
QMessageBox::Ok );
delete layer;
return 0;
}
}

// Convert to multi if necessary
Expand All @@ -5679,8 +5712,6 @@ QgsVectorLayer * QgisApp::pasteToNewMemoryVector()
QGis::WkbType type = QGis::flatType( feature.geometry()->wkbType() );
if ( type == QGis::WKBUnknown || type == QGis::WKBNoGeometry ) continue;

QgsDebugMsg( QString( "type = %1" ).arg( type ) );

if ( QGis::singleType( wkbType ) != QGis::singleType( type ) )
{
feature.setGeometry( 0 );
Expand All @@ -5691,9 +5722,15 @@ QgsVectorLayer * QgisApp::pasteToNewMemoryVector()
feature.geometry()->convertToMultiType();
}
}
layer->addFeatures( features );
layer->commitChanges();
if ( ! layer->addFeatures( features ) || ! layer->commitChanges() )
{
QgsDebugMsg( "Cannot add features or commit changes" );
delete layer;
return 0;
}
layer->removeSelection();

QgsDebugMsg( QString( "%1 features pasted to memory layer" ).arg( layer->featureCount() ) );
return layer;
}

Expand Down
4 changes: 3 additions & 1 deletion src/app/qgisapp.h
Expand Up @@ -109,6 +109,8 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
public:
//! Constructor
QgisApp( QSplashScreen *splash, bool restorePlugins = true, QWidget * parent = 0, Qt::WFlags fl = Qt::Window );
//! Constructor for unit tests
QgisApp( );
//! Destructor
~QgisApp();
/**
Expand Down Expand Up @@ -538,7 +540,7 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
//! copies features on the clipboard to a new vector layer
void pasteAsNewVector();
//! copies features on the clipboard to a new memory vector layer
void pasteAsNewMemoryVector();
QgsVectorLayer * pasteAsNewMemoryVector( const QString & theLayerName = QString() );
//! copies style of the active layer to the clipboard
/**
\param sourceLayer The layer where the style will be taken from
Expand Down
4 changes: 4 additions & 0 deletions src/core/qgsvectordataprovider.cpp
Expand Up @@ -245,16 +245,20 @@ const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeT
bool QgsVectorDataProvider::supportedType( const QgsField &field ) const
{
int i;
QgsDebugMsgLevel( QString( "field name = %1 type = %2 length = %3 precision = %4" ).arg( field.name() ).arg( QVariant::typeToName( field.type() ) ).arg( field.length() ).arg( field.precision() ), 2 );
for ( i = 0; i < mNativeTypes.size(); i++ )
{
QgsDebugMsgLevel( QString( "native field type = %1 min length = %2 max length = %3 min precision = %4 max precision = %5" ).arg( QVariant::typeToName( mNativeTypes[i].mType ) ).arg( mNativeTypes[i].mMinLen ).arg( mNativeTypes[i].mMaxLen ).arg( mNativeTypes[i].mMinPrec ).arg( mNativeTypes[i].mMaxPrec ), 2 );
if ( field.type() == mNativeTypes[i].mType &&
field.length() >= mNativeTypes[i].mMinLen && field.length() <= mNativeTypes[i].mMaxLen &&
field.precision() >= mNativeTypes[i].mMinPrec && field.precision() <= mNativeTypes[i].mMaxPrec )
{
QgsDebugMsg( "native type matches" );
return true;
}
}

QgsDebugMsg( "no sufficient native type found" );
return false;
}

Expand Down
10 changes: 8 additions & 2 deletions src/providers/memory/qgsmemoryprovider.cpp
Expand Up @@ -73,7 +73,13 @@ QgsMemoryProvider::QgsMemoryProvider( QString uri )

mNativeTypes
<< QgsVectorDataProvider::NativeType( tr( "Whole number (integer)" ), "integer", QVariant::Int, 0, 10 )
<< QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), "double", QVariant::Double, 0, 20, 0, 5 )
// Decimal number from OGR/Shapefile/dbf may come with length up to 32 and
// precision up to length-2 = 30 (default, if width is not specified in dbf is length = 24 precision = 15)
// We know that double (QVariant::Double) has only 15-16 significant numbers,
// but setting that correct limits would disable the use of memory provider with
// data from Shapefiles. In any case, the data are handled as doubles.
// So the limits set here are not correct but enable use of data from Shapefiles.
<< QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), "double", QVariant::Double, 0, 32, 0, 30 )
<< QgsVectorDataProvider::NativeType( tr( "Text (string)" ), "string", QVariant::String, 0, 255 )
;

Expand Down Expand Up @@ -309,6 +315,7 @@ bool QgsMemoryProvider::addAttributes( const QList<QgsField> &attributes )
{
for ( QList<QgsField>::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
{
// Why are attributes restricted to int,double and string only?
switch ( it->type() )
{
case QVariant::Int:
Expand All @@ -319,7 +326,6 @@ bool QgsMemoryProvider::addAttributes( const QList<QgsField> &attributes )
QgsDebugMsg( "Field type not supported: " + it->typeName() );
continue;
}

// add new field as a last one
mFields.append( *it );

Expand Down
1 change: 1 addition & 0 deletions tests/src/CMakeLists.txt
Expand Up @@ -3,6 +3,7 @@ IF (ENABLE_TESTS)
ADD_SUBDIRECTORY(gui)
ADD_SUBDIRECTORY(analysis)
ADD_SUBDIRECTORY(providers)
ADD_SUBDIRECTORY(app)
IF (WITH_BINDINGS)
ADD_SUBDIRECTORY(python)
ENDIF (WITH_BINDINGS)
Expand Down
86 changes: 86 additions & 0 deletions tests/src/app/CMakeLists.txt
@@ -0,0 +1,86 @@
#####################################################
# Don't forget to include output directory, otherwise
# the UI file won't be wrapped!
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/core/composer
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/symbology-ng
${CMAKE_BINARY_DIR}/src/ui
${CMAKE_SOURCE_DIR}/src/gui
${CMAKE_SOURCE_DIR}/src/python
${CMAKE_SOURCE_DIR}/src/app
${CMAKE_SOURCE_DIR}/src/app/pluginmanager
${QT_INCLUDE_DIR}
${GDAL_INCLUDE_DIR}
${PROJ_INCLUDE_DIR}
${GEOS_INCLUDE_DIR}
)

#############################################################
# Compiler defines

# This define is used for tests that need to locate the test
# data under tests/testdata in the qgis source tree.
# the TEST_DATA_DIR variable is set in the top level CMakeLists.txt
ADD_DEFINITIONS(-DTEST_DATA_DIR="\\"${TEST_DATA_DIR}\\"")

ADD_DEFINITIONS(-DINSTALL_PREFIX="\\"${CMAKE_INSTALL_PREFIX}\\"")
#############################################################
# libraries

# because of htonl
IF (WIN32)
SET(PLATFORM_LIBRARIES wsock32)
ENDIF (WIN32)

# Since the tests are not actually installed, but rather
# run directly from the build/src/tests dir we need to
# ensure the qgis libs can be found.
IF (APPLE)
# For Mac OS X, the executable must be at the root of the bundle's executable folder
# SET (CMAKE_INSTALL_NAME_DIR @executable_path/../../../src/core)
ENDIF (APPLE)

#note for tests we should not include the moc of our
#qtests in the executable file list as the moc is
#directly included in the sources
#and should not be compiled twice. Trying to include
#them in will cause an error at build time

#No relinking and full RPATH for the install tree
#See: http://www.cmake.org/Wiki/CMake_RPATH_handling#No_relinking_and_full_RPATH_for_the_install_tree

MACRO (ADD_QGIS_TEST testname testsrc)
SET(qgis_${testname}_SRCS ${testsrc} ${util_SRCS})
SET(qgis_${testname}_MOC_CPPS ${testsrc})
QT4_WRAP_CPP(qgis_${testname}_MOC_SRCS ${qgis_${testname}_MOC_CPPS})
ADD_CUSTOM_TARGET(qgis_${testname}moc ALL DEPENDS ${qgis_${testname}_MOC_SRCS})
ADD_EXECUTABLE(qgis_${testname} ${qgis_${testname}_SRCS})
ADD_DEPENDENCIES(qgis_${testname} qgis_${testname}moc)
TARGET_LINK_LIBRARIES(qgis_${testname}
${QT_QTXML_LIBRARY}
${QT_QTCORE_LIBRARY}
${QT_QTSQL_LIBRARY}
${QT_QTSVG_LIBRARY}
${QT_QTTEST_LIBRARY}
${PROJ_LIBRARY}
${GEOS_LIBRARY}
${GDAL_LIBRARY}
${QWT_LIBRARY}
${QWTPOLAR_LIBRARY}
qgis_core
qgis_gui
qgis_analysis
qgis_app)
ADD_TEST(qgis_${testname} ${CMAKE_CURRENT_BINARY_DIR}/../../../output/bin/qgis_${testname})
#SET_TARGET_PROPERTIES(qgis_${testname} PROPERTIES
# INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${QGIS_LIB_DIR}
# INSTALL_RPATH_USE_LINK_PATH true )
ENDMACRO (ADD_QGIS_TEST)

#############################################################
# Tests:

ADD_QGIS_TEST(qgisappclippboard testqgisappclipboard.cpp)

0 comments on commit 250df51

Please sign in to comment.