[QGIS Commit] r10551 - in trunk/qgis/src/app: . attributetable
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Mon Apr 13 05:17:47 EDT 2009
Author: wonder
Date: 2009-04-13 05:17:47 -0400 (Mon, 13 Apr 2009)
New Revision: 10551
Added:
trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp
trunk/qgis/src/app/attributetable/qgsattributetabledialog.h
trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp
trunk/qgis/src/app/attributetable/qgsattributetablemodel.h
trunk/qgis/src/app/attributetable/qgsattributetableview.cpp
trunk/qgis/src/app/attributetable/qgsattributetableview.h
Removed:
trunk/qgis/src/app/attributetable/BeataDialog.cpp
trunk/qgis/src/app/attributetable/BeataDialog.h
trunk/qgis/src/app/attributetable/BeataModel.cpp
trunk/qgis/src/app/attributetable/BeataModel.h
trunk/qgis/src/app/attributetable/BeataView.cpp
trunk/qgis/src/app/attributetable/BeataView.h
Modified:
trunk/qgis/src/app/CMakeLists.txt
Log:
Renaming of files "Beata" -> "qgsattributetable".
Build temporarily broken, to be fixed in next commit.
Modified: trunk/qgis/src/app/CMakeLists.txt
===================================================================
--- trunk/qgis/src/app/CMakeLists.txt 2009-04-13 09:10:22 UTC (rev 10550)
+++ trunk/qgis/src/app/CMakeLists.txt 2009-04-13 09:17:47 UTC (rev 10551)
@@ -83,9 +83,9 @@
ogr/qgsopenvectorlayerdialog.cpp
ogr/qgsnewogrconnection.cpp
- attributetable/BeataDialog.cpp
- attributetable/BeataModel.cpp
- attributetable/BeataView.cpp
+ attributetable/qgsattributetabledialog.cpp
+ attributetable/qgsattributetablemodel.cpp
+ attributetable/qgsattributetableview.cpp
)
@@ -153,8 +153,8 @@
ogr/qgsopenvectorlayerdialog.h
ogr/qgsnewogrconnection.h
- attributetable/BeataDialog.h
- attributetable/BeataModel.h
+ attributetable/qgsattributetabledialog.h
+ attributetable/qgsattributetablemodel.h
)
IF (POSTGRES_FOUND)
Deleted: trunk/qgis/src/app/attributetable/BeataDialog.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/BeataDialog.cpp 2009-04-13 09:10:22 UTC (rev 10550)
+++ trunk/qgis/src/app/attributetable/BeataDialog.cpp 2009-04-13 09:17:47 UTC (rev 10551)
@@ -1,529 +0,0 @@
-/***************************************************************************
- BeataDialog.cpp
- BEtter Attribute TAble
- -------------------
- date : Feb 2009
- copyright : Vita Cizek
- email : weetya (at) gmail.com
-
- ***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include <QtGui>
-
-#include "BeataDialog.h"
-#include "BeataModel.h"
-#include "BeataView.h"
-
-#include <qgsapplication.h>
-#include <qgsvectordataprovider.h>
-#include <qgsvectorlayer.h>
-#include <qgssearchstring.h>
-#include <qgssearchtreenode.h>
-
-#include "qgisapp.h"
-#include "qgssearchquerybuilder.h"
-#include "qgslogger.h"
-
-
-class QBeataTableDock : public QDockWidget
-{
- public:
- QBeataTableDock( const QString & title, QWidget * parent = 0, Qt::WindowFlags flags = 0 )
- : QDockWidget( title, parent, flags )
- {
- setObjectName( "AttributeTable" ); // set object name so the position can be saved
- }
-
- virtual void closeEvent( QCloseEvent * ev )
- {
- deleteLater();
- }
-};
-
-
-BeataDialog::BeataDialog( QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags )
- : QDialog( parent, flags ), mDock( NULL )
-{
- mLayer = theLayer;
-
- setupUi( this );
-
- setAttribute( Qt::WA_DeleteOnClose );
-
- QSettings settings;
- restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() );
-
- mView->setLayer( mLayer );
- mFilterModel = ( BeataFilterModel * ) mView->model();
- mModel = ( BeataModel * )(( BeataFilterModel * )mView->model() )->sourceModel();
-
- mQuery = query;
- mColumnBox = columnBox;
- columnBoxInit();
-
- QSettings mySettings;
- bool myDockFlag = mySettings.value( "/qgis/dockAttributeTable", false ).toBool();
- if ( myDockFlag )
- {
- mDock = new QBeataTableDock( tr( "Attribute table - %1" ).arg( mLayer->name() ), QgisApp::instance() );
- mDock->setAllowedAreas( Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea );
- mDock->setWidget( this );
- QgisApp::instance()->addDockWidget( Qt::BottomDockWidgetArea, mDock );
- }
-
- setWindowTitle( tr( "Attribute table - %1" ).arg( mLayer->name() ) );
-
- mRemoveSelectionButton->setIcon( getThemeIcon( "/mActionUnselectAttributes.png" ) );
- mSelectedToTopButton->setIcon( getThemeIcon( "/mActionSelectedToTop.png" ) );
- mCopySelectedRowsButton->setIcon( getThemeIcon( "/mActionCopySelected.png" ) );
- mZoomMapToSelectedRowsButton->setIcon( getThemeIcon( "/mActionZoomToSelected.png" ) );
- mInvertSelectionButton->setIcon( getThemeIcon( "/mActionInvertSelection.png" ) );
- mToggleEditingButton->setIcon( getThemeIcon( "/mActionToggleEditing.png" ) );
- // toggle editing
- mToggleEditingButton->setCheckable( true );
- mToggleEditingButton->setEnabled( mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues );
-
- // info from table to application
- connect( this, SIGNAL( editingToggled( QgsMapLayer * ) ), QgisApp::instance(), SLOT( toggleEditing( QgsMapLayer * ) ) );
- // info from layer to table
- connect( mLayer, SIGNAL( editingStarted() ), 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( 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
- on_cbxShowSelectedOnly_toggled( false );
-
- mLastClickedHeaderIndex = 0;
- mSelectionModel = new QItemSelectionModel( mFilterModel );
- updateSelectionFromLayer();
-}
-
-BeataDialog::~BeataDialog()
-{
-}
-
-void BeataDialog::closeEvent( QCloseEvent* event )
-{
- QDialog::closeEvent( event );
-
- if ( mDock == NULL )
- {
- QSettings settings;
- settings.setValue( "/Windows/BetterAttributeTable/geometry", saveGeometry() );
- }
-}
-
-
-QIcon BeataDialog::getThemeIcon( const QString theName )
-{
- // copied from QgisApp::getThemeIcon. To be removed when merged to SVN
-
- QString myPreferredPath = QgsApplication::activeThemePath() + QDir::separator() + theName;
- QString myDefaultPath = QgsApplication::defaultThemePath() + QDir::separator() + theName;
- if ( QFile::exists( myPreferredPath ) )
- {
- return QIcon( myPreferredPath );
- }
- else if ( QFile::exists( myDefaultPath ) )
- {
- //could still return an empty icon if it
- //doesnt exist in the default theme either!
- return QIcon( myDefaultPath );
- }
- else
- {
- return QIcon();
- }
-}
-
-void BeataDialog::showAdvanced()
-{
- mMenuActions->exec( QCursor::pos() );
-}
-
-void BeataDialog::on_mSelectedToTopButton_clicked()
-{
- int freeIndex = 0;
-
- //QgsFeatureIds fids = mSelectedFeatures;
- //QgsFeatureIds::Iterator it = fids.begin();
-
- mModel->incomingChangeLayout();
-
- QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
- for ( ; it != mSelectedFeatures.end(); ++it, ++freeIndex )
- {
- QModelIndex sourceIndex = mFilterModel->mapToSource( mFilterModel->index( freeIndex, 0 ) );
- mModel->swapRows( mModel->rowToId( sourceIndex.row() ), *it );
- }
-
- /*
- while (it != fids.end())
- { //map!!!!
- //mModel->swapRows(mModel->rowToId(freeIndex), *it);
- //QModelIndex index = mFilterModel->mapFromSource(mModel->index(mModel->idToRow(*it), 0));
- QModelIndex sourceIndex = mFilterModel->mapToSource(mFilterModel->index(freeIndex, 0));
- mModel->swapRows(mModel->rowToId(sourceIndex.row()), *it);
- //mModel->swapRows(freeIndex, *it);
-
- if (fids.empty())
- break;
- else
- ++it;
-
- ++freeIndex;
- }
- */
- // just select proper rows
- //mModel->reload(mModel->index(0,0), mModel->index(mModel->rowCount(), mModel->columnCount()));
- //mModel->changeLayout();
- mModel->resetModel();
- updateSelection();
-}
-
-void BeataDialog::on_mCopySelectedRowsButton_clicked()
-{
- QgisApp::instance()->editCopy( mLayer );
-}
-
-void BeataDialog::on_mZoomMapToSelectedRowsButton_clicked()
-{
- QgisApp::instance()->zoomToSelected();
-}
-
-void BeataDialog::on_mInvertSelectionButton_clicked()
-{
- mLayer->invertSelection();
-}
-
-void BeataDialog::on_mRemoveSelectionButton_clicked()
-{
- mLayer->removeSelection();
-}
-
-void BeataDialog::on_cbxShowSelectedOnly_toggled( bool theFlag )
-{
- mFilterModel->mHideUnselected = theFlag;
- mFilterModel->invalidate();
- //TODO: weird
- //mModel->changeLayout();
-}
-
-void BeataDialog::columnBoxInit()
-{
- QgsFieldMap fieldMap = mLayer->dataProvider()->fields();
- QgsFieldMap::Iterator it = fieldMap.begin();
-
- for ( ; it != fieldMap.end(); ++it )
- mColumnBox->addItem( it.value().name() );
-}
-
-int BeataDialog::columnBoxColumnId()
-{
- QgsFieldMap fieldMap = mLayer->dataProvider()->fields();
- QgsFieldMap::Iterator it = fieldMap.begin();
-
- for ( ; it != fieldMap.end(); ++it )
- if ( it.value().name() == mColumnBox->currentText() )
- return it.key();
-
- return 0;
-}
-
-void BeataDialog::updateSelection()
-{
- QModelIndex index;
- mView->setSelectionMode( QAbstractItemView::MultiSelection );
-
- QItemSelection selection;
-
- QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
- for ( ; it != mSelectedFeatures.end(); ++it )
- {
- QModelIndex leftUpIndex = mFilterModel->mapFromSource( mModel->index( mModel->idToRow( *it ), 0 ) );
- QModelIndex rightBottomIndex = mFilterModel->mapFromSource( mModel->index( mModel->idToRow( *it ), mModel->columnCount() - 1 ) );
- selection.append( QItemSelectionRange( leftUpIndex, rightBottomIndex ) );
- //selection.append(QItemSelectionRange(leftUpIndex, leftUpIndex));
- }
-
- mSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );// | QItemSelectionModel::Columns);
- mView->setSelectionModel( mSelectionModel );
- mView->setSelectionMode( QAbstractItemView::NoSelection );
-
- /*for (int i = 0; i < mModel->rowCount(); ++i)
- {
- int id = mModel->rowToId(i);
- QgsDebugMsg(id);
- }
- QgsDebugMsg("--------------");
- */
-}
-
-void BeataDialog::updateRowSelection( int index )
-{
- // map index to filter model
- //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
-
- if ( mView->shiftPressed )
- {
- QgsDebugMsg( "shift" );
- // get the first and last index of the rows to be selected/deselected
- int first, last;
- if ( index > mLastClickedHeaderIndex )
- {
- first = mLastClickedHeaderIndex + 1;
- last = index;
- }
- else if ( index == mLastClickedHeaderIndex )
- {
- // row was selected and now it is shift-clicked
- // ignore the shift and deselect the row
- first = last = index;
- }
- else
- {
- first = index;
- last = mLastClickedHeaderIndex - 1;
- }
-
- // for all the rows update the selection, without starting a new selection
- if ( first <= last )
- updateRowSelection( first, last, false );
-
- mLastClickedHeaderIndex = last;
- }
- else if ( mView->ctrlPressed )
- {
- QgsDebugMsg( "ctrl" );
- // update the single row selection, without starting a new selection
- updateRowSelection( index, index, false );
-
- // the next shift would start from here
- mLastClickedHeaderIndex = index;
- }
- else
- {
- QgsDebugMsg( "ordinary click" );
- // update the single row selection, start a new selection if the row was not selected
- updateRowSelection( index, index, true );
-
- // the next shift would start from here
- mLastClickedHeaderIndex = index;
- }
-}
-
-// fast row deselection needed
-void BeataDialog::updateRowSelection( int first, int last, bool startNewSelection )
-{
- disconnect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
-
- //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
- // Id must be mapped to table/view row
- QModelIndex index = mFilterModel->mapToSource( mFilterModel->index( first, 0 ) );
- int fid = mModel->rowToId( index.row() );
- bool wasSelected = mSelectedFeatures.contains( fid );
-
- // new selection should be created
- if ( startNewSelection )
- {
- mView->clearSelection();
- mSelectedFeatures.clear();
-
- if ( wasSelected )
- {
- mLayer->removeSelection();
- connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
- return;
- }
-
- // set clicked row to current
- mView->setCurrentIndex( mFilterModel->index( first, 0 ) );
- mView->setSelectionMode( QAbstractItemView::SingleSelection );
-
- //QModelIndex index = mFilterModel->mapFromSource(mModel->index(first, 0));
-
- mView->selectRow( first );
- mView->setSelectionMode( QAbstractItemView::NoSelection );
-
- mSelectedFeatures.insert( fid );
- //mLayer->setSelectedFeatures(mSelectedFeatures);
- mLayer->removeSelection();
- mLayer->select( fid );
- //mFilterModel->invalidate();
- connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
- return;
- }
-
- // existing selection should be updated
- for ( int i = first; i <= last; ++i )
- {
- if ( i > first )
- {
- // Id must be mapped to table/view row
- index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
- fid = mModel->rowToId( index.row() );
- wasSelected = mSelectedFeatures.contains( fid );
- }
-
- if ( wasSelected )
- mSelectedFeatures.remove( fid );
- else
- mSelectedFeatures.insert( fid );
- }
- //mFilterModel->invalidate();
-
- /*
- QItemSelection selection;
- QModelIndex leftUpIndex = mFilterModel->index(first, 0);
- QModelIndex rightBottomIndex = mFilterModel->index(last, mModel->columnCount() - 1);
- selection.append(QItemSelectionRange(leftUpIndex, rightBottomIndex));
- mSelectionModel->select(selection, QItemSelectionModel::Select);
- mView->setSelectionModel(mSelectionModel);
- */
- updateSelection();
- mLayer->setSelectedFeatures( mSelectedFeatures );
- connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
-}
-
-void BeataDialog::updateSelectionFromLayer()
-{
- QgsDebugMsg( "updateFromLayer" );
- mSelectedFeatures = mLayer->selectedFeaturesIds();
- updateSelection();
-}
-
-void BeataDialog::doSearch( QString searchString )
-{
- // parse search string and build parsed tree
- QgsSearchString search;
- if ( !search.setString( searchString ) )
- {
- QMessageBox::critical( this, tr( "Search string parsing error" ), search.parserErrorMsg() );
- return;
- }
-
- QgsSearchTreeNode* searchTree = search.tree();
- if ( searchTree == NULL )
- {
- QMessageBox::information( this, tr( "Search results" ), tr( "You've supplied an empty search string." ) );
- return;
- }
-
- QApplication::setOverrideCursor( Qt::WaitCursor );
-
- mSelectedFeatures.clear();
- mLayer->select( mLayer->pendingAllAttributesList(), QgsRectangle(), false );
-
- QgsFeature f;
- while ( mLayer->nextFeature( f ) )
- {
- if ( searchTree->checkAgainst( mLayer->pendingFields(), f.attributeMap() ) )
- mSelectedFeatures << f.id();
-
- // check if there were errors during evaluating
- if ( searchTree->hasError() )
- break;
- }
-
- QApplication::restoreOverrideCursor();
-
- if ( searchTree->hasError() )
- {
- QMessageBox::critical( this, tr( "Error during search" ), searchTree->errorMsg() );
- return;
- }
-
- // update view
- updateSelection();
-
- disconnect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
- mLayer->setSelectedFeatures( mSelectedFeatures );
- connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
-
- QString str;
- if ( mSelectedFeatures.size() )
- str.sprintf( tr( "Found %d matching features.", "", mSelectedFeatures.size() ).toUtf8(), mSelectedFeatures.size() );
- else
- str = tr( "No matching features found." );
-
- QMessageBox::information( this, tr( "Search results" ), str );
-}
-
-void BeataDialog::search()
-{
-
- QString str = mColumnBox->currentText();
-
- const QgsFieldMap& flds = mLayer->dataProvider()->fields();
- int fldIndex = mLayer->dataProvider()->fieldNameIndex( str );
- QVariant::Type fldType = flds[fldIndex].type();
- bool numeric = ( fldType == QVariant::Int || fldType == QVariant::Double );
-
- if ( numeric )
- str += " = '";
- else
- str += " ~ '";
-
- str += mQuery->displayText();
- str += "'";
-
- doSearch( str );
-}
-
-void BeataDialog::on_mAdvancedSearchButton_clicked()
-{
- QgsSearchQueryBuilder dlg( mLayer, this );
- dlg.setSearchString( mQuery->displayText() );
-
- if ( dlg.exec() )
- doSearch( dlg.searchString() );
-}
-
-void BeataDialog::on_mToggleEditingButton_toggled()
-{
- emit editingToggled( mLayer );
-}
-
-void BeataDialog::editingToggled()
-{
- mToggleEditingButton->setChecked( mLayer->isEditable() );
-
- // (probably reload data if user stopped editing - possible revert)
- mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
-
- // not necessary to set table read only if layer is not editable
- // because model always reflects actual state when returning item flags
-}
-
-// not used now
-void BeataDialog::startEditing()
-{
- mLayer->startEditing();
-}
-
-// not used now
-void BeataDialog::submit()
-{
- mLayer->commitChanges();
-}
-
-// not used now
-void BeataDialog::revert()
-{
- mLayer->rollBack();
- mModel->revert();
- mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
-}
Deleted: trunk/qgis/src/app/attributetable/BeataDialog.h
===================================================================
--- trunk/qgis/src/app/attributetable/BeataDialog.h 2009-04-13 09:10:22 UTC (rev 10550)
+++ trunk/qgis/src/app/attributetable/BeataDialog.h 2009-04-13 09:17:47 UTC (rev 10551)
@@ -1,107 +0,0 @@
-/***************************************************************************
- BeataDialog.h
- BEtter Attribute TAble
- -------------------
- date : Feb 2009
- copyright : Vita Cizek
- email : weetya (at) gmail.com
-
- ***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef BEATADIALOG_H_
-#define BEATADIALOG_H_
-
-#include <QDialog>
-#include <QModelIndex>
-#include <QItemSelectionModel>
-#include <QMutex>
-
-#include "ui_BeataGui.h"
-
-class QgsMapLayer;
-class QgsVectorLayer;
-
-#include "qgsvectorlayer.h" //QgsFeatureIds
-
-class QDialogButtonBox;
-class QPushButton;
-class QLineEdit;
-class QComboBox;
-class QMenu;
-class QDockWidget;
-
-class BeataModel;
-class BeataFilterModel;
-class BeataView;
-
-class BeataDialog : public QDialog, private Ui::BeataDialogGui
-{
- Q_OBJECT
-
- public:
- BeataDialog( QgsVectorLayer *theLayer, QWidget *parent = 0, Qt::WindowFlags flags = Qt::Window );
- ~BeataDialog();
-
- public slots:
- void editingToggled();
-
- private slots:
- void submit();
- void revert();
- void search();
- void on_mAdvancedSearchButton_clicked();
- void updateSelection();
- void updateSelectionFromLayer();
- void updateRowSelection( int index );
- void updateRowSelection( int first, int last, bool startNewSelection );
-
- void on_cbxShowSelectedOnly_toggled( bool theFlag );
- void on_mCopySelectedRowsButton_clicked();
-
- void on_mToggleEditingButton_toggled();
- void on_mInvertSelectionButton_clicked();
- void on_mRemoveSelectionButton_clicked();
- void on_mZoomMapToSelectedRowsButton_clicked();
- void on_mSelectedToTopButton_clicked();
- void showAdvanced();
- void startEditing();
-
- signals:
- void editingToggled( QgsMapLayer * );
-
- protected:
- void closeEvent( QCloseEvent* event );
-
- private:
- void columnBoxInit();
- int columnBoxColumnId();
- void doSearch( QString searchString );
-
- QIcon getThemeIcon( const QString theName );
-
- QLineEdit *mQuery;
- QComboBox *mColumnBox;
- QComboBox *mShowBox;
-
- QMenu* mMenuActions;
- QAction* mActionToggleEditing;
-
- BeataModel *mModel;
- BeataFilterModel *mFilterModel;
- QgsVectorLayer *mLayer;
- QgsFeatureIds mSelectedFeatures;
-
- QItemSelectionModel* mSelectionModel;
- int mLastClickedHeaderIndex;
-
- QDockWidget *mDock;
-};
-
-#endif
Deleted: trunk/qgis/src/app/attributetable/BeataModel.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/BeataModel.cpp 2009-04-13 09:10:22 UTC (rev 10550)
+++ trunk/qgis/src/app/attributetable/BeataModel.cpp 2009-04-13 09:17:47 UTC (rev 10551)
@@ -1,645 +0,0 @@
-/***************************************************************************
- BeataModel.cpp
- --------------------------------------
- Date : Feb 2009
- Copyright : (C) 2009 Vita Cizek
- Email : weetya (at) gmail.com
- ***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "BeataModel.h"
-#include "BeataView.h"
-
-#include "qgsvectordataprovider.h"
-#include "qgsfield.h"
-#include "qgsvectorlayer.h"
-
-#include <QtGui>
-#include <QVariant>
-#include <QtAlgorithms>
-#include "qgslogger.h"
-
-//could be faster when type guessed before sorting
-bool idColumnPair::operator<( const idColumnPair &b ) const
-{
- //QVariat thinks gid is a string!
- QVariant::Type columnType = columnItem.type();
-
- if ( columnType == QVariant::Int || columnType == QVariant::UInt || columnType == QVariant::LongLong || columnType == QVariant::ULongLong )
- return columnItem.toLongLong() < b.columnItem.toLongLong();
-
- if ( columnType == QVariant::Double )
- return columnItem.toDouble() < b.columnItem.toDouble();
-
- return columnItem.toString() < b.columnItem.toString();
-}
-
-//////////////////
-// Filter Model //
-//////////////////
-
-void BeataFilterModel::sort( int column, Qt::SortOrder order )
-{
- (( BeataModel * )sourceModel() )->sort( column, order );
-}
-
-BeataFilterModel::BeataFilterModel( QgsVectorLayer* theLayer )
-{
- mLayer = theLayer;
- mHideUnselected = false;
- setDynamicSortFilter( true );
-}
-
-bool BeataFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
-{
- if ( mHideUnselected )
- // unreadable? yes, i agree :-)
- return mLayer->selectedFeaturesIds().contains((( BeataModel * )sourceModel() )->rowToId( sourceRow ) );
-
- return true;
-}
-
-/*
-QModelIndex BeataFilterModel::mapFromSource ( const QModelIndex& sourceIndex ) const
-{
- return sourceIndex;
-}
-
-QModelIndex BeataFilterModel::mapToSource ( const QModelIndex& filterIndex ) const
-{
- return filterIndex;
-}
-*/
-
-////////////////
-// BeataModel //
-////////////////
-
-BeataModel::BeataModel( QgsVectorLayer *theLayer, QObject *parent )
- : QAbstractTableModel( parent )
-{
- mLastRowId = -1;
- mLastRow = NULL;
- mLayer = theLayer;
- mFeatureCount = mLayer->pendingFeatureCount();
- mFieldCount = mLayer->pendingFields().size();
- mAttributes = mLayer->pendingAllAttributesList();
-
- connect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
- //connect(mLayer, SIGNAL(attributeAdded(int)), this, SLOT( attributeAdded(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(featureDeleted(int)), this, SLOT( featureDeleted(int)));
- //connect(mLayer, SIGNAL(featureAdded(int)), this, SLOT( featureAdded(int)));
-
- loadLayer();
-}
-
-void BeataModel::featureDeleted( int fid )
-{
- QgsDebugMsg( "entered." );
-
-#ifdef QGISDEBUG
- int idx = mIdRowMap[fid];
- QgsDebugMsg( idx );
- QgsDebugMsg( fid );
-#endif
-
-#if 0
- --mFeatureCount;
- mIdRowMap.remove( fid );
- mRowIdMap.remove( idx );
-
- // fill the hole in the view
- if ( idx != mFeatureCount )
- {
- QgsDebugMsg( "jo" );
- //mRowIdMap[idx] = mRowIdMap[mFeatureCount];
- //mIdRowMap[mRowIdMap[idx]] = idx;
- int movedId = mRowIdMap[mFeatureCount];
- mRowIdMap.remove( mFeatureCount );
- mRowIdMap.insert( idx, movedId );
- mIdRowMap[movedId] = idx;
- //mIdRowMap.remove(mRowIdMap[idx]);
- //mIdRowMap.insert(mRowIdMap[idx], idx);
- }
-
- QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
- emit layoutChanged();
- //reload(index(0,0), index(rowCount(), columnCount()));
-#endif
-
- QgsDebugMsg( "id->row" );
- QMap<int, int>::iterator it;
- for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
- QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
-
- QgsDebugMsg( "row->id" );
-
- for ( it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
- QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
-
-}
-
-void BeataModel::featureAdded( int fid )
-{
- QgsDebugMsg( "BM feature added" );
- ++mFeatureCount;
- mIdRowMap.insert( fid, mFeatureCount - 1 );
- mRowIdMap.insert( mFeatureCount - 1, fid );
- QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
- reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
-}
-
-void BeataModel::attributeAdded( int idx )
-{
- QgsDebugMsg( "BM attribute added" );
- loadLayer();
- QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
- reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
- emit modelChanged();
-}
-
-void BeataModel::attributeDeleted( int idx )
-{
- QgsDebugMsg( "BM attribute deleted" );
- loadLayer();
- QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
- reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
- emit modelChanged();
-}
-
-void BeataModel::layerDeleted()
-{
- QgsDebugMsg( "entered." );
- mIdRowMap.clear();
- mRowIdMap.clear();
- QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
- 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 )
-{
- QgsDebugMsg( "entered." );
- reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
-}
-
-void BeataModel::layerModified( bool onlyGeometry )
-{
- if ( onlyGeometry )
- return;
-
- loadLayer();
- emit modelChanged();
-}
-
-void BeataModel::loadLayer()
-{
- QgsDebugMsg( "entered." );
-
- QgsFeature f;
- bool ins = false, rm = false;
-
- mRowIdMap.clear();
- mIdRowMap.clear();
-
- if ( mFeatureCount < mLayer->pendingFeatureCount() )
- {
- QgsDebugMsg( "ins" );
- ins = true;
- beginInsertRows( QModelIndex(), mFeatureCount, mLayer->pendingFeatureCount() - 1 );
-// QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() - 1));
- }
- else if ( mFeatureCount > mLayer->pendingFeatureCount() )
- {
- QgsDebugMsg( "rm" );
- rm = true;
- beginRemoveRows( QModelIndex(), mLayer->pendingFeatureCount(), mFeatureCount - 1 );
-// QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() -1));
- }
-
- mLayer->select( QgsAttributeList(), QgsRectangle(), false );
-
- for ( int i = 0; mLayer->nextFeature( f ); ++i )
- {
- mRowIdMap.insert( i, f.id() );
- mIdRowMap.insert( f.id(), i );
- }
-
- // not needed when we have featureAdded signal
- mFeatureCount = mLayer->pendingFeatureCount();
- mFieldCount = mLayer->pendingFields().size();
-
- if ( ins )
- {
- endInsertRows();
- QgsDebugMsg( "end ins" );
- }
- else if ( rm )
- {
- endRemoveRows();
- QgsDebugMsg( "end rm" );
- }
-
-#if 0
- QgsDebugMsg( "id->row" );
- QMap<int, int>::iterator it;
- for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
- QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
-
- 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 )
-{
- if ( a == b )
- return;
-
- int rowA = idToRow( a );
- int rowB = idToRow( b );
-
- //emit layoutAboutToBeChanged();
-
- mRowIdMap.remove( rowA );
- mRowIdMap.remove( rowB );
- mRowIdMap.insert( rowA, b );
- mRowIdMap.insert( rowB, a );
-
- mIdRowMap.remove( a );
- mIdRowMap.remove( b );
- mIdRowMap.insert( a, rowB );
- mIdRowMap.insert( b, rowA );
-
- //emit layoutChanged();
-}
-
-int BeataModel::idToRow( const int id ) const
-{
- if ( !mIdRowMap.contains( id ) )
- {
- QgsDebugMsg( QString( "idToRow: id %1 not in map" ).arg( id ) );
- return -1;
- }
-
- return mIdRowMap[id];
-}
-
-int BeataModel::rowToId( const int id ) const
-{
- if ( !mRowIdMap.contains( id ) )
- {
- QgsDebugMsg( QString( "rowToId: row %1 not in map" ).arg( id ) );
- return -1;
- }
-
- return mRowIdMap[id];
-}
-
-int BeataModel::rowCount( const QModelIndex &parent ) const
-{
- return mFeatureCount;
-}
-
-int BeataModel::columnCount( const QModelIndex &parent ) const
-{
- return mFieldCount;
-}
-
-QVariant BeataModel::headerData( int section, Qt::Orientation orientation, int role ) const
-{
- if ( role == Qt::DisplayRole )
- {
- if ( orientation == Qt::Vertical ) //row
- {
- return QVariant( section );
- }
- else
- {
- QgsField field = mLayer->pendingFields()[ mAttributes[section] ]; //column
- return QVariant( field.name() );
- }
- }
- else return QVariant();
-}
-
-void BeataModel::sort( int column, Qt::SortOrder order )
-{
- QgsAttributeMap row;
- idColumnPair pair;
- QgsAttributeList attrs;
- QgsFeature f;
-
- attrs.append( mAttributes[column] );
-
- emit layoutAboutToBeChanged();
-// QgsDebugMsg("SORTing");
-
- mSortList.clear();
- mLayer->select( attrs, QgsRectangle(), false );
- while ( mLayer->nextFeature( f ) )
- {
- row = f.attributeMap();
-
- pair.id = f.id();
- pair.columnItem = row[ mAttributes[column] ];
-
- mSortList.append( pair );
- }
-
- if ( order == Qt::AscendingOrder )
- qStableSort( mSortList.begin(), mSortList.end() );
- else
- qStableSort( mSortList.begin(), mSortList.end(), qGreater<idColumnPair>() );
-
- // recalculate id<->row maps
- mRowIdMap.clear();
- mIdRowMap.clear();
-
- int i = 0;
- QList<idColumnPair>::Iterator it;
- for ( it = mSortList.begin(); it != mSortList.end(); ++it, ++i )
- {
- mRowIdMap.insert( i, it->id );
- mIdRowMap.insert( it->id, i );
- }
-
- // restore selection
- emit layoutChanged();
- //reset();
- emit modelChanged();
-}
-
-QVariant BeataModel::data( const QModelIndex &index, int role ) const
-{
- if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
- return QVariant();
-
- QVariant::Type fldType = mLayer->pendingFields()[ mAttributes[index.column()] ].type();
- 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 )
- return QVariant( "ERROR" );
-
- mLastRowId = rowToId( index.row() );
- mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
- }
-
- if ( !mLastRow )
- return QVariant( "ERROR" );
-
- QVariant& val = ( *mLastRow )[ mAttributes[index.column()] ];
-
- if ( val.isNull() )
- {
- // if the value is NULL, show that in table, but don't show "NULL" text in editor
- if ( role == Qt::EditRole )
- return QVariant();
- else
- return QVariant( "NULL" );
- }
-
- // force also numeric data for EditRole to be strings
- // otherwise it creates spinboxes instead of line edits
- // (probably not what we do want)
- if ( fldNumeric && role == Qt::EditRole )
- return val.toString();
-
- // convert to QString from some other representation
- // this prevents displaying greater numbers in exponential format
- return val.toString();
-}
-
-bool BeataModel::setData( const QModelIndex &index, const QVariant &value, int role )
-{
- if ( !index.isValid() || role != Qt::EditRole )
- return false;
-
- if ( !mLayer->isEditable() )
- return false;
-
- bool res = mLayer->featureAtId( rowToId( index.row() ), mFeat, false, true );
-
- if ( res )
- {
- mLastRowId = rowToId( index.row() );
- mLastRow = ( QgsAttributeMap * )( &( mFeat.attributeMap() ) );
-
- mLayer->changeAttributeValue( rowToId( index.row() ), index.column(), value, true );
- }
-
- if ( !mLayer->isModified() )
- return false;
-
- emit dataChanged( index, index );
- return true;
-}
-
-Qt::ItemFlags BeataModel::flags( const QModelIndex &index ) const
-{
- if ( !index.isValid() )
- return Qt::ItemIsEnabled;
-
- Qt::ItemFlags flags = QAbstractItemModel::flags( index );
-
- if ( mLayer->isEditable() )
- flags |= Qt::ItemIsEditable;
-
- return flags;
-}
-
-void BeataModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
-{
- emit dataChanged( index1, index2 );
-}
-
-void BeataModel::resetModel()
-{
- reset();
-}
-
-void BeataModel::changeLayout()
-{
- emit layoutChanged();
-}
-
-void BeataModel::incomingChangeLayout()
-{
- emit layoutAboutToBeChanged();
-}
-
-/////////////////////
-// In-Memory model //
-/////////////////////
-
-void BeataMemModel::loadLayer()
-{
- BeataModel::loadLayer();
- mLayer->select( mLayer->pendingAllAttributesList(), QgsRectangle(), false );
-
- QgsFeature f;
- while ( mLayer->nextFeature( f ) )
- mFeatureMap.insert( f.id(), f );
-}
-
-BeataMemModel::BeataMemModel
-( QgsVectorLayer *theLayer )
- : BeataModel( theLayer )
-{
- loadLayer();
-}
-
-QVariant BeataMemModel::data( const QModelIndex &index, int role ) const
-{
- if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
- return QVariant();
-
- QVariant::Type fldType = mLayer->pendingFields()[ mAttributes[index.column()] ].type();
- 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);
- bool res = mFeatureMap.contains( rowToId( index.row() ) );
-
- if ( !res )
- return QVariant( "ERROR" );
-
- mLastRowId = rowToId( index.row() );
- mFeat = mFeatureMap[rowToId( index.row() )];
- mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
- }
-
- if ( !mLastRow )
- return QVariant( "ERROR" );
-
- QVariant &val = ( *mLastRow )[ mAttributes[index.column()] ];
-
- if ( val.isNull() )
- {
- // if the value is NULL, show that in table, but don't show "NULL" text in editor
- if ( role == Qt::EditRole )
- return QVariant();
- else
- return QVariant( "NULL" );
- }
-
- // force also numeric data for EditRole to be strings
- // otherwise it creates spinboxes instead of line edits
- // (probably not what we do want)
- if ( fldNumeric && role == Qt::EditRole )
- return val.toString();
-
- // convert to QString from some other representation
- // this prevents displaying greater numbers in exponential format
- return val.toString();
-}
-
-bool BeataMemModel::setData( const QModelIndex &index, const QVariant &value, int role )
-{
- if ( !index.isValid() || role != Qt::EditRole )
- return false;
-
- if ( !mLayer->isEditable() )
- return false;
-
- //bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true);
- bool res = mFeatureMap.contains( rowToId( index.row() ) );
-
- if ( res )
- {
- mLastRowId = rowToId( index.row() );
- mFeat = mFeatureMap[rowToId( index.row() )];
- mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
-
-
-// QgsDebugMsg(mFeatureMap[rowToId(index.row())].id());
- mFeatureMap[rowToId( index.row() )].changeAttribute( index.column(), value );
- // propagate back to the layer
- mLayer->changeAttributeValue( rowToId( index.row() ), index.column(), value, true );
- }
-
- if ( !mLayer->isModified() )
- return false;
-
- emit dataChanged( index, index );
- return true;
-}
-
-void BeataMemModel::featureDeleted( int fid )
-{
- QgsDebugMsg( "entered." );
- mFeatureMap.remove( fid );
- BeataModel::featureDeleted( fid );
-}
-
-void BeataMemModel::featureAdded( int fid )
-{
- QgsDebugMsg( "entered." );
- QgsFeature f;
- mLayer->featureAtId( fid, f, false, true );
- mFeatureMap.insert( fid, f );
- BeataModel::featureAdded( fid );
-}
-
-#if 0
-void BeataMemModel::attributeAdded( int idx )
-{
- QgsDebugMsg( "entered." );
- loadLayer();
- reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
-}
-
-void BeataMemModel::attributeDeleted( int idx )
-{
- QgsDebugMsg( "entered." );
- loadLayer();
- reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
-}
-#endif
-
-void BeataMemModel::layerDeleted()
-{
- QgsDebugMsg( "entered." );
- mFeatureMap.clear();
- BeataModel::layerDeleted();
-}
-
-void BeataMemModel::attributeValueChanged( int fid, int idx, const QVariant &value )
-{
- QgsDebugMsg( "entered." );
- mFeatureMap[fid].changeAttribute( idx, value );
- reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
-}
Deleted: trunk/qgis/src/app/attributetable/BeataModel.h
===================================================================
--- trunk/qgis/src/app/attributetable/BeataModel.h 2009-04-13 09:10:22 UTC (rev 10550)
+++ trunk/qgis/src/app/attributetable/BeataModel.h 2009-04-13 09:17:47 UTC (rev 10551)
@@ -1,141 +0,0 @@
-/***************************************************************************
- BeataModel.h
- BEtter Attribute TAble
- -------------------
- date : Feb 2009
- copyright : Vita Cizek
- email : weetya (at) gmail.com
-
- ***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef BEATAMODEL_H
-#define BEATAMODEL_H
-
-#include <QAbstractTableModel>
-#include <QSortFilterProxyModel>
-#include <QModelIndex>
-#include <QObject>
-
-//QGIS Includes
-#include "qgis.h"
-#include "qgsfeature.h" //QgsAttributeMap
-#include "qgsvectorlayer.h" //QgsAttributeList
-
-class idColumnPair
-{
- public:
- int id;
- QVariant columnItem;
-
- bool operator<( const idColumnPair &b ) const;
-};
-
-class BeataFilterModel: public QSortFilterProxyModel
-{
- public:
- BeataFilterModel( QgsVectorLayer* theLayer );
- //QModelIndex mapToSource ( const QModelIndex & filterIndex ) const;
- //QModelIndex mapFromSource ( const QModelIndex & sourceIndex ) const;
- bool mHideUnselected;
- virtual void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
- protected:
- bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const;
- private:
- QgsVectorLayer* mLayer;
-};
-
-
-class BeataModel: public QAbstractTableModel
-{
- Q_OBJECT
-
- public:
- BeataModel( QgsVectorLayer *theLayer, QObject *parent = 0 );
-
- int rowCount( const QModelIndex &parent = QModelIndex() ) const;
- int columnCount( const QModelIndex &parent = QModelIndex() ) const;
-
- QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
- virtual QVariant data( const QModelIndex &index, int role ) const;
- virtual bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole );
- Qt::ItemFlags flags( const QModelIndex &index ) const;
-
- void reload( const QModelIndex &index1, const QModelIndex &index2 );
- void resetModel();
- void changeLayout();
- void incomingChangeLayout();
- int idToRow( const int id ) const;
- int rowToId( const int id ) const;
- virtual void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
- void swapRows( int a, int b );
-
- QgsVectorLayer* layer() const { return mLayer; }
-
- signals:
- void modelChanged();
- void setNumRows( int oldNum, int newNum );
-
- private slots:
- virtual void attributeAdded( int idx );
- virtual void attributeDeleted( int idx );
- virtual void attributeValueChanged( int fid, int idx, const QVariant &value );
- virtual void layerModified( bool onlyGeometry );
-
- protected slots:
- virtual void featureDeleted( int fid );
- virtual void featureAdded( int fid );
- virtual void layerDeleted();
-
- protected:
- QgsVectorLayer *mLayer;
- int mFeatureCount;
- int mFieldCount;
- mutable int mLastRowId;
- mutable QgsFeature mFeat;
-
- mutable QgsAttributeMap *mLastRow;
- QgsAttributeList mAttributes;
-
- QList<idColumnPair> mSortList;
- QMap<int, int> mIdRowMap;
- QMap<int, int> mRowIdMap;
-
- void initIdMaps();
- virtual void loadLayer();
-
-};
-
-class BeataMemModel: public BeataModel
-{
- Q_OBJECT
-
- public:
- BeataMemModel( QgsVectorLayer *theLayer );//, QObject *parent = 0);
-
- protected slots:
- virtual void featureDeleted( int fid );
- virtual void featureAdded( int fid );
- virtual void layerDeleted();
-
- private slots:
- //virtual void attributeAdded (int idx);
- //virtual void attributeDeleted (int idx);
- virtual void attributeValueChanged( int fid, int idx, const QVariant &value );
- //virtual void layerModified(bool onlyGeometry);
-
- private:
- virtual QVariant data( const QModelIndex &index, int role ) const;
- virtual bool setData( const QModelIndex &index, const QVariant &value, int role );
- virtual void loadLayer();
-
- QMap<int, QgsFeature> mFeatureMap;
-};
-
-#endif
Deleted: trunk/qgis/src/app/attributetable/BeataView.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/BeataView.cpp 2009-04-13 09:10:22 UTC (rev 10550)
+++ trunk/qgis/src/app/attributetable/BeataView.cpp 2009-04-13 09:17:47 UTC (rev 10551)
@@ -1,144 +0,0 @@
-/***************************************************************************
- BeataView.cpp
- --------------------------------------
- Date : Feb 2009
- Copyright : (C) 2009 Vita Cizek
- Email : weetya (at) gmail.com
- ***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include <QModelIndex>
-#include <QItemDelegate>
-#include <QHeaderView>
-#include <QSettings>
-#include <QLineEdit>
-#include <QPainter>
-#include <QKeyEvent>
-
-#include "BeataView.h"
-#include "BeataModel.h"
-
-#include "qgslogger.h"
-#include "qgsvectorlayer.h"
-#include "qgsvectordataprovider.h"
-
-
-class BeataDelegate : public QItemDelegate
-{
- public:
- BeataDelegate( QObject* parent = NULL ) : QItemDelegate( parent ) {}
-
- QWidget * createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
- {
- QWidget *editor = QItemDelegate::createEditor( parent, option, index );
-
- QLineEdit *le = dynamic_cast<QLineEdit*>( editor );
- if ( !le ) return editor;
-
- const BeataModel* m = dynamic_cast<const BeataModel*>( index.model() );
- if ( !m ) return editor;
-
- int col = index.column();
- QVariant::Type type = m->layer()->dataProvider()->fields()[col].type();
-
- if ( type == QVariant::Int )
- {
- le->setValidator( new QIntValidator( le ) );
- }
- else if ( type == QVariant::Double )
- {
- le->setValidator( new QDoubleValidator( le ) );
- }
-
- return editor;
- }
-
-
- void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
- {
- QItemDelegate::paint( painter, option, index );
-
- if ( option.state & QStyle::State_HasFocus )
- {
- QRect r = option.rect.adjusted( 1, 1, -1, -1 );
- QPen p( QBrush( QColor( 0, 255, 127 ) ), 2 );
- painter->save();
- painter->setPen( p );
- painter->drawRect( r );
- painter->restore();
- }
- }
-
-};
-
-BeataView::BeataView( QWidget* parent )
- : QTableView( parent )
-{
- QSettings settings;
- restoreGeometry( settings.value( "/BetterTable/geometry" ).toByteArray() );
-
- verticalHeader()->setDefaultSectionSize( 20 );
- horizontalHeader()->setHighlightSections( false );
-
- setItemDelegate( new BeataDelegate( this ) );
-
- setSelectionBehavior( QAbstractItemView::SelectRows );
- setSelectionMode( QAbstractItemView::NoSelection );
- setSortingEnabled( true );
-
- shiftPressed = false;
- ctrlPressed = false;
-}
-
-void BeataView::setLayer( QgsVectorLayer* layer )
-{
- BeataModel *bModel;
-
- if ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::RandomSelectGeometryAtId )
- bModel = new BeataModel( layer );
- else
- bModel = new BeataMemModel( layer );
-
- BeataFilterModel* bfModel = new BeataFilterModel( layer );
- bfModel->setSourceModel( bModel );
-
- setModel( bfModel );
-}
-
-BeataView::~BeataView()
-{
-}
-
-void BeataView::closeEvent( QCloseEvent *event )
-{
- QSettings settings;
- settings.setValue( "/BetterAttributeTable/geometry", QVariant( saveGeometry() ) );
-}
-
-void BeataView::keyPressEvent( QKeyEvent *event )
-{
- // shift pressed
- if ( event->key() == Qt::Key_Shift )// && event->modifiers() & Qt::ShiftModifier)
- shiftPressed = true;
- else if ( event->key() == Qt::Key_Control )
- ctrlPressed = true;
- else
- QTableView::keyPressEvent( event );
-}
-
-void BeataView::keyReleaseEvent( QKeyEvent *event )
-{
- // workaround for some Qt bug
- if ( event->key() == Qt::Key_Shift || event->key() == -1 )
- shiftPressed = false;
- else if ( event->key() == Qt::Key_Control )
- ctrlPressed = false;
- else
- QTableView::keyReleaseEvent( event );
-}
Deleted: trunk/qgis/src/app/attributetable/BeataView.h
===================================================================
--- trunk/qgis/src/app/attributetable/BeataView.h 2009-04-13 09:10:22 UTC (rev 10550)
+++ trunk/qgis/src/app/attributetable/BeataView.h 2009-04-13 09:17:47 UTC (rev 10551)
@@ -1,44 +0,0 @@
-/***************************************************************************
- BeataView.h
- --------------------------------------
- Date : Feb 2009
- Copyright : (C) 2009 Vita Cizek
- Email : weetya (at) gmail.com
- ***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef BEATAVIEW_H_
-#define BEATAVIEW_H_
-
-#include <QTableView>
-
-class QgsVectorLayer;
-
-
-class BeataView: public QTableView
-{
-//private slots:
- //void setRows(int rows);
-
- public:
- BeataView( QWidget* parent = NULL );
- virtual ~BeataView();
-
- void setLayer( QgsVectorLayer* layer );
-
- void closeEvent( QCloseEvent *event );
- void keyPressEvent( QKeyEvent *event );
- void keyReleaseEvent( QKeyEvent *event );
-
- //make those private
- bool shiftPressed;
- bool ctrlPressed;
-};
-
-#endif
Copied: trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp (from rev 10549, trunk/qgis/src/app/attributetable/BeataDialog.cpp)
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp (rev 0)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp 2009-04-13 09:17:47 UTC (rev 10551)
@@ -0,0 +1,529 @@
+/***************************************************************************
+ BeataDialog.cpp
+ BEtter Attribute TAble
+ -------------------
+ date : Feb 2009
+ copyright : Vita Cizek
+ email : weetya (at) gmail.com
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <QtGui>
+
+#include "BeataDialog.h"
+#include "BeataModel.h"
+#include "BeataView.h"
+
+#include <qgsapplication.h>
+#include <qgsvectordataprovider.h>
+#include <qgsvectorlayer.h>
+#include <qgssearchstring.h>
+#include <qgssearchtreenode.h>
+
+#include "qgisapp.h"
+#include "qgssearchquerybuilder.h"
+#include "qgslogger.h"
+
+
+class QBeataTableDock : public QDockWidget
+{
+ public:
+ QBeataTableDock( const QString & title, QWidget * parent = 0, Qt::WindowFlags flags = 0 )
+ : QDockWidget( title, parent, flags )
+ {
+ setObjectName( "AttributeTable" ); // set object name so the position can be saved
+ }
+
+ virtual void closeEvent( QCloseEvent * ev )
+ {
+ deleteLater();
+ }
+};
+
+
+BeataDialog::BeataDialog( QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags )
+ : QDialog( parent, flags ), mDock( NULL )
+{
+ mLayer = theLayer;
+
+ setupUi( this );
+
+ setAttribute( Qt::WA_DeleteOnClose );
+
+ QSettings settings;
+ restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() );
+
+ mView->setLayer( mLayer );
+ mFilterModel = ( BeataFilterModel * ) mView->model();
+ mModel = ( BeataModel * )(( BeataFilterModel * )mView->model() )->sourceModel();
+
+ mQuery = query;
+ mColumnBox = columnBox;
+ columnBoxInit();
+
+ QSettings mySettings;
+ bool myDockFlag = mySettings.value( "/qgis/dockAttributeTable", false ).toBool();
+ if ( myDockFlag )
+ {
+ mDock = new QBeataTableDock( tr( "Attribute table - %1" ).arg( mLayer->name() ), QgisApp::instance() );
+ mDock->setAllowedAreas( Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea );
+ mDock->setWidget( this );
+ QgisApp::instance()->addDockWidget( Qt::BottomDockWidgetArea, mDock );
+ }
+
+ setWindowTitle( tr( "Attribute table - %1" ).arg( mLayer->name() ) );
+
+ mRemoveSelectionButton->setIcon( getThemeIcon( "/mActionUnselectAttributes.png" ) );
+ mSelectedToTopButton->setIcon( getThemeIcon( "/mActionSelectedToTop.png" ) );
+ mCopySelectedRowsButton->setIcon( getThemeIcon( "/mActionCopySelected.png" ) );
+ mZoomMapToSelectedRowsButton->setIcon( getThemeIcon( "/mActionZoomToSelected.png" ) );
+ mInvertSelectionButton->setIcon( getThemeIcon( "/mActionInvertSelection.png" ) );
+ mToggleEditingButton->setIcon( getThemeIcon( "/mActionToggleEditing.png" ) );
+ // toggle editing
+ mToggleEditingButton->setCheckable( true );
+ mToggleEditingButton->setEnabled( mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues );
+
+ // info from table to application
+ connect( this, SIGNAL( editingToggled( QgsMapLayer * ) ), QgisApp::instance(), SLOT( toggleEditing( QgsMapLayer * ) ) );
+ // info from layer to table
+ connect( mLayer, SIGNAL( editingStarted() ), 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( 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
+ on_cbxShowSelectedOnly_toggled( false );
+
+ mLastClickedHeaderIndex = 0;
+ mSelectionModel = new QItemSelectionModel( mFilterModel );
+ updateSelectionFromLayer();
+}
+
+BeataDialog::~BeataDialog()
+{
+}
+
+void BeataDialog::closeEvent( QCloseEvent* event )
+{
+ QDialog::closeEvent( event );
+
+ if ( mDock == NULL )
+ {
+ QSettings settings;
+ settings.setValue( "/Windows/BetterAttributeTable/geometry", saveGeometry() );
+ }
+}
+
+
+QIcon BeataDialog::getThemeIcon( const QString theName )
+{
+ // copied from QgisApp::getThemeIcon. To be removed when merged to SVN
+
+ QString myPreferredPath = QgsApplication::activeThemePath() + QDir::separator() + theName;
+ QString myDefaultPath = QgsApplication::defaultThemePath() + QDir::separator() + theName;
+ if ( QFile::exists( myPreferredPath ) )
+ {
+ return QIcon( myPreferredPath );
+ }
+ else if ( QFile::exists( myDefaultPath ) )
+ {
+ //could still return an empty icon if it
+ //doesnt exist in the default theme either!
+ return QIcon( myDefaultPath );
+ }
+ else
+ {
+ return QIcon();
+ }
+}
+
+void BeataDialog::showAdvanced()
+{
+ mMenuActions->exec( QCursor::pos() );
+}
+
+void BeataDialog::on_mSelectedToTopButton_clicked()
+{
+ int freeIndex = 0;
+
+ //QgsFeatureIds fids = mSelectedFeatures;
+ //QgsFeatureIds::Iterator it = fids.begin();
+
+ mModel->incomingChangeLayout();
+
+ QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
+ for ( ; it != mSelectedFeatures.end(); ++it, ++freeIndex )
+ {
+ QModelIndex sourceIndex = mFilterModel->mapToSource( mFilterModel->index( freeIndex, 0 ) );
+ mModel->swapRows( mModel->rowToId( sourceIndex.row() ), *it );
+ }
+
+ /*
+ while (it != fids.end())
+ { //map!!!!
+ //mModel->swapRows(mModel->rowToId(freeIndex), *it);
+ //QModelIndex index = mFilterModel->mapFromSource(mModel->index(mModel->idToRow(*it), 0));
+ QModelIndex sourceIndex = mFilterModel->mapToSource(mFilterModel->index(freeIndex, 0));
+ mModel->swapRows(mModel->rowToId(sourceIndex.row()), *it);
+ //mModel->swapRows(freeIndex, *it);
+
+ if (fids.empty())
+ break;
+ else
+ ++it;
+
+ ++freeIndex;
+ }
+ */
+ // just select proper rows
+ //mModel->reload(mModel->index(0,0), mModel->index(mModel->rowCount(), mModel->columnCount()));
+ //mModel->changeLayout();
+ mModel->resetModel();
+ updateSelection();
+}
+
+void BeataDialog::on_mCopySelectedRowsButton_clicked()
+{
+ QgisApp::instance()->editCopy( mLayer );
+}
+
+void BeataDialog::on_mZoomMapToSelectedRowsButton_clicked()
+{
+ QgisApp::instance()->zoomToSelected();
+}
+
+void BeataDialog::on_mInvertSelectionButton_clicked()
+{
+ mLayer->invertSelection();
+}
+
+void BeataDialog::on_mRemoveSelectionButton_clicked()
+{
+ mLayer->removeSelection();
+}
+
+void BeataDialog::on_cbxShowSelectedOnly_toggled( bool theFlag )
+{
+ mFilterModel->mHideUnselected = theFlag;
+ mFilterModel->invalidate();
+ //TODO: weird
+ //mModel->changeLayout();
+}
+
+void BeataDialog::columnBoxInit()
+{
+ QgsFieldMap fieldMap = mLayer->dataProvider()->fields();
+ QgsFieldMap::Iterator it = fieldMap.begin();
+
+ for ( ; it != fieldMap.end(); ++it )
+ mColumnBox->addItem( it.value().name() );
+}
+
+int BeataDialog::columnBoxColumnId()
+{
+ QgsFieldMap fieldMap = mLayer->dataProvider()->fields();
+ QgsFieldMap::Iterator it = fieldMap.begin();
+
+ for ( ; it != fieldMap.end(); ++it )
+ if ( it.value().name() == mColumnBox->currentText() )
+ return it.key();
+
+ return 0;
+}
+
+void BeataDialog::updateSelection()
+{
+ QModelIndex index;
+ mView->setSelectionMode( QAbstractItemView::MultiSelection );
+
+ QItemSelection selection;
+
+ QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
+ for ( ; it != mSelectedFeatures.end(); ++it )
+ {
+ QModelIndex leftUpIndex = mFilterModel->mapFromSource( mModel->index( mModel->idToRow( *it ), 0 ) );
+ QModelIndex rightBottomIndex = mFilterModel->mapFromSource( mModel->index( mModel->idToRow( *it ), mModel->columnCount() - 1 ) );
+ selection.append( QItemSelectionRange( leftUpIndex, rightBottomIndex ) );
+ //selection.append(QItemSelectionRange(leftUpIndex, leftUpIndex));
+ }
+
+ mSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );// | QItemSelectionModel::Columns);
+ mView->setSelectionModel( mSelectionModel );
+ mView->setSelectionMode( QAbstractItemView::NoSelection );
+
+ /*for (int i = 0; i < mModel->rowCount(); ++i)
+ {
+ int id = mModel->rowToId(i);
+ QgsDebugMsg(id);
+ }
+ QgsDebugMsg("--------------");
+ */
+}
+
+void BeataDialog::updateRowSelection( int index )
+{
+ // map index to filter model
+ //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
+
+ if ( mView->shiftPressed )
+ {
+ QgsDebugMsg( "shift" );
+ // get the first and last index of the rows to be selected/deselected
+ int first, last;
+ if ( index > mLastClickedHeaderIndex )
+ {
+ first = mLastClickedHeaderIndex + 1;
+ last = index;
+ }
+ else if ( index == mLastClickedHeaderIndex )
+ {
+ // row was selected and now it is shift-clicked
+ // ignore the shift and deselect the row
+ first = last = index;
+ }
+ else
+ {
+ first = index;
+ last = mLastClickedHeaderIndex - 1;
+ }
+
+ // for all the rows update the selection, without starting a new selection
+ if ( first <= last )
+ updateRowSelection( first, last, false );
+
+ mLastClickedHeaderIndex = last;
+ }
+ else if ( mView->ctrlPressed )
+ {
+ QgsDebugMsg( "ctrl" );
+ // update the single row selection, without starting a new selection
+ updateRowSelection( index, index, false );
+
+ // the next shift would start from here
+ mLastClickedHeaderIndex = index;
+ }
+ else
+ {
+ QgsDebugMsg( "ordinary click" );
+ // update the single row selection, start a new selection if the row was not selected
+ updateRowSelection( index, index, true );
+
+ // the next shift would start from here
+ mLastClickedHeaderIndex = index;
+ }
+}
+
+// fast row deselection needed
+void BeataDialog::updateRowSelection( int first, int last, bool startNewSelection )
+{
+ disconnect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
+
+ //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
+ // Id must be mapped to table/view row
+ QModelIndex index = mFilterModel->mapToSource( mFilterModel->index( first, 0 ) );
+ int fid = mModel->rowToId( index.row() );
+ bool wasSelected = mSelectedFeatures.contains( fid );
+
+ // new selection should be created
+ if ( startNewSelection )
+ {
+ mView->clearSelection();
+ mSelectedFeatures.clear();
+
+ if ( wasSelected )
+ {
+ mLayer->removeSelection();
+ connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
+ return;
+ }
+
+ // set clicked row to current
+ mView->setCurrentIndex( mFilterModel->index( first, 0 ) );
+ mView->setSelectionMode( QAbstractItemView::SingleSelection );
+
+ //QModelIndex index = mFilterModel->mapFromSource(mModel->index(first, 0));
+
+ mView->selectRow( first );
+ mView->setSelectionMode( QAbstractItemView::NoSelection );
+
+ mSelectedFeatures.insert( fid );
+ //mLayer->setSelectedFeatures(mSelectedFeatures);
+ mLayer->removeSelection();
+ mLayer->select( fid );
+ //mFilterModel->invalidate();
+ connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
+ return;
+ }
+
+ // existing selection should be updated
+ for ( int i = first; i <= last; ++i )
+ {
+ if ( i > first )
+ {
+ // Id must be mapped to table/view row
+ index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
+ fid = mModel->rowToId( index.row() );
+ wasSelected = mSelectedFeatures.contains( fid );
+ }
+
+ if ( wasSelected )
+ mSelectedFeatures.remove( fid );
+ else
+ mSelectedFeatures.insert( fid );
+ }
+ //mFilterModel->invalidate();
+
+ /*
+ QItemSelection selection;
+ QModelIndex leftUpIndex = mFilterModel->index(first, 0);
+ QModelIndex rightBottomIndex = mFilterModel->index(last, mModel->columnCount() - 1);
+ selection.append(QItemSelectionRange(leftUpIndex, rightBottomIndex));
+ mSelectionModel->select(selection, QItemSelectionModel::Select);
+ mView->setSelectionModel(mSelectionModel);
+ */
+ updateSelection();
+ mLayer->setSelectedFeatures( mSelectedFeatures );
+ connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
+}
+
+void BeataDialog::updateSelectionFromLayer()
+{
+ QgsDebugMsg( "updateFromLayer" );
+ mSelectedFeatures = mLayer->selectedFeaturesIds();
+ updateSelection();
+}
+
+void BeataDialog::doSearch( QString searchString )
+{
+ // parse search string and build parsed tree
+ QgsSearchString search;
+ if ( !search.setString( searchString ) )
+ {
+ QMessageBox::critical( this, tr( "Search string parsing error" ), search.parserErrorMsg() );
+ return;
+ }
+
+ QgsSearchTreeNode* searchTree = search.tree();
+ if ( searchTree == NULL )
+ {
+ QMessageBox::information( this, tr( "Search results" ), tr( "You've supplied an empty search string." ) );
+ return;
+ }
+
+ QApplication::setOverrideCursor( Qt::WaitCursor );
+
+ mSelectedFeatures.clear();
+ mLayer->select( mLayer->pendingAllAttributesList(), QgsRectangle(), false );
+
+ QgsFeature f;
+ while ( mLayer->nextFeature( f ) )
+ {
+ if ( searchTree->checkAgainst( mLayer->pendingFields(), f.attributeMap() ) )
+ mSelectedFeatures << f.id();
+
+ // check if there were errors during evaluating
+ if ( searchTree->hasError() )
+ break;
+ }
+
+ QApplication::restoreOverrideCursor();
+
+ if ( searchTree->hasError() )
+ {
+ QMessageBox::critical( this, tr( "Error during search" ), searchTree->errorMsg() );
+ return;
+ }
+
+ // update view
+ updateSelection();
+
+ disconnect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
+ mLayer->setSelectedFeatures( mSelectedFeatures );
+ connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
+
+ QString str;
+ if ( mSelectedFeatures.size() )
+ str.sprintf( tr( "Found %d matching features.", "", mSelectedFeatures.size() ).toUtf8(), mSelectedFeatures.size() );
+ else
+ str = tr( "No matching features found." );
+
+ QMessageBox::information( this, tr( "Search results" ), str );
+}
+
+void BeataDialog::search()
+{
+
+ QString str = mColumnBox->currentText();
+
+ const QgsFieldMap& flds = mLayer->dataProvider()->fields();
+ int fldIndex = mLayer->dataProvider()->fieldNameIndex( str );
+ QVariant::Type fldType = flds[fldIndex].type();
+ bool numeric = ( fldType == QVariant::Int || fldType == QVariant::Double );
+
+ if ( numeric )
+ str += " = '";
+ else
+ str += " ~ '";
+
+ str += mQuery->displayText();
+ str += "'";
+
+ doSearch( str );
+}
+
+void BeataDialog::on_mAdvancedSearchButton_clicked()
+{
+ QgsSearchQueryBuilder dlg( mLayer, this );
+ dlg.setSearchString( mQuery->displayText() );
+
+ if ( dlg.exec() )
+ doSearch( dlg.searchString() );
+}
+
+void BeataDialog::on_mToggleEditingButton_toggled()
+{
+ emit editingToggled( mLayer );
+}
+
+void BeataDialog::editingToggled()
+{
+ mToggleEditingButton->setChecked( mLayer->isEditable() );
+
+ // (probably reload data if user stopped editing - possible revert)
+ mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
+
+ // not necessary to set table read only if layer is not editable
+ // because model always reflects actual state when returning item flags
+}
+
+// not used now
+void BeataDialog::startEditing()
+{
+ mLayer->startEditing();
+}
+
+// not used now
+void BeataDialog::submit()
+{
+ mLayer->commitChanges();
+}
+
+// not used now
+void BeataDialog::revert()
+{
+ mLayer->rollBack();
+ mModel->revert();
+ mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
+}
Copied: trunk/qgis/src/app/attributetable/qgsattributetabledialog.h (from rev 10549, trunk/qgis/src/app/attributetable/BeataDialog.h)
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledialog.h (rev 0)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledialog.h 2009-04-13 09:17:47 UTC (rev 10551)
@@ -0,0 +1,107 @@
+/***************************************************************************
+ BeataDialog.h
+ BEtter Attribute TAble
+ -------------------
+ date : Feb 2009
+ copyright : Vita Cizek
+ email : weetya (at) gmail.com
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef BEATADIALOG_H_
+#define BEATADIALOG_H_
+
+#include <QDialog>
+#include <QModelIndex>
+#include <QItemSelectionModel>
+#include <QMutex>
+
+#include "ui_BeataGui.h"
+
+class QgsMapLayer;
+class QgsVectorLayer;
+
+#include "qgsvectorlayer.h" //QgsFeatureIds
+
+class QDialogButtonBox;
+class QPushButton;
+class QLineEdit;
+class QComboBox;
+class QMenu;
+class QDockWidget;
+
+class BeataModel;
+class BeataFilterModel;
+class BeataView;
+
+class BeataDialog : public QDialog, private Ui::BeataDialogGui
+{
+ Q_OBJECT
+
+ public:
+ BeataDialog( QgsVectorLayer *theLayer, QWidget *parent = 0, Qt::WindowFlags flags = Qt::Window );
+ ~BeataDialog();
+
+ public slots:
+ void editingToggled();
+
+ private slots:
+ void submit();
+ void revert();
+ void search();
+ void on_mAdvancedSearchButton_clicked();
+ void updateSelection();
+ void updateSelectionFromLayer();
+ void updateRowSelection( int index );
+ void updateRowSelection( int first, int last, bool startNewSelection );
+
+ void on_cbxShowSelectedOnly_toggled( bool theFlag );
+ void on_mCopySelectedRowsButton_clicked();
+
+ void on_mToggleEditingButton_toggled();
+ void on_mInvertSelectionButton_clicked();
+ void on_mRemoveSelectionButton_clicked();
+ void on_mZoomMapToSelectedRowsButton_clicked();
+ void on_mSelectedToTopButton_clicked();
+ void showAdvanced();
+ void startEditing();
+
+ signals:
+ void editingToggled( QgsMapLayer * );
+
+ protected:
+ void closeEvent( QCloseEvent* event );
+
+ private:
+ void columnBoxInit();
+ int columnBoxColumnId();
+ void doSearch( QString searchString );
+
+ QIcon getThemeIcon( const QString theName );
+
+ QLineEdit *mQuery;
+ QComboBox *mColumnBox;
+ QComboBox *mShowBox;
+
+ QMenu* mMenuActions;
+ QAction* mActionToggleEditing;
+
+ BeataModel *mModel;
+ BeataFilterModel *mFilterModel;
+ QgsVectorLayer *mLayer;
+ QgsFeatureIds mSelectedFeatures;
+
+ QItemSelectionModel* mSelectionModel;
+ int mLastClickedHeaderIndex;
+
+ QDockWidget *mDock;
+};
+
+#endif
Copied: trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp (from rev 10549, trunk/qgis/src/app/attributetable/BeataModel.cpp)
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp (rev 0)
+++ trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp 2009-04-13 09:17:47 UTC (rev 10551)
@@ -0,0 +1,645 @@
+/***************************************************************************
+ BeataModel.cpp
+ --------------------------------------
+ Date : Feb 2009
+ Copyright : (C) 2009 Vita Cizek
+ Email : weetya (at) gmail.com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "BeataModel.h"
+#include "BeataView.h"
+
+#include "qgsvectordataprovider.h"
+#include "qgsfield.h"
+#include "qgsvectorlayer.h"
+
+#include <QtGui>
+#include <QVariant>
+#include <QtAlgorithms>
+#include "qgslogger.h"
+
+//could be faster when type guessed before sorting
+bool idColumnPair::operator<( const idColumnPair &b ) const
+{
+ //QVariat thinks gid is a string!
+ QVariant::Type columnType = columnItem.type();
+
+ if ( columnType == QVariant::Int || columnType == QVariant::UInt || columnType == QVariant::LongLong || columnType == QVariant::ULongLong )
+ return columnItem.toLongLong() < b.columnItem.toLongLong();
+
+ if ( columnType == QVariant::Double )
+ return columnItem.toDouble() < b.columnItem.toDouble();
+
+ return columnItem.toString() < b.columnItem.toString();
+}
+
+//////////////////
+// Filter Model //
+//////////////////
+
+void BeataFilterModel::sort( int column, Qt::SortOrder order )
+{
+ (( BeataModel * )sourceModel() )->sort( column, order );
+}
+
+BeataFilterModel::BeataFilterModel( QgsVectorLayer* theLayer )
+{
+ mLayer = theLayer;
+ mHideUnselected = false;
+ setDynamicSortFilter( true );
+}
+
+bool BeataFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
+{
+ if ( mHideUnselected )
+ // unreadable? yes, i agree :-)
+ return mLayer->selectedFeaturesIds().contains((( BeataModel * )sourceModel() )->rowToId( sourceRow ) );
+
+ return true;
+}
+
+/*
+QModelIndex BeataFilterModel::mapFromSource ( const QModelIndex& sourceIndex ) const
+{
+ return sourceIndex;
+}
+
+QModelIndex BeataFilterModel::mapToSource ( const QModelIndex& filterIndex ) const
+{
+ return filterIndex;
+}
+*/
+
+////////////////
+// BeataModel //
+////////////////
+
+BeataModel::BeataModel( QgsVectorLayer *theLayer, QObject *parent )
+ : QAbstractTableModel( parent )
+{
+ mLastRowId = -1;
+ mLastRow = NULL;
+ mLayer = theLayer;
+ mFeatureCount = mLayer->pendingFeatureCount();
+ mFieldCount = mLayer->pendingFields().size();
+ mAttributes = mLayer->pendingAllAttributesList();
+
+ connect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
+ //connect(mLayer, SIGNAL(attributeAdded(int)), this, SLOT( attributeAdded(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(featureDeleted(int)), this, SLOT( featureDeleted(int)));
+ //connect(mLayer, SIGNAL(featureAdded(int)), this, SLOT( featureAdded(int)));
+
+ loadLayer();
+}
+
+void BeataModel::featureDeleted( int fid )
+{
+ QgsDebugMsg( "entered." );
+
+#ifdef QGISDEBUG
+ int idx = mIdRowMap[fid];
+ QgsDebugMsg( idx );
+ QgsDebugMsg( fid );
+#endif
+
+#if 0
+ --mFeatureCount;
+ mIdRowMap.remove( fid );
+ mRowIdMap.remove( idx );
+
+ // fill the hole in the view
+ if ( idx != mFeatureCount )
+ {
+ QgsDebugMsg( "jo" );
+ //mRowIdMap[idx] = mRowIdMap[mFeatureCount];
+ //mIdRowMap[mRowIdMap[idx]] = idx;
+ int movedId = mRowIdMap[mFeatureCount];
+ mRowIdMap.remove( mFeatureCount );
+ mRowIdMap.insert( idx, movedId );
+ mIdRowMap[movedId] = idx;
+ //mIdRowMap.remove(mRowIdMap[idx]);
+ //mIdRowMap.insert(mRowIdMap[idx], idx);
+ }
+
+ QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
+ emit layoutChanged();
+ //reload(index(0,0), index(rowCount(), columnCount()));
+#endif
+
+ QgsDebugMsg( "id->row" );
+ QMap<int, int>::iterator it;
+ for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
+ QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
+
+ QgsDebugMsg( "row->id" );
+
+ for ( it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
+ QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
+
+}
+
+void BeataModel::featureAdded( int fid )
+{
+ QgsDebugMsg( "BM feature added" );
+ ++mFeatureCount;
+ mIdRowMap.insert( fid, mFeatureCount - 1 );
+ mRowIdMap.insert( mFeatureCount - 1, fid );
+ QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
+ reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
+}
+
+void BeataModel::attributeAdded( int idx )
+{
+ QgsDebugMsg( "BM attribute added" );
+ loadLayer();
+ QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
+ reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
+ emit modelChanged();
+}
+
+void BeataModel::attributeDeleted( int idx )
+{
+ QgsDebugMsg( "BM attribute deleted" );
+ loadLayer();
+ QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
+ reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
+ emit modelChanged();
+}
+
+void BeataModel::layerDeleted()
+{
+ QgsDebugMsg( "entered." );
+ mIdRowMap.clear();
+ mRowIdMap.clear();
+ QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
+ 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 )
+{
+ QgsDebugMsg( "entered." );
+ reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
+}
+
+void BeataModel::layerModified( bool onlyGeometry )
+{
+ if ( onlyGeometry )
+ return;
+
+ loadLayer();
+ emit modelChanged();
+}
+
+void BeataModel::loadLayer()
+{
+ QgsDebugMsg( "entered." );
+
+ QgsFeature f;
+ bool ins = false, rm = false;
+
+ mRowIdMap.clear();
+ mIdRowMap.clear();
+
+ if ( mFeatureCount < mLayer->pendingFeatureCount() )
+ {
+ QgsDebugMsg( "ins" );
+ ins = true;
+ beginInsertRows( QModelIndex(), mFeatureCount, mLayer->pendingFeatureCount() - 1 );
+// QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() - 1));
+ }
+ else if ( mFeatureCount > mLayer->pendingFeatureCount() )
+ {
+ QgsDebugMsg( "rm" );
+ rm = true;
+ beginRemoveRows( QModelIndex(), mLayer->pendingFeatureCount(), mFeatureCount - 1 );
+// QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() -1));
+ }
+
+ mLayer->select( QgsAttributeList(), QgsRectangle(), false );
+
+ for ( int i = 0; mLayer->nextFeature( f ); ++i )
+ {
+ mRowIdMap.insert( i, f.id() );
+ mIdRowMap.insert( f.id(), i );
+ }
+
+ // not needed when we have featureAdded signal
+ mFeatureCount = mLayer->pendingFeatureCount();
+ mFieldCount = mLayer->pendingFields().size();
+
+ if ( ins )
+ {
+ endInsertRows();
+ QgsDebugMsg( "end ins" );
+ }
+ else if ( rm )
+ {
+ endRemoveRows();
+ QgsDebugMsg( "end rm" );
+ }
+
+#if 0
+ QgsDebugMsg( "id->row" );
+ QMap<int, int>::iterator it;
+ for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
+ QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
+
+ 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 )
+{
+ if ( a == b )
+ return;
+
+ int rowA = idToRow( a );
+ int rowB = idToRow( b );
+
+ //emit layoutAboutToBeChanged();
+
+ mRowIdMap.remove( rowA );
+ mRowIdMap.remove( rowB );
+ mRowIdMap.insert( rowA, b );
+ mRowIdMap.insert( rowB, a );
+
+ mIdRowMap.remove( a );
+ mIdRowMap.remove( b );
+ mIdRowMap.insert( a, rowB );
+ mIdRowMap.insert( b, rowA );
+
+ //emit layoutChanged();
+}
+
+int BeataModel::idToRow( const int id ) const
+{
+ if ( !mIdRowMap.contains( id ) )
+ {
+ QgsDebugMsg( QString( "idToRow: id %1 not in map" ).arg( id ) );
+ return -1;
+ }
+
+ return mIdRowMap[id];
+}
+
+int BeataModel::rowToId( const int id ) const
+{
+ if ( !mRowIdMap.contains( id ) )
+ {
+ QgsDebugMsg( QString( "rowToId: row %1 not in map" ).arg( id ) );
+ return -1;
+ }
+
+ return mRowIdMap[id];
+}
+
+int BeataModel::rowCount( const QModelIndex &parent ) const
+{
+ return mFeatureCount;
+}
+
+int BeataModel::columnCount( const QModelIndex &parent ) const
+{
+ return mFieldCount;
+}
+
+QVariant BeataModel::headerData( int section, Qt::Orientation orientation, int role ) const
+{
+ if ( role == Qt::DisplayRole )
+ {
+ if ( orientation == Qt::Vertical ) //row
+ {
+ return QVariant( section );
+ }
+ else
+ {
+ QgsField field = mLayer->pendingFields()[ mAttributes[section] ]; //column
+ return QVariant( field.name() );
+ }
+ }
+ else return QVariant();
+}
+
+void BeataModel::sort( int column, Qt::SortOrder order )
+{
+ QgsAttributeMap row;
+ idColumnPair pair;
+ QgsAttributeList attrs;
+ QgsFeature f;
+
+ attrs.append( mAttributes[column] );
+
+ emit layoutAboutToBeChanged();
+// QgsDebugMsg("SORTing");
+
+ mSortList.clear();
+ mLayer->select( attrs, QgsRectangle(), false );
+ while ( mLayer->nextFeature( f ) )
+ {
+ row = f.attributeMap();
+
+ pair.id = f.id();
+ pair.columnItem = row[ mAttributes[column] ];
+
+ mSortList.append( pair );
+ }
+
+ if ( order == Qt::AscendingOrder )
+ qStableSort( mSortList.begin(), mSortList.end() );
+ else
+ qStableSort( mSortList.begin(), mSortList.end(), qGreater<idColumnPair>() );
+
+ // recalculate id<->row maps
+ mRowIdMap.clear();
+ mIdRowMap.clear();
+
+ int i = 0;
+ QList<idColumnPair>::Iterator it;
+ for ( it = mSortList.begin(); it != mSortList.end(); ++it, ++i )
+ {
+ mRowIdMap.insert( i, it->id );
+ mIdRowMap.insert( it->id, i );
+ }
+
+ // restore selection
+ emit layoutChanged();
+ //reset();
+ emit modelChanged();
+}
+
+QVariant BeataModel::data( const QModelIndex &index, int role ) const
+{
+ if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
+ return QVariant();
+
+ QVariant::Type fldType = mLayer->pendingFields()[ mAttributes[index.column()] ].type();
+ 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 )
+ return QVariant( "ERROR" );
+
+ mLastRowId = rowToId( index.row() );
+ mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
+ }
+
+ if ( !mLastRow )
+ return QVariant( "ERROR" );
+
+ QVariant& val = ( *mLastRow )[ mAttributes[index.column()] ];
+
+ if ( val.isNull() )
+ {
+ // if the value is NULL, show that in table, but don't show "NULL" text in editor
+ if ( role == Qt::EditRole )
+ return QVariant();
+ else
+ return QVariant( "NULL" );
+ }
+
+ // force also numeric data for EditRole to be strings
+ // otherwise it creates spinboxes instead of line edits
+ // (probably not what we do want)
+ if ( fldNumeric && role == Qt::EditRole )
+ return val.toString();
+
+ // convert to QString from some other representation
+ // this prevents displaying greater numbers in exponential format
+ return val.toString();
+}
+
+bool BeataModel::setData( const QModelIndex &index, const QVariant &value, int role )
+{
+ if ( !index.isValid() || role != Qt::EditRole )
+ return false;
+
+ if ( !mLayer->isEditable() )
+ return false;
+
+ bool res = mLayer->featureAtId( rowToId( index.row() ), mFeat, false, true );
+
+ if ( res )
+ {
+ mLastRowId = rowToId( index.row() );
+ mLastRow = ( QgsAttributeMap * )( &( mFeat.attributeMap() ) );
+
+ mLayer->changeAttributeValue( rowToId( index.row() ), index.column(), value, true );
+ }
+
+ if ( !mLayer->isModified() )
+ return false;
+
+ emit dataChanged( index, index );
+ return true;
+}
+
+Qt::ItemFlags BeataModel::flags( const QModelIndex &index ) const
+{
+ if ( !index.isValid() )
+ return Qt::ItemIsEnabled;
+
+ Qt::ItemFlags flags = QAbstractItemModel::flags( index );
+
+ if ( mLayer->isEditable() )
+ flags |= Qt::ItemIsEditable;
+
+ return flags;
+}
+
+void BeataModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
+{
+ emit dataChanged( index1, index2 );
+}
+
+void BeataModel::resetModel()
+{
+ reset();
+}
+
+void BeataModel::changeLayout()
+{
+ emit layoutChanged();
+}
+
+void BeataModel::incomingChangeLayout()
+{
+ emit layoutAboutToBeChanged();
+}
+
+/////////////////////
+// In-Memory model //
+/////////////////////
+
+void BeataMemModel::loadLayer()
+{
+ BeataModel::loadLayer();
+ mLayer->select( mLayer->pendingAllAttributesList(), QgsRectangle(), false );
+
+ QgsFeature f;
+ while ( mLayer->nextFeature( f ) )
+ mFeatureMap.insert( f.id(), f );
+}
+
+BeataMemModel::BeataMemModel
+( QgsVectorLayer *theLayer )
+ : BeataModel( theLayer )
+{
+ loadLayer();
+}
+
+QVariant BeataMemModel::data( const QModelIndex &index, int role ) const
+{
+ if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
+ return QVariant();
+
+ QVariant::Type fldType = mLayer->pendingFields()[ mAttributes[index.column()] ].type();
+ 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);
+ bool res = mFeatureMap.contains( rowToId( index.row() ) );
+
+ if ( !res )
+ return QVariant( "ERROR" );
+
+ mLastRowId = rowToId( index.row() );
+ mFeat = mFeatureMap[rowToId( index.row() )];
+ mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
+ }
+
+ if ( !mLastRow )
+ return QVariant( "ERROR" );
+
+ QVariant &val = ( *mLastRow )[ mAttributes[index.column()] ];
+
+ if ( val.isNull() )
+ {
+ // if the value is NULL, show that in table, but don't show "NULL" text in editor
+ if ( role == Qt::EditRole )
+ return QVariant();
+ else
+ return QVariant( "NULL" );
+ }
+
+ // force also numeric data for EditRole to be strings
+ // otherwise it creates spinboxes instead of line edits
+ // (probably not what we do want)
+ if ( fldNumeric && role == Qt::EditRole )
+ return val.toString();
+
+ // convert to QString from some other representation
+ // this prevents displaying greater numbers in exponential format
+ return val.toString();
+}
+
+bool BeataMemModel::setData( const QModelIndex &index, const QVariant &value, int role )
+{
+ if ( !index.isValid() || role != Qt::EditRole )
+ return false;
+
+ if ( !mLayer->isEditable() )
+ return false;
+
+ //bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true);
+ bool res = mFeatureMap.contains( rowToId( index.row() ) );
+
+ if ( res )
+ {
+ mLastRowId = rowToId( index.row() );
+ mFeat = mFeatureMap[rowToId( index.row() )];
+ mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
+
+
+// QgsDebugMsg(mFeatureMap[rowToId(index.row())].id());
+ mFeatureMap[rowToId( index.row() )].changeAttribute( index.column(), value );
+ // propagate back to the layer
+ mLayer->changeAttributeValue( rowToId( index.row() ), index.column(), value, true );
+ }
+
+ if ( !mLayer->isModified() )
+ return false;
+
+ emit dataChanged( index, index );
+ return true;
+}
+
+void BeataMemModel::featureDeleted( int fid )
+{
+ QgsDebugMsg( "entered." );
+ mFeatureMap.remove( fid );
+ BeataModel::featureDeleted( fid );
+}
+
+void BeataMemModel::featureAdded( int fid )
+{
+ QgsDebugMsg( "entered." );
+ QgsFeature f;
+ mLayer->featureAtId( fid, f, false, true );
+ mFeatureMap.insert( fid, f );
+ BeataModel::featureAdded( fid );
+}
+
+#if 0
+void BeataMemModel::attributeAdded( int idx )
+{
+ QgsDebugMsg( "entered." );
+ loadLayer();
+ reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
+}
+
+void BeataMemModel::attributeDeleted( int idx )
+{
+ QgsDebugMsg( "entered." );
+ loadLayer();
+ reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
+}
+#endif
+
+void BeataMemModel::layerDeleted()
+{
+ QgsDebugMsg( "entered." );
+ mFeatureMap.clear();
+ BeataModel::layerDeleted();
+}
+
+void BeataMemModel::attributeValueChanged( int fid, int idx, const QVariant &value )
+{
+ QgsDebugMsg( "entered." );
+ mFeatureMap[fid].changeAttribute( idx, value );
+ reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
+}
Copied: trunk/qgis/src/app/attributetable/qgsattributetablemodel.h (from rev 10549, trunk/qgis/src/app/attributetable/BeataModel.h)
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetablemodel.h (rev 0)
+++ trunk/qgis/src/app/attributetable/qgsattributetablemodel.h 2009-04-13 09:17:47 UTC (rev 10551)
@@ -0,0 +1,141 @@
+/***************************************************************************
+ BeataModel.h
+ BEtter Attribute TAble
+ -------------------
+ date : Feb 2009
+ copyright : Vita Cizek
+ email : weetya (at) gmail.com
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef BEATAMODEL_H
+#define BEATAMODEL_H
+
+#include <QAbstractTableModel>
+#include <QSortFilterProxyModel>
+#include <QModelIndex>
+#include <QObject>
+
+//QGIS Includes
+#include "qgis.h"
+#include "qgsfeature.h" //QgsAttributeMap
+#include "qgsvectorlayer.h" //QgsAttributeList
+
+class idColumnPair
+{
+ public:
+ int id;
+ QVariant columnItem;
+
+ bool operator<( const idColumnPair &b ) const;
+};
+
+class BeataFilterModel: public QSortFilterProxyModel
+{
+ public:
+ BeataFilterModel( QgsVectorLayer* theLayer );
+ //QModelIndex mapToSource ( const QModelIndex & filterIndex ) const;
+ //QModelIndex mapFromSource ( const QModelIndex & sourceIndex ) const;
+ bool mHideUnselected;
+ virtual void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
+ protected:
+ bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const;
+ private:
+ QgsVectorLayer* mLayer;
+};
+
+
+class BeataModel: public QAbstractTableModel
+{
+ Q_OBJECT
+
+ public:
+ BeataModel( QgsVectorLayer *theLayer, QObject *parent = 0 );
+
+ int rowCount( const QModelIndex &parent = QModelIndex() ) const;
+ int columnCount( const QModelIndex &parent = QModelIndex() ) const;
+
+ QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
+ virtual QVariant data( const QModelIndex &index, int role ) const;
+ virtual bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole );
+ Qt::ItemFlags flags( const QModelIndex &index ) const;
+
+ void reload( const QModelIndex &index1, const QModelIndex &index2 );
+ void resetModel();
+ void changeLayout();
+ void incomingChangeLayout();
+ int idToRow( const int id ) const;
+ int rowToId( const int id ) const;
+ virtual void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
+ void swapRows( int a, int b );
+
+ QgsVectorLayer* layer() const { return mLayer; }
+
+ signals:
+ void modelChanged();
+ void setNumRows( int oldNum, int newNum );
+
+ private slots:
+ virtual void attributeAdded( int idx );
+ virtual void attributeDeleted( int idx );
+ virtual void attributeValueChanged( int fid, int idx, const QVariant &value );
+ virtual void layerModified( bool onlyGeometry );
+
+ protected slots:
+ virtual void featureDeleted( int fid );
+ virtual void featureAdded( int fid );
+ virtual void layerDeleted();
+
+ protected:
+ QgsVectorLayer *mLayer;
+ int mFeatureCount;
+ int mFieldCount;
+ mutable int mLastRowId;
+ mutable QgsFeature mFeat;
+
+ mutable QgsAttributeMap *mLastRow;
+ QgsAttributeList mAttributes;
+
+ QList<idColumnPair> mSortList;
+ QMap<int, int> mIdRowMap;
+ QMap<int, int> mRowIdMap;
+
+ void initIdMaps();
+ virtual void loadLayer();
+
+};
+
+class BeataMemModel: public BeataModel
+{
+ Q_OBJECT
+
+ public:
+ BeataMemModel( QgsVectorLayer *theLayer );//, QObject *parent = 0);
+
+ protected slots:
+ virtual void featureDeleted( int fid );
+ virtual void featureAdded( int fid );
+ virtual void layerDeleted();
+
+ private slots:
+ //virtual void attributeAdded (int idx);
+ //virtual void attributeDeleted (int idx);
+ virtual void attributeValueChanged( int fid, int idx, const QVariant &value );
+ //virtual void layerModified(bool onlyGeometry);
+
+ private:
+ virtual QVariant data( const QModelIndex &index, int role ) const;
+ virtual bool setData( const QModelIndex &index, const QVariant &value, int role );
+ virtual void loadLayer();
+
+ QMap<int, QgsFeature> mFeatureMap;
+};
+
+#endif
Copied: trunk/qgis/src/app/attributetable/qgsattributetableview.cpp (from rev 10549, trunk/qgis/src/app/attributetable/BeataView.cpp)
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetableview.cpp (rev 0)
+++ trunk/qgis/src/app/attributetable/qgsattributetableview.cpp 2009-04-13 09:17:47 UTC (rev 10551)
@@ -0,0 +1,144 @@
+/***************************************************************************
+ BeataView.cpp
+ --------------------------------------
+ Date : Feb 2009
+ Copyright : (C) 2009 Vita Cizek
+ Email : weetya (at) gmail.com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <QModelIndex>
+#include <QItemDelegate>
+#include <QHeaderView>
+#include <QSettings>
+#include <QLineEdit>
+#include <QPainter>
+#include <QKeyEvent>
+
+#include "BeataView.h"
+#include "BeataModel.h"
+
+#include "qgslogger.h"
+#include "qgsvectorlayer.h"
+#include "qgsvectordataprovider.h"
+
+
+class BeataDelegate : public QItemDelegate
+{
+ public:
+ BeataDelegate( QObject* parent = NULL ) : QItemDelegate( parent ) {}
+
+ QWidget * createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
+ {
+ QWidget *editor = QItemDelegate::createEditor( parent, option, index );
+
+ QLineEdit *le = dynamic_cast<QLineEdit*>( editor );
+ if ( !le ) return editor;
+
+ const BeataModel* m = dynamic_cast<const BeataModel*>( index.model() );
+ if ( !m ) return editor;
+
+ int col = index.column();
+ QVariant::Type type = m->layer()->dataProvider()->fields()[col].type();
+
+ if ( type == QVariant::Int )
+ {
+ le->setValidator( new QIntValidator( le ) );
+ }
+ else if ( type == QVariant::Double )
+ {
+ le->setValidator( new QDoubleValidator( le ) );
+ }
+
+ return editor;
+ }
+
+
+ void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
+ {
+ QItemDelegate::paint( painter, option, index );
+
+ if ( option.state & QStyle::State_HasFocus )
+ {
+ QRect r = option.rect.adjusted( 1, 1, -1, -1 );
+ QPen p( QBrush( QColor( 0, 255, 127 ) ), 2 );
+ painter->save();
+ painter->setPen( p );
+ painter->drawRect( r );
+ painter->restore();
+ }
+ }
+
+};
+
+BeataView::BeataView( QWidget* parent )
+ : QTableView( parent )
+{
+ QSettings settings;
+ restoreGeometry( settings.value( "/BetterTable/geometry" ).toByteArray() );
+
+ verticalHeader()->setDefaultSectionSize( 20 );
+ horizontalHeader()->setHighlightSections( false );
+
+ setItemDelegate( new BeataDelegate( this ) );
+
+ setSelectionBehavior( QAbstractItemView::SelectRows );
+ setSelectionMode( QAbstractItemView::NoSelection );
+ setSortingEnabled( true );
+
+ shiftPressed = false;
+ ctrlPressed = false;
+}
+
+void BeataView::setLayer( QgsVectorLayer* layer )
+{
+ BeataModel *bModel;
+
+ if ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::RandomSelectGeometryAtId )
+ bModel = new BeataModel( layer );
+ else
+ bModel = new BeataMemModel( layer );
+
+ BeataFilterModel* bfModel = new BeataFilterModel( layer );
+ bfModel->setSourceModel( bModel );
+
+ setModel( bfModel );
+}
+
+BeataView::~BeataView()
+{
+}
+
+void BeataView::closeEvent( QCloseEvent *event )
+{
+ QSettings settings;
+ settings.setValue( "/BetterAttributeTable/geometry", QVariant( saveGeometry() ) );
+}
+
+void BeataView::keyPressEvent( QKeyEvent *event )
+{
+ // shift pressed
+ if ( event->key() == Qt::Key_Shift )// && event->modifiers() & Qt::ShiftModifier)
+ shiftPressed = true;
+ else if ( event->key() == Qt::Key_Control )
+ ctrlPressed = true;
+ else
+ QTableView::keyPressEvent( event );
+}
+
+void BeataView::keyReleaseEvent( QKeyEvent *event )
+{
+ // workaround for some Qt bug
+ if ( event->key() == Qt::Key_Shift || event->key() == -1 )
+ shiftPressed = false;
+ else if ( event->key() == Qt::Key_Control )
+ ctrlPressed = false;
+ else
+ QTableView::keyReleaseEvent( event );
+}
Copied: trunk/qgis/src/app/attributetable/qgsattributetableview.h (from rev 10549, trunk/qgis/src/app/attributetable/BeataView.h)
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetableview.h (rev 0)
+++ trunk/qgis/src/app/attributetable/qgsattributetableview.h 2009-04-13 09:17:47 UTC (rev 10551)
@@ -0,0 +1,44 @@
+/***************************************************************************
+ BeataView.h
+ --------------------------------------
+ Date : Feb 2009
+ Copyright : (C) 2009 Vita Cizek
+ Email : weetya (at) gmail.com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef BEATAVIEW_H_
+#define BEATAVIEW_H_
+
+#include <QTableView>
+
+class QgsVectorLayer;
+
+
+class BeataView: public QTableView
+{
+//private slots:
+ //void setRows(int rows);
+
+ public:
+ BeataView( QWidget* parent = NULL );
+ virtual ~BeataView();
+
+ void setLayer( QgsVectorLayer* layer );
+
+ void closeEvent( QCloseEvent *event );
+ void keyPressEvent( QKeyEvent *event );
+ void keyReleaseEvent( QKeyEvent *event );
+
+ //make those private
+ bool shiftPressed;
+ bool ctrlPressed;
+};
+
+#endif
More information about the QGIS-commit
mailing list