tabbedplotwidget.cpp
Go to the documentation of this file.
1 #include <QMenu>
2 #include <QSignalMapper>
3 #include <QAction>
4 #include <QTabBar>
5 #include <QSvgGenerator>
6 #include <QInputDialog>
7 #include <QMouseEvent>
8 #include <QFileDialog>
9 #include <QApplication>
10 #include <QPainter>
11 #include <QTabWidget>
12 #include <QPushButton>
13 #include <QHBoxLayout>
14 #include "qwt_plot_renderer.h"
15 #include "mainwindow.h"
16 #include "tabbedplotwidget.h"
17 #include "tab_widget.h"
18 #include "svg_util.h"
19 
20 std::map<QString, TabbedPlotWidget*> TabbedPlotWidget::_instances;
21 
22 TabbedPlotWidget::TabbedPlotWidget(QString name, QMainWindow* mainwindow,
23  PlotDataMapRef& mapped_data, QMainWindow* parent)
24  : QWidget(parent)
25  , _mapped_data(mapped_data)
26  , _name(name)
27  , _main_window(mainwindow)
28 {
29  MainWindow* main_window = dynamic_cast<MainWindow*>(_main_window);
30 
31  setContentsMargins(0,0,0,0);
32 
33  if (main_window == parent)
34  {
35  _parent_type = "main_window";
36  }
37  else
38  {
39  _parent_type = "floating_window";
40  }
41 
43  {
44  throw std::runtime_error("This is not supposed to happen");
45  }
46  // register this instance
47  _instances[_name] = this;
48 
49  _horizontal_link = true;
50 
51  QHBoxLayout* main_layout = new QHBoxLayout(this);
52  main_layout->setMargin(0);
53 
54  _tabWidget = new QTabWidget(this);
55  _tabWidget->setTabsClosable(true);
56  _tabWidget->setMovable(true);
57 
58  connect(_tabWidget->tabBar(), &QTabBar::tabBarDoubleClicked,
60 
61  main_layout->addWidget(_tabWidget);
62 
63  connect(_tabWidget, &QTabWidget::currentChanged,
65 
66  tabWidget()->tabBar()->installEventFilter(this);
67 
68 
69  // TODO _action_savePlots = new QAction(tr("&Save plots to file"), this);
70  // TODO connect(_action_savePlots, &QAction::triggered, this, &TabbedPlotWidget::on_savePlotsToFile);
71 
72 // _tab_menu = new QMenu(this);
73 // _tab_menu->addSeparator();
74 // //_tab_menu->addAction(_action_savePlots);
75 // _tab_menu->addSeparator();
76 
77  connect(this, &TabbedPlotWidget::destroyed, main_window, &MainWindow::on_tabbedAreaDestroyed);
78  connect(this, &TabbedPlotWidget::tabAdded, main_window, &MainWindow::onPlotTabAdded);
80 
81  // TODO connect(_tabWidget, &TabWidget::movingPlotWidgetToTab, this, &TabbedPlotWidget::onMoveWidgetIntoNewTab);
82 
83  this->addTab({});
84 
85  _buttonAddTab = new QPushButton("",this);
86  _buttonAddTab->setFlat(true);
87  _buttonAddTab->setFixedSize( QSize(32,32));
88  _buttonAddTab->setFocusPolicy(Qt::NoFocus);
89 
90  connect(_buttonAddTab, &QPushButton::pressed, this, &TabbedPlotWidget::on_addTabButton_pressed);
91 }
92 
93 void TabbedPlotWidget::paintEvent(QPaintEvent *event)
94 {
95  QWidget::paintEvent(event);
96 
97  auto size = tabWidget()->tabBar()->size();
98  _buttonAddTab->move( QPoint( size.width()+ 5, 0) );
99 }
100 
101 
103 {
104  return static_cast<PlotDocker*>(tabWidget()->currentWidget());
105 }
106 
108 {
109  return _tabWidget;
110 }
111 
112 const QTabWidget* TabbedPlotWidget::tabWidget() const
113 {
114  return _tabWidget;
115 }
116 
118 {
119  static int tab_suffix_count = 1;
120 
121  // this must be done before ant PlotDocker is created
127 
128  if( tab_name.isEmpty() )
129  {
130  tab_name = QString("tab%1").arg(tab_suffix_count++);
131  }
132 
133  auto docker = new PlotDocker(tab_name, _mapped_data, this);
135 
136  tabWidget()->addTab(docker, tab_name);
137 
138  emit tabAdded(docker);
139  // we need to send the signal for the very first widget
140  emit docker->plotWidgetAdded( docker->plotAt(0) );
141 
142  int index = tabWidget()->count() - 1;
143 
144  QWidget* button_widget = new QWidget();
145  QHBoxLayout* layout = new QHBoxLayout(button_widget);
146  layout->setSpacing(2);
147  layout->setMargin(0);
148 
149  QPushButton* close_button = new QPushButton();
150 
151  QSettings settings;
152  QString theme = settings.value("StyleSheet::theme", "light").toString();
153  close_button->setIcon(LoadSvgIcon(":/resources/svg/close-button.svg", theme));
154 
155  close_button->setFixedSize( QSize(16,16));
156  close_button->setFlat(true);
157  connect(close_button, &QPushButton::pressed,
158  this, [this](){ on_tabWidget_tabCloseRequested(tabWidget()->tabBar()->currentIndex());} );
159 
160  layout->addWidget(close_button);
161  tabWidget()->tabBar()->setTabButton(index, QTabBar::RightSide, button_widget);
162 
163  docker->setHorizontalLink(_horizontal_link);
164 
165  tabWidget()->setCurrentWidget(docker);
166 
167  return docker;
168 }
169 
170 QDomElement TabbedPlotWidget::xmlSaveState(QDomDocument& doc) const
171 {
172  QDomElement tabbed_area = doc.createElement("tabbed_widget");
173 
174  tabbed_area.setAttribute("name", _name);
175  tabbed_area.setAttribute("parent", _parent_type);
176 
177  for (int i = 0; i < tabWidget()->count(); i++)
178  {
179  PlotDocker* widget = static_cast<PlotDocker*>(tabWidget()->widget(i));
180  QDomElement element = widget->xmlSaveState(doc);
181 
182  element.setAttribute("tab_name", tabWidget()->tabText(i));
183  tabbed_area.appendChild(element);
184  }
185 
186  QDomElement current_plotmatrix = doc.createElement("currentTabIndex");
187  current_plotmatrix.setAttribute("index", tabWidget()->currentIndex());
188  tabbed_area.appendChild(current_plotmatrix);
189 
190  return tabbed_area;
191 }
192 
193 bool TabbedPlotWidget::xmlLoadState(QDomElement& tabbed_area)
194 {
195  int prev_count = tabWidget()->count();
196 
197  for (auto docker_elem = tabbed_area.firstChildElement("Tab");
198  !docker_elem.isNull();
199  docker_elem = docker_elem.nextSiblingElement("Tab"))
200  {
201  QString tab_name = docker_elem.attribute("tab_name");
202  PlotDocker* docker = addTab( tab_name );
203 
204  bool success = docker->xmlLoadState(docker_elem);
205 
206  if (!success)
207  {
208  return false;
209  }
210  }
211 
212  // remove old ones
213  for(int i=0; i<prev_count; i++ )
214  {
215  tabWidget()->removeTab(0);
216  }
217 
218  QDomElement current_tab = tabbed_area.firstChildElement("currentTabIndex");
219  int current_index = current_tab.attribute("index").toInt();
220 
221  if (current_index >= 0 && current_index < tabWidget()->count())
222  {
223  tabWidget()->setCurrentIndex(current_index);
224  }
225 
226  emit undoableChange();
227  return true;
228 }
229 
230 void TabbedPlotWidget::setStreamingMode(bool streaming_mode)
231 {
232 
233 }
234 
236 {
237 
238 }
239 
241 {
242  int idx = tabWidget()->tabBar()->currentIndex();
243 
244  bool ok = true;
245  QString newName = QInputDialog::getText(this, tr("Change the tab name"), tr("New name:"),
246  QLineEdit::Normal, tabWidget()->tabText(idx), &ok);
247  if (ok)
248  {
249  tabWidget()->setTabText(idx, newName);
250  currentTab()->setName(newName);
251  }
252 }
253 
254 
256 {
257  _buttonAddTab->setIcon(LoadSvgIcon(":/resources/svg/add_tab.svg", theme));
258 }
259 
260 
262 {
263  addTab(nullptr);
264  emit undoableChange();
265 }
266 
268 {
269  if (tabWidget()->count() == 0)
270  {
271  if (_parent_type.compare("main_window") == 0)
272  {
273  addTab(nullptr);
274  }
275  else
276  {
277  this->parent()->deleteLater();
278  }
279  }
280 
281  PlotDocker* tab = dynamic_cast<PlotDocker*>(tabWidget()->widget(index));
282  if (tab)
283  {
284  tab->replot();
285  }
286  for (int i=0; i<tabWidget()->count(); i++ )
287  {
288  auto button = _tabWidget->tabBar()->tabButton(i, QTabBar::RightSide);
289  if( button ){
290  button->setHidden( i!=index );
291  }
292  }
293 }
294 
296 {
297  PlotDocker* tab = dynamic_cast<PlotDocker*>( tabWidget()->widget(index) );
298 
299  // first add then delete.
300  // Otherwise currentPlotGrid might be empty
301  if (tabWidget()->count() == 1)
302  {
304  }
305 
306  PlotDocker* docker = static_cast<PlotDocker*>(tabWidget()->widget(index));
307 
308  for (unsigned p = 0; p < docker->plotCount(); p++)
309  {
310  PlotWidget* plot = docker->plotAt(p);
311  plot->removeAllCurves();
312  plot->deleteLater();
313  }
314  docker->deleteLater();
315 
316  tabWidget()->removeTab(index);
317  emit undoableChange();
318 
319 }
320 
322 {
323  _horizontal_link = checked;
324 
325  for (int i = 0; i < tabWidget()->count(); i++)
326  {
327  PlotDocker* tab = static_cast<PlotDocker*>(tabWidget()->widget(i));
329  }
330 }
331 
332 void TabbedPlotWidget::on_requestTabMovement(const QString& destination_name)
333 {
334  TabbedPlotWidget* destination_widget = TabbedPlotWidget::_instances[destination_name];
335 
336  PlotDocker* tab_to_move = currentTab();
337  int index = tabWidget()->tabBar()->currentIndex();
338 
339  const QString& tab_name = this->tabWidget()->tabText(index);
340 
341  destination_widget->tabWidget()->addTab(tab_to_move, tab_name);
342  emit undoableChange();
343 }
344 
346 {
348 }
349 
350 bool TabbedPlotWidget::eventFilter(QObject* obj, QEvent* event)
351 {
352  QTabBar* tab_bar = tabWidget()->tabBar();
353 
354  if (obj == tab_bar)
355  {
356  if (event->type() == QEvent::MouseButtonPress)
357  {
358  QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
359 
360  int index = tab_bar->tabAt(mouse_event->pos());
361  tab_bar->setCurrentIndex(index);
362 
363  if (mouse_event->button() == Qt::RightButton)
364  {
365  //QMenu* submenu = new QMenu("Move tab to...");
366  // _tab_menu->addMenu(submenu);
367 
368  // QSignalMapper* signalMapper = new QSignalMapper(submenu);
369 
370  //-----------------------------------
371 // QAction* action_new_window = submenu->addAction("New Window");
372 // submenu->addSeparator();
373 // connect(action_new_window, &QAction::triggered, this, &TabbedPlotWidget::on_moveTabIntoNewWindow);
374 
375 // //-----------------------------------
376 // for (auto& it : TabbedPlotWidget::_instances)
377 // {
378 // QString name = it.first;
379 // TabbedPlotWidget* tabbed_menu = it.second;
380 // if (tabbed_menu != this)
381 // {
382 // QAction* action = submenu->addAction(name);
383 // connect(action, SIGNAL(triggered()), signalMapper, SLOT(map()));
384 // signalMapper->setMapping(action, name);
385 // }
386 // }
387 
388 // connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(on_requestTabMovement(QString)));
389 
390 // //-------------------------------
394 
398 
399 // _tab_menu->exec(mouse_event->globalPos());
400 // //-------------------------------
401 // submenu->deleteLater();
402  }
403  }
404  }
405 
406  // Standard event processing
407  return QObject::eventFilter(obj, event);
408 }
409 
410 void TabbedPlotWidget::closeEvent(QCloseEvent* event)
411 {
413 }
414 
415 const std::map<QString, TabbedPlotWidget*>& TabbedPlotWidget::instances()
416 {
418 }
419 
421 {
422  auto it = TabbedPlotWidget::_instances.find(key);
423  if (it == TabbedPlotWidget::_instances.end())
424  {
425  return nullptr;
426  }
427  else
428  {
429  return it->second;
430  }
431 }
432 
434 {
435  // ui->widgetControls->setVisible(visible);
436 }
TabbedPlotWidget(QString name, QMainWindow *main_window, PlotDataMapRef &mapped_data, QMainWindow *parent)
int success(int count)
Definition: test6.c:567
If the flag is set each dock area has a tabs menu button.
Definition: DockManager.h:174
void removeAllCurves()
Definition: plotwidget.cpp:743
void on_stylesheetChanged(QString style_dir)
PlotWidget * plotAt(int index)
void onPlotTabAdded(PlotDocker *docker)
Definition: mainwindow.cpp:784
QIcon LoadSvgIcon(QString filename, QString style_name="light")
Definition: svg_util.h:17
void on_tabWidget_currentChanged(int index)
void on_buttonLinkHorizontalScale_toggled(bool checked)
QMainWindow * _main_window
int plotCount() const
static std::map< QString, TabbedPlotWidget * > _instances
void on_requestTabMovement(const QString &destination_name)
QString name() const
void setName(QString name)
Definition: plot_docker.cpp:56
void tabAdded(PlotDocker *)
~TabbedPlotWidget() override
PlotDataMapRef & _mapped_data
void sendTabToNewWindow(PlotDocker *)
constexpr size_t count()
Definition: core.h:960
PlotDocker * currentTab()
If this option is enabled, the tab of a dock widget is always displayed - even if it is the only visi...
Definition: DockManager.h:172
void paintEvent(QPaintEvent *event) override
bool xmlLoadState(QDomElement &tabbed_area)
void setStreamingMode(bool streaming_mode)
void on_tabbedAreaDestroyed(QObject *object)
See QSplitter::setOpaqueResize() documentation.
Definition: DockManager.h:162
QPushButton * _buttonAddTab
static void setConfigFlag(eConfigFlag Flag, bool On=true)
QTabWidget * tabWidget()
static TabbedPlotWidget * instance(const QString &key)
const char * name
bool xmlLoadState(QDomElement &tab_element)
virtual void closeEvent(QCloseEvent *event) override
QDomElement xmlSaveState(QDomDocument &doc) const
void replot()
QTabWidget * _tabWidget
virtual bool eventFilter(QObject *obj, QEvent *event) override
If the flag is set each dock area has an undock button.
Definition: DockManager.h:173
void onUndoableChange()
Definition: mainwindow.cpp:291
QDomElement xmlSaveState(QDomDocument &doc) const
void setHorizontalLink(bool enabled)
void setControlsVisible(bool visible)
void on_tabWidget_tabCloseRequested(int index)
PlotDocker * addTab(QString name)
void undoableChange()
const QString _name
static const std::map< QString, TabbedPlotWidget * > & instances()


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 04:02:48