filterablelistwidget.cpp
Go to the documentation of this file.
00001 #include "filterablelistwidget.h"
00002 #include "ui_filterablelistwidget.h"
00003 #include "PlotJuggler/alphanum.hpp"
00004 #include <QDebug>
00005 #include <QLayoutItem>
00006 #include <QMenu>
00007 #include <QSettings>
00008 #include <QDrag>
00009 #include <QMimeData>
00010 #include <QHeaderView>
00011 #include <QFontDatabase>
00012 #include <QMessageBox>
00013 #include <QApplication>
00014 #include <QPainter>
00015 #include <QCompleter>
00016 
00017 class TreeModelCompleter : public QCompleter
00018 {
00019 
00020 public:
00021     TreeModelCompleter(QAbstractItemModel *model, QObject *parent = 0): QCompleter(model, parent)
00022     {  }
00023 
00024     QStringList splitPath(const QString &path) const override {
00025         return path.split('/');
00026     }
00027 
00028     QString pathFromIndex(const QModelIndex &index) const override
00029     {
00030         QStringList dataList;
00031         for (QModelIndex i = index; i.isValid(); i = i.parent())
00032         {
00033             QString name = model()->data(i, completionRole()).toString();
00034             dataList.prepend(name);
00035         }
00036         return dataList.join('/');
00037     }
00038 };
00039 
00040 FilterableListWidget::FilterableListWidget(QWidget *parent) :
00041     QWidget(parent),
00042     ui(new Ui::FilterableListWidget),
00043     _tree_model( new QStandardItemModel(this)),
00044     _completer( new TreeModelCompleter(_tree_model, this) )
00045 {
00046     ui->setupUi(this);
00047     ui->tableWidget->viewport()->installEventFilter( this );
00048     ui->lineEdit->installEventFilter( this );
00049 
00050     ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
00051     ui->tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
00052     ui->tableWidget->horizontalHeader()->resizeSection(1, 120);
00053 
00054     ui->widgetOptions->setVisible(false);
00055 
00056     ui->radioRegExp->setAutoExclusive(true);
00057     ui->radioContains->setAutoExclusive(true);
00058     ui->radioPrefix->setAutoExclusive(true);
00059 
00060     _completer->setCompletionMode( QCompleter::PopupCompletion );
00061 
00062     QSettings settings( "IcarusTechnology", "PlotJuggler");
00063 
00064     QString active_filter = settings.value("FilterableListWidget.searchFilter", "radioContains").toString();
00065     if( active_filter == "radioRegExp")        ui->radioRegExp->setChecked(true);
00066     else if( active_filter == "radioPrefix")   ui->radioPrefix->setChecked(true);
00067     else if( active_filter == "radioContains") ui->radioContains->setChecked(true);
00068 
00069 }
00070 
00071 FilterableListWidget::~FilterableListWidget()
00072 {
00073     QSettings settings( "IcarusTechnology", "PlotJuggler");
00074 
00075     if(ui->radioRegExp->isChecked())
00076         settings.setValue("FilterableListWidget.searchFilter", "radioRegExp");
00077     else if(ui->radioPrefix->isChecked())
00078         settings.setValue("FilterableListWidget.searchFilter", "radioPrefix");
00079     else if(ui->radioContains->isChecked())
00080         settings.setValue("FilterableListWidget.searchFilter", "radioContains");
00081 
00082     delete ui;
00083 }
00084 
00085 int FilterableListWidget::rowCount() const
00086 {
00087     return ui->tableWidget->rowCount();
00088 }
00089 
00090 void FilterableListWidget::clear()
00091 {
00092     ui->tableWidget->setRowCount(0);
00093     _tree_model->clear();
00094     ui->labelNumberDisplayed->setText( "0 of 0");
00095 }
00096 
00097 class CustomSortedTableItem: public QTableWidgetItem
00098 {
00099 
00100  public:
00101      CustomSortedTableItem(const QString& name): QTableWidgetItem(name) {}
00102 
00103      bool operator< (const QTableWidgetItem &other) const
00104      {
00105          return doj::alphanum_impl(this->text().toLocal8Bit().constData(),
00106                                    other.text().toLocal8Bit().constData()) < 0;
00107      }
00108  };
00109 
00110 void FilterableListWidget::addItem(const QString &item_name, bool sort_columns)
00111 {
00112     auto item = new CustomSortedTableItem(item_name);
00113     const int row = rowCount();
00114     ui->tableWidget->setRowCount(row+1);
00115     ui->tableWidget->setItem(row, 0, item);
00116 
00117     auto val_cell = new QTableWidgetItem("-");
00118     val_cell->setTextAlignment(Qt::AlignRight);
00119     val_cell->setFlags( Qt::NoItemFlags | Qt::ItemIsEnabled );
00120     val_cell->setFont(  QFontDatabase::systemFont(QFontDatabase::FixedFont) );
00121 
00122     ui->tableWidget->setItem(row, 1, val_cell );
00123     if( sort_columns )
00124     {
00125       ui->tableWidget->sortByColumn(0,Qt::AscendingOrder);
00126     }
00127 
00128     addToCompletionTree(item);
00129 }
00130 
00131 void FilterableListWidget::sortColumns()
00132 {
00133   ui->tableWidget->sortByColumn(0,Qt::AscendingOrder);
00134 }
00135 
00136 
00137 QList<int>
00138 FilterableListWidget::findRowsByName(const QString &text) const
00139 {
00140     QList<int> output;
00141     QList<QTableWidgetItem*> item_list = ui->tableWidget->findItems( text, Qt::MatchExactly);
00142     for(QTableWidgetItem* item : item_list)
00143     {
00144         if(item->column() == 0) {
00145             output.push_back( item->row() );
00146         }
00147     }
00148     return output;
00149 }
00150 
00151 const QTableWidget *FilterableListWidget::getTable() const
00152 {
00153     return ui->tableWidget;
00154 }
00155 
00156 
00157 void FilterableListWidget::updateFilter()
00158 {
00159     on_lineEdit_textChanged( ui->lineEdit->text() );
00160 }
00161 
00162 void FilterableListWidget::keyPressEvent(QKeyEvent *event)
00163 {
00164     if( event->key() == Qt::Key_Delete){
00165         removeSelectedCurves();
00166     }
00167 }
00168 
00169 bool FilterableListWidget::eventFilter(QObject *object, QEvent *event)
00170 {
00171     QObject *obj = object;
00172     while ( obj != NULL )
00173     {
00174         if( obj == ui->tableWidget || obj == ui->lineEdit ) break;
00175         obj = obj->parent();
00176     }
00177 
00178     if(obj == ui->tableWidget)
00179     {
00180         if(event->type() == QEvent::MouseButtonPress)
00181         {
00182             QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event);
00183             if(mouse_event->button() == Qt::LeftButton )
00184             {
00185                 _newX_modifier = false;
00186                 _drag_start_pos = mouse_event->pos();
00187             }
00188             else if(mouse_event->button() == Qt::RightButton )
00189             {
00190                 _newX_modifier = true;
00191                 _drag_start_pos = mouse_event->pos();
00192             }
00193         }
00194         else if(event->type() == QEvent::MouseMove)
00195         {
00196             QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event);
00197             double distance_from_click = (mouse_event->pos() - _drag_start_pos).manhattanLength();
00198 
00199             if ((mouse_event->buttons() == Qt::LeftButton || mouse_event->buttons() == Qt::RightButton) &&
00200                     distance_from_click >= QApplication::startDragDistance())
00201             {
00202                 QDrag *drag = new QDrag(this);
00203                 QMimeData *mimeData = new QMimeData;
00204 
00205                 QByteArray mdata;
00206                 QDataStream stream(&mdata, QIODevice::WriteOnly);
00207 
00208                 for(QTableWidgetItem* item: ui->tableWidget->selectedItems()) {
00209                     stream << item->text();
00210                 }
00211                 if( _newX_modifier )
00212                 {
00213                     if( ui->tableWidget->selectedItems().size() == 1)
00214                     {
00215                         mimeData->setData("curveslist/new_X_axis", mdata);
00216 
00217                         QPixmap cursor( QSize(160,30) );
00218                         cursor.fill();
00219 
00220                         QPainter painter;
00221                         painter.begin( &cursor);
00222                         painter.setPen(QColor(22, 22, 22));
00223 
00224                         QString text("set as new X axis");
00225                         painter.setFont( QFont("Arial", 14 ) );
00226 
00227                         painter.drawText( QRect(0, 0, 160, 30), Qt::AlignHCenter | Qt::AlignVCenter, text );
00228                         painter.end();
00229 
00230                         drag->setDragCursor(cursor, Qt::MoveAction);
00231                     }
00232                     else{
00233                         //abort
00234                         QWidget::eventFilter(object,event);
00235                     }
00236                 }
00237                 else{
00238                     mimeData->setData("curveslist/add_curve", mdata);
00239                 }
00240 
00241                 drag->setMimeData(mimeData);
00242                 drag->exec(Qt::CopyAction | Qt::MoveAction);
00243             }
00244         }
00245     }
00246 
00247 //    if( obj == ui->lineEdit )
00248 //    {
00249 //        if(event->type() == QEvent::KeyPress)
00250 //        {
00251 //            QKeyEvent *key_event = static_cast<QKeyEvent*>(event);
00252 //            if( key_event->key() | Qt::Key_Tab || key_event->key() | Qt::Key_Enter)
00253 //            {
00254 //                qDebug() << "key event" ;
00255 //                if( _completer->completionCount() == 1)
00256 //                {
00257 //                    qDebug() << "pathFromIndex "  <<
00258 //                    _completer->pathFromIndex( _completer->currentIndex() );
00259 //                }
00260 //            }
00261 //        }
00262 //    }
00263     return QWidget::eventFilter(object,event);
00264 }
00265 
00266 
00267 void FilterableListWidget::on_radioContains_toggled(bool checked)
00268 {
00269     if(checked) {
00270         updateFilter();
00271         ui->lineEdit->setCompleter( nullptr );
00272     }
00273 }
00274 
00275 void FilterableListWidget::on_radioRegExp_toggled(bool checked)
00276 {
00277     if(checked) {
00278         updateFilter();
00279         ui->lineEdit->setCompleter( nullptr );
00280     }
00281 }
00282 
00283 void FilterableListWidget::addToCompletionTree(QTableWidgetItem* item)
00284 {
00285     QString name = item->data(Qt::DisplayRole).toString();
00286     QStringList parts = name.split('/');
00287 
00288     QStandardItem *parent_item = _tree_model->invisibleRootItem();
00289 
00290     for (int col=0; col < parts.count(); col++)
00291     {
00292         bool already_stored = false;
00293         for (int row = 0; row < parent_item->rowCount() && !already_stored; row++)
00294         {
00295             if( parent_item->child(row)->text() == parts[col])
00296             {
00297                 already_stored = true;
00298                 parent_item = parent_item->child(row);
00299             }
00300         }
00301         if( !already_stored )
00302         {
00303             QStandardItem *item = new QStandardItem(parts[col]);
00304             parent_item->appendRow(item);
00305             parent_item = item;
00306         }
00307     }
00308 }
00309 
00310 void FilterableListWidget::on_radioPrefix_toggled(bool checked)
00311 {
00312     if(checked) {
00313         updateFilter();
00314         ui->lineEdit->setCompleter( _completer );
00315     }
00316 }
00317 
00318 void FilterableListWidget::on_checkBoxCaseSensitive_toggled(bool checked)
00319 {
00320     updateFilter();
00321 }
00322 
00323 
00324 void FilterableListWidget::on_lineEdit_textChanged(const QString &search_string)
00325 {
00326     int item_count = rowCount();
00327     int visible_count = 0;
00328     bool updated = false;
00329 
00330     Qt::CaseSensitivity cs = Qt::CaseInsensitive;
00331     if( ui->checkBoxCaseSensitive->isChecked())
00332     {
00333         cs = Qt::CaseSensitive;
00334     }
00335     QRegExp regexp( search_string,  cs, QRegExp::Wildcard );
00336     QRegExpValidator v(regexp, 0);
00337 
00338     for (int row=0; row< rowCount(); row++)
00339     {
00340         QTableWidgetItem* item = ui->tableWidget->item(row,0);
00341         QString name = item->text();
00342         int pos = 0;
00343         bool toHide = false;
00344 
00345         if( ui->radioRegExp->isChecked())
00346         {
00347             toHide = v.validate( name, pos ) != QValidator::Acceptable;
00348         }
00349         else if( ui->radioPrefix->isChecked())
00350         {
00351             toHide = !name.startsWith( search_string, cs ) ;
00352         }
00353         else if( ui->radioContains->isChecked())
00354         {
00355             QStringList items = search_string.split(' ');
00356             for (int i=0; i< items.size(); i++)
00357             {
00358                 if( name.contains(items[i], cs) == false )
00359                 {
00360                     toHide = true;
00361                 }
00362             }
00363         }
00364         if( !toHide ) visible_count++;
00365 
00366         if( toHide != ui->tableWidget->isRowHidden(row) ) updated = true;
00367 
00368         ui->tableWidget->setRowHidden(row, toHide );
00369     }
00370     ui->labelNumberDisplayed->setText( QString::number( visible_count ) + QString(" of ") + QString::number( item_count ) );
00371 
00372     if(updated){
00373         emit hiddenItemsChanged();
00374     }
00375 }
00376 
00377 void FilterableListWidget::on_pushButtonSettings_toggled(bool checked)
00378 {
00379     ui->widgetOptions->setVisible(checked);
00380 }
00381 
00382 void FilterableListWidget::on_checkBoxHideSecondColumn_toggled(bool checked)
00383 {
00384     if(checked){
00385         ui->tableWidget->hideColumn(1);
00386         emit hiddenItemsChanged();
00387     }
00388     else{
00389         ui->tableWidget->showColumn(1);
00390         emit hiddenItemsChanged();
00391     }
00392 }
00393 
00394 void FilterableListWidget::removeSelectedCurves()
00395 {
00396     QMessageBox::StandardButton reply;
00397     reply = QMessageBox::question(0, tr("Warning"),
00398                                   tr("Do you really want to remove these data?\n"),
00399                                   QMessageBox::Yes | QMessageBox::No,
00400                                   QMessageBox::No );
00401 
00402     if( reply == QMessageBox::Yes ) {
00403 
00404         while( ui->tableWidget->selectedItems().size() > 0 )
00405         {
00406             QTableWidgetItem* item = ui->tableWidget->selectedItems().first();
00407             emit deleteCurve( item->text() );
00408         }
00409     }
00410 
00411     // rebuild the tree model
00412     _tree_model->clear();
00413     for (int row=0; row< rowCount(); row++)
00414     {
00415         QTableWidgetItem* item = ui->tableWidget->item(row,0);
00416         addToCompletionTree(item);
00417     }
00418 
00419     updateFilter();
00420 }
00421 
00422 void FilterableListWidget::removeRow(int row)
00423 {
00424     ui->tableWidget->removeRow(row);
00425 }
00426 
00427 


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56