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


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Aug 11 2024 02:24:26