use QgsDebugMsg instead of iostream in BEATA and reindent

git-svn-id: http://svn.osgeo.org/qgis/trunk@10425 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
jef 2009-03-27 17:37:59 +00:00
parent 4e049f7490
commit a2d3b38029
2 changed files with 413 additions and 397 deletions

View File

@ -1,5 +1,5 @@
/*************************************************************************** /***************************************************************************
BeataDialog.cpp BeataDialog.cpp
BEtter Attribute TAble BEtter Attribute TAble
------------------- -------------------
date : Feb 2009 date : Feb 2009
@ -29,6 +29,7 @@
#include "qgisapp.h" #include "qgisapp.h"
#include "qgssearchquerybuilder.h" #include "qgssearchquerybuilder.h"
#include "qgslogger.h"
class QBeataTableDock : public QDockWidget class QBeataTableDock : public QDockWidget
@ -37,7 +38,7 @@ class QBeataTableDock : public QDockWidget
QBeataTableDock( const QString & title, QWidget * parent = 0, Qt::WindowFlags flags = 0 ) QBeataTableDock( const QString & title, QWidget * parent = 0, Qt::WindowFlags flags = 0 )
: QDockWidget( title, parent, flags ) : QDockWidget( title, parent, flags )
{ {
setObjectName("AttributeTable"); // set object name so the position can be saved setObjectName( "AttributeTable" ); // set object name so the position can be saved
} }
virtual void closeEvent( QCloseEvent * ev ) virtual void closeEvent( QCloseEvent * ev )
@ -47,21 +48,21 @@ class QBeataTableDock : public QDockWidget
}; };
BeataDialog::BeataDialog(QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags) BeataDialog::BeataDialog( QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags )
: QDialog(parent, flags), mDock(NULL) : QDialog( parent, flags ), mDock( NULL )
{ {
mLayer = theLayer; mLayer = theLayer;
setupUi(this); setupUi( this );
setAttribute(Qt::WA_DeleteOnClose); setAttribute( Qt::WA_DeleteOnClose );
QSettings settings; QSettings settings;
restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() ); restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() );
mView->setLayer(mLayer); mView->setLayer( mLayer );
mFilterModel = (BeataFilterModel *) mView->model(); mFilterModel = ( BeataFilterModel * ) mView->model();
mModel = (BeataModel *)((BeataFilterModel *)mView->model())->sourceModel(); mModel = ( BeataModel * )(( BeataFilterModel * )mView->model() )->sourceModel();
mQuery = query; mQuery = query;
mColumnBox = columnBox; mColumnBox = columnBox;
@ -78,35 +79,35 @@ BeataDialog::BeataDialog(QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFl
} }
setWindowTitle( tr( "Attribute table - %1" ).arg( mLayer->name() ) ); setWindowTitle( tr( "Attribute table - %1" ).arg( mLayer->name() ) );
mRemoveSelectionButton->setIcon(getThemeIcon( "/mActionUnselectAttributes.png" )); mRemoveSelectionButton->setIcon( getThemeIcon( "/mActionUnselectAttributes.png" ) );
mSelectedToTopButton->setIcon(getThemeIcon( "/mActionSelectedToTop.png" )); mSelectedToTopButton->setIcon( getThemeIcon( "/mActionSelectedToTop.png" ) );
mCopySelectedRowsButton->setIcon(getThemeIcon( "/mActionCopySelected.png" )); mCopySelectedRowsButton->setIcon( getThemeIcon( "/mActionCopySelected.png" ) );
mZoomMapToSelectedRowsButton->setIcon(getThemeIcon( "/mActionZoomToSelected.png" ) ); mZoomMapToSelectedRowsButton->setIcon( getThemeIcon( "/mActionZoomToSelected.png" ) );
mInvertSelectionButton->setIcon(getThemeIcon( "/mActionInvertSelection.png" ) ); mInvertSelectionButton->setIcon( getThemeIcon( "/mActionInvertSelection.png" ) );
mToggleEditingButton->setIcon(getThemeIcon( "/mActionToggleEditing.png" ) ); mToggleEditingButton->setIcon( getThemeIcon( "/mActionToggleEditing.png" ) );
// toggle editing // toggle editing
mToggleEditingButton->setCheckable( true ); mToggleEditingButton->setCheckable( true );
mToggleEditingButton->setEnabled( mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ); mToggleEditingButton->setEnabled( mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues );
// info from table to application // info from table to application
connect( this, SIGNAL( editingToggled( QgsMapLayer * ) ), QgisApp::instance(), SLOT( toggleEditing( QgsMapLayer * ) ) ); connect( this, SIGNAL( editingToggled( QgsMapLayer * ) ), QgisApp::instance(), SLOT( toggleEditing( QgsMapLayer * ) ) );
// info from layer to table // info from layer to table
connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) );
connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) ); connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );
connect(searchButton, SIGNAL(clicked()), this, SLOT(search()));
connect(mLayer, SIGNAL(selectionChanged()), this, SLOT(updateSelectionFromLayer())); connect( searchButton, SIGNAL( clicked() ), this, SLOT( search() ) );
connect(mLayer, SIGNAL(layerDeleted()), this, SLOT( close()));
connect(mView->verticalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(updateRowSelection(int))); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
connect(mModel, SIGNAL(modelChanged()), this, SLOT(updateSelection())); connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) );
connect( mView->verticalHeader(), SIGNAL( sectionClicked( int ) ), this, SLOT( updateRowSelection( int ) ) );
connect( mModel, SIGNAL( modelChanged() ), this, SLOT( updateSelection() ) );
//make sure to show all recs on first load //make sure to show all recs on first load
on_cbxShowSelectedOnly_toggled( false ); on_cbxShowSelectedOnly_toggled( false );
mLastClickedHeaderIndex = 0; mLastClickedHeaderIndex = 0;
mSelectionModel = new QItemSelectionModel(mFilterModel); mSelectionModel = new QItemSelectionModel( mFilterModel );
updateSelectionFromLayer(); updateSelectionFromLayer();
} }
@ -117,7 +118,7 @@ BeataDialog::~BeataDialog()
void BeataDialog::closeEvent( QCloseEvent* event ) void BeataDialog::closeEvent( QCloseEvent* event )
{ {
QDialog::closeEvent( event ); QDialog::closeEvent( event );
if ( mDock == NULL ) if ( mDock == NULL )
{ {
QSettings settings; QSettings settings;
@ -129,7 +130,7 @@ void BeataDialog::closeEvent( QCloseEvent* event )
QIcon BeataDialog::getThemeIcon( const QString theName ) QIcon BeataDialog::getThemeIcon( const QString theName )
{ {
// copied from QgisApp::getThemeIcon. To be removed when merged to SVN // copied from QgisApp::getThemeIcon. To be removed when merged to SVN
QString myPreferredPath = QgsApplication::activeThemePath() + QDir::separator() + theName; QString myPreferredPath = QgsApplication::activeThemePath() + QDir::separator() + theName;
QString myDefaultPath = QgsApplication::defaultThemePath() + QDir::separator() + theName; QString myDefaultPath = QgsApplication::defaultThemePath() + QDir::separator() + theName;
if ( QFile::exists( myPreferredPath ) ) if ( QFile::exists( myPreferredPath ) )
@ -150,7 +151,7 @@ QIcon BeataDialog::getThemeIcon( const QString theName )
void BeataDialog::showAdvanced() void BeataDialog::showAdvanced()
{ {
mMenuActions->exec(QCursor::pos()); mMenuActions->exec( QCursor::pos() );
} }
void BeataDialog::on_mSelectedToTopButton_clicked() void BeataDialog::on_mSelectedToTopButton_clicked()
@ -163,29 +164,29 @@ void BeataDialog::on_mSelectedToTopButton_clicked()
mModel->incomingChangeLayout(); mModel->incomingChangeLayout();
QgsFeatureIds::Iterator it = mSelectedFeatures.begin(); QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
for (; it != mSelectedFeatures.end(); ++it, ++freeIndex) for ( ; it != mSelectedFeatures.end(); ++it, ++freeIndex )
{ {
QModelIndex sourceIndex = mFilterModel->mapToSource(mFilterModel->index(freeIndex, 0)); QModelIndex sourceIndex = mFilterModel->mapToSource( mFilterModel->index( freeIndex, 0 ) );
mModel->swapRows(mModel->rowToId(sourceIndex.row()), *it); mModel->swapRows( mModel->rowToId( sourceIndex.row() ), *it );
} }
/* /*
while (it != fids.end()) while (it != fids.end())
{ //map!!!! { //map!!!!
//mModel->swapRows(mModel->rowToId(freeIndex), *it); //mModel->swapRows(mModel->rowToId(freeIndex), *it);
//QModelIndex index = mFilterModel->mapFromSource(mModel->index(mModel->idToRow(*it), 0)); //QModelIndex index = mFilterModel->mapFromSource(mModel->index(mModel->idToRow(*it), 0));
QModelIndex sourceIndex = mFilterModel->mapToSource(mFilterModel->index(freeIndex, 0)); QModelIndex sourceIndex = mFilterModel->mapToSource(mFilterModel->index(freeIndex, 0));
mModel->swapRows(mModel->rowToId(sourceIndex.row()), *it); mModel->swapRows(mModel->rowToId(sourceIndex.row()), *it);
//mModel->swapRows(freeIndex, *it); //mModel->swapRows(freeIndex, *it);
if (fids.empty()) if (fids.empty())
break; break;
else else
++it; ++it;
++freeIndex; ++freeIndex;
} }
*/ */
// just select proper rows // just select proper rows
//mModel->reload(mModel->index(0,0), mModel->index(mModel->rowCount(), mModel->columnCount())); //mModel->reload(mModel->index(0,0), mModel->index(mModel->rowCount(), mModel->columnCount()));
//mModel->changeLayout(); //mModel->changeLayout();
@ -195,7 +196,7 @@ void BeataDialog::on_mSelectedToTopButton_clicked()
void BeataDialog::on_mCopySelectedRowsButton_clicked() void BeataDialog::on_mCopySelectedRowsButton_clicked()
{ {
QgisApp::instance()->editCopy(mLayer); QgisApp::instance()->editCopy( mLayer );
} }
void BeataDialog::on_mZoomMapToSelectedRowsButton_clicked() void BeataDialog::on_mZoomMapToSelectedRowsButton_clicked()
@ -226,8 +227,8 @@ void BeataDialog::columnBoxInit()
QgsFieldMap fieldMap = mLayer->dataProvider()->fields(); QgsFieldMap fieldMap = mLayer->dataProvider()->fields();
QgsFieldMap::Iterator it = fieldMap.begin(); QgsFieldMap::Iterator it = fieldMap.begin();
for (; it != fieldMap.end(); ++it) for ( ; it != fieldMap.end(); ++it )
mColumnBox->addItem(it.value().name()); mColumnBox->addItem( it.value().name() );
} }
int BeataDialog::columnBoxColumnId() int BeataDialog::columnBoxColumnId()
@ -235,8 +236,8 @@ int BeataDialog::columnBoxColumnId()
QgsFieldMap fieldMap = mLayer->dataProvider()->fields(); QgsFieldMap fieldMap = mLayer->dataProvider()->fields();
QgsFieldMap::Iterator it = fieldMap.begin(); QgsFieldMap::Iterator it = fieldMap.begin();
for (; it != fieldMap.end(); ++it) for ( ; it != fieldMap.end(); ++it )
if (it.value().name() == mColumnBox->currentText()) if ( it.value().name() == mColumnBox->currentText() )
return it.key(); return it.key();
return 0; return 0;
@ -245,137 +246,145 @@ int BeataDialog::columnBoxColumnId()
void BeataDialog::updateSelection() void BeataDialog::updateSelection()
{ {
QModelIndex index; QModelIndex index;
mView->setSelectionMode(QAbstractItemView::MultiSelection); mView->setSelectionMode( QAbstractItemView::MultiSelection );
QItemSelection selection; QItemSelection selection;
QgsFeatureIds::Iterator it = mSelectedFeatures.begin(); QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
for (; it != mSelectedFeatures.end(); ++it) for ( ; it != mSelectedFeatures.end(); ++it )
{ {
QModelIndex leftUpIndex = mFilterModel->mapFromSource(mModel->index(mModel->idToRow(*it), 0)); QModelIndex leftUpIndex = mFilterModel->mapFromSource( mModel->index( mModel->idToRow( *it ), 0 ) );
QModelIndex rightBottomIndex = mFilterModel->mapFromSource(mModel->index(mModel->idToRow(*it), mModel->columnCount() - 1)); QModelIndex rightBottomIndex = mFilterModel->mapFromSource( mModel->index( mModel->idToRow( *it ), mModel->columnCount() - 1 ) );
selection.append(QItemSelectionRange(leftUpIndex, rightBottomIndex)); selection.append( QItemSelectionRange( leftUpIndex, rightBottomIndex ) );
//selection.append(QItemSelectionRange(leftUpIndex, leftUpIndex)); //selection.append(QItemSelectionRange(leftUpIndex, leftUpIndex));
} }
mSelectionModel->select(selection, QItemSelectionModel::ClearAndSelect);// | QItemSelectionModel::Columns); mSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );// | QItemSelectionModel::Columns);
mView->setSelectionModel(mSelectionModel); mView->setSelectionModel( mSelectionModel );
mView->setSelectionMode(QAbstractItemView::NoSelection); mView->setSelectionMode( QAbstractItemView::NoSelection );
/*for (int i = 0; i < mModel->rowCount(); ++i) /*for (int i = 0; i < mModel->rowCount(); ++i)
{ {
int id = mModel->rowToId(i); int id = mModel->rowToId(i);
std::cout << id << "\n"; QgsDebugMsg(id);
} }
std::cout << "--------------\n"; QgsDebugMsg("--------------");
*/ */
} }
void BeataDialog::updateRowSelection(int index) void BeataDialog::updateRowSelection( int index )
{ {
// map index to filter model // map index to filter model
//index = mFilterModel->mapFromSource(mModel->index(index, 0)).row(); //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
if (mView->shiftPressed) { if ( mView->shiftPressed )
std::cout << "shift\n"; {
QgsDebugMsg( "shift" );
// get the first and last index of the rows to be selected/deselected // get the first and last index of the rows to be selected/deselected
int first, last; int first, last;
if (index > mLastClickedHeaderIndex) { if ( index > mLastClickedHeaderIndex )
{
first = mLastClickedHeaderIndex + 1; first = mLastClickedHeaderIndex + 1;
last = index; last = index;
} }
else if (index == mLastClickedHeaderIndex) { else if ( index == mLastClickedHeaderIndex )
{
// row was selected and now it is shift-clicked // row was selected and now it is shift-clicked
// ignore the shift and deselect the row // ignore the shift and deselect the row
first = last = index; first = last = index;
} }
else { else
{
first = index; first = index;
last = mLastClickedHeaderIndex - 1; last = mLastClickedHeaderIndex - 1;
} }
// for all the rows update the selection, without starting a new selection // for all the rows update the selection, without starting a new selection
if (first <= last) if ( first <= last )
updateRowSelection(first, last, false); updateRowSelection( first, last, false );
mLastClickedHeaderIndex = last; mLastClickedHeaderIndex = last;
} }
else if (mView->ctrlPressed) { else if ( mView->ctrlPressed )
std::cout << "ctrl\n"; {
QgsDebugMsg( "ctrl" );
// update the single row selection, without starting a new selection // update the single row selection, without starting a new selection
updateRowSelection(index, index, false); updateRowSelection( index, index, false );
// the next shift would start from here // the next shift would start from here
mLastClickedHeaderIndex = index; mLastClickedHeaderIndex = index;
} }
else { else
std::cout << "ordinary click\n"; {
QgsDebugMsg( "ordinary click" );
// update the single row selection, start a new selection if the row was not selected // update the single row selection, start a new selection if the row was not selected
updateRowSelection(index, index, true); updateRowSelection( index, index, true );
// the next shift would start from here // the next shift would start from here
mLastClickedHeaderIndex = index; mLastClickedHeaderIndex = index;
} }
} }
// fast row deselection needed // fast row deselection needed
void BeataDialog::updateRowSelection(int first, int last, bool startNewSelection) void BeataDialog::updateRowSelection( int first, int last, bool startNewSelection )
{ {
disconnect(mLayer, SIGNAL(selectionChanged()), this, SLOT(updateSelectionFromLayer())); disconnect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
//index = mFilterModel->mapFromSource(mModel->index(index, 0)).row(); //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
// Id must be mapped to table/view row // Id must be mapped to table/view row
QModelIndex index = mFilterModel->mapToSource(mFilterModel->index(first, 0)); QModelIndex index = mFilterModel->mapToSource( mFilterModel->index( first, 0 ) );
int fid = mModel->rowToId(index.row()); int fid = mModel->rowToId( index.row() );
bool wasSelected = mSelectedFeatures.contains(fid); bool wasSelected = mSelectedFeatures.contains( fid );
// new selection should be created // new selection should be created
if (startNewSelection) if ( startNewSelection )
{ {
mView->clearSelection(); mView->clearSelection();
mSelectedFeatures.clear(); mSelectedFeatures.clear();
if (wasSelected) if ( wasSelected )
{ {
mLayer->removeSelection(); mLayer->removeSelection();
connect(mLayer, SIGNAL(selectionChanged()), this, SLOT(updateSelectionFromLayer())); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
return; return;
} }
// set clicked row to current // set clicked row to current
mView->setCurrentIndex(mFilterModel->index(first, 0)); mView->setCurrentIndex( mFilterModel->index( first, 0 ) );
mView->setSelectionMode(QAbstractItemView::SingleSelection); mView->setSelectionMode( QAbstractItemView::SingleSelection );
//QModelIndex index = mFilterModel->mapFromSource(mModel->index(first, 0)); //QModelIndex index = mFilterModel->mapFromSource(mModel->index(first, 0));
mView->selectRow(first); mView->selectRow( first );
mView->setSelectionMode(QAbstractItemView::NoSelection); mView->setSelectionMode( QAbstractItemView::NoSelection );
mSelectedFeatures.insert(fid); mSelectedFeatures.insert( fid );
//mLayer->setSelectedFeatures(mSelectedFeatures); //mLayer->setSelectedFeatures(mSelectedFeatures);
mLayer->removeSelection(); mLayer->removeSelection();
mLayer->select(fid); mLayer->select( fid );
//mFilterModel->invalidate(); //mFilterModel->invalidate();
connect(mLayer, SIGNAL(selectionChanged()), this, SLOT(updateSelectionFromLayer())); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
return; return;
} }
// existing selection should be updated // existing selection should be updated
for (int i = first; i <= last; ++i) { for ( int i = first; i <= last; ++i )
if (i > first) { {
if ( i > first )
{
// Id must be mapped to table/view row // Id must be mapped to table/view row
index = mFilterModel->mapToSource(mFilterModel->index(i, 0)); index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
fid = mModel->rowToId(index.row()); fid = mModel->rowToId( index.row() );
wasSelected = mSelectedFeatures.contains(fid); wasSelected = mSelectedFeatures.contains( fid );
} }
if (wasSelected) if ( wasSelected )
mSelectedFeatures.remove(fid); mSelectedFeatures.remove( fid );
else else
mSelectedFeatures.insert(fid); mSelectedFeatures.insert( fid );
} }
//mFilterModel->invalidate(); //mFilterModel->invalidate();
/* /*
QItemSelection selection; QItemSelection selection;
QModelIndex leftUpIndex = mFilterModel->index(first, 0); QModelIndex leftUpIndex = mFilterModel->index(first, 0);
@ -385,72 +394,72 @@ void BeataDialog::updateRowSelection(int first, int last, bool startNewSelection
mView->setSelectionModel(mSelectionModel); mView->setSelectionModel(mSelectionModel);
*/ */
updateSelection(); updateSelection();
mLayer->setSelectedFeatures(mSelectedFeatures); mLayer->setSelectedFeatures( mSelectedFeatures );
connect(mLayer, SIGNAL(selectionChanged()), this, SLOT(updateSelectionFromLayer())); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
} }
void BeataDialog::updateSelectionFromLayer() void BeataDialog::updateSelectionFromLayer()
{ {
std::cout << "updateFromLayer\n"; QgsDebugMsg( "updateFromLayer" );
mSelectedFeatures = mLayer->selectedFeaturesIds(); mSelectedFeatures = mLayer->selectedFeaturesIds();
updateSelection(); updateSelection();
} }
void BeataDialog::doSearch(QString searchString) void BeataDialog::doSearch( QString searchString )
{ {
// parse search string and build parsed tree // parse search string and build parsed tree
QgsSearchString search; QgsSearchString search;
if (!search.setString(searchString)) if ( !search.setString( searchString ) )
{ {
QMessageBox::critical(this, tr("Search string parsing error"), search.parserErrorMsg()); QMessageBox::critical( this, tr( "Search string parsing error" ), search.parserErrorMsg() );
return; return;
} }
QgsSearchTreeNode* searchTree = search.tree(); QgsSearchTreeNode* searchTree = search.tree();
if (searchTree == NULL) if ( searchTree == NULL )
{ {
QMessageBox::information(this, tr("Search results"), tr("You've supplied an empty search string.")); QMessageBox::information( this, tr( "Search results" ), tr( "You've supplied an empty search string." ) );
return; return;
} }
QApplication::setOverrideCursor(Qt::WaitCursor); QApplication::setOverrideCursor( Qt::WaitCursor );
mSelectedFeatures.clear(); mSelectedFeatures.clear();
mLayer->select(mLayer->pendingAllAttributesList(), QgsRectangle(), false); mLayer->select( mLayer->pendingAllAttributesList(), QgsRectangle(), false );
QgsFeature f; QgsFeature f;
while (mLayer->nextFeature(f)) while ( mLayer->nextFeature( f ) )
{ {
if (searchTree->checkAgainst(mLayer->pendingFields(), f.attributeMap())) if ( searchTree->checkAgainst( mLayer->pendingFields(), f.attributeMap() ) )
mSelectedFeatures << f.id(); mSelectedFeatures << f.id();
// check if there were errors during evaluating // check if there were errors during evaluating
if (searchTree->hasError()) if ( searchTree->hasError() )
break; break;
} }
QApplication::restoreOverrideCursor(); QApplication::restoreOverrideCursor();
if (searchTree->hasError()) if ( searchTree->hasError() )
{ {
QMessageBox::critical(this, tr("Error during search"), searchTree->errorMsg()); QMessageBox::critical( this, tr( "Error during search" ), searchTree->errorMsg() );
return; return;
} }
// update view // update view
updateSelection(); updateSelection();
disconnect(mLayer, SIGNAL(selectionChanged()), this, SLOT(updateSelectionFromLayer())); disconnect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
mLayer->setSelectedFeatures(mSelectedFeatures); mLayer->setSelectedFeatures( mSelectedFeatures );
connect(mLayer, SIGNAL(selectionChanged()), this, SLOT(updateSelectionFromLayer())); connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
QString str; QString str;
if (mSelectedFeatures.size()) if ( mSelectedFeatures.size() )
str.sprintf(tr("Found %d matching features.", "", mSelectedFeatures.size()).toUtf8(), mSelectedFeatures.size()); str.sprintf( tr( "Found %d matching features.", "", mSelectedFeatures.size() ).toUtf8(), mSelectedFeatures.size() );
else else
str = tr("No matching features found."); str = tr( "No matching features found." );
QMessageBox::information(this, tr("Search results"), str); QMessageBox::information( this, tr( "Search results" ), str );
} }
void BeataDialog::search() void BeataDialog::search()
@ -459,28 +468,28 @@ void BeataDialog::search()
QString str = mColumnBox->currentText(); QString str = mColumnBox->currentText();
const QgsFieldMap& flds = mLayer->dataProvider()->fields(); const QgsFieldMap& flds = mLayer->dataProvider()->fields();
int fldIndex = mLayer->dataProvider()->fieldNameIndex(str); int fldIndex = mLayer->dataProvider()->fieldNameIndex( str );
QVariant::Type fldType = flds[fldIndex].type(); QVariant::Type fldType = flds[fldIndex].type();
bool numeric = (fldType == QVariant::Int || fldType == QVariant::Double); bool numeric = ( fldType == QVariant::Int || fldType == QVariant::Double );
if (numeric) if ( numeric )
str += " = '"; str += " = '";
else else
str += " ~ '"; str += " ~ '";
str += mQuery->displayText(); str += mQuery->displayText();
str += "'"; str += "'";
doSearch(str); doSearch( str );
} }
void BeataDialog::on_mAdvancedSearchButton_clicked() void BeataDialog::on_mAdvancedSearchButton_clicked()
{ {
QgsSearchQueryBuilder dlg(mLayer, this); QgsSearchQueryBuilder dlg( mLayer, this );
dlg.setSearchString(mQuery->displayText()); dlg.setSearchString( mQuery->displayText() );
if (dlg.exec()) if ( dlg.exec() )
doSearch(dlg.searchString()); doSearch( dlg.searchString() );
} }
void BeataDialog::on_mToggleEditingButton_toggled() void BeataDialog::on_mToggleEditingButton_toggled()
@ -491,10 +500,10 @@ void BeataDialog::on_mToggleEditingButton_toggled()
void BeataDialog::editingToggled() void BeataDialog::editingToggled()
{ {
mToggleEditingButton->setChecked( mLayer->isEditable() ); mToggleEditingButton->setChecked( mLayer->isEditable() );
// (probably reload data if user stopped editing - possible revert) // (probably reload data if user stopped editing - possible revert)
mModel->reload(mModel->index(0,0), mModel->index(mModel->rowCount(), mModel->columnCount())); mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
// not necessary to set table read only if layer is not editable // not necessary to set table read only if layer is not editable
// because model always reflects actual state when returning item flags // because model always reflects actual state when returning item flags
} }
@ -516,5 +525,5 @@ void BeataDialog::revert()
{ {
mLayer->rollBack(); mLayer->rollBack();
mModel->revert(); mModel->revert();
mModel->reload(mModel->index(0,0), mModel->index(mModel->rowCount(), mModel->columnCount())); mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
} }

View File

@ -1,7 +1,7 @@
/*************************************************************************** /***************************************************************************
BeataModel.cpp BeataModel.cpp
-------------------------------------- --------------------------------------
Date : Feb 2009 Date : Feb 2009
Copyright : (C) 2009 Vita Cizek Copyright : (C) 2009 Vita Cizek
Email : weetya (at) gmail.com Email : weetya (at) gmail.com
*************************************************************************** ***************************************************************************
@ -23,18 +23,19 @@
#include <QtGui> #include <QtGui>
#include <QVariant> #include <QVariant>
#include <QtAlgorithms> #include <QtAlgorithms>
#include "qgslogger.h"
//could be faster when type guessed before sorting //could be faster when type guessed before sorting
bool idColumnPair::operator<(const idColumnPair &b) const bool idColumnPair::operator<( const idColumnPair &b ) const
{ {
//QVariat thinks gid is a string! //QVariat thinks gid is a string!
QVariant::Type columnType = columnItem.type(); QVariant::Type columnType = columnItem.type();
if (columnType == QVariant::Int || columnType == QVariant::UInt || columnType == QVariant::LongLong || columnType == QVariant::ULongLong) if ( columnType == QVariant::Int || columnType == QVariant::UInt || columnType == QVariant::LongLong || columnType == QVariant::ULongLong )
return columnItem.toLongLong() < b.columnItem.toLongLong(); return columnItem.toLongLong() < b.columnItem.toLongLong();
if (columnType == QVariant::Double) if ( columnType == QVariant::Double )
return columnItem.toDouble() < b.columnItem.toDouble(); return columnItem.toDouble() < b.columnItem.toDouble();
return columnItem.toString() < b.columnItem.toString(); return columnItem.toString() < b.columnItem.toString();
} }
@ -43,23 +44,23 @@ bool idColumnPair::operator<(const idColumnPair &b) const
// Filter Model // // Filter Model //
////////////////// //////////////////
void BeataFilterModel::sort(int column, Qt::SortOrder order) void BeataFilterModel::sort( int column, Qt::SortOrder order )
{ {
((BeataModel *)sourceModel())->sort(column, order); (( BeataModel * )sourceModel() )->sort( column, order );
} }
BeataFilterModel::BeataFilterModel(QgsVectorLayer* theLayer) BeataFilterModel::BeataFilterModel( QgsVectorLayer* theLayer )
{ {
mLayer = theLayer; mLayer = theLayer;
mHideUnselected = false; mHideUnselected = false;
setDynamicSortFilter(true); setDynamicSortFilter( true );
} }
bool BeataFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const bool BeataFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
{ {
if(mHideUnselected) if ( mHideUnselected )
// unreadable? yes, i agree :-) // unreadable? yes, i agree :-)
return mLayer->selectedFeaturesIds().contains(((BeataModel *)sourceModel())->rowToId(sourceRow)); return mLayer->selectedFeaturesIds().contains((( BeataModel * )sourceModel() )->rowToId( sourceRow ) );
return true; return true;
} }
@ -80,8 +81,9 @@ QModelIndex BeataFilterModel::mapToSource ( const QModelIndex& filterIndex ) con
// BeataModel // // BeataModel //
//////////////// ////////////////
BeataModel::BeataModel(QgsVectorLayer *theLayer, QObject *parent) BeataModel::BeataModel( QgsVectorLayer *theLayer, QObject *parent )
: QAbstractTableModel(parent) { : QAbstractTableModel( parent )
{
mLastRowId = -1; mLastRowId = -1;
mLastRow = NULL; mLastRow = NULL;
mLayer = theLayer; mLayer = theLayer;
@ -89,106 +91,107 @@ BeataModel::BeataModel(QgsVectorLayer *theLayer, QObject *parent)
mFieldCount = mLayer->dataProvider()->fieldCount(); mFieldCount = mLayer->dataProvider()->fieldCount();
mAttributes = mLayer->dataProvider()->attributeIndexes(); mAttributes = mLayer->dataProvider()->attributeIndexes();
connect(mLayer, SIGNAL(layerModified(bool)), this, SLOT( layerModified(bool))); connect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
//connect(mLayer, SIGNAL(attributeAdded(int)), this, SLOT( attributeAdded(int))); //connect(mLayer, SIGNAL(attributeAdded(int)), this, SLOT( attributeAdded(int)));
//connect(mLayer, SIGNAL(attributeDeleted(int)), this, SLOT( attributeDeleted(int))); //connect(mLayer, SIGNAL(attributeDeleted(int)), this, SLOT( attributeDeleted(int)));
//connect(mLayer, SIGNAL(attributeValueChanged(int, int, const QVariant&)), this, SLOT( attributeValueChanged(int, int, const QVariant&))); //connect(mLayer, SIGNAL(attributeValueChanged(int, int, const QVariant&)), this, SLOT( attributeValueChanged(int, int, const QVariant&)));
//connect(mLayer, SIGNAL(featureDeleted(int)), this, SLOT( featureDeleted(int))); //connect(mLayer, SIGNAL(featureDeleted(int)), this, SLOT( featureDeleted(int)));
//connect(mLayer, SIGNAL(featureAdded(int)), this, SLOT( featureAdded(int))); //connect(mLayer, SIGNAL(featureAdded(int)), this, SLOT( featureAdded(int)));
loadLayer(); loadLayer();
} }
void BeataModel::featureDeleted(int fid) void BeataModel::featureDeleted( int fid )
{ {
std::cout << "BM feature deleted\n"; QgsDebugMsg( "entered." );
int idx = mIdRowMap[fid]; int idx = mIdRowMap[fid];
std::cout << idx; QgsDebugMsg( idx );
std::cout << fid; QgsDebugMsg( fid );
#if 0
--mFeatureCount;
mIdRowMap.remove( fid );
mRowIdMap.remove( idx );
/*--mFeatureCount;
mIdRowMap.remove(fid);
mRowIdMap.remove(idx);
// fill the hole in the view // fill the hole in the view
if (idx != mFeatureCount) if ( idx != mFeatureCount )
{ {
std::cout << "jo"; QgsDebugMsg( "jo" );
//mRowIdMap[idx] = mRowIdMap[mFeatureCount]; //mRowIdMap[idx] = mRowIdMap[mFeatureCount];
//mIdRowMap[mRowIdMap[idx]] = idx; //mIdRowMap[mRowIdMap[idx]] = idx;
int movedId = mRowIdMap[mFeatureCount]; int movedId = mRowIdMap[mFeatureCount];
mRowIdMap.remove(mFeatureCount); mRowIdMap.remove( mFeatureCount );
mRowIdMap.insert(idx, movedId); mRowIdMap.insert( idx, movedId );
mIdRowMap[movedId] = idx; mIdRowMap[movedId] = idx;
//mIdRowMap.remove(mRowIdMap[idx]); //mIdRowMap.remove(mRowIdMap[idx]);
//mIdRowMap.insert(mRowIdMap[idx], idx); //mIdRowMap.insert(mRowIdMap[idx], idx);
} }
std::cout << "map sizes:" << mRowIdMap.size() << ", " << mIdRowMap.size(); QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
emit layoutChanged(); emit layoutChanged();
//reload(index(0,0), index(rowCount(), columnCount())); //reload(index(0,0), index(rowCount(), columnCount()));
std::cout << "\n"; #endif
*/
std::cout << "id->row"; QgsDebugMsg( "id->row" );
QMap<int, int>::iterator it; QMap<int, int>::iterator it;
for (it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it) for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
std::cout << it.key() << "->" << *it << "\n"; QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
std::cout << "row->id"; QgsDebugMsg( "row->id" );
for (it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it) for ( it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
std::cout << it.key() << "->" << *it << "\n"; QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
} }
void BeataModel::featureAdded(int fid) void BeataModel::featureAdded( int fid )
{ {
std::cout << "BM feature added\n"; QgsDebugMsg( "BM feature added" );
++mFeatureCount; ++mFeatureCount;
mIdRowMap.insert(fid, mFeatureCount - 1); mIdRowMap.insert( fid, mFeatureCount - 1 );
mRowIdMap.insert(mFeatureCount - 1, fid); mRowIdMap.insert( mFeatureCount - 1, fid );
std::cout << "map sizes:" << mRowIdMap.size() << ", " << mIdRowMap.size() << "\n";; QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
reload(index(0,0), index(rowCount(), columnCount())); reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
} }
void BeataModel::attributeAdded (int idx) void BeataModel::attributeAdded( int idx )
{ {
std::cout << "BM attribute added\n"; QgsDebugMsg( "BM attribute added" );
loadLayer(); loadLayer();
std::cout << "map sizes:" << mRowIdMap.size() << ", " << mIdRowMap.size() << "\n";; QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
reload(index(0,0), index(rowCount(), columnCount())); reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
emit modelChanged(); emit modelChanged();
} }
void BeataModel::attributeDeleted (int idx) void BeataModel::attributeDeleted( int idx )
{ {
std::cout << "BM attribute deleted\n"; QgsDebugMsg( "BM attribute deleted" );
loadLayer(); loadLayer();
std::cout << "map sizes:" << mRowIdMap.size() << ", " << mIdRowMap.size() << "\n";; QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
reload(index(0,0), index(rowCount(), columnCount())); reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
emit modelChanged(); emit modelChanged();
} }
void BeataModel::layerDeleted() void BeataModel::layerDeleted()
{ {
std::cout << "BM attribute deleted\n"; QgsDebugMsg( "entered." );
mIdRowMap.clear(); mIdRowMap.clear();
mRowIdMap.clear(); mRowIdMap.clear();
std::cout << "map sizes:" << mRowIdMap.size() << ", " << mIdRowMap.size() << "\n";; QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
reload(index(0,0), index(rowCount(), columnCount())); reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
}
//TODO: check whether caching in data()/setData() doesn't cache old value
void BeataModel::attributeValueChanged (int fid, int idx, const QVariant &value)
{
std::cout << "BM attribute changed\n";
reload(index(0,0), index(rowCount(), columnCount()));
} }
void BeataModel::layerModified(bool onlyGeometry) //TODO: check whether caching in data()/setData() doesn't cache old value
void BeataModel::attributeValueChanged( int fid, int idx, const QVariant &value )
{ {
if (onlyGeometry) QgsDebugMsg( "entered." );
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
}
void BeataModel::layerModified( bool onlyGeometry )
{
if ( onlyGeometry )
return; return;
loadLayer(); loadLayer();
@ -197,7 +200,7 @@ void BeataModel::layerModified(bool onlyGeometry)
void BeataModel::loadLayer() void BeataModel::loadLayer()
{ {
std::cout << "BM loadlayer\n"; QgsDebugMsg( "entered." );
QgsFeature f; QgsFeature f;
bool ins = false, rm = false; bool ins = false, rm = false;
@ -205,157 +208,157 @@ void BeataModel::loadLayer()
mRowIdMap.clear(); mRowIdMap.clear();
mIdRowMap.clear(); mIdRowMap.clear();
if (mFeatureCount < mLayer->pendingFeatureCount()) if ( mFeatureCount < mLayer->pendingFeatureCount() )
{ {
std::cout<<"ins\n"; QgsDebugMsg( "ins" );
ins = true; ins = true;
beginInsertRows(QModelIndex(), mFeatureCount, mLayer->pendingFeatureCount() - 1); beginInsertRows( QModelIndex(), mFeatureCount, mLayer->pendingFeatureCount() - 1 );
//std::cout << mFeatureCount << ", " << mLayer->pendingFeatureCount() - 1 << "\n"; // QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() - 1));
} }
else if (mFeatureCount > mLayer->pendingFeatureCount()) else if ( mFeatureCount > mLayer->pendingFeatureCount() )
{ {
std::cout<<"rm\n"; QgsDebugMsg( "rm" );
rm = true; rm = true;
beginRemoveRows(QModelIndex(), mLayer->pendingFeatureCount(), mFeatureCount - 1); beginRemoveRows( QModelIndex(), mLayer->pendingFeatureCount(), mFeatureCount - 1 );
//std::cout << mFeatureCount << ", " << mLayer->pendingFeatureCount() -1 << "\n"; // QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() -1));
} }
mLayer->select(QgsAttributeList(), QgsRectangle(), false); mLayer->select( QgsAttributeList(), QgsRectangle(), false );
for (int i = 0; mLayer->nextFeature(f); ++i) for ( int i = 0; mLayer->nextFeature( f ); ++i )
{ {
mRowIdMap.insert(i, f.id()); mRowIdMap.insert( i, f.id() );
mIdRowMap.insert(f.id(), i); mIdRowMap.insert( f.id(), i );
} }
// not needed when we have featureAdded signal // not needed when we have featureAdded signal
mFeatureCount = mLayer->pendingFeatureCount(); mFeatureCount = mLayer->pendingFeatureCount();
mFieldCount = mLayer->dataProvider()->fieldCount(); mFieldCount = mLayer->dataProvider()->fieldCount();
if (ins) if ( ins )
{ {
endInsertRows(); endInsertRows();
std::cout << "end ins\n"; QgsDebugMsg( "end ins" );
} }
else if (rm) else if ( rm )
{ {
endRemoveRows(); endRemoveRows();
std::cout << "end rm\n"; QgsDebugMsg( "end rm" );
} }
/* std::cout << "id->row"; #if 0
QgsDebugMsg( "id->row" );
QMap<int, int>::iterator it; QMap<int, int>::iterator it;
for (it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it) for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
std::cout << it.key() << "->" << *it << "\n"; QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
std::cout << "row->id";
for (it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it)
std::cout << it.key() << "->" << *it << "\n";*/
QgsDebugMsg( "row->id" );
for ( it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
#endif
} }
void BeataModel::swapRows(int a, int b) void BeataModel::swapRows( int a, int b )
{ {
if (a == b) if ( a == b )
return; return;
int rowA = idToRow(a); int rowA = idToRow( a );
int rowB = idToRow(b); int rowB = idToRow( b );
//emit layoutAboutToBeChanged(); //emit layoutAboutToBeChanged();
mRowIdMap.remove(rowA); mRowIdMap.remove( rowA );
mRowIdMap.remove(rowB); mRowIdMap.remove( rowB );
mRowIdMap.insert(rowA, b); mRowIdMap.insert( rowA, b );
mRowIdMap.insert(rowB, a); mRowIdMap.insert( rowB, a );
mIdRowMap.remove(a); mIdRowMap.remove( a );
mIdRowMap.remove(b); mIdRowMap.remove( b );
mIdRowMap.insert(a, rowB); mIdRowMap.insert( a, rowB );
mIdRowMap.insert(b, rowA); mIdRowMap.insert( b, rowA );
//emit layoutChanged(); //emit layoutChanged();
} }
int BeataModel::idToRow(const int id) const int BeataModel::idToRow( const int id ) const
{ {
if (!mIdRowMap.contains(id)) if ( !mIdRowMap.contains( id ) )
{ {
std::cout << "idToRow: id " << id << " not in map\n"; QgsDebugMsg( QString( "idToRow: id %1 not in map" ).arg( id ) );
return -1; return -1;
} }
return mIdRowMap[id]; return mIdRowMap[id];
} }
int BeataModel::rowToId(const int id) const int BeataModel::rowToId( const int id ) const
{ {
if (!mRowIdMap.contains(id)) if ( !mRowIdMap.contains( id ) )
{ {
std::cout << "rowToId: row " << id << " not in map\n"; QgsDebugMsg( QString( "rowToId: row %1 not in map" ).arg( id ) );
return -1; return -1;
} }
return mRowIdMap[id]; return mRowIdMap[id];
} }
int BeataModel::rowCount(const QModelIndex &parent) const int BeataModel::rowCount( const QModelIndex &parent ) const
{ {
return mFeatureCount; return mFeatureCount;
} }
int BeataModel::columnCount(const QModelIndex &parent) const int BeataModel::columnCount( const QModelIndex &parent ) const
{ {
return mFieldCount; return mFieldCount;
} }
QVariant BeataModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant BeataModel::headerData( int section, Qt::Orientation orientation, int role ) const
{ {
if (role == Qt::DisplayRole) if ( role == Qt::DisplayRole )
{ {
if (orientation == Qt::Vertical) //row if ( orientation == Qt::Vertical ) //row
{ {
return QVariant(section); return QVariant( section );
} }
else else
{ {
QgsField field = mLayer->dataProvider()->fields()[section]; //column QgsField field = mLayer->dataProvider()->fields()[section]; //column
return QVariant(field.name()); return QVariant( field.name() );
} }
} }
else return QVariant(); else return QVariant();
} }
void BeataModel::sort(int column, Qt::SortOrder order) void BeataModel::sort( int column, Qt::SortOrder order )
{ {
QgsAttributeMap row; QgsAttributeMap row;
idColumnPair pair; idColumnPair pair;
QgsAttributeList attrs; QgsAttributeList attrs;
QgsFeature f; QgsFeature f;
attrs.append(column); attrs.append( column );
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
//std::cout << "SORTing\n"; // QgsDebugMsg("SORTing");
mSortList.clear(); mSortList.clear();
mLayer->select(attrs, QgsRectangle(), false); mLayer->select( attrs, QgsRectangle(), false );
while (mLayer->nextFeature(f)) while ( mLayer->nextFeature( f ) )
{ {
row = f.attributeMap(); row = f.attributeMap();
pair.id = f.id(); pair.id = f.id();
pair.columnItem = row[column]; pair.columnItem = row[column];
mSortList.append(pair); mSortList.append( pair );
} }
if (order == Qt::AscendingOrder) if ( order == Qt::AscendingOrder )
qStableSort(mSortList.begin(), mSortList.end()); qStableSort( mSortList.begin(), mSortList.end() );
else else
qStableSort(mSortList.begin(), mSortList.end(), qGreater<idColumnPair>()); qStableSort( mSortList.begin(), mSortList.end(), qGreater<idColumnPair>() );
// recalculate id<->row maps // recalculate id<->row maps
mRowIdMap.clear(); mRowIdMap.clear();
@ -363,10 +366,10 @@ void BeataModel::sort(int column, Qt::SortOrder order)
int i = 0; int i = 0;
QList<idColumnPair>::Iterator it; QList<idColumnPair>::Iterator it;
for (it = mSortList.begin(); it != mSortList.end(); ++it, ++i) for ( it = mSortList.begin(); it != mSortList.end(); ++it, ++i )
{ {
mRowIdMap.insert(i, it->id); mRowIdMap.insert( i, it->id );
mIdRowMap.insert(it->id, i); mIdRowMap.insert( it->id, i );
} }
// restore selection // restore selection
@ -375,96 +378,97 @@ void BeataModel::sort(int column, Qt::SortOrder order)
emit modelChanged(); emit modelChanged();
} }
QVariant BeataModel::data(const QModelIndex &index, int role) const QVariant BeataModel::data( const QModelIndex &index, int role ) const
{ {
if (!index.isValid() || (role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole) ) if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
return QVariant(); return QVariant();
QVariant::Type fldType = mLayer->dataProvider()->fields()[index.column()].type(); QVariant::Type fldType = mLayer->dataProvider()->fields()[index.column()].type();
bool fldNumeric = (fldType == QVariant::Int || fldType == QVariant::Double); bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double );
if (role == Qt::TextAlignmentRole)
{
if (fldNumeric)
return QVariant(Qt::AlignRight);
else
return QVariant(Qt::AlignLeft);
}
// if we don't have the row in current cache, load it from layer first
if (mLastRowId != rowToId(index.row()))
{
bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true);
if (!res) if ( role == Qt::TextAlignmentRole )
return QVariant("ERROR"); {
if ( fldNumeric )
mLastRowId = rowToId(index.row()); return QVariant( Qt::AlignRight );
mLastRow = (QgsAttributeMap *)(&(mFeat.attributeMap())); else
return QVariant( Qt::AlignLeft );
} }
QVariant& val = (*mLastRow)[index.column()]; // if we don't have the row in current cache, load it from layer first
if ( mLastRowId != rowToId( index.row() ) )
if (val.isNull()) {
bool res = mLayer->featureAtId( rowToId( index.row() ), mFeat, false, true );
if ( !res )
return QVariant( "ERROR" );
mLastRowId = rowToId( index.row() );
mLastRow = ( QgsAttributeMap * )( &( mFeat.attributeMap() ) );
}
QVariant& val = ( *mLastRow )[index.column()];
if ( val.isNull() )
{ {
// if the value is NULL, show that in table, but don't show "NULL" text in editor // if the value is NULL, show that in table, but don't show "NULL" text in editor
if (role == Qt::EditRole) if ( role == Qt::EditRole )
return QVariant(); return QVariant();
else else
return QVariant("NULL"); return QVariant( "NULL" );
} }
// force also numeric data for EditRole to be strings // force also numeric data for EditRole to be strings
// otherwise it creates spinboxes instead of line edits // otherwise it creates spinboxes instead of line edits
// (probably not what we do want) // (probably not what we do want)
if (fldNumeric && role == Qt::EditRole) if ( fldNumeric && role == Qt::EditRole )
return val.toString(); return val.toString();
// convert to QString from some other representation // convert to QString from some other representation
// this prevents displaying greater numbers in exponential format // this prevents displaying greater numbers in exponential format
return val.toString(); return val.toString();
} }
bool BeataModel::setData(const QModelIndex &index, const QVariant &value, int role) bool BeataModel::setData( const QModelIndex &index, const QVariant &value, int role )
{ {
if (!index.isValid() || role != Qt::EditRole) if ( !index.isValid() || role != Qt::EditRole )
return false; return false;
if (!mLayer->isEditable()) if ( !mLayer->isEditable() )
return false; return false;
bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true); bool res = mLayer->featureAtId( rowToId( index.row() ), mFeat, false, true );
if (res) { if ( res )
mLastRowId = rowToId(index.row()); {
mLastRow = (QgsAttributeMap *)(&(mFeat.attributeMap())); mLastRowId = rowToId( index.row() );
mLastRow = ( QgsAttributeMap * )( &( mFeat.attributeMap() ) );
mLayer->changeAttributeValue(rowToId(index.row()), index.column(), value, true); mLayer->changeAttributeValue( rowToId( index.row() ), index.column(), value, true );
} }
if (!mLayer->isModified()) if ( !mLayer->isModified() )
return false; return false;
emit dataChanged(index, index); emit dataChanged( index, index );
return true; return true;
} }
Qt::ItemFlags BeataModel::flags(const QModelIndex &index) const Qt::ItemFlags BeataModel::flags( const QModelIndex &index ) const
{ {
if (!index.isValid()) if ( !index.isValid() )
return Qt::ItemIsEnabled; return Qt::ItemIsEnabled;
Qt::ItemFlags flags = QAbstractItemModel::flags(index); Qt::ItemFlags flags = QAbstractItemModel::flags( index );
if (mLayer->isEditable()) if ( mLayer->isEditable() )
flags |= Qt::ItemIsEditable; flags |= Qt::ItemIsEditable;
return flags; return flags;
} }
void BeataModel::reload(const QModelIndex &index1, const QModelIndex &index2) void BeataModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
{ {
emit dataChanged(index1, index2); emit dataChanged( index1, index2 );
} }
void BeataModel::resetModel() void BeataModel::resetModel()
@ -489,142 +493,145 @@ void BeataModel::incomingChangeLayout()
void BeataMemModel::loadLayer() void BeataMemModel::loadLayer()
{ {
BeataModel::loadLayer(); BeataModel::loadLayer();
mLayer->select(mLayer->pendingAllAttributesList(), QgsRectangle(), false); mLayer->select( mLayer->pendingAllAttributesList(), QgsRectangle(), false );
QgsFeature f; QgsFeature f;
while (mLayer->nextFeature(f)) while ( mLayer->nextFeature( f ) )
mFeatureMap.insert(f.id(), f); mFeatureMap.insert( f.id(), f );
} }
BeataMemModel::BeataMemModel BeataMemModel::BeataMemModel
(QgsVectorLayer *theLayer) ( QgsVectorLayer *theLayer )
: BeataModel(theLayer) : BeataModel( theLayer )
{ {
loadLayer(); loadLayer();
} }
QVariant BeataMemModel::data(const QModelIndex &index, int role) const QVariant BeataMemModel::data( const QModelIndex &index, int role ) const
{ {
if (!index.isValid() || (role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole)) if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
return QVariant(); return QVariant();
QVariant::Type fldType = mLayer->dataProvider()->fields()[index.column()].type(); QVariant::Type fldType = mLayer->dataProvider()->fields()[index.column()].type();
bool fldNumeric = (fldType == QVariant::Int || fldType == QVariant::Double); bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double );
if (role == Qt::TextAlignmentRole) if ( role == Qt::TextAlignmentRole )
{ {
if (fldNumeric) if ( fldNumeric )
return QVariant(Qt::AlignRight); return QVariant( Qt::AlignRight );
else else
return QVariant(Qt::AlignLeft); return QVariant( Qt::AlignLeft );
} }
// if we don't have the row in current cache, load it from layer first // if we don't have the row in current cache, load it from layer first
if (mLastRowId != rowToId(index.row())) if ( mLastRowId != rowToId( index.row() ) )
{ {
//bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true); //bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true);
bool res = mFeatureMap.contains(rowToId(index.row())); bool res = mFeatureMap.contains( rowToId( index.row() ) );
if (!res) if ( !res )
return QVariant("ERROR"); return QVariant( "ERROR" );
mLastRowId = rowToId(index.row()); mLastRowId = rowToId( index.row() );
mFeat = mFeatureMap[rowToId(index.row())]; mFeat = mFeatureMap[rowToId( index.row() )];
mLastRow = (QgsAttributeMap *)(&(mFeat.attributeMap())); mLastRow = ( QgsAttributeMap * )( &( mFeat.attributeMap() ) );
} }
QVariant& val = (*mLastRow)[index.column()];
if (val.isNull()) QVariant& val = ( *mLastRow )[index.column()];
if ( val.isNull() )
{ {
// if the value is NULL, show that in table, but don't show "NULL" text in editor // if the value is NULL, show that in table, but don't show "NULL" text in editor
if (role == Qt::EditRole) if ( role == Qt::EditRole )
return QVariant(); return QVariant();
else else
return QVariant("NULL"); return QVariant( "NULL" );
} }
// force also numeric data for EditRole to be strings // force also numeric data for EditRole to be strings
// otherwise it creates spinboxes instead of line edits // otherwise it creates spinboxes instead of line edits
// (probably not what we do want) // (probably not what we do want)
if (fldNumeric && role == Qt::EditRole) if ( fldNumeric && role == Qt::EditRole )
return val.toString(); return val.toString();
// convert to QString from some other representation // convert to QString from some other representation
// this prevents displaying greater numbers in exponential format // this prevents displaying greater numbers in exponential format
return val.toString(); return val.toString();
} }
bool BeataMemModel::setData(const QModelIndex &index, const QVariant &value, int role) bool BeataMemModel::setData( const QModelIndex &index, const QVariant &value, int role )
{ {
if (!index.isValid() || role != Qt::EditRole) if ( !index.isValid() || role != Qt::EditRole )
return false; return false;
if (!mLayer->isEditable()) if ( !mLayer->isEditable() )
return false; return false;
//bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true); //bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true);
bool res = mFeatureMap.contains(rowToId(index.row())); bool res = mFeatureMap.contains( rowToId( index.row() ) );
if (res) { if ( res )
mLastRowId = rowToId(index.row()); {
mFeat = mFeatureMap[rowToId(index.row())]; mLastRowId = rowToId( index.row() );
mLastRow = (QgsAttributeMap *)(&(mFeat.attributeMap())); mFeat = mFeatureMap[rowToId( index.row() )];
mLastRow = ( QgsAttributeMap * )( &( mFeat.attributeMap() ) );
//std::cout << mFeatureMap[rowToId(index.row())].id(); // QgsDebugMsg(mFeatureMap[rowToId(index.row())].id());
mFeatureMap[rowToId(index.row())].changeAttribute(index.column(), value); mFeatureMap[rowToId( index.row() )].changeAttribute( index.column(), value );
// propagate back to the layer // propagate back to the layer
mLayer->changeAttributeValue(rowToId(index.row()), index.column(), value, true); mLayer->changeAttributeValue( rowToId( index.row() ), index.column(), value, true );
} }
if (!mLayer->isModified()) if ( !mLayer->isModified() )
return false; return false;
emit dataChanged(index, index); emit dataChanged( index, index );
return true; return true;
} }
void BeataMemModel::featureDeleted(int fid) void BeataMemModel::featureDeleted( int fid )
{ {
std::cout << "BMM feature deleted\n"; QgsDebugMsg( "entered." );
mFeatureMap.remove(fid); mFeatureMap.remove( fid );
BeataModel::featureDeleted(fid); BeataModel::featureDeleted( fid );
} }
void BeataMemModel::featureAdded(int fid) void BeataMemModel::featureAdded( int fid )
{ {
std::cout << "BMM feature added\n"; QgsDebugMsg( "entered." );
QgsFeature f; QgsFeature f;
mLayer->featureAtId(fid, f, false, true); mLayer->featureAtId( fid, f, false, true );
mFeatureMap.insert(fid, f); mFeatureMap.insert( fid, f );
BeataModel::featureAdded(fid); BeataModel::featureAdded( fid );
} }
/*void BeataMemModel::attributeAdded (int idx) #if 0
void BeataMemModel::attributeAdded( int idx )
{ {
std::cout << "attribute added\n"; QgsDebugMsg( "entered." );
loadLayer(); loadLayer();
reload(index(0,0), index(rowCount(), columnCount())); reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
} }
void BeataMemModel::attributeDeleted (int idx) void BeataMemModel::attributeDeleted( int idx )
{ {
std::cout << "attribute deleted\n"; QgsDebugMsg( "entered." );
loadLayer(); loadLayer();
reload(index(0,0), index(rowCount(), columnCount())); reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
} }
*/ #endif
void BeataMemModel::layerDeleted ()
void BeataMemModel::layerDeleted()
{ {
std::cout << "BMM layer del\n"; QgsDebugMsg( "entered." );
mFeatureMap.clear(); mFeatureMap.clear();
BeataModel::layerDeleted(); BeataModel::layerDeleted();
} }
void BeataMemModel::attributeValueChanged (int fid, int idx, const QVariant &value) void BeataMemModel::attributeValueChanged( int fid, int idx, const QVariant &value )
{ {
std::cout << "BMM attribute changed\n"; QgsDebugMsg( "entered." );
mFeatureMap[fid].changeAttribute(idx, value); mFeatureMap[fid].changeAttribute( idx, value );
reload(index(0,0), index(rowCount(), columnCount())); reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
} }