[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