232 changes: 225 additions & 7 deletions src/app/qgsoptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
#include <QSettings>
#include <QColorDialog>
#include <QLocale>
#include <QProcess>
#include <QToolBar>
#include <QScrollBar>
#include <QSize>
#include <QStyleFactory>
#include <QMessageBox>
Expand Down Expand Up @@ -68,6 +70,8 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
{
setupUi( this );

connect( mOptionsSplitter, SIGNAL( splitterMoved( int, int ) ), this, SLOT( updateVerticalTabs() ) );

connect( cmbTheme, SIGNAL( activated( const QString& ) ), this, SLOT( themeChanged( const QString& ) ) );
connect( cmbTheme, SIGNAL( highlighted( const QString& ) ), this, SLOT( themeChanged( const QString& ) ) );
connect( cmbTheme, SIGNAL( textChanged( const QString& ) ), this, SLOT( themeChanged( const QString& ) ) );
Expand Down Expand Up @@ -110,6 +114,97 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
spinBoxIdentifyValue->setMinimum( 0.01 );
spinBoxIdentifyValue->setValue( identifyValue );

// custom environment variables
bool useCustomVars = settings.value( "qgis/customEnvVarsUse", QVariant( false ) ).toBool();
mCustomVariablesChkBx->setChecked( useCustomVars );
if ( !useCustomVars )
{
mAddCustomVarBtn->setEnabled( false );
mRemoveCustomVarBtn->setEnabled( false );
mCustomVariablesTable->setEnabled( false );
}
QStringList customVarsList = settings.value( "qgis/customEnvVars", "" ).toStringList();
foreach ( const QString &varStr, customVarsList )
{
int pos = varStr.indexOf( QLatin1Char( '|' ) );
if ( pos == -1 )
continue;
QString varStrApply = varStr.left( pos );
QString varStrNameValue = varStr.mid( pos + 1 );
pos = varStrNameValue.indexOf( QLatin1Char( '=' ) );
if ( pos == -1 )
continue;
QString varStrName = varStrNameValue.left( pos );
QString varStrValue = varStrNameValue.mid( pos + 1 );

addCustomEnvVarRow( varStrName, varStrValue, varStrApply );
}
QFontMetrics fmCustomVar( mCustomVariablesTable->horizontalHeader()->font() );
int fmCustomVarH = fmCustomVar.height() + 2;
mCustomVariablesTable->horizontalHeader()->setFixedHeight( fmCustomVarH );

mCustomVariablesTable->setColumnWidth( 0, 120 );
if ( mCustomVariablesTable->rowCount() > 0 )
{
mCustomVariablesTable->resizeColumnToContents( 1 );
}
else
{
mCustomVariablesTable->setColumnWidth( 1, 120 );
}

// current environment variables
mCurrentVariablesTable->horizontalHeader()->setFixedHeight( fmCustomVarH );
QMap<QString, QString> sysVarsMap = QgsApplication::systemEnvVars();
QStringList currentVarsList = QProcess::systemEnvironment();

foreach ( const QString &varStr, currentVarsList )
{
int pos = varStr.indexOf( QLatin1Char( '=' ) );
if ( pos == -1 )
continue;
QStringList varStrItms;
QString varStrName = varStr.left( pos );
QString varStrValue = varStr.mid( pos + 1 );
varStrItms << varStrName << varStrValue;

// check if different than system variable
QString sysVarVal = QString( "" );
bool sysVarMissing = !sysVarsMap.contains( varStrName );
if ( sysVarMissing )
sysVarVal = tr( "not present" );

if ( !sysVarMissing && sysVarsMap.value( varStrName ) != varStrValue )
sysVarVal = sysVarsMap.value( varStrName );

if ( !sysVarVal.isEmpty() )
sysVarVal = tr( "System value: %1" ).arg( sysVarVal );

int rowCnt = mCurrentVariablesTable->rowCount();
mCurrentVariablesTable->insertRow( rowCnt );

QFont fItm;
for ( int i = 0; i < varStrItms.size(); ++i )
{
QTableWidgetItem* varNameItm = new QTableWidgetItem( varStrItms.at( i ) );
varNameItm->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable
| Qt::ItemIsEditable | Qt::ItemIsDragEnabled );
fItm = varNameItm->font();
if ( !sysVarVal.isEmpty() )
{
fItm.setBold( true );
varNameItm->setFont( fItm );
varNameItm->setToolTip( sysVarVal );
}
mCurrentVariablesTable->setItem( rowCnt, i, varNameItm );
}
fItm.setBold( true );
QFontMetrics fmRow( fItm );
mCurrentVariablesTable->setRowHeight( rowCnt, fmRow.height() + 6 );
}
if ( mCurrentVariablesTable->rowCount() > 0 )
mCurrentVariablesTable->resizeColumnToContents( 0 );

//local directories to search when loading c++ plugins
QString myPaths = settings.value( "plugins/searchPathsForPlugins", "" ).toString();
if ( !myPaths.isEmpty() )
Expand Down Expand Up @@ -611,23 +706,61 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
mOverlayAlgorithmComboBox->setCurrentIndex( 0 );
} //default is central point

// restore window and widget geometry/state
restoreGeometry( settings.value( "/Windows/Options/geometry" ).toByteArray() );
mOptionsSplitter->restoreState( settings.value( "/Windows/Options/splitState" ).toByteArray() );

int currentIndx = settings.value( "/Windows/Options/row" ).toInt();
mOptionsListWidget->setCurrentRow( currentIndx );
mOptionsStackedWidget->setCurrentIndex( currentIndx );

// load gdal driver list only when gdal tab is first opened
mLoadedGdalDriverList = false;

// tabWidget->setCurrentIndex( settings.value( "/Windows/Options/row" ).toInt() );
int currentTab = settings.value( "/Windows/Options/row" ).toInt();
tabWidget->setCurrentIndex( currentTab );
on_tabWidget_currentChanged( currentTab );
// update option section frame state
on_mOptionsListWidget_currentRowChanged( currentIndx );
}

//! Destructor
QgsOptions::~QgsOptions()
{
QSettings settings;
settings.setValue( "/Windows/Options/geometry", saveGeometry() );
settings.setValue( "/Windows/Options/row", tabWidget->currentIndex() );
settings.setValue( "/Windows/Options/splitState", mOptionsSplitter->saveState() );
settings.setValue( "/Windows/Options/row", mOptionsListWidget->currentRow() );
}

void QgsOptions::showEvent( QShowEvent * e )
{
Q_UNUSED( e );
updateVerticalTabs();
}

void QgsOptions::resizeEvent( QResizeEvent * e )
{
Q_UNUSED( e );
if ( mOptionsListWidget->isVisible() )
updateVerticalTabs();
}

void QgsOptions::updateVerticalTabs()
{
// auto-resize splitter for vert scrollbar without covering icons in icon-only mode
// TODO: mOptionsListWidget has fixed 32px wide icons for now, allow user-defined
int iconWidth = mOptionsListWidget->iconSize().width();
int snapToIconWidth = iconWidth + 32;
QList<int> splitSizes = mOptionsSplitter->sizes();
bool iconOnly = splitSizes.at( 0 ) <= snapToIconWidth;

int newWidth = mOptionsListWidget->verticalScrollBar()->isVisible() ? iconWidth + 26 : iconWidth + 12;
mOptionsListWidget->setMinimumWidth( newWidth );
if ( iconOnly )
{
splitSizes[1] = splitSizes.at( 1 ) - ( splitSizes.at( 0 ) - newWidth );
splitSizes[0] = newWidth;
mOptionsSplitter->setSizes( splitSizes );
}
mOptionsListWidget->setWordWrap( !iconOnly );
}

void QgsOptions::on_cbxProjectDefaultNew_toggled( bool checked )
Expand Down Expand Up @@ -781,6 +914,23 @@ void QgsOptions::saveOptions()
{
QSettings settings;

// custom environment variables
settings.setValue( "qgis/customEnvVarsUse", QVariant( mCustomVariablesChkBx->isChecked() ) );
QStringList customVars;
for ( int i = 0; i < mCustomVariablesTable->rowCount(); ++i )
{
if ( mCustomVariablesTable->item( i, 1 )->text().isEmpty() )
continue;
QComboBox* varApplyCmbBx = qobject_cast<QComboBox*>( mCustomVariablesTable->cellWidget( i, 0 ) );
QString customVar = varApplyCmbBx->itemData( varApplyCmbBx->currentIndex() ).toString();
customVar += "|";
customVar += mCustomVariablesTable->item( i, 1 )->text();
customVar += "=";
customVar += mCustomVariablesTable->item( i, 2 )->text();
customVars << customVar;
}
settings.setValue( "qgis/customEnvVars", QVariant( customVars ) );

//search directories for user plugins
QString myPaths;
for ( int i = 0; i < mListPluginPaths->count(); ++i )
Expand Down Expand Up @@ -1211,6 +1361,74 @@ QStringList QgsOptions::i18nList()
return myList;
}

void QgsOptions::addCustomEnvVarRow( QString varName, QString varVal, QString varApply )
{
int rowCnt = mCustomVariablesTable->rowCount();
mCustomVariablesTable->insertRow( rowCnt );

QComboBox* varApplyCmbBx = new QComboBox( this );
varApplyCmbBx->addItem( tr( "Overwrite" ), QVariant( "overwrite" ) );
varApplyCmbBx->addItem( tr( "If Undefined" ), QVariant( "undefined" ) );
varApplyCmbBx->addItem( tr( "Unset" ), QVariant( "unset" ) );
varApplyCmbBx->addItem( tr( "Prepend" ), QVariant( "prepend" ) );
varApplyCmbBx->addItem( tr( "Append" ), QVariant( "append" ) );
varApplyCmbBx->setCurrentIndex( varApply.isEmpty() ? 0 : varApplyCmbBx->findData( QVariant( varApply ) ) );

QFont cbf = varApplyCmbBx->font();
QFontMetrics cbfm = QFontMetrics( cbf );
cbf.setPointSize( cbf.pointSize() - 2 );
varApplyCmbBx->setFont( cbf );
mCustomVariablesTable->setCellWidget( rowCnt, 0, varApplyCmbBx );

Qt::ItemFlags itmFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable
| Qt::ItemIsEditable | Qt::ItemIsDropEnabled;

QTableWidgetItem* varNameItm = new QTableWidgetItem( varName );
varNameItm->setFlags( itmFlags );
mCustomVariablesTable->setItem( rowCnt, 1, varNameItm );

QTableWidgetItem* varValueItm = new QTableWidgetItem( varVal );
varNameItm->setFlags( itmFlags );
mCustomVariablesTable->setItem( rowCnt, 2, varValueItm );

mCustomVariablesTable->setRowHeight( rowCnt, cbfm.height() + 8 );
}

void QgsOptions::on_mAddCustomVarBtn_clicked()
{
addCustomEnvVarRow( QString( "" ), QString( "" ) );
mCustomVariablesTable->setFocus();
mCustomVariablesTable->setCurrentCell( mCustomVariablesTable->rowCount() - 1, 1 );
mCustomVariablesTable->edit( mCustomVariablesTable->currentIndex() );
}

void QgsOptions::on_mRemoveCustomVarBtn_clicked()
{
mCustomVariablesTable->removeRow( mCustomVariablesTable->currentRow() );
}

void QgsOptions::on_mCurrentVariablesQGISChxBx_toggled( bool qgisSpecific )
{
for ( int i = mCurrentVariablesTable->rowCount() - 1; i >= 0; --i )
{
if ( qgisSpecific )
{
QString itmTxt = mCurrentVariablesTable->item( i, 0 )->text();
if ( !itmTxt.startsWith( "QGIS", Qt::CaseInsensitive ) )
mCurrentVariablesTable->hideRow( i );
}
else
{
mCurrentVariablesTable->showRow( i );
}
}
if ( mCurrentVariablesTable->rowCount() > 0 )
{
mCurrentVariablesTable->sortByColumn( 0, Qt::AscendingOrder );
mCurrentVariablesTable->resizeColumnToContents( 0 );
}
}

void QgsOptions::on_mBtnAddPluginPath_clicked()
{
QString myDir = QFileDialog::getExistingDirectory(
Expand Down Expand Up @@ -1302,10 +1520,10 @@ void QgsOptions::on_mClearCache_clicked()
#endif
}

void QgsOptions::on_tabWidget_currentChanged( int theTab )
void QgsOptions::on_mOptionsListWidget_currentRowChanged( int theIndx )
{
// load gdal driver list when gdal tab is first opened
if ( theTab == 1 && ! mLoadedGdalDriverList )
if ( theIndx == 2 && ! mLoadedGdalDriverList )
{
loadGdalDriverList();
}
Expand Down
34 changes: 31 additions & 3 deletions src/app/qgsoptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
/**Remove an URL to exclude from Proxy*/
void on_mRemoveUrlPushButton_clicked();

/** Slot to add a custom environment variable to the app
* @note added in QGIS 1.9
*/
void on_mAddCustomVarBtn_clicked();

/** Slot to remove a custom environment variable from the app
* @note added in QGIS 1.9
*/
void on_mRemoveCustomVarBtn_clicked();

/** Slot to filter out current environment variables not specific to QGIS
* @note added in QGIS 1.9
*/
void on_mCurrentVariablesQGISChxBx_toggled( bool qgisSpecific );

/* Let the user add a path to the list of search paths
* used for finding user Plugin libs.
* @note added in QGIS 1.7
Expand Down Expand Up @@ -174,10 +189,15 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
*/
void on_pbnExportScales_clicked();

/** Auto slot executed when the active page in the main widget stack is changed
* @note added in 2.0
/** Auto slot executed when the active item in the option section list widget is changed
* @note added in 1.9
*/
void on_mOptionsListWidget_currentRowChanged( int theIndx );

/** Slot to update widget of vertical tabs
* @note added in QGIS 1.9
*/
void on_tabWidget_currentChanged( int theTab );
void updateVerticalTabs();

/* Load the list of drivers available in GDAL
* @note added in 2.0
Expand All @@ -197,6 +217,14 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
QgsCoordinateReferenceSystem mLayerDefaultCrs;
bool mLoadedGdalDriverList;

/** Generate table row for custom environment variables
* @note added in QGIS 1.9
*/
void addCustomEnvVarRow( QString varName, QString varVal, QString varApply = QString() );

protected:
void showEvent( QShowEvent * e );
void resizeEvent( QResizeEvent * e );
};

#endif // #ifndef QGSOPTIONS_H
3 changes: 2 additions & 1 deletion src/core/gps/tok.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ double nmea_atof( const char *str, int str_sz )

if ( str_sz < NMEA_CONVSTR_BUF )
{
const char *oldlocale = setlocale( LC_NUMERIC, NULL );

memcpy( &buff[0], str, str_sz );
buff[str_sz] = '\0';
const char *oldlocale = setlocale( LC_NUMERIC, NULL );
setlocale( LC_NUMERIC, "C" );
res = strtod( &buff[0], &tmp_ptr );
setlocale( LC_NUMERIC, oldlocale );
Expand Down
15 changes: 15 additions & 0 deletions src/core/qgsapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <QFileOpenEvent>
#include <QMessageBox>
#include <QPalette>
#include <QProcess>
#include <QSettings>
#include <QIcon>
#include <QPixmap>
Expand All @@ -50,6 +51,7 @@ QString ABISYM( QgsApplication::mLibraryPath );
QString ABISYM( QgsApplication::mLibexecPath );
QString ABISYM( QgsApplication::mThemeName );
QStringList ABISYM( QgsApplication::mDefaultSvgPaths );
QMap<QString, QString> ABISYM( QgsApplication::mSystemEnvVars );
QString ABISYM( QgsApplication::mConfigPath );
bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
QString ABISYM( QgsApplication::mBuildSourcePath );
Expand Down Expand Up @@ -152,6 +154,19 @@ void QgsApplication::init( QString customConfigPath )

ABISYM( mDefaultSvgPaths ) << qgisSettingsDirPath() + QString( "svg/" );

// store system environment variables passed to application, before they are adjusted
QMap<QString, QString> systemEnvVarMap;
foreach ( const QString &varStr, QProcess::systemEnvironment() )
{
int pos = varStr.indexOf( QLatin1Char( '=' ) );
if ( pos == -1 )
continue;
QString varStrName = varStr.left( pos );
QString varStrValue = varStr.mid( pos + 1 );
systemEnvVarMap.insert( varStrName, varStrValue );
}
ABISYM( mSystemEnvVars ) = systemEnvVarMap;

// set a working directory up for gdal to write .aux.xml files into
// for cases where the raster dir is read only to the user
// if the env var is already set it will be used preferentially
Expand Down
7 changes: 6 additions & 1 deletion src/core/qgsapplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ class CORE_EXPORT QgsApplication: public QApplication
//! @note added in 1.4
static const QStringList svgPaths();

//! Returns the system environment variables passed to application.
//! @note added in 1.9
static const QMap<QString, QString> systemEnvVars() { return ABISYM( mSystemEnvVars ); }

//! Returns the path to the application prefix directory.
static const QString prefixPath();

Expand Down Expand Up @@ -253,7 +257,7 @@ class CORE_EXPORT QgsApplication: public QApplication
* GDAL_SKIP environment variable)
* @note added in 2.0
*/
static QStringList skippedGdalDrivers( ) { return ABISYM( mGdalSkipList ); };
static QStringList skippedGdalDrivers( ) { return ABISYM( mGdalSkipList ); }

/** Apply the skipped drivers list to gdal
* @see skipGdalDriver
Expand All @@ -277,6 +281,7 @@ class CORE_EXPORT QgsApplication: public QApplication
static QString ABISYM( mLibexecPath );
static QString ABISYM( mThemeName );
static QStringList ABISYM( mDefaultSvgPaths );
static QMap<QString, QString> ABISYM( mSystemEnvVars );

static QString ABISYM( mConfigPath );

Expand Down
15 changes: 13 additions & 2 deletions src/core/qgsbrowsermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "qgsproviderregistry.h"

#include "qgsbrowsermodel.h"
#include "qgsproject.h"

#include <QSettings>

Expand All @@ -40,8 +41,18 @@ QgsBrowserModel::~QgsBrowserModel()

void QgsBrowserModel::addRootItems()
{
// give the home directory a prominent first place
QgsDirectoryItem *item = new QgsDirectoryItem( NULL, tr( "Home" ), QDir::homePath() );
QgsDirectoryItem *item;

QString home = QgsProject::instance()->homePath();

if( !home.isNull() )
{
item = new QgsDirectoryItem( NULL, tr( "Project home" ), home );
mRootItems << item;
}

// give the home directory a prominent second place
item = new QgsDirectoryItem( NULL, tr( "Home" ), QDir::homePath() );
QStyle *style = QApplication::style();
QIcon homeIcon( style->standardPixmap( QStyle::SP_DirHomeIcon ) );
item->setIcon( homeIcon );
Expand Down
5 changes: 2 additions & 3 deletions src/core/qgsbrowsermodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,6 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel

bool hasChildren( const QModelIndex &parent = QModelIndex() ) const;

// Reload the whole model
void reload();

// Refresh item specified by path
void refresh( QString path );

Expand All @@ -93,6 +90,8 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
void fetchMore( const QModelIndex & parent );

public slots:
// Reload the whole model
void reload();

void beginInsertItems( QgsDataItem *parent, int first, int last );
void endInsertItems();
Expand Down
13 changes: 13 additions & 0 deletions src/core/qgsmaplayerregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ QgsMapLayer * QgsMapLayerRegistry::mapLayer( QString theLayerId )
return mMapLayers.value( theLayerId );
}

QList<QgsMapLayer *> QgsMapLayerRegistry::mapLayersByName( QString layerName )
{
QList<QgsMapLayer *> myResultList;
foreach ( QgsMapLayer* layer, mMapLayers )
{
if ( layer->name() == layerName )
{
myResultList << layer;
}
}
return myResultList;
}

//introduced in 1.8
QList<QgsMapLayer *> QgsMapLayerRegistry::addMapLayers(
QList<QgsMapLayer *> theMapLayers,
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsmaplayerregistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ class CORE_EXPORT QgsMapLayerRegistry : public QObject
//! Retrieve a pointer to a loaded layer by id
QgsMapLayer *mapLayer( QString theLayerId );

//! Retrieve a pointer to a loaded layer by name
QList<QgsMapLayer *> mapLayersByName( QString layerName );

//! Retrieve the mapLayers collection (mainly intended for use by projection)
QMap<QString, QgsMapLayer*> & mapLayers();

Expand Down
17 changes: 9 additions & 8 deletions src/core/qgsnetworkreplyparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@

class CORE_EXPORT QgsNetworkReplyParser : public QObject
{
Q_OBJECT
Q_OBJECT

public:
/** Constructor
* @param reply */
QgsNetworkReplyParser( QNetworkReply *reply );

/** Indicates if successfully parsed
/** Indicates if successfully parsed
* @return true if successfully parsed */
bool isValid() const { return mValid; }

Expand All @@ -49,20 +49,21 @@ class CORE_EXPORT QgsNetworkReplyParser : public QObject

/** Get part header
* @param part part index
* @param headerName header name
* @return raw header */
QByteArray rawHeader ( int part, const QByteArray & headerName ) const { return mHeaders.value(part).value(headerName); }
QByteArray rawHeader( int part, const QByteArray & headerName ) const { return mHeaders.value( part ).value( headerName ); }

/** Get part part body
* @param part part index
* @return part body */
QByteArray body ( int part ) const { return mBodies.value(part); }
QByteArray body( int part ) const { return mBodies.value( part ); }

/** Parsing error */
QString error() const { return mError; }

/** Test if reply is multipart.
* @return true if reply is multipart */
static bool isMultipart ( QNetworkReply *reply );
static bool isMultipart( QNetworkReply *reply );

private:
QNetworkReply *mReply;
Expand All @@ -72,10 +73,10 @@ class CORE_EXPORT QgsNetworkReplyParser : public QObject
QString mError;

/* List of header maps */
QList< QMap<QByteArray,QByteArray> > mHeaders;
QList< QMap<QByteArray, QByteArray> > mHeaders;

/* List of part bodies */
QList<QByteArray> mBodies;
};

#endif
#endif
13 changes: 10 additions & 3 deletions src/core/qgsproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1368,11 +1368,11 @@ QString QgsProject::readPath( QString src ) const
// That means that it was saved with an earlier version of "relative path support",
// where the source file had to exist and only the project directory was stripped
// from the filename.
QFileInfo pfi( fileName() );
if ( !pfi.exists() )
QString home = homePath();
if( home.isNull() )
return src;

QFileInfo fi( pfi.canonicalPath() + "/" + src );
QFileInfo fi( home + "/" + src );

if ( !fi.exists() )
{
Expand Down Expand Up @@ -1763,4 +1763,11 @@ void QgsProjectBadLayerDefaultHandler::handleBadLayers( QList<QDomNode> /*layers
// just ignore any bad layers
}

QString QgsProject::homePath() const
{
QFileInfo pfi( fileName() );
if ( !pfi.exists() )
return QString::null;

return pfi.canonicalPath();
}
5 changes: 5 additions & 0 deletions src/core/qgsproject.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,11 @@ class CORE_EXPORT QgsProject : public QObject
@note added in version 1.9*/
bool topologicalEditing() const;

/** Return project's home path
@return home path of project (or QString::null if not set)
@note added in version 2.0 */
QString homePath() const;

protected:

/** Set error message from read/write operation
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsvectordataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,12 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
*/
virtual QgsAttributeList attributeIndexes();

/**
* Return list of indexes of fields that make up the primary key
* @note added in 2.0
*/
virtual QgsAttributeList pkAttributeIndexes() { return QgsAttributeList(); }

/**
* Set whether provider should also return features that don't have
* associated geometry. false by default
Expand Down
213 changes: 126 additions & 87 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
, mLabel( 0 )
, mLabelOn( false )
, mVertexMarkerOnlyForSelection( false )
, mEditorLayout( GeneratedLayout )
, mFetching( false )
, mJoinBuffer( 0 )
, mDiagramRenderer( 0 )
Expand Down Expand Up @@ -2512,16 +2513,13 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo

if ( mDataProvider )
{
//use default value where possible (primary key issue), otherwise the value from the original (split) feature
QgsAttributeMap newAttributes = select_it->attributeMap();
QVariant defaultValue;
foreach ( int j, newAttributes.keys() )

// overwrite primary key field with default values
foreach ( int idx, pendingPkAttributesList() )
{
defaultValue = mDataProvider->defaultValue( j );
if ( !defaultValue.isNull() )
{
newAttributes.insert( j, defaultValue );
}
if( newAttributes.contains( idx ) )
newAttributes.insert( idx, mDataProvider->defaultValue( idx ) );
}

newFeature.setAttributeMap( newAttributes );
Expand Down Expand Up @@ -3129,28 +3127,6 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
//also restore custom properties (for labeling-ng)
readCustomProperties( node, "labeling" );

// tab display
QDomNode editorLayoutNode = node.namedItem( "editorlayout" );
if ( editorLayoutNode.isNull() )
{
mEditorLayout = GeneratedLayout;
}
else
{
if ( editorLayoutNode.toElement().text() == "uifilelayout" )
{
mEditorLayout = UiFileLayout;
}
else if ( editorLayoutNode.toElement().text() == "tablayout" )
{
mEditorLayout = TabLayout;
}
else
{
mEditorLayout = GeneratedLayout;
}
}

// Test if labeling is on or off
QDomNode labelnode = node.namedItem( "label" );
QDomElement element = labelnode.toElement();
Expand Down Expand Up @@ -3330,6 +3306,27 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
}
}

// tab display
QDomNode editorLayoutNode = node.namedItem( "editorlayout" );
if ( editorLayoutNode.isNull() )
{
mEditorLayout = GeneratedLayout;
}
else
{
if ( editorLayoutNode.toElement().text() == "uifilelayout" )
{
mEditorLayout = UiFileLayout;
}
else if ( editorLayoutNode.toElement().text() == "tablayout" )
{
mEditorLayout = TabLayout;
}
else
{
mEditorLayout = GeneratedLayout;
}
}

//Attributes excluded from WMS and WFS
mExcludeAttributesWMS.clear();
Expand Down Expand Up @@ -3390,7 +3387,9 @@ QgsAttributeEditorElement* QgsVectorLayer::attributeEditorElementFromDomElement(
}
else if ( elem.tagName() == "attributeEditorField" )
{
newElement = new QgsAttributeEditorField( elem.attribute( "name" ), elem.attribute( "idx" ).toInt(), parent );
QString name = elem.attribute( "name" );
int idx = *( dataProvider()->fieldNameMap() ).find( name );
newElement = new QgsAttributeEditorField( name, idx, parent );
}

return newElement;
Expand Down Expand Up @@ -3446,26 +3445,6 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
//save customproperties (for labeling ng)
writeCustomProperties( node, doc );

// tab display
QDomElement editorLayoutElem = doc.createElement( "editorlayout" );
switch ( mEditorLayout )
{
case UiFileLayout:
editorLayoutElem.appendChild( doc.createTextNode( "uifilelayout" ) );
break;

case TabLayout:
editorLayoutElem.appendChild( doc.createTextNode( "tablayout" ) );
break;

case GeneratedLayout:
default:
editorLayoutElem.appendChild( doc.createTextNode( "generatedlayout" ) );
break;
}

node.appendChild( editorLayoutElem );

// add the display field
QDomElement dField = doc.createElement( "displayfield" );
QDomText dFieldText = doc.createTextNode( displayField() );
Expand Down Expand Up @@ -3608,6 +3587,26 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
afField.appendChild( afText );
node.appendChild( afField );

// tab display
QDomElement editorLayoutElem = doc.createElement( "editorlayout" );
switch ( mEditorLayout )
{
case UiFileLayout:
editorLayoutElem.appendChild( doc.createTextNode( "uifilelayout" ) );
break;

case TabLayout:
editorLayoutElem.appendChild( doc.createTextNode( "tablayout" ) );
break;

case GeneratedLayout:
default:
editorLayoutElem.appendChild( doc.createTextNode( "generatedlayout" ) );
break;
}

node.appendChild( editorLayoutElem );

//attribute aliases
if ( mAttributeAliasMap.size() > 0 )
{
Expand Down Expand Up @@ -3890,6 +3889,21 @@ QgsAttributeList QgsVectorLayer::pendingAllAttributesList()
return mUpdatedFields.keys();
}

QgsAttributeList QgsVectorLayer::pendingPkAttributesList()
{
QgsAttributeList pkAttributesList;

foreach ( int idx, mDataProvider->pkAttributeIndexes() )
{
if ( !mUpdatedFields.contains( idx ) )
continue;

pkAttributesList << idx;
}

return pkAttributesList;
}

int QgsVectorLayer::pendingFeatureCount()
{
return mDataProvider->featureCount()
Expand Down Expand Up @@ -3970,14 +3984,31 @@ bool QgsVectorLayer::commitChanges()
}
}

// collect new feature ids that weren't deleted again and forget still
// pending updates for deleted features
QHash<QgsFeatureId, int> addedFeaturesIdx;
for ( int i = 0; i < mAddedFeatures.size(); i++ )
{
const QgsFeature &f = mAddedFeatures.at( i );
if ( !mDeletedFeatureIds.remove( f.id() ) )
{
addedFeaturesIdx.insert( f.id(), i );
}
else
{
mChangedAttributeValues.remove( f.id() );
mChangedGeometries.remove( f.id() );
}
}

//
// remap changed and attributes of added features
//
bool attributeChangesOk = true;
if ( attributesChanged )
{
// map updates field indexes to names
QMap<int, QString> src;
QHash<int, QString> src;
for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
{
src[ it.key()] = it.value().name();
Expand All @@ -3987,7 +4018,7 @@ bool QgsVectorLayer::commitChanges()
const QgsFieldMap &pFields = mDataProvider->fields();

// map provider table names to field indexes
QMap<QString, int> dst;
QHash<QString, int> dst;
for ( QgsFieldMap::const_iterator it = pFields.begin(); it != pFields.end(); it++ )
{
dst[ it.value().name()] = it.key();
Expand Down Expand Up @@ -4019,8 +4050,8 @@ bool QgsVectorLayer::commitChanges()
}

// map updated fields to provider fields
QMap<int, int> remap;
for ( QMap<int, QString>::const_iterator it = src.begin(); it != src.end(); it++ )
QHash<int, int> remap;
for ( QHash<int, QString>::const_iterator it = src.begin(); it != src.end(); it++ )
{
if ( dst.contains( it.value() ) )
{
Expand Down Expand Up @@ -4060,7 +4091,7 @@ bool QgsVectorLayer::commitChanges()
QgsFieldMap attributes;

// update private field map
for ( QMap<int, int>::iterator it = remap.begin(); it != remap.end(); it++ )
for ( QHash<int, int>::iterator it = remap.begin(); it != remap.end(); it++ )
attributes[ it.value()] = mUpdatedFields[ it.key()];

mUpdatedFields = attributes;
Expand Down Expand Up @@ -4088,21 +4119,42 @@ bool QgsVectorLayer::commitChanges()
}
}

//
// delete features
//
if ( mDeletedFeatureIds.size() > 0 )
{
if (( cap & QgsVectorDataProvider::DeleteFeatures ) && mDataProvider->deleteFeatures( mDeletedFeatureIds ) )
{
mCommitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
foreach ( const QgsFeatureId &id, mDeletedFeatureIds )
{
mChangedAttributeValues.remove( id );
mChangedGeometries.remove( id );
}

emit committedFeaturesRemoved( id(), mDeletedFeatureIds );

mDeletedFeatureIds.clear();
}
else
{
mCommitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
success = false;
}
}

//
// add features
//
if ( mAddedFeatures.size() > 0 )
{
for ( int i = 0; i < mAddedFeatures.size(); i++ )
foreach ( int i, addedFeaturesIdx.values() )
{
QgsFeature &f = mAddedFeatures[i];

if ( mDeletedFeatureIds.contains( f.id() ) )
if ( mDeletedFeatureIds.remove( f.id() ) )
{
mDeletedFeatureIds.remove( f.id() );

if ( mChangedGeometries.contains( f.id() ) )
mChangedGeometries.remove( f.id() );

mAddedFeatures.removeAt( i-- );
continue;
Expand Down Expand Up @@ -4174,31 +4226,6 @@ bool QgsVectorLayer::commitChanges()
}
}

//
// delete features
//
if ( mDeletedFeatureIds.size() > 0 )
{
if (( cap & QgsVectorDataProvider::DeleteFeatures ) && mDataProvider->deleteFeatures( mDeletedFeatureIds ) )
{
mCommitErrors << tr( "SUCCESS: %n feature(s) deleted.", "deleted features count", mDeletedFeatureIds.size() );
for ( QgsFeatureIds::const_iterator it = mDeletedFeatureIds.begin(); it != mDeletedFeatureIds.end(); it++ )
{
mChangedAttributeValues.remove( *it );
mChangedGeometries.remove( *it );
}

emit committedFeaturesRemoved( id(), mDeletedFeatureIds );

mDeletedFeatureIds.clear();
}
else
{
mCommitErrors << tr( "ERROR: %n feature(s) not deleted.", "not deleted features count", mDeletedFeatureIds.size() );
success = false;
}
}

if ( !success )
{
if ( mDataProvider->hasErrors() )
Expand Down Expand Up @@ -5779,6 +5806,18 @@ QString QgsVectorLayer::metadata()
myMetadata += "</td></tr>";
}

QgsAttributeList pkAttrList = pendingPkAttributesList();
if ( !pkAttrList.isEmpty() )
{
myMetadata += "<tr><td>";
myMetadata += tr( "Primary key attributes: " );
foreach( int idx, pkAttrList )
{
myMetadata += pendingFields()[ idx ].name() + " ";
}
myMetadata += "</td></tr>";
}


//feature count
myMetadata += "<tr><td>";
Expand Down
7 changes: 6 additions & 1 deletion src/core/qgsvectorlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
* @param elem the DOM element
* @param parent the QObject which will own this object
*/
static QgsAttributeEditorElement* attributeEditorElementFromDomElement( QDomElement &elem, QObject* parent );
QgsAttributeEditorElement* attributeEditorElementFromDomElement( QDomElement &elem, QObject* parent );

/** Read the symbology for the current layer from the Dom node supplied.
* @param node node that will contain the symbology definition for this layer.
Expand Down Expand Up @@ -632,6 +632,11 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** returns list of attributes */
QgsAttributeList pendingAllAttributesList();

/** returns list of attribute making up the primary key
* @note added in 2.0
*/
QgsAttributeList pendingPkAttributesList();

/** returns feature count after commit */
int pendingFeatureCount();

Expand Down
32 changes: 28 additions & 4 deletions src/core/qgsvectorlayerimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "qgsvectorlayerimport.h"
#include "qgsproviderregistry.h"

#include <QProgressDialog>

#define FEATURE_BUFFER_SIZE 200

typedef QgsVectorLayerImport::ImportError createEmptyLayer_t(
Expand All @@ -45,8 +47,10 @@ QgsVectorLayerImport::QgsVectorLayerImport( const QString &uri,
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* crs,
bool overwrite,
const QMap<QString, QVariant> *options )
const QMap<QString, QVariant> *options,
QProgressDialog *progress )
: mErrorCount( 0 )
, mProgress( progress )
{
mProvider = NULL;

Expand Down Expand Up @@ -83,7 +87,7 @@ QgsVectorLayerImport::QgsVectorLayerImport( const QString &uri,
QgsDebugMsg( "Created empty layer" );

QgsVectorDataProvider *vectorProvider = ( QgsVectorDataProvider* ) pReg->provider( providerKey, uri );
if ( !vectorProvider || !vectorProvider->isValid() )
if ( !vectorProvider || !vectorProvider->isValid() || ( vectorProvider->capabilities() & QgsVectorDataProvider::AddFeatures ) == 0 )
{
mError = ErrInvalidLayer;
mErrorMessage = QObject::tr( "Loading of layer failed" );
Expand Down Expand Up @@ -181,7 +185,8 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
bool onlySelected,
QString *errorMessage,
bool skipAttributeCreation,
QMap<QString, QVariant> *options )
QMap<QString, QVariant> *options,
QProgressDialog *progress )
{
const QgsCoordinateReferenceSystem* outputCRS;
QgsCoordinateTransform* ct = 0;
Expand Down Expand Up @@ -255,7 +260,7 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
}

QgsVectorLayerImport * writer =
new QgsVectorLayerImport( uri, providerKey, fields, wkbType, outputCRS, overwrite, options );
new QgsVectorLayerImport( uri, providerKey, fields, wkbType, outputCRS, overwrite, options, progress );

// check whether file creation was successful
ImportError err = writer->hasError();
Expand Down Expand Up @@ -298,9 +303,23 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
*errorMessage = QObject::tr( "Feature write errors:" );
}

if ( progress )
{
progress->setRange( 0, layer->featureCount() );
}

// write all features
while ( layer->nextFeature( fet ) )
{
if ( progress && progress->wasCanceled() )
{
if ( errorMessage )
{
*errorMessage += "\n" + QObject::tr( "Import was canceled at %1 of %2" ).arg( progress->value() ).arg( progress->maximum() );
}
break;
}

if ( writer->errorCount() > 1000 )
{
if ( errorMessage )
Expand Down Expand Up @@ -348,6 +367,11 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
}
}
n++;

if ( progress )
{
progress->setValue( n );
}
}

// flush the buffer to be sure that all features are written
Expand Down
9 changes: 7 additions & 2 deletions src/core/qgsvectorlayerimport.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"

class QProgressDialog;

/** \ingroup core
* A convenience class for writing vector files to disk.
There are two possibilities how to use this class:
Expand Down Expand Up @@ -59,7 +61,8 @@ class CORE_EXPORT QgsVectorLayerImport
bool onlySelected = false,
QString *errorMessage = 0,
bool skipAttributeCreation = false,
QMap<QString, QVariant> *options = 0
QMap<QString, QVariant> *options = 0,
QProgressDialog *progress = 0
);

/** create a empty layer and add fields to it */
Expand All @@ -69,7 +72,8 @@ class CORE_EXPORT QgsVectorLayerImport
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* crs,
bool overwrite = false,
const QMap<QString, QVariant> *options = 0
const QMap<QString, QVariant> *options = 0,
QProgressDialog *progress = 0
);

/** checks whether there were any errors */
Expand Down Expand Up @@ -102,6 +106,7 @@ class CORE_EXPORT QgsVectorLayerImport
QMap<int, int> mOldToNewAttrIdx;

QgsFeatureList mFeatureBuffer;
QProgressDialog *mProgress;
};

#endif
18 changes: 12 additions & 6 deletions src/core/qgswfsdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ class CORE_EXPORT QgsWFSData: public QObject
{
Q_OBJECT
public:
/** Constructor.
@param uri request uri
@param extent the extent of the WFS layer
@param features the features of the layer
@param idMap
@param geometryAttribute
@param thematicAttributes
@param wkbType */
QgsWFSData(
const QString& uri,
QgsRectangle* extent,
Expand All @@ -46,11 +54,7 @@ class CORE_EXPORT QgsWFSData: public QObject
~QgsWFSData();

/**Does the Http GET request to the wfs server
@param query string (to define the requested typename)
@param extent the extent of the WFS layer
@param srs the reference system of the layer
@param features the features of the layer
@return 0 in case of success*/
@return 0 in case of success */
int getWFSData();

private slots:
Expand Down Expand Up @@ -108,7 +112,9 @@ class CORE_EXPORT QgsWFSData: public QObject
@return 0 in case of success*/
int readEpsgFromAttribute( int& epsgNr, const XML_Char** attr ) const;
/**Reads attribute as string
@return attribute value or an empty string if no such attribute*/
@param attributeName
@param attr
@return attribute value or an empty string if no such attribute*/
QString readAttribute( const QString& attributeName, const XML_Char** attr ) const;
/**Creates a rectangle from a coordinate string.
@return 0 in case of success*/
Expand Down
6 changes: 6 additions & 0 deletions src/gui/attributetable/qgsattributetableidcolumnpair.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ bool QgsAttributeTableIdColumnPair::operator<( const QgsAttributeTableIdColumnPa
//QVariant thinks gid is a string!
QVariant::Type columnType = mItem.type();

if ( mItem.isNull() )
return 1;

if ( b.mItem.isNull() )
return 0;

switch ( columnType )
{
case QVariant::Int:
Expand Down
22 changes: 19 additions & 3 deletions src/gui/qgsattributeeditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <qgsmaplayerregistry.h>
#include <qgslogger.h>

#include <QScrollArea>
#include <QPushButton>
#include <QLineEdit>
#include <QTextEdit>
Expand Down Expand Up @@ -987,13 +988,23 @@ QWidget* QgsAttributeEditor::createWidgetFromDef( const QgsAttributeEditorElemen
QGroupBox* groupBox = new QGroupBox( parent );
groupBox->setTitle( container->name() );
myContainer = groupBox;
newWidget = myContainer;
}
else
{
myContainer = new QWidget( parent );
QScrollArea *scrollArea = new QScrollArea( parent );

myContainer = new QWidget( scrollArea );

scrollArea->setWidget( myContainer );
scrollArea->setWidgetResizable( true );
scrollArea->setFrameShape( QFrame::NoFrame );

newWidget = scrollArea;
}

QGridLayout* gbLayout = new QGridLayout( myContainer );
myContainer->setLayout( gbLayout );

int index = 0;

Expand All @@ -1010,17 +1021,22 @@ QWidget* QgsAttributeEditor::createWidgetFromDef( const QgsAttributeEditorElemen
}
else
{
const QgsAttributeEditorField* fieldDef = dynamic_cast<const QgsAttributeEditorField*>( childDef );

//show attribute alias if available
QString myFieldName = vl->attributeDisplayName( fieldDef->idx() );
QLabel * mypLabel = new QLabel( myContainer );
gbLayout->addWidget( mypLabel, index, 0 );
mypLabel->setText( childDef->name() );
mypLabel->setText( myFieldName );

// add editor widget
gbLayout->addWidget( editor, index, 1 );
}

++index;
}
gbLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );

newWidget = myContainer;
break;
}

Expand Down
5 changes: 1 addition & 4 deletions src/gui/qgssearchquerybuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,11 @@ void QgsSearchQueryBuilder::populateFields()
return;

QgsDebugMsg( "entering." );
QRegExp reQuote( "[A-Za-z_][A-Za-z0-9_]*" );
const QgsFieldMap& fields = mLayer->pendingFields();
for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it )
{
QString fieldName = it->name();
mFieldMap[fieldName] = it.key();
if ( !reQuote.exactMatch( fieldName ) ) // quote if necessary
fieldName = QgsExpression::quotedColumnRef( fieldName );
QStandardItem *myItem = new QStandardItem( fieldName );
myItem->setEditable( false );
mModelFields->insertRow( mModelFields->rowCount(), myItem );
Expand Down Expand Up @@ -314,7 +311,7 @@ void QgsSearchQueryBuilder::setSearchString( QString searchString )

void QgsSearchQueryBuilder::on_lstFields_doubleClicked( const QModelIndex &index )
{
txtSQL->insertPlainText( "\"" + mModelFields->data( index ).toString() + "\"" );
txtSQL->insertPlainText( QgsExpression::quotedColumnRef( mModelFields->data( index ).toString() ) );
}

void QgsSearchQueryBuilder::on_lstValues_doubleClicked( const QModelIndex &index )
Expand Down
2 changes: 1 addition & 1 deletion src/providers/mssql/qgsmssqlprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,7 @@ QgsVectorLayerImport::ImportError QgsMssqlProvider::createEmptyLayer(
QString pk = primaryKey = "qgs_fid";
for ( QgsFieldMap::const_iterator fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
{
if ( fldIt.value().name() == pk )
if ( fldIt.value().name() == primaryKey )
{
// it already exists, try again with a new name
primaryKey = QString( "%1_%2" ).arg( pk ).arg( index++ );
Expand Down
58 changes: 50 additions & 8 deletions src/providers/postgres/qgspostgresdataitems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,51 @@
#include "qgsapplication.h"

#include <QMessageBox>
#include <QProgressDialog>

QGISEXTERN bool deleteLayer( const QString& uri, QString& errCause );

// ---------------------------------------------------------------------------
QgsPGConnectionItem::QgsPGConnectionItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
, mColumnTypeThread( 0 )
{
mIcon = QgsApplication::getThemeIcon( "mIconConnect.png" );
}

QgsPGConnectionItem::~QgsPGConnectionItem()
{
stop();
}

void QgsPGConnectionItem::stop()
{
if ( mColumnTypeThread )
{
mColumnTypeThread->stop();
mColumnTypeThread->wait();
delete mColumnTypeThread;
mColumnTypeThread = 0;
}
}

void QgsPGConnectionItem::refresh()
{
QApplication::setOverrideCursor( Qt::WaitCursor );

stop();

foreach ( QgsDataItem *child, mChildren )
{
deleteChildItem( child );
}

foreach ( QgsDataItem *item, createChildren() )
{
addChildItem( item, true );
}

QApplication::restoreOverrideCursor();
}

QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
Expand All @@ -42,6 +75,8 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
QVector<QgsDataItem*> children;
QgsDataSourceURI uri = QgsPostgresConn::connUri( mName );

mSchemaMap.clear();

mConn = QgsPostgresConn::connectDb( uri.connectionInfo(), true );
if ( !mConn )
return children;
Expand All @@ -62,7 +97,7 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
return children;
}

QgsGeomColumnTypeThread *columnTypeThread = 0;
stop();

foreach ( QgsPostgresLayerProperty layerProperty, layerProperties )
{
Expand All @@ -76,17 +111,17 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()

if ( QgsPostgresConn::wkbTypeFromPostgis( layerProperty.type ) == QGis::WKBUnknown )
{
if ( !columnTypeThread )
if ( !mColumnTypeThread )
{
QgsPostgresConn *conn = QgsPostgresConn::connectDb( uri.connectionInfo(), true /* readonly */ );
if ( conn )
{
columnTypeThread = new QgsGeomColumnTypeThread( conn, true /* use estimated metadata */ );
mColumnTypeThread = new QgsGeomColumnTypeThread( conn, true /* use estimated metadata */ );

connect( columnTypeThread, SIGNAL( setLayerType( QgsPostgresLayerProperty ) ),
connect( mColumnTypeThread, SIGNAL( setLayerType( QgsPostgresLayerProperty ) ),
this, SLOT( setLayerType( QgsPostgresLayerProperty ) ) );
connect( this, SIGNAL( addGeometryColumn( QgsPostgresLayerProperty ) ),
columnTypeThread, SLOT( addGeometryColumn( QgsPostgresLayerProperty ) ) );
mColumnTypeThread, SLOT( addGeometryColumn( QgsPostgresLayerProperty ) ) );
}
}

Expand All @@ -98,8 +133,8 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
schemaItem->addLayer( layerProperty );
}

if ( columnTypeThread )
columnTypeThread->start();
if ( mColumnTypeThread )
mColumnTypeThread->start();

return children;
}
Expand Down Expand Up @@ -186,6 +221,11 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )

qApp->setOverrideCursor( Qt::WaitCursor );

QProgressDialog *progress = new QProgressDialog( tr( "Copying features..." ), tr( "Abort" ), 0, 0, 0 );
progress->setWindowTitle( tr( "Import layer" ) );
progress->setWindowModality( Qt::WindowModal );
progress->show();

QStringList importResults;
bool hasError = false;
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
Expand All @@ -207,7 +247,7 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
QgsDebugMsg( "URI " + uri.uri() );
QgsVectorLayerImport::ImportError err;
QString importError;
err = QgsVectorLayerImport::importLayer( srcLayer, uri.uri(), "postgres", &srcLayer->crs(), false, &importError );
err = QgsVectorLayerImport::importLayer( srcLayer, uri.uri(), "postgres", &srcLayer->crs(), false, &importError, false, 0, progress );
if ( err == QgsVectorLayerImport::NoError )
importResults.append( tr( "%1: OK!" ).arg( u.name ) );
else
Expand All @@ -225,6 +265,8 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
delete srcLayer;
}

delete progress;

qApp->restoreOverrideCursor();

if ( hasError )
Expand Down
4 changes: 4 additions & 0 deletions src/providers/postgres/qgspostgresdataitems.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class QgsPGConnectionItem : public QgsDataCollectionItem

QgsPostgresConn *connection() const { return mConn; }

void refresh();

signals:
void addGeometryColumn( QgsPostgresLayerProperty );

Expand All @@ -71,8 +73,10 @@ class QgsPGConnectionItem : public QgsDataCollectionItem
void setLayerType( QgsPostgresLayerProperty layerProperty );

private:
void stop();
QgsPostgresConn *mConn;
QMap<QString, QgsPGSchemaItem * > mSchemaMap;
QgsGeomColumnTypeThread *mColumnTypeThread;
};

class QgsPGSchemaItem : public QgsDataCollectionItem
Expand Down
2 changes: 1 addition & 1 deletion src/providers/postgres/qgspostgresprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3274,7 +3274,7 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
QString pk = primaryKey = "id";
for ( QgsFieldMap::const_iterator fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
{
if ( fldIt.value().name() == pk )
if ( fldIt.value().name() == primaryKey )
{
// it already exists, try again with a new name
primaryKey = QString( "%1_%2" ).arg( pk ).arg( index++ );
Expand Down
4 changes: 3 additions & 1 deletion src/providers/postgres/qgspostgresprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ class QgsPostgresProvider : public QgsVectorDataProvider

QgsAttributeList attributeIndexes();

QgsAttributeList pkAttributeIndexes() { return mPrimaryKeyAttrs; }

/**Returns the default value for field specified by @c fieldName */
QVariant defaultValue( QString fieldName, QString tableName = QString::null, QString schemaName = QString::null );

Expand Down Expand Up @@ -445,7 +447,7 @@ class QgsPostgresProvider : public QgsVectorDataProvider
long layerId;
};

TopoLayerInfo mTopoLayerInfo;
TopoLayerInfo mTopoLayerInfo;

bool getTopoLayerInfo();

Expand Down
2 changes: 1 addition & 1 deletion src/providers/wms/qgswmssourceselect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ QgsWMSSourceSelect::QgsWMSSourceSelect( QWidget * parent, Qt::WFlags fl, bool ma
: QDialog( parent, fl )
, mManagerMode( managerMode )
, mEmbeddedMode( embeddedMode )
, mCurrentTileset( 0 )
, mDefaultCRS( GEO_EPSG_CRS_AUTHID )
, mCurrentTileset( 0 )
{
setupUi( this );

Expand Down
6,037 changes: 3,197 additions & 2,840 deletions src/ui/qgsoptionsbase.ui

Large diffs are not rendered by default.