00001 #include <QtCore/QtDebug>
00002 #include <QtCore/QSet>
00003 #include <QtCore/QMap>
00004 #include <QtCore/QSettings>
00005 #include <QtCore/QVariant>
00006 #include <QtGui/QContextMenuEvent>
00007 #include <QtGui/QAction>
00008 #include <QtGui/QWidget>
00009 #include <QtGui/QMenu>
00010 #include <QtGui/QHeaderView>
00011 #include <QtGui/QMessageBox>
00012 #include <QtGui/QItemSelectionModel>
00013
00014 #include "ACE/foldertableview.h"
00015 #include "ACE/foldertablemodel.h"
00016 #include "ACE/foldertabledelegate.h"
00017 #include "ACE/miscDialogs.h"
00018
00019
00020 FolderTableView::FolderTableView( QWidget* parent, FolderTableModel* theModel ):
00021 QTableView( parent ),
00022 folderTableModel( theModel )
00023 {
00024 QSettings settings;
00025 settings.beginGroup( "Preferences/FolderTables/Display" );
00026 setAlternatingRowColors( settings.value( "AlternatingRowColors", true ).toBool() );
00027 bool s = settings.value( "SortingEnabled", true ).toBool();
00028 setSortingEnabled( s );
00029 horizontalHeader()->setSortIndicatorShown( s );
00030 horizontalHeader()->setClickable( s );
00031 horizontalHeader()->setDefaultAlignment( Qt::AlignLeft );
00032 settings.endGroup();
00033
00034 createActions();
00035 fillCellsDialog = new FillCellsDialog( this );
00036 folderTableDelegate = new FolderTableDelegate( this );
00037 setItemDelegate( folderTableDelegate );
00038 setModel( folderTableModel );
00039 }
00040
00041 FolderTableView::~FolderTableView()
00042 {
00043
00044
00045
00046 delete fillCellsDialog;
00047 delete folderTableDelegate;
00048 selectionInspectionResults.clear();
00049 }
00050
00051 void FolderTableView::enableSorting( bool enabled )
00052 {
00053 if ( enabled && !( folderTableModel->isFiltered() ) )
00054 {
00055 QSettings settings;
00056 settings.beginGroup( "Preferences/FolderTables/Display" );
00057 enabled = settings.value( "SortingEnabled", true ).toBool();
00058 settings.endGroup();
00059 }
00060 else
00061 qWarning() << "Sorting is disabled and/or filter is active.";
00062 setSortingEnabled( enabled );
00063 horizontalHeader()->setSortIndicatorShown( enabled );
00064 horizontalHeader()->setSortIndicatorShown( enabled );
00065 horizontalHeader()->setClickable( enabled );
00066 }
00067
00068 QModelIndexList FolderTableView::excludeHiddenItems( QModelIndexList fullSelection )
00069 {
00070 QModelIndexList filteredModelIndexList;
00071 filteredModelIndexList.clear();
00072
00073 foreach ( QModelIndex index, fullSelection )
00074 {
00075 if ( !isRowHidden( index.row() ) )
00076 filteredModelIndexList.append( index );
00077 }
00078 return filteredModelIndexList;
00079 }
00080
00081 void FolderTableView::focusInEvent( QFocusEvent* event )
00082 {
00083 emit checkButtons( false );
00084
00085 emit updateFilterTarget( folderTableModel, objectName() );
00086 QTableView::focusInEvent( event );
00087 }
00088
00089 void FolderTableView::focusOutEvent( QFocusEvent* event )
00090 {
00091 emit checkButtons( false );
00092 QTableView::focusOutEvent( event );
00093 }
00094
00095 void FolderTableView::contextMenuEvent( QContextMenuEvent* event )
00096 {
00097 selectionInspectionResults.clear();
00098 QModelIndex currentTableModelIndex( indexAt( event->pos() ) );
00099 currentSelectionModel = selectionModel();
00100 QModelIndexList indexes = excludeHiddenItems( currentSelectionModel->selectedIndexes() );
00101 if ( !currentTableModelIndex.isValid() )
00102 return;
00103 QMenu menu( this );
00104 testSelection( indexes );
00105 if ( selectionInspectionResults.contains( newRows ) )
00106 {
00107 menu.addAction( actionCommit );
00108 menu.addAction( actionRemove );
00109 if ( folderTableModel->flags( currentTableModelIndex ) & Qt::ItemIsEditable )
00110 {
00111 menu.addAction( actionFillCells );
00112 }
00113 }
00114 if ( selectionInspectionResults.contains( oldRows ) )
00115 {
00116 menu.addAction( actionClone );
00117 }
00118 if ( folderTableModel->canSetDisplayAsMask( indexes ) && ( currentTableModelIndex.column() < 1 || currentTableModelIndex.column() > 2 ) )
00119 {
00120 menu.addSeparator();
00121 QMenu* displayAsMenu = menu.addMenu( tr( "Display as" ) );
00122 displayAsMenu->addAction( actionDisplayAsHex );
00123 displayAsMenu->addAction( actionDisplayAsOct );
00124 displayAsMenu->addAction( actionDisplayAsDec );
00125 if ( !folderTableModel->getDisplayAsMask( currentTableModelIndex.column() ) == noMask )
00126 {
00127 displayAsMenu->addAction( actionDisplayAs_Remove );
00128 }
00129 }
00130 menu.exec( event->globalPos() );
00131 }
00132
00133 void FolderTableView::createActions()
00134 {
00135 actionClone = new QAction( tr( "&Clone rows" ), this );
00136
00137 actionClone->setStatusTip( tr( "Create a new row based on an existing one." ) );
00138 QObject::connect( actionClone, SIGNAL( triggered() ), this, SLOT( slotNewRow() ) );
00139
00140 actionCommit = new QAction( tr( "Commit" ), this );
00141 actionCommit->setStatusTip( tr( "Commit the newly added rows to the COOL database." ) );
00142 QObject::connect( actionCommit, SIGNAL( triggered() ), this, SLOT( slotCommit() ) );
00143
00144 actionRemove = new QAction( tr( "Remove rows" ), this );
00145 actionRemove->setStatusTip( tr( "Remove the uncommitted row." ) );
00146 QObject::connect( actionRemove, SIGNAL( triggered() ), this, SLOT( slotRemove() ) );
00147
00148 actionFillCells = new QAction( tr( "Fill" ), this );
00149 actionFillCells->setStatusTip( tr( "Fill selected cells with the same value." ) );
00150 QObject::connect( actionFillCells, SIGNAL( triggered() ), this, SLOT( slotFillCells() ) );
00151
00152 actionDisplayAsDec = new QAction( tr( "Dec" ), this );
00153 actionDisplayAsDec->setStatusTip( tr( "Display all values in the column to decimal." ) );
00154 QObject::connect( actionDisplayAsDec, SIGNAL( triggered() ), this, SLOT( slotDisplayAsDec() ) );
00155
00156 actionDisplayAsHex = new QAction( tr( "Hex" ), this );
00157 actionDisplayAsHex->setStatusTip( tr( "Display all values in the column to hexadecimal." ) );
00158 QObject::connect( actionDisplayAsHex, SIGNAL( triggered() ), this, SLOT( slotDisplayAsHex() ) );
00159
00160 actionDisplayAsOct = new QAction( tr( "Oct" ), this );
00161 actionDisplayAsOct->setStatusTip( tr( "Display all values in the column to octal." ) );
00162 QObject::connect( actionDisplayAsOct, SIGNAL( triggered() ), this, SLOT( slotDisplayAsOct() ) );
00163
00164 actionDisplayAsDateTime = new QAction( tr( "Date/Time" ), this );
00165 actionDisplayAsDateTime->setStatusTip( tr( "Converts UTC to Date/Time format." ) );
00166 QObject::connect( actionDisplayAsDateTime, SIGNAL( triggered() ), this, SLOT( slotDisplayAsDateTime() ) );
00167
00168 actionDisplayAs_Remove = new QAction( tr( "No mask" ), this );
00169 actionDisplayAs_Remove->setStatusTip( tr( "Remove any mask currently in place." ) );
00170 QObject::connect( actionDisplayAs_Remove, SIGNAL( triggered() ), this, SLOT( slotDisplayAs_Remove() ) );
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 }
00181
00182 void FolderTableView::testSelection( QModelIndexList& currentSelectionList )
00183 {
00184 QModelIndex currentSelection;
00185 QSet< int > rowSet;
00186 QSet< unsigned int > channelIdSet;
00187 int row( -1 );
00188 bool rowIsNew( false );
00189 unsigned int channelId( 0 );
00190 foreach ( currentSelection, currentSelectionList )
00191 {
00192 row = currentSelection.row();
00193 channelId = folderTableModel->getRootTableItem()->child( row )->getChannelId();
00194 rowIsNew = folderTableModel->isNewRow( row );
00195 if ( rowIsNew )
00196 {
00197 if ( selectionInspectionResults.contains( newRows ) )
00198 {
00199 selectionInspectionResults[ newRows ].append( currentSelection );
00200 }
00201 else
00202 {
00203 QModelIndexList indexList = QModelIndexList();
00204 indexList.append( currentSelection );
00205 selectionInspectionResults[ newRows ] = indexList;
00206 }
00207 }
00208 else
00209 {
00210 if ( selectionInspectionResults.contains( oldRows ) )
00211 {
00212 selectionInspectionResults[ oldRows ].append( currentSelection );
00213 }
00214 else
00215 {
00216 QModelIndexList indexList = QModelIndexList();
00217 indexList.append( currentSelection );
00218 selectionInspectionResults[ oldRows ] = indexList;
00219 }
00220 }
00221 if ( !rowSet.contains( row ) )
00222 {
00223 rowSet.insert( row );
00224 if ( channelIdSet.contains( channelId ) )
00225 {
00226
00227
00228
00229
00230
00231
00232 if ( rowIsNew )
00233 {
00234 if ( selectionInspectionResults.contains( duplicateNewRows ) )
00235 {
00236 selectionInspectionResults[ duplicateNewRows ].append( currentSelection );
00237 }
00238 else
00239 {
00240 QModelIndexList indexList = QModelIndexList();
00241 indexList.append( currentSelection );
00242 selectionInspectionResults[ duplicateNewRows ] = indexList;
00243 }
00244 }
00245 else
00246 {
00247 if ( selectionInspectionResults.contains( duplicateOldRows ) )
00248 {
00249 selectionInspectionResults[ duplicateOldRows ].append( currentSelection );
00250 }
00251 else
00252 {
00253 QModelIndexList indexList = QModelIndexList();
00254 indexList.append( currentSelection );
00255 selectionInspectionResults[ duplicateOldRows ] = indexList;
00256 }
00257 }
00258 }
00259 else
00260 {
00261 channelIdSet.insert( channelId );
00262 }
00263 }
00264 }
00265 }
00266
00267 int FolderTableView::selectionRowCount( QModelIndexList& currentSelectionList )
00268 {
00269 QModelIndex currentSelection;
00270 QSet< int > rowSet;
00271 foreach ( currentSelection, currentSelectionList )
00272 {
00273 rowSet.insert( currentSelection.row() );
00274 }
00275 return rowSet.size();
00276 }
00277
00278 void FolderTableView::setRowsHidden( QList< int > rows, bool hide )
00279 {
00280 foreach ( int row, rows )
00281 {
00282 setRowHidden( row, hide );
00283 }
00284
00285
00286 foreach ( int row, rows )
00287 {
00288 folderTableModel->getRootTableItem()->child( row )->setHidden( hide );
00289 }
00290 }
00291
00292 void FolderTableView::showAllRows()
00293 {
00294 int rowCount = folderTableModel->rowCount();
00295 for ( int row = 0; row < rowCount; row++ )
00296 {
00297 setRowHidden( row, false );
00298 }
00299
00300
00301 for ( int row = 0; row < rowCount; row++ )
00302 {
00303 folderTableModel->getRootTableItem()->child( row )->setHidden( false );
00304 }
00305 folderTableModel->setFiltered( false );
00306 }
00307
00308 FolderTableModel* FolderTableView::getFolderTableModel() const
00309 {
00310 return folderTableModel;
00311 }
00312
00313 void FolderTableView::slotNewRow()
00314 {
00315 if ( selectionInspectionResults.contains( duplicateOldRows ) )
00316 {
00317 QMessageBox::warning(
00318 this,
00319 tr( "Selection Error" ),
00320 tr( "The current selection includes duplicate channels!\nPlease only select unique channels from existing (i.e. committed) rows." ),
00321 QMessageBox::Ok,
00322 QMessageBox::Ok );
00323 return;
00324 }
00325 if ( !selectionInspectionResults.contains( oldRows ) )
00326 {
00327 QMessageBox::warning(
00328 this,
00329 tr( "Selection Error" ),
00330 tr( "No existing rows to clone. Please choose only existing (i.e. committed) rows to clone." ),
00331 QMessageBox::Ok,
00332 QMessageBox::Ok );
00333 return;
00334 }
00335 if ( selectionInspectionResults.contains( newRows ) )
00336 {
00337 QMessageBox::information(
00338 this,
00339 tr( "Selection Warning" ),
00340 tr( "Newly created rows cannot be cloned. These rows will be ignored." ),
00341 QMessageBox::Ok,
00342 QMessageBox::Ok );
00343 }
00344 QSet< unsigned int > newRowChannelIds( folderTableModel->newRowChannelIds() );
00345 QModelIndex currentSelection;
00346 QSet< int > ignoredRows;
00347 QSet< int > selectedRows;
00348 int row;
00349 foreach ( currentSelection, selectionInspectionResults.value( oldRows ) )
00350 {
00351 row = currentSelection.row();
00352
00353 if ( !newRowChannelIds.contains( folderTableModel->getRootTableItem()->child( row )->getChannelId() ) )
00354 {
00355 if ( !selectedRows.contains( row ) )
00356 {
00357 folderTableModel->setDefaultCopyRow( row );
00358 folderTableModel->insertRows( folderTableModel->rowCount() );
00359 selectedRows.insert( row );
00360 }
00361 continue;
00362 }
00363 else
00364 {
00365 ignoredRows.insert( row );
00366 }
00367 }
00368 if ( !ignoredRows.isEmpty() )
00369 {
00370 QMessageBox::information(
00371 this,
00372 tr( "Selection Warning" ),
00373 tr( "Selected rows with channel ids identical to newly cloned rows have been ignored." ),
00374 QMessageBox::Ok,
00375 QMessageBox::Ok );
00376 }
00377 emit checkButtons();
00378 scrollToBottom();
00379 }
00380
00381 void FolderTableView::slotCommit()
00382 {
00383 folderTableModel->commit();
00384 emit checkButtons();
00385 }
00386
00387 void FolderTableView::slotRemove()
00388 {
00389 if ( selectionInspectionResults.contains( oldRows ) )
00390 {
00391 QMessageBox::warning(
00392 this,
00393 tr( "Selection Warning" ),
00394 tr( "The current selection includes existing entries !\nThese will not be removed." ),
00395 QMessageBox::Ok,
00396 QMessageBox::Ok );
00397 }
00398 if ( !selectionInspectionResults.contains( newRows ) )
00399 {
00400 QMessageBox::information(
00401 this,
00402 tr( "Selection Error" ),
00403 tr( "No newly created rows selected. Nothing to remove." ),
00404 QMessageBox::Ok,
00405 QMessageBox::Ok );
00406 return;
00407 }
00408
00409 QMap< int, bool > selectedRows;
00410 QMap< int, bool >::const_iterator i;
00411 QModelIndex currentSelection;
00412 int row;
00413 foreach ( currentSelection, selectionInspectionResults.value( newRows ) )
00414 {
00415 row = currentSelection.row();
00416 if ( !selectedRows.contains( row ) )
00417 {
00418 selectedRows[ row ] = true;
00419 }
00420 }
00421 for ( i = selectedRows.constEnd() - 1 ; i != selectedRows.constBegin() - 1; --i )
00422 {
00423 folderTableModel->removeRows( i.key() );
00424 }
00425 emit checkButtons();
00426 }
00427
00428 void FolderTableView::slotFillCells()
00429 {
00430
00431 if ( selectionInspectionResults.contains( oldRows ) )
00432 {
00433 QMessageBox::warning(
00434 this,
00435 tr( "Selection Warning" ),
00436 tr( "The current selection includes existing entries !\nThese will be ignored." ),
00437 QMessageBox::Ok,
00438 QMessageBox::Ok );
00439 }
00440
00441
00442 QVariant::Type controlType = getFolderTableModel()->getQVariantType( selectionInspectionResults.value( newRows )[ 0 ] );
00443 foreach ( QModelIndex index, selectionInspectionResults.value( newRows ) )
00444 {
00445 if ( !getFolderTableModel()->getQVariantType( index ) == controlType )
00446 {
00447 QMessageBox::warning(
00448 this,
00449 tr( "Selection Error" ),
00450 tr( "The current selection includes entries of different types!\nPlease amend selection." ),
00451 QMessageBox::Ok,
00452 QMessageBox::Ok );
00453 return;
00454 }
00455 }
00456
00457
00458 fillCellsDialog->lineEdit->setInputMask( getFolderTableModel()->getInputMask( selectionInspectionResults.value( newRows )[ 0 ] ) );
00459 fillCellsDialog->lineEdit->setValidator( getFolderTableModel()->getValidator( selectionInspectionResults.value( newRows )[ 0 ] ) );
00460
00461 fillCellsDialog->exec();
00462 if ( fillCellsDialog->result() == QDialog::Accepted )
00463 {
00464 folderTableModel->setData( selectionInspectionResults.value( newRows ), QVariant( fillCellsDialog->text() ) );
00465 }
00466 }
00467
00468 void FolderTableView::slotDisplayAsHex()
00469 {
00470 int column;
00471 QSet< int > columnSet;
00472 QModelIndex tempModelIndex;
00473 QModelIndexList tempModelIndexList( selectionInspectionResults.value( oldRows, QModelIndexList() ) );
00474 tempModelIndexList += selectionInspectionResults.value( newRows, QModelIndexList() );
00475 foreach ( tempModelIndex, tempModelIndexList )
00476 {
00477 column = tempModelIndex.column();
00478 if ( columnSet.contains( column ) )
00479 {
00480 continue;
00481 }
00482 else
00483 {
00484 columnSet.insert( column );
00485 folderTableModel->setDisplayAsMask( tempModelIndex, hexMask );
00486 }
00487 }
00488 }
00489
00490 void FolderTableView::slotDisplayAsDec()
00491 {
00492 int column;
00493 QSet< int > columnSet;
00494 QModelIndex tempModelIndex;
00495 QModelIndexList tempModelIndexList( selectionInspectionResults.value( oldRows, QModelIndexList() ) );
00496 tempModelIndexList += selectionInspectionResults.value( newRows, QModelIndexList() );
00497 foreach ( tempModelIndex, tempModelIndexList )
00498 {
00499 column = tempModelIndex.column();
00500 if ( columnSet.contains( column ) )
00501 {
00502 continue;
00503 }
00504 else
00505 {
00506 columnSet.insert( column );
00507 folderTableModel->setDisplayAsMask( tempModelIndex, decMask );
00508 }
00509 }
00510 }
00511
00512 void FolderTableView::slotDisplayAsOct()
00513 {
00514 int column;
00515 QSet< int > columnSet;
00516 QModelIndex tempModelIndex;
00517 QModelIndexList tempModelIndexList( selectionInspectionResults.value( oldRows, QModelIndexList() ) );
00518 tempModelIndexList += selectionInspectionResults.value( newRows, QModelIndexList() );
00519 foreach ( tempModelIndex, tempModelIndexList )
00520 {
00521 column = tempModelIndex.column();
00522 if ( columnSet.contains( column ) )
00523 {
00524 continue;
00525 }
00526 else
00527 {
00528 columnSet.insert( column );
00529 folderTableModel->setDisplayAsMask( tempModelIndex, octMask );
00530 }
00531 }
00532 }
00533
00534 void FolderTableView::slotDisplayAsDateTime()
00535 {
00536 int column;
00537 QSet< int > columnSet;
00538 QModelIndex tempModelIndex;
00539 QModelIndexList tempModelIndexList( selectionInspectionResults.value( oldRows, QModelIndexList() ) );
00540 tempModelIndexList += selectionInspectionResults.value( newRows, QModelIndexList() );
00541 foreach ( tempModelIndex, tempModelIndexList )
00542 {
00543 column = tempModelIndex.column();
00544 if ( columnSet.contains( column ) )
00545 {
00546 continue;
00547 }
00548 else
00549 {
00550 columnSet.insert( column );
00551 folderTableModel->setDisplayAsMask( tempModelIndex, datetimeMask );
00552 }
00553 }
00554 }
00555
00556 void FolderTableView::slotDisplayAs_Remove()
00557 {
00558 int column;
00559 QSet< int > columnSet;
00560 QModelIndex tempModelIndex;
00561 QModelIndexList tempModelIndexList( selectionInspectionResults.value( oldRows, QModelIndexList() ) );
00562 tempModelIndexList += selectionInspectionResults.value( newRows, QModelIndexList() );
00563 foreach ( tempModelIndex, tempModelIndexList )
00564 {
00565 column = tempModelIndex.column();
00566 if ( columnSet.contains( column ) )
00567 {
00568 continue;
00569 }
00570 else
00571 {
00572 columnSet.insert( column );
00573 folderTableModel->setDisplayAsMask( tempModelIndex, noMask );
00574 }
00575 }
00576 }
00577
00578 void FolderTableView::slotSetFocus()
00579 {
00580 setFocus();
00581 }
00582
00583 void FolderTableView::slotApplyFilter( FolderTableModel* tableModel, QList< int > hiddenRows )
00584 {
00585 bool anyRowsToHide( !hiddenRows.isEmpty() );
00586
00587 if ( tableModel == folderTableModel )
00588 {
00589 if ( anyRowsToHide )
00590 {
00591 setRowsHidden( hiddenRows, true );
00592 }
00593 else
00594 {
00595 showAllRows();
00596 }
00597 folderTableModel->setFiltered( anyRowsToHide );
00598 }
00599 }