tabbedplotwidget.cpp
Go to the documentation of this file.
1 #include <QMenu>
2 #include <QSignalMapper>
3 #include <QAction>
4 #include <QInputDialog>
5 #include <QMouseEvent>
6 #include <QFileDialog>
7 #include <QApplication>
8 #include "qwt_plot_renderer.h"
9 #include "mainwindow.h"
10 #include "tabbedplotwidget.h"
11 #include "tab_widget.h"
12 #include "ui_tabbedplotwidget.h"
13 
14 std::map<QString,TabbedPlotWidget*> TabbedPlotWidget::_instances;
15 
17  QMainWindow *main_window_,
18  PlotMatrix *first_tab,
19  PlotDataMapRef &mapped_data,
20  QMainWindow *parent ) :
21  QWidget(parent),
22  _mapped_data(mapped_data),
23  ui(new Ui::TabbedPlotWidget),
24  _name(name),
25  _labels_status (LabelStatus::RIGHT)
26 {
27  MainWindow* main_window = static_cast<MainWindow*>(main_window_);
28 
29  if( main_window == parent){
30  _parent_type = "main_window";
31  }
32  else
33  {
34  _parent_type = "floating_window";
35  }
36 
37  if( TabbedPlotWidget::_instances.count(_name) > 0)
38  {
39  throw std::runtime_error("This is not supposed to happen");
40  }
41  // register this instance
42  _instances[_name] = this;
43 
44  ui->setupUi(this);
45 
46  _horizontal_link = true;
47 
48  tabWidget()->tabBar()->installEventFilter( this );
49 
50  _action_renameTab = new QAction(tr("Rename tab"), this);
51  connect( _action_renameTab, &QAction::triggered, this, &TabbedPlotWidget::on_renameCurrentTab);
52 
53  QIcon iconSave;
54  iconSave.addFile(QStringLiteral(":/icons/resources/light/save.png"), QSize(26, 26));
55  _action_savePlots = new QAction(tr("&Save plots to file"), this);
56  _action_savePlots->setIcon(iconSave);
57  connect(_action_savePlots, &QAction::triggered, this, &TabbedPlotWidget::on_savePlotsToFile);
58 
59  _tab_menu = new QMenu(this);
60  _tab_menu->addAction( _action_renameTab );
61  _tab_menu->addSeparator();
62  _tab_menu->addAction( _action_savePlots );
63  _tab_menu->addSeparator();
64 
65  connect( this, &TabbedPlotWidget::destroyed, main_window, &MainWindow::on_tabbedAreaDestroyed );
67  connect( this, &TabbedPlotWidget::matrixAdded, main_window, &MainWindow::onPlotMatrixAdded);
69 
71 
72  this->addTab(first_tab);
73 }
74 
75 //void TabbedPlotWidget::setSiblingsList(const std::map<QString, TabbedPlotWidget *> &other_tabbed_widgets)
76 //{
77 // _other_siblings = other_tabbed_widgets;
78 //}
79 
81 {
82  return static_cast<PlotMatrix*>( tabWidget()->currentWidget() );
83 }
84 
86 {
87  return ui->tabWidget;
88 }
89 
90 const QTabWidget* TabbedPlotWidget::tabWidget() const
91 {
92  return ui->tabWidget;
93 }
94 
95 
97 {
98  if( !tab )
99  {
100  tab = new PlotMatrix("plot", _mapped_data, this);
101  tabWidget()->addTab( tab, QString("plot") );
102 
103  QApplication::processEvents();
104  emit matrixAdded( tab );
105  tab->addColumn();
106  }
107  else{
108  tabWidget()->addTab( tab, tab->name() );
109  }
110 
111  tabWidget()->setCurrentWidget( tab );
113 }
114 
115 QDomElement TabbedPlotWidget::xmlSaveState(QDomDocument &doc) const
116 {
117  QDomElement tabbed_area = doc.createElement( "tabbed_widget" );
118 
119  tabbed_area.setAttribute("name", _name);
120  tabbed_area.setAttribute("parent", _parent_type);
121 
122  for(int i=0; i< tabWidget()->count(); i++)
123  {
124  PlotMatrix* widget = static_cast<PlotMatrix*>( tabWidget()->widget(i) );
125  QDomElement element = widget->xmlSaveState(doc);
126 
127  element.setAttribute("tab_name", tabWidget()->tabText(i) );
128  tabbed_area.appendChild( element );
129  }
130 
131  QDomElement current_plotmatrix = doc.createElement( "currentPlotMatrix" );
132  current_plotmatrix.setAttribute( "index", tabWidget()->currentIndex() );
133  tabbed_area.appendChild( current_plotmatrix );
134 
135  return tabbed_area;
136 }
137 
138 bool TabbedPlotWidget::xmlLoadState(QDomElement &tabbed_area)
139 {
140  int num_tabs = tabWidget()->count();
141  int index = 0;
142 
143  QDomElement plotmatrix_el;
144 
145  for ( plotmatrix_el = tabbed_area.firstChildElement( "plotmatrix" ) ;
146  !plotmatrix_el.isNull();
147  plotmatrix_el = plotmatrix_el.nextSiblingElement( "plotmatrix" ) )
148  {
149  // add if tabs are too few
150  if( index == num_tabs)
151  {
152  this->addTab( NULL );
153  num_tabs++;
154  }
155  PlotMatrix* plot_matrix = static_cast<PlotMatrix*>( tabWidget()->widget(index) );
156  bool success = plot_matrix->xmlLoadState( plotmatrix_el );
157 
158  // read tab name
159  if( plotmatrix_el.hasAttribute("tab_name"))
160  {
161  QString tab_name = plotmatrix_el.attribute("tab_name" );
162  tabWidget()->setTabText( index, tab_name );
163  plot_matrix->setName( tab_name );
164  }
165 
166  if( !success )
167  {
168  return false;
169  }
170 
171  index++;
172  }
173 
174  // remove if tabs are too much
175  while( num_tabs > index ){
176  tabWidget()->removeTab( num_tabs-1 );
177  num_tabs--;
178  }
179 
180  QDomElement current_plotmatrix = tabbed_area.firstChildElement( "currentPlotMatrix" );
181  int current_index = current_plotmatrix.attribute( "index" ).toInt();
182 
183  if(current_index>=0 && current_index < tabWidget()->count())
184  {
185  tabWidget()->setCurrentIndex( current_index );
186  }
187  return true;
188 }
189 
190 void TabbedPlotWidget::setStreamingMode(bool streaming_mode)
191 {
192  ui->buttonLinkHorizontalScale->setEnabled( !streaming_mode );
193  ui->pushVerticalResize->setEnabled( !streaming_mode );
194  ui->pushHorizontalResize->setEnabled( !streaming_mode );
195 }
196 
197 
199 
200  delete ui;
201 }
202 
204 {
205  int idx = tabWidget()->tabBar()->currentIndex ();
206 
207  bool ok = true;
208  QString newName = QInputDialog::getText (
209  this, tr ("Change Name of the selected tab"),
210  tr ("Insert New Tab Name"),
211  QLineEdit::Normal,
212  tabWidget()->tabText (idx),
213  &ok);
214 
215  if (ok) {
216  tabWidget()->setTabText (idx, newName);
217  currentTab()->setName( newName );
218  }
219 }
220 
222 {
223  int idx = tabWidget()->tabBar()->currentIndex();
224  PlotMatrix* matrix = static_cast<PlotMatrix*>( tabWidget()->widget(idx) );
225 
226  QFileDialog saveDialog;
227  saveDialog.setAcceptMode(QFileDialog::AcceptSave);
228  saveDialog.setDefaultSuffix("png");
229  saveDialog.selectFile(currentTab()->name());
230 
231  saveDialog.setNameFilter("Compatible formats (*.jpg *.jpeg *.png)");
232 
233  saveDialog.exec();
234 
235  if(saveDialog.result() == QDialog::Accepted && !saveDialog.selectedFiles().empty())
236  {
237  QString fileName = saveDialog.selectedFiles().first();
238 
239  saveTabImage(fileName, matrix);
240  }
241 }
242 
243 void TabbedPlotWidget::saveTabImage(QString fileName, PlotMatrix* matrix)
244 {
245  QPixmap pixmap (1200,900);
246  QPainter * painter = new QPainter(&pixmap);
247 
248  if ( !fileName.isEmpty() )
249  {
250  QwtPlotRenderer rend;
251 
252  int delta_X = pixmap.width() / matrix->colsCount();
253  int delta_Y = pixmap.height() / matrix->rowsCount();
254 
255  for (unsigned c=0; c< matrix->colsCount(); c++)
256  {
257  for (unsigned r=0; r< matrix->rowsCount(); r++)
258  {
259  PlotWidget* widget = matrix->plotAt(r,c);
260  QRect rect(delta_X*c, delta_Y*r, delta_X, delta_Y);
261  rend.render(widget,painter, rect);
262  }
263  }
264  pixmap.save(fileName);
265  }
266 }
267 
269 {
270  currentTab()->addRow();
272  emit undoableChangeHappened();
273 }
274 
276 {
277  currentTab()->addColumn();
279  emit undoableChangeHappened();
280 }
281 
283 {
285  emit undoableChangeHappened();
286 }
287 
289 {
291  emit undoableChangeHappened();
292 }
293 
295 {
297  emit undoableChangeHappened();
298 }
299 
301 {
302  int src_row, src_col;
303  PlotMatrix* src_matrix = nullptr;
304  PlotWidget* source = nullptr;
305 
306  auto func = [&](QTabWidget * tabs)
307  {
308  for (int t=0; t < tabs->count(); t++)
309  {
310  PlotMatrix* matrix = static_cast<PlotMatrix*>(tabs->widget(t));
311 
312  for(unsigned row=0; row< matrix->rowsCount(); row++)
313  {
314  for(unsigned col=0; col< matrix->colsCount(); col++)
315  {
316  PlotWidget* plot = matrix->plotAt(row, col);
317  if( plot->windowTitle() == plot_name)
318  {
319  src_matrix = matrix;
320  src_row = row;
321  src_col = col;
322  source = plot;
323  return;
324  }
325  }
326  }
327  }
328  };
329 
330  for(const auto& it: TabbedPlotWidget::instances())
331  {
332  func( it.second->tabWidget() );
333  }
334 
335  addTab();
336  PlotMatrix* dst_matrix = currentTab();
337  PlotWidget* destination = dst_matrix->plotAt(0,0);
338 
339  src_matrix->gridLayout()->removeWidget( source );
340  dst_matrix->gridLayout()->removeWidget( destination );
341 
342  src_matrix->gridLayout()->addWidget( destination, src_row, src_col );
343  dst_matrix->gridLayout()->addWidget( source, 0, 0 );
344  source->changeBackgroundColor( Qt::white );
345  destination->changeBackgroundColor( Qt::white );
346 
347  src_matrix->removeEmpty();
348  src_matrix->updateLayout();
349  dst_matrix->updateLayout();
350  emit undoableChangeHappened();
351 
352 }
353 
355 {
356  addTab( nullptr );
357  emit undoableChangeHappened();
358 }
359 
361 {
362  currentTab()->removeEmpty();
363  emit undoableChangeHappened();
364 }
365 
367 {
368  if( tabWidget()->count() == 0)
369  {
370  if( _parent_type.compare("main_window") == 0)
371  {
372  addTab( NULL);
373  }
374  else{
375  this->parent()->deleteLater();
376  }
377  }
378 
379  PlotMatrix* tab = static_cast<PlotMatrix*>( tabWidget()->widget(index) );
380  if( tab )
381  {
382  tab->replot();
383  }
384 }
385 
387 {
388  PlotMatrix* tab = static_cast<PlotMatrix*>( tabWidget()->widget(index) );
389 
390  bool close_confirmed = true;
391  if( tab->plotCount() == 1 )
392  {
393  if( tab->plotAt(0)->isEmpty()){
394  close_confirmed = false;
395  }
396  }
397 
398  QMessageBox::StandardButton do_remove = QMessageBox::Yes;
399 
400  if( close_confirmed )
401  {
402  tabWidget()->setCurrentIndex( index );
403  QApplication::processEvents();
404 
405  do_remove = QMessageBox::question( this, tr("Warning"),
406  tr("Do you really want to destroy this tab?\n"),
407  QMessageBox::Yes | QMessageBox::No,
408  QMessageBox::No );
409  }
410  if( do_remove == QMessageBox::Yes )
411  {
412  // first add then delete.
413  // Otherwise currentPlotGrid might be empty
414  if( tabWidget()->count() == 1){
416  }
417 
418  PlotMatrix* matrix = static_cast<PlotMatrix*>( tabWidget()->widget(index) );
419 
420  for(unsigned p=0; p< matrix->plotCount(); p++)
421  {
422  PlotWidget* plot = matrix->plotAt(p);
423  plot->detachAllCurves();
424  plot->deleteLater();
425  }
426 
427  tabWidget()->removeTab( index );
428  emit undoableChangeHappened();
429  }
430 }
431 
433 {
434  _horizontal_link = checked;
435 
436  for (int i = 0; i < tabWidget()->count(); i++)
437  {
438  PlotMatrix* tab = static_cast<PlotMatrix*>( tabWidget()->widget(i) );
440  }
441 }
442 
443 void TabbedPlotWidget::on_requestTabMovement(const QString & destination_name)
444 {
445  TabbedPlotWidget* destination_widget = TabbedPlotWidget::_instances[destination_name];
446 
447  PlotMatrix* tab_to_move = currentTab();
448  int index = tabWidget()->tabBar()->currentIndex ();
449 
450  const QString& tab_name = this->tabWidget()->tabText(index);
451 
452  destination_widget->tabWidget()->addTab( tab_to_move, tab_name );
453 
454  qDebug() << "move "<< tab_name<< " into " << destination_name;
455  emit undoableChangeHappened();
456 }
457 
459 {
460  emit sendTabToNewWindow( currentTab() );
461 }
462 
464 {
465  switch(_labels_status)
466  {
467  case LabelStatus::LEFT: _labels_status = LabelStatus::HIDDEN; break;
468  case LabelStatus::RIGHT: _labels_status = LabelStatus::LEFT; break;
469  case LabelStatus::HIDDEN: _labels_status = LabelStatus::RIGHT; break;
470  }
472 }
473 
474 
475 bool TabbedPlotWidget::eventFilter(QObject *obj, QEvent *event)
476 {
477  QTabBar* tab_bar = tabWidget()->tabBar();
478 
479  if (obj == tab_bar )
480  {
481  if( event->type() == QEvent::MouseButtonPress)
482  {
483  QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event);
484 
485  int index = tab_bar->tabAt( mouse_event->pos() );
486  tab_bar->setCurrentIndex( index );
487 
488 
489  if( mouse_event->button() == Qt::RightButton )
490  {
491  QMenu* submenu = new QMenu("Move tab to...");
492  _tab_menu->addMenu( submenu );
493 
494  std::map<QString,TabbedPlotWidget*>::iterator it;
495  QSignalMapper* signalMapper = new QSignalMapper(submenu);
496 
497  //-----------------------------------
498  QAction* action_new_window = submenu->addAction( "New Window" );
499 
500  QIcon icon;
501  icon.addFile(QStringLiteral(":/icons/resources/light/stacks.png"), QSize(16, 16));
502 
503  action_new_window->setIcon( icon);
504  submenu->addSeparator();
505 
506  connect( action_new_window, &QAction::triggered, this, &TabbedPlotWidget::on_moveTabIntoNewWindow );
507 
508  //-----------------------------------
509  for(auto& it : TabbedPlotWidget::_instances)
510  {
511  QString name = it.first;
512  TabbedPlotWidget* tabbed_menu = it.second;
513  if( tabbed_menu != this )
514  {
515  QAction* action = submenu->addAction( name );
516  connect(action, SIGNAL(triggered()), signalMapper, SLOT(map()));
517  signalMapper->setMapping( action, name );
518  }
519  }
520 
521  connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(on_requestTabMovement(QString)) );
522 
523  //-------------------------------
524  _tab_menu->exec( mouse_event->globalPos() );
525  //-------------------------------
526  submenu->deleteLater();
527  }
528  }
529  }
530 
531  // Standard event processing
532  return QObject::eventFilter(obj, event);
533 }
534 
536 {
537  for(int i=0; i< tabWidget()->count(); i++)
538  {
539  PlotMatrix* matrix = static_cast<PlotMatrix*>( tabWidget()->widget(i) );
540 
541  for(unsigned p=0; p< matrix->plotCount(); p++)
542  {
543  PlotWidget* plot = matrix->plotAt(p);
544 
545  plot->activateLegend( _labels_status != LabelStatus::HIDDEN );
546  if( _labels_status == LabelStatus::LEFT)
547  {
548  plot->setLegendAlignment( Qt::AlignLeft );
549  }
550  else if( _labels_status == LabelStatus::RIGHT)
551  {
552  plot->setLegendAlignment( Qt::AlignRight);
553  }
554  plot->replot();
555  }
556  }
557 }
558 
559 void TabbedPlotWidget::closeEvent(QCloseEvent *event)
560 {
562 }
563 
564 const std::map<QString, TabbedPlotWidget *> &TabbedPlotWidget::instances()
565 {
567 }
568 
570 {
571  auto it = TabbedPlotWidget::_instances.find(key);
572  if( it == TabbedPlotWidget::_instances.end())
573  {
574  return nullptr;
575  }
576  else{
577  return it->second;
578  }
579 }
580 
582 {
583  ui->widgetControls->setVisible(visible);
584 }
585 
586 
587 
void maximumZoomOutVertical()
Definition: plotmatrix.cpp:387
QGridLayout * gridLayout()
Definition: plotmatrix.cpp:369
void on_pushVerticalResize_pressed()
void on_pushButtonZoomMax_pressed()
void addTab(PlotMatrix *tab=nullptr)
void replot() override
QAction * _action_renameTab
void onPlotMatrixAdded(PlotMatrix *matrix)
Definition: mainwindow.cpp:668
static void saveTabImage(QString fileName, PlotMatrix *matrix)
TabbedPlotWidget(QString name, QMainWindow *main_window, PlotMatrix *first_tab, PlotDataMapRef &mapped_data, QMainWindow *parent)
void on_tabWidget_currentChanged(int index)
void on_buttonLinkHorizontalScale_toggled(bool checked)
void detachAllCurves()
Definition: plotwidget.cpp:593
void undoableChangeHappened()
QDomElement xmlSaveState(QDomDocument &doc) const
Definition: plotmatrix.cpp:265
void activateLegend(bool activate)
bool isEmpty() const
Definition: plotwidget.cpp:473
void addRow()
Definition: plotmatrix.cpp:54
LabelStatus _labels_status
static std::map< QString, TabbedPlotWidget * > _instances
bool xmlLoadState(QDomElement &plotmatrix_element)
Definition: plotmatrix.cpp:288
void on_requestTabMovement(const QString &destination_name)
QString name() const
PlotWidget * plotAt(unsigned row, unsigned column)
Definition: plotmatrix.cpp:223
Renderer for exporting a plot to a document, a printer or anything else, that is supported by QPainte...
const QString & name() const
Definition: plotmatrix.cpp:364
char * end
unsigned plotCount() const
Definition: plotmatrix.cpp:193
~TabbedPlotWidget() override
PlotDataMapRef & _mapped_data
void on_pushHorizontalResize_pressed()
Ui::TabbedPlotWidget * ui
bool xmlLoadState(QDomElement &tabbed_area)
unsigned colsCount() const
Definition: plotmatrix.cpp:188
void setStreamingMode(bool streaming_mode)
void on_tabbedAreaDestroyed(QObject *object)
void movingPlotWidgetToTab(QString plot_name)
unsigned rowsCount() const
Definition: plotmatrix.cpp:183
QTabWidget * tabWidget()
void onMoveWidgetIntoNewTab(QString plot_name)
static TabbedPlotWidget * instance(const QString &key)
void on_pushButtonShowLabel_pressed()
virtual void closeEvent(QCloseEvent *event) override
action
PlotMatrix * currentTab()
void changeBackgroundColor(QColor color)
void updateLayout()
Definition: plotmatrix.cpp:328
void replot()
Definition: plotmatrix.cpp:343
void removeEmpty()
Definition: plotmatrix.cpp:157
void setLegendAlignment(Qt::Alignment alignment)
virtual bool eventFilter(QObject *obj, QEvent *event) override
void matrixAdded(PlotMatrix *)
void setHorizontalLink(bool linked)
Definition: plotmatrix.cpp:353
virtual void render(QwtPlot *, QPainter *, const QRectF &rect) const
void setName(const QString &new_name)
Definition: plotmatrix.cpp:359
void onUndoableChange()
Definition: mainwindow.cpp:214
int i
void sendTabToNewWindow(PlotMatrix *)
QDomElement xmlSaveState(QDomDocument &doc) const
void addColumn()
Definition: plotmatrix.cpp:72
void setControlsVisible(bool visible)
void on_tabWidget_tabCloseRequested(int index)
void maximumZoomOut()
Definition: plotmatrix.cpp:400
void maximumZoomOutHorizontal()
Definition: plotmatrix.cpp:374
QAction * _action_savePlots
const QString _name
static const std::map< QString, TabbedPlotWidget * > & instances()
void onCreateFloatingWindow(PlotMatrix *first_tab=nullptr)


plotjuggler
Author(s): Davide Faconti
autogenerated on Sat Jul 6 2019 03:44:18