curvelist_panel.cpp
Go to the documentation of this file.
00001 #include "curvelist_panel.h"
00002 #include "ui_curvelist_panel.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 #include <QStandardItem>
00017 #include <QWheelEvent>
00018 #include <QItemSelectionModel>
00019 
00020 class SortedTableItem: public QStandardItem
00021 {
00022 
00023 public:
00024     SortedTableItem(const QString& name): QStandardItem(name), str(name.toStdString()) {}
00025 
00026     bool operator< (const SortedTableItem &other) const
00027     {
00028         return doj::alphanum_impl(this->str.c_str(),
00029                                   other.str.c_str()) < 0;
00030     }
00031 private:
00032     std::string str;
00033 };
00034 
00035 
00036 //-------------------------------------------------
00037 
00038 CurveListPanel::CurveListPanel(const CustomPlotMap &mapped_math_plots,
00039                                            QWidget *parent) :
00040     QWidget(parent),
00041     ui(new Ui::CurveListPanel),
00042     _completer( new TreeModelCompleter(this) ),
00043     _custom_plots(mapped_math_plots),
00044     _point_size(9)
00045 {
00046     ui->setupUi(this);
00047     ui->tableView->viewport()->installEventFilter( this );
00048 
00049     _model = new QStandardItemModel(0, 2, this);
00050 
00051     for(auto table_view: {ui->tableView, ui->tableViewCustom})
00052     {
00053         table_view->viewport()->installEventFilter( this );
00054         table_view->setModel( _model );
00055         table_view->horizontalHeader()->setStretchLastSection (true);
00056         table_view->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
00057     }
00058 
00059     ui->widgetOptions->setVisible(false);
00060 
00061     ui->radioRegExp->setAutoExclusive(true);
00062     ui->radioContains->setAutoExclusive(true);
00063     ui->radioPrefix->setAutoExclusive(true);
00064 
00065     _completer->setCompletionMode( QCompleter::PopupCompletion );
00066 
00067     QSettings settings;
00068 
00069     QString active_filter = settings.value("FilterableListWidget.searchFilter").toString();
00070     if( active_filter == "radioRegExp"){
00071 
00072         ui->radioRegExp->setChecked(true);
00073     }
00074     else if( active_filter == "radioPrefix"){
00075 
00076         ui->radioPrefix->setChecked(true);
00077     }
00078     else if( active_filter == "radioContains"){
00079 
00080         ui->radioContains->setChecked(true);
00081     }
00082 
00083     _point_size = settings.value("FilterableListWidget/table_point_size", 9).toInt();
00084 
00085     _completer_need_update = ui->radioPrefix->isChecked();
00086     ui->lineEdit->setCompleter( _completer_need_update ? _completer : nullptr );
00087 
00088     ui->splitter->setStretchFactor(0,5);
00089     ui->splitter->setStretchFactor(1,1);
00090 
00091     connect(  ui->tableViewCustom->selectionModel(), &QItemSelectionModel::selectionChanged,
00092               this, &CurveListPanel::onCustomSelectionChanged );
00093 }
00094 
00095 CurveListPanel::~CurveListPanel()
00096 {
00097     delete ui;
00098 }
00099 
00100 int CurveListPanel::rowCount() const
00101 {
00102     return _model->rowCount();
00103 }
00104 
00105 void CurveListPanel::clear()
00106 {
00107     _model->setRowCount(0);
00108     _completer->clear();
00109     ui->labelNumberDisplayed->setText( "0 of 0");
00110 }
00111 
00112 void CurveListPanel::addItem(const QString &item_name)
00113 {
00114     if( _model->findItems(item_name).size() > 0)
00115     {
00116         return;
00117     }
00118 
00119     auto item = new SortedTableItem(item_name);
00120     QFont font = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
00121     font.setPointSize(_point_size);
00122     item->setFont(font);
00123     const int row = rowCount();
00124     _model->setRowCount(row+1);
00125     _model->setItem(row, 0, item);
00126 
00127     auto val_cell = new QStandardItem("-");
00128     val_cell->setTextAlignment(Qt::AlignRight);
00129     val_cell->setFlags( Qt::NoItemFlags | Qt::ItemIsEnabled );
00130     font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
00131     font.setPointSize( _point_size );
00132     val_cell->setFont( font );
00133     val_cell->setFlags(Qt::NoItemFlags);
00134 
00135     _model->setItem(row, 1, val_cell );
00136 
00137     if( _completer_need_update )
00138     {
00139         _completer->addToCompletionTree(item_name);
00140     }
00141 }
00142 
00143 void CurveListPanel::refreshColumns()
00144 {
00145     ui->tableView->sortByColumn(0,Qt::AscendingOrder);
00146     ui->tableViewCustom->sortByColumn(0,Qt::AscendingOrder);
00147 
00148     ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
00149     ui->tableViewCustom->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
00150 
00151     updateFilter();
00152 }
00153 
00154 
00155 int CurveListPanel::findRowByName(const std::string &text) const
00156 {
00157     auto item_list = _model->findItems( QString::fromStdString( text ), Qt::MatchExactly);
00158     if( item_list.isEmpty())
00159     {
00160         return -1;
00161     }
00162     if( item_list.count()>1)
00163     {
00164         qDebug() << "FilterableListWidget constins multiple rows with the same name";
00165         return -1;
00166     }
00167     return item_list.front()->row();
00168 }
00169 
00170 
00171 void CurveListPanel::updateFilter()
00172 {
00173     on_lineEdit_textChanged( ui->lineEdit->text() );
00174 }
00175 
00176 void CurveListPanel::keyPressEvent(QKeyEvent *event)
00177 {
00178     if( event->key() == Qt::Key_Delete){
00179         removeSelectedCurves();
00180     }
00181 }
00182 
00183 bool CurveListPanel::eventFilter(QObject *object, QEvent *event)
00184 {
00185     auto obj = object;
00186     while ( obj && obj != ui->tableView && obj != ui->tableViewCustom )
00187     {
00188         obj = obj->parent();
00189     }
00190 
00191     //Ignore obj different than tableViews
00192     if(!obj)
00193     {
00194         return QWidget::eventFilter(object,event);
00195     }
00196 
00197     bool shift_modifier_pressed = (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier);
00198     bool ctrl_modifier_pressed  = (QGuiApplication::keyboardModifiers() == Qt::ControlModifier);
00199 
00200     if(event->type() == QEvent::MouseButtonPress)
00201     {
00202         QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event);
00203 
00204         _dragging = false;
00205         _drag_start_pos = mouse_event->pos();
00206 
00207         if( !shift_modifier_pressed && !ctrl_modifier_pressed )
00208         {
00209             if( obj == ui->tableView)
00210             {
00211                 ui->tableViewCustom->clearSelection() ;
00212             }
00213             if( obj == ui->tableViewCustom)
00214             {
00215                 ui->tableView->clearSelection() ;
00216             }
00217         }
00218 
00219         if(mouse_event->button() == Qt::LeftButton )
00220         {
00221             _newX_modifier = false;
00222         }
00223         else if(mouse_event->button() == Qt::RightButton )
00224         {
00225             _newX_modifier = true;
00226         }
00227         else {
00228             return false;
00229         }
00230         return QWidget::eventFilter(object,event);
00231     }
00232     else if(event->type() == QEvent::MouseMove)
00233     {
00234         QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event);
00235         double distance_from_click = (mouse_event->pos() - _drag_start_pos).manhattanLength();
00236 
00237         if ((mouse_event->buttons() == Qt::LeftButton ||
00238              mouse_event->buttons() == Qt::RightButton) &&
00239             distance_from_click >= QApplication::startDragDistance() &&
00240             !_dragging)
00241         {
00242             _dragging = true;
00243             QDrag *drag = new QDrag(this);
00244             QMimeData *mimeData = new QMimeData;
00245 
00246             QByteArray mdata;
00247             QDataStream stream(&mdata, QIODevice::WriteOnly);
00248 
00249             for(const auto& curve_name: getNonHiddenSelectedRows())
00250             {
00251                 stream << QString::fromStdString(curve_name);
00252             }
00253 
00254             if( !_newX_modifier )
00255             {
00256                 mimeData->setData("curveslist/add_curve", mdata);
00257             }
00258             else
00259             {
00260                 if(getNonHiddenSelectedRows().size() != 1)
00261                 {
00262                     return false;
00263                 }
00264                 mimeData->setData("curveslist/new_X_axis", mdata);
00265 
00266                 QPixmap cursor( QSize(160,30) );
00267                 cursor.fill(Qt::transparent);
00268 
00269                 QPainter painter;
00270                 painter.begin( &cursor);
00271                 painter.setPen(QColor(22, 22, 22));
00272 
00273                 QString text("set as new X axis");
00274                 painter.setFont( QFont("Arial", 14 ) );
00275 
00276                 painter.setBackground(Qt::transparent);
00277                 painter.drawText( QRect(0, 0, 160, 30), Qt::AlignHCenter | Qt::AlignVCenter, text );
00278                 painter.end();
00279 
00280                 drag->setDragCursor(cursor, Qt::MoveAction);
00281             }
00282 
00283             drag->setMimeData(mimeData);
00284             drag->exec(Qt::CopyAction | Qt::MoveAction);
00285         }
00286         return true;
00287     }
00288     else if(event->type() == QEvent::Wheel)
00289     {
00290         QWheelEvent *wheel_event = dynamic_cast<QWheelEvent*>(event);
00291         int prev_size = _point_size;
00292         if( ctrl_modifier_pressed )
00293         {
00294             if( _point_size > 6 && wheel_event->delta() < 0 )
00295             {
00296                 _point_size--;
00297             }
00298             else if( _point_size < 14 && wheel_event->delta() > 0 )
00299             {
00300                 _point_size++;
00301             }
00302             if( _point_size != prev_size)
00303             {
00304                 auto horizontal = ui->tableView->horizontalHeader();
00305                 horizontal->setSectionResizeMode(0, QHeaderView::Fixed);
00306                 horizontal->setSectionResizeMode(1, QHeaderView::Fixed);
00307 
00308                 auto vertical = ui->tableView->verticalHeader();
00309                 vertical->setSectionResizeMode(0, QHeaderView::Fixed);
00310                 vertical->setSectionResizeMode(1, QHeaderView::Fixed);
00311 
00312                 for (int row=0; row< rowCount(); row++)
00313                 {
00314                     for (int col=0; col< 2; col++)
00315                     {
00316                         auto item = _model->item( row, col );
00317                         auto font = item->font();
00318                         font.setPointSize( _point_size );
00319                         item->setFont( font );
00320                     }
00321                 }
00322 
00323                 horizontal->setSectionResizeMode(0, QHeaderView::ResizeToContents);
00324                 horizontal->setSectionResizeMode(1, QHeaderView::Stretch);
00325                 vertical->setSectionResizeMode(0, QHeaderView::ResizeToContents);
00326                 vertical->setSectionResizeMode(1, QHeaderView::ResizeToContents);
00327 
00328                 QSettings settings;
00329                 settings.setValue("FilterableListWidget/table_point_size", _point_size);
00330             }
00331             return true;
00332         }
00333     }
00334 
00335     return QWidget::eventFilter(object,event);
00336 }
00337 
00338 std::vector<std::string> CurveListPanel::getNonHiddenSelectedRows()
00339 {
00340     std::vector<std::string> non_hidden_list;
00341 
00342     for(auto table_view: {ui->tableView, ui->tableViewCustom})
00343     {
00344         for (const auto &selected_index : table_view->selectionModel()->selectedRows(0))
00345         {
00346             if (!table_view->isRowHidden(selected_index.row()))
00347             {
00348                 auto item = _model->item( selected_index.row(), 0 );
00349                 non_hidden_list.push_back(item->text().toStdString());
00350             }
00351         }
00352     }
00353     return non_hidden_list;
00354 }
00355 
00356 QTableView *CurveListPanel::getTableView() const
00357 {
00358     return ui->tableView;
00359 }
00360 
00361 QTableView *CurveListPanel::getCustomView() const
00362 {
00363     return ui->tableViewCustom;
00364 }
00365 
00366 void CurveListPanel::on_radioContains_toggled(bool checked)
00367 {
00368     if(checked) {
00369         updateFilter();
00370         ui->lineEdit->setCompleter( nullptr );
00371         QSettings settings;
00372         settings.setValue("FilterableListWidget.searchFilter", "radioContains");
00373     }
00374 }
00375 
00376 void CurveListPanel::on_radioRegExp_toggled(bool checked)
00377 {
00378     if(checked) {
00379         updateFilter();
00380         ui->lineEdit->setCompleter( nullptr );
00381         QSettings settings;
00382         settings.setValue("FilterableListWidget.searchFilter", "radioRegExp");
00383     }
00384 }
00385 
00386 void CurveListPanel::on_radioPrefix_toggled(bool checked)
00387 {
00388     _completer_need_update = checked;
00389 
00390     if( checked )
00391     {
00392         _completer->clear();
00393         for (int row=0; row< rowCount(); row++)
00394         {
00395             auto item = _model->item(row,0);
00396             _completer->addToCompletionTree(item->text());
00397         }
00398 
00399         updateFilter();
00400         ui->lineEdit->setCompleter( _completer );
00401         QSettings settings;
00402         settings.setValue("FilterableListWidget.searchFilter", "radioPrefix");
00403     }
00404 }
00405 
00406 void CurveListPanel::on_checkBoxCaseSensitive_toggled(bool )
00407 {
00408     updateFilter();
00409 }
00410 
00411 void CurveListPanel::on_lineEdit_textChanged(const QString &search_string)
00412 {
00413     int item_count = rowCount();
00414     int visible_count = 0;
00415     bool updated = false;
00416 
00417     Qt::CaseSensitivity cs = Qt::CaseInsensitive;
00418     if( ui->checkBoxCaseSensitive->isChecked())
00419     {
00420         cs = Qt::CaseSensitive;
00421     }
00422     QRegExp regexp( search_string,  cs, QRegExp::Wildcard );
00423     QRegExpValidator v(regexp, nullptr);
00424 
00425     QStringList spaced_items = search_string.split(' ');
00426 
00427     for (int row=0; row < rowCount(); row++)
00428     {
00429         auto item = _model->item(row,0);
00430         QString name = item->text();
00431         int pos = 0;
00432         bool toHide = false;
00433 
00434         if( search_string.isEmpty() == false )
00435         {
00436             if( ui->radioRegExp->isChecked())
00437             {
00438                 toHide = v.validate( name, pos ) != QValidator::Acceptable;
00439             }
00440             else if( ui->radioPrefix->isChecked())
00441             {
00442                 toHide = !name.startsWith( search_string, cs ) ;
00443             }
00444             else if( ui->radioContains->isChecked())
00445             {
00446                 for (const auto& item: spaced_items)
00447                 {
00448                     if( name.contains(item, cs) == false )
00449                     {
00450                         toHide = true;
00451                         break;
00452                     }
00453                 }
00454             }
00455         }
00456         if( !toHide ) visible_count++;
00457 
00458         if( toHide != ui->tableView->isRowHidden(row) ) updated = true;
00459 
00460         const auto name_std = name.toStdString();
00461         const bool is_custom_plot = _custom_plots.count(name_std) > 0;
00462 
00463 
00464         ui->tableView->setRowHidden(row, toHide || is_custom_plot );
00465         ui->tableViewCustom->setRowHidden(row, toHide || !is_custom_plot );
00466     }
00467     ui->labelNumberDisplayed->setText( QString::number( visible_count ) + QString(" of ") +
00468                                        QString::number( item_count ) );
00469 
00470     if(updated){
00471         emit hiddenItemsChanged();
00472     }
00473 }
00474 
00475 void CurveListPanel::on_pushButtonSettings_toggled(bool checked)
00476 {
00477     ui->widgetOptions->setVisible(checked);
00478 }
00479 
00480 void CurveListPanel::on_checkBoxHideSecondColumn_toggled(bool checked)
00481 {
00482     for(auto table_view: {ui->tableView, ui->tableViewCustom})
00483     {
00484         if(checked){
00485             table_view->hideColumn(1);
00486         }
00487         else{
00488             table_view->showColumn(1);
00489         }
00490     }
00491     emit hiddenItemsChanged();
00492 }
00493 
00494 void CurveListPanel::removeSelectedCurves()
00495 {
00496     QMessageBox::StandardButton reply;
00497     reply = QMessageBox::question(nullptr, tr("Warning"),
00498                                   tr("Do you really want to remove these data?\n"),
00499                                   QMessageBox::Yes | QMessageBox::No,
00500                                   QMessageBox::No );
00501 
00502     if (reply == QMessageBox::Yes)
00503     {
00504         emit deleteCurves(getNonHiddenSelectedRows());
00505     }
00506 
00507     // rebuild the tree model
00508     if( _completer_need_update )
00509     {
00510         _completer->clear();
00511         for (int row=0; row< rowCount(); row++)
00512         {
00513             auto item = _model->item(row);
00514             _completer->addToCompletionTree(item->text());
00515         }
00516     }
00517 
00518     updateFilter();
00519 }
00520 
00521 void CurveListPanel::removeRow(int row)
00522 {
00523     _model->removeRow(row);
00524 }
00525 
00526 void CurveListPanel::on_buttonAddCustom_clicked()
00527 {
00528     auto curve_names = getNonHiddenSelectedRows();
00529     if( curve_names.empty() )
00530     {
00531         emit createMathPlot("");
00532     }
00533     else
00534     {
00535         createMathPlot( curve_names.front() );
00536     }
00537     on_lineEdit_textChanged( ui->lineEdit->text() );
00538 }
00539 
00540 //void FilterableListWidget::on_buttonRefreshAll_clicked()
00541 //{
00542 //    for(auto& it: _mapped_math_plots)
00543 //    {
00544 //        emit refreshMathPlot( it.second->name() );
00545 //    }
00546 //}
00547 
00548 void CurveListPanel::onCustomSelectionChanged(const QItemSelection&, const QItemSelection &)
00549 {
00550     int selected_items = 0;
00551 
00552     for (const auto &index : ui->tableViewCustom->selectionModel()->selectedRows(0))
00553     {
00554         if (! ui->tableViewCustom->isRowHidden(index.row()) )
00555         {
00556             selected_items++;
00557         }
00558     }
00559 
00560     bool enabled = selected_items == 1;
00561     ui->buttonEditCustom->setEnabled( enabled );
00562     ui->buttonEditCustom->setToolTip( enabled ? "Edit the selected custom timeserie" :
00563                                                 "Select a single custom Timeserie to Edit it");
00564 }
00565 
00566 void CurveListPanel::on_buttonEditCustom_clicked()
00567 {
00568     int selected_count = 0;
00569     QModelIndex selected_index;
00570     auto table_view = ui->tableViewCustom;
00571 
00572     for (QModelIndex index : table_view->selectionModel()->selectedRows(0))
00573     {
00574         if (!table_view->isRowHidden( index.row()) )
00575         {
00576             selected_count++;
00577             selected_index = index;
00578         }
00579     }
00580     if( selected_count != 1)
00581     {
00582         return;
00583     }
00584 
00585     auto item = _model->item( selected_index.row(), 0 );
00586     editMathPlot( item->text().toStdString() );
00587 }
00588 
00589 void CurveListPanel::clearSelections()
00590 {
00591     ui->tableViewCustom->clearSelection();
00592     ui->tableView->clearSelection();
00593 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Wed Jul 3 2019 19:28:04