Un principiante en las Artes Gráficas Una experiencia en un sector que nos envuelve… El blog personal de David Pinelo.

30Nov/091

AbanQ: Añadiendo una nueva columna de ordenación en el FLDataTable

El trabajo con sistemas ERP, y especialmente con AbanQ siempre se basan en la navegación por listados de datos (o grids de datos). No estoy muy seguro de que realmente ese sea el sistema más usable o adecuado, pero al menos es muy popular.

En mi afán de tratar de hacer la herramienta aún más usable, echaba en falta una segunda columna de ordenación. Si mi empresa factura todo a través de AbanQ, el número de datos en esa rejilla es grande. Puede filtrarse utilizando el campo de filtro directo que AbanQ provee, pero ese campo de filtro también limita la ordenación de los datos filtrados que se presentan. Tener una segunda columna, como aparece en la imágen, puede ayudar aún más a localizar datos rápidamente.
Doble columna de ordenacion

Bien, veamos cómo hacerlo.

Como siempre, tocaremos un poquito de código de AbanQ... y de Qt 3.3.

Al lío:

Primero añadir, en el FLWidgetTableDB.ui mediante el Qt Designer 3.3 el segundo combobox de ordenación. Lo vamos a llamar comboBoxFieldToSearch2 (muy original... :P). También debemos añadir en el Designer un Slot,

void putSecondCol (const QString &)

y añadimos una conexión:

Sender: comboBoxFieldToSearch2
Signal: activated (const QString &)
Receiver: FLWidgetTableDB
Slot: putSecondCol(const QString &)

Vale. Hemos terminado en Designer. Toca código en C++ de AbanQ.

Definimos ese slot que acabamos de crear en Designer en el código de AbanQ (en esto sí que han ganado las Qt 4 eliminando la definición de slots en el designer...)

Archivo: FLObjectFactory.h
....
class FL_EXPORT FLTableDBInterface : public QObject {
  ...
public:
...
/**
dpinelo: Establece el segundo campo de búsqueda
*/
void putSecondCol( const QString & c ) {
obj_->putSecondCol( c );
}

De esta forma, cuando el usuario cliquee en el combo, se producirá la ordenación por el segundo campo.

Archivo: FLTableDB.h
...
class FL_EXPORT FLTableDB: public FLWidgetTableDB {
  ...
  private:
  /**
  dpinelo Indica el número de columna por la que ordenar los registros
   */
  int sortColumn2_;
  /**
  dpinelo Indica el sentido ascendente o descendente del la ordenacion actual de los registros
   */
  bool orderAsc2_;

  protected slots:
  ...
  // dpinelo
  void putSecondCol( int c );
  void putSecondCol( const QString & c );

Y ahora vamos al código de verdad. Sólo he querido añadir la funcionalidad de ordenación secundaria... de modo que sigo dejando la mayor parte de la responsabilidad de la ordenación al código de AbanQ. Busco que el usuario pueda visualizar por una columna diferente, y cambiar el orden de visualización en esa columna.

Para este fichero, mejor pongo un diff .... Ya digo, tengo que organizar todas mis diferencias de código y publicarlas aquí adecuadamente. Espero poder hacerlo la semana que viene, antes de publicar las modificaciones de integración con OpenKM y JasperServer

Index: abanq/src/flbase/FLTableDB.cpp
===================================================================
--- abanq/src/flbase/FLTableDB.cpp	(revisión: 117)
+++ abanq/src/flbase/FLTableDB.cpp	(copia de trabajo)
@@ -89,7 +89,9 @@
     tabDataLayout->addWidget( tableRecords_ );
     setTabOrder( tableRecords_, lineEditSearch );
     setTabOrder( lineEditSearch, comboBoxFieldToSearch );
-    lineEditSearch->installEventFilter( this );
+	// dpinelo
+	setTabOrder( comboBoxFieldToSearch, comboBoxFieldToSearch2 );
+	lineEditSearch->installEventFilter( this );
     tableRecords_->installEventFilter( this );
     connect( tableRecords_->horizontalHeader(), SIGNAL( clicked( int ) ), this, SLOT( switchSortOrder( int ) ) );
   }
@@ -109,7 +111,9 @@
     tabDataLayout->addWidget( tableRecords_ );
     setTabOrder( tableRecords_, lineEditSearch );
     setTabOrder( lineEditSearch, comboBoxFieldToSearch );
-    lineEditSearch->installEventFilter( this );
+	// dpinelo
+	setTabOrder( comboBoxFieldToSearch, comboBoxFieldToSearch2 );
+	lineEditSearch->installEventFilter( this );
     tableRecords_->installEventFilter( this );
   }
   FLSqlCursor * tCursor = tableRecords_->cursor();
@@ -127,7 +131,8 @@
 }
 bool FLTableDB::eventFilter( QObject * obj, QEvent * ev ) {
-  if ( !tableRecords_ || !lineEditSearch || !comboBoxFieldToSearch || !cursorVisualizacion_ )
+	// dpinelo
+  if ( !tableRecords_ || !lineEditSearch || !comboBoxFieldToSearch || !cursorVisualizacion_ || !comboBoxFieldToSearch2 )
     return FLWidgetTableDB::eventFilter( obj, ev );
   if ( ev->type() == QEvent::KeyPress && obj == tableRecords_ ) {
     QKeyEvent * k = static_cast<QKeyEvent *>( ev );
@@ -165,21 +170,55 @@
 }
 void FLTableDB::putFirstCol( const QString & c ) {
-        // dpinelo: No entiendo cómo el código funciona sin esto...
-        FLTableMetaData *tMD = cursorVisualizacion_->metadata();
-        cursorVisualizacion_->setSort( cursorVisualizacion_->index( tMD->fieldAliasToName( c ) ) );
-  moveCol( c, QString::null );
+	// dpinelo: Introducimos la ordenación por los dos campos
+	QSqlIndex sort;
+	FLTableMetaData *tMD = cursorVisualizacion_->metadata();
+	sort.append ( tMD->fieldAliasToName( c ) );
+	sort.append ( tMD->fieldAliasToName( comboBoxFieldToSearch2->text( comboBoxFieldToSearch2->currentItem() ) ) );
+	cursorVisualizacion_->setSort( sort );
+	moveCol( c, QString::null );
 }
 void FLTableDB::putFirstCol( int c ) {
-        // dpinelo: No entiendo cómo el código funciona sin esto...
-        QHeader *horizHeader = tableRecords()->horizontalHeader();
-        FLTableMetaData *tMD = cursorVisualizacion_->metadata();
-        cursorVisualizacion_->setSort( cursorVisualizacion_->index( tMD->fieldAliasToName( horizHeader->label(c) ) ) );
-  moveCol( c, 0 );
+	// dpinelo: Introducimos la ordenación por los dos campos
+	QSqlIndex sort;
+	QHeader *horizHeader = tableRecords()->horizontalHeader();
+	FLTableMetaData *tMD = cursorVisualizacion_->metadata();
+	sort.append ( tMD->fieldAliasToName( horizHeader->label(c) ) );
+	sort.append ( tMD->fieldAliasToName( comboBoxFieldToSearch2->text( comboBoxFieldToSearch2->currentItem() ) ) );
+	cursorVisualizacion_->setSort( sort );
+	moveCol( c, 0 );
 }
-void FLTableDB::moveCol( const QString & from, const QString & to ) {
+// dpinelo
+void FLTableDB::putSecondCol( const QString & c ) {
+    // dpinelo: Introducimos la ordenación por los dos campos
+	QSqlIndex sort;
+	FLTableMetaData *tMD = cursorVisualizacion_->metadata();
+	sort.append ( tMD->fieldAliasToName( comboBoxFieldToSearch->text( comboBoxFieldToSearch->currentItem() ) ) );
+	sort.append ( tMD->fieldAliasToName( c ) );
+	cursorVisualizacion_->setSort( sort );
+	// Aprovechamos que siempre, el combo box de filtro presenta sus items ordenados igual que el grid
+	if ( c != comboBoxFieldToSearch->text( comboBoxFieldToSearch->currentItem() + 1 ) ) {
+		moveCol( c, comboBoxFieldToSearch->text( comboBoxFieldToSearch->currentItem() + 1 ), false );
+	}
+}
+
+void FLTableDB::putSecondCol( int c ) {
+    // dpinelo: No entiendo cómo el código funciona sin esto...
+	QSqlIndex sort;
+	QHeader *horizHeader = tableRecords()->horizontalHeader();
+	FLTableMetaData *tMD = cursorVisualizacion_->metadata();
+	sort.append ( tMD->fieldAliasToName( comboBoxFieldToSearch->text( comboBoxFieldToSearch->currentItem() ) ) );
+	sort.append (  tMD->fieldAliasToName( horizHeader->label(c) ) );
+	cursorVisualizacion_->setSort( sort );
+	// Aprovechamos que siempre, el combo box de filtro presenta sus items ordenados igual que el grid
+	if ( c != ( comboBoxFieldToSearch->currentItem() + 1 ) ) {
+		moveCol( c, ( comboBoxFieldToSearch->currentItem() + 1), false );
+	}
+}
+
+void FLTableDB::moveCol( const QString & from, const QString & to, bool firstSearch ) {
   if ( !topWidget || !cursorVisualizacion_ || !showed )
     return ;
@@ -210,11 +249,12 @@
 #endif
     return;
   }
-  moveCol( iFrom - sortColumn_, iTo - sortColumn_ );
+  moveCol( iFrom - sortColumn_, iTo - sortColumn_, firstSearch );
 }
-void FLTableDB::moveCol( int from, int to ) {
-  if ( from == to || !lineEditSearch || !comboBoxFieldToSearch || !cursorVisualizacion_ )
+void FLTableDB::moveCol( int from, int to, bool firstSearch ) {
+	// dpinelo
+  if ( from == to || !lineEditSearch || !comboBoxFieldToSearch || !cursorVisualizacion_ || !comboBoxFieldToSearch2 )
     return ;
   if ( comboBoxFieldToSearch->text( from ) == "*" || comboBoxFieldToSearch->text( to ) == "*" )
@@ -252,10 +292,13 @@
   refresh( true );
   if ( !textSearch.isEmpty() ) {
     refresh( false, true );
-    disconnect( lineEditSearch, SIGNAL( textChanged( const QString& ) ), this, SLOT( filterRecords( const QString& ) ) );
-    lineEditSearch->setText( textSearch );
-    connect( lineEditSearch, SIGNAL( textChanged( const QString& ) ), this, SLOT( filterRecords( const QString& ) ) );
-    lineEditSearch->selectAll();
+	if ( firstSearch ) {
+		disconnect( lineEditSearch, SIGNAL( textChanged( const QString& ) ), this, SLOT( filterRecords( const QString& ) ) );
+		// dpinelo
+    	lineEditSearch->setText( textSearch );
+    	connect( lineEditSearch, SIGNAL( textChanged( const QString& ) ), this, SLOT( filterRecords( const QString& ) ) );
+	    lineEditSearch->selectAll();
+	}
     seekCursor();
     QTimer::singleShot( 0, tableRecords_, SLOT( ensureRowSelectedVisible() ) );
   } else
@@ -329,7 +372,9 @@
 }
 void FLTableDB::refresh( const bool refreshHead, const bool refreshData ) {
-  if ( !lineEditSearch || !comboBoxFieldToSearch || !cursorVisualizacion_ || ( topWidget && !topWidget->isShown() ) )
+	// dpinelo
+  if ( !lineEditSearch || !comboBoxFieldToSearch || !cursorVisualizacion_ || ( topWidget && !topWidget->isShown() ) ||
+	 !comboBoxFieldToSearch2 )
     return ;
   FLTableMetaData * tMD = cursorVisualizacion_->metadata();
@@ -349,7 +394,7 @@
                                           true, 0, 0, false, false, false, QVariant(), false, QString::null, true, false, false );
         tMD->addFieldMD( fieldCheck );
       }
-          if ( !cursorVisualizacion_->contains( fieldNameCheckColumn_ ) ) {
+      if ( !cursorVisualizacion_->contains( fieldNameCheckColumn_ ) ) {
                   QSqlRecord recordCursor( *( cursorVisualizacion_->editBuffer() ) );
         QSqlFieldInfo fakeFieldInfo( fieldNameCheckColumn_, QVariant::Bool, -1, -1, -1, QVariant(), 0, false, false, true );
                 cursorVisualizacion_->clear();
@@ -432,9 +477,11 @@
 	comboBoxFieldToSearch->insertItem( "*" );
     horizHeader->setClickEnabled( false );
     horizHeader->setClickEnabled( true, sortColumn_ );
-    horizHeader->setSortIndicator( -1, Qt::Ascending );
+	// dpinelo
+	horizHeader->setClickEnabled( true, sortColumn2_ );
+	horizHeader->setSortIndicator( -1, Qt::Ascending );
     horizHeader->setSortIndicator( sortColumn_, ( orderAsc_ ? Qt::Ascending : Qt::Descending ) );
-    horizHeader->show();
+	horizHeader->show();
   }
   if ( refreshData || sender() ) {
@@ -1013,10 +1060,15 @@
   aliasCheckColumn_ = t;
 }
-void FLTableDB::switchSortOrder( int ) {
-  orderAsc_ = !orderAsc_;
-  tableRecords()->hide();
-  refresh( true, true );
+void FLTableDB::switchSortOrder( int col ) {
+  // dpinelo
+	if ( col == 0 ) {
+		orderAsc_ = !orderAsc_;
+	} else if ( col == 1 ) {
+		orderAsc2_ = !orderAsc2_;
+	}
+	tableRecords()->hide();
+	refresh( true, true );
 }
 void FLTableDB::activeTabData( bool on ) {

Eah... por ahí va eso.

Comentarios (1) Trackbacks (0)
  1. Simplemente excelente explicación.
    gracias


Deja un comentario

Debes iniciar sesión para dejar un comentario.

Sin trackbacks por el momento.