plot_docker.cpp
Go to the documentation of this file.
1 #include "plot_docker.h"
2 #include "plotwidget_editor.h"
3 #include "Qads/DockSplitter.h"
4 #include <QPushButton>
5 #include <QBoxLayout>
6 #include <QMouseEvent>
7 #include <QSplitter>
8 #include <QDebug>
9 #include <QInputDialog>
10 #include <QLineEdit>
11 #include "svg_util.h"
12 
14 {
15 public:
17  {
18  auto title_bar = new ads::CDockAreaTitleBar(dock_area);
19  title_bar->setVisible(false);
20  return title_bar;
21  }
22 };
23 
24 
25 PlotDocker::PlotDocker(QString name, PlotDataMapRef& datamap, QWidget *parent):
26  ads::CDockManager(parent), _name(name), _datamap(datamap)
27 {
29 
30  auto CreateFirstWidget = [&]()
31  {
32  if( dockAreaCount() == 0)
33  {
34  DockWidget* widget = new DockWidget(datamap, this);
35 
36  auto area = addDockWidget(ads::TopDockWidgetArea, widget);
37  area->setAllowedAreas(ads::OuterDockAreas);
38 
39  this->plotWidgetAdded( widget->plotWidget() );
40 
42  }
43  };
44 
45  connect(this, &ads::CDockManager::dockWidgetRemoved, this, CreateFirstWidget);
46 
48 
49  CreateFirstWidget();
50 }
51 
52 QString PlotDocker::name() const{
53  return _name;
54 }
55 
57 {
58  _name = name;
59 }
60 
61 
62 QDomElement saveChildNodesState(QDomDocument &doc, QWidget* widget)
63 {
64  QSplitter* splitter = qobject_cast<QSplitter*>(widget);
65  if (splitter)
66  {
67  QDomElement splitter_elem = doc.createElement("DockSplitter");
68  splitter_elem.setAttribute("orientation", (splitter->orientation() == Qt::Horizontal) ? "|" : "-");
69  splitter_elem.setAttribute("count", QString::number(splitter->count()));
70 
71  QString sizes_str;
72  int total_size = 0;
73  for(int size : splitter->sizes() )
74  {
75  total_size += size;
76  }
77  for(int size : splitter->sizes() )
78  {
79  sizes_str += QString::number( double(size)/double(total_size) );
80  sizes_str += ";";
81  }
82  sizes_str.resize( sizes_str.size()-1 );
83  splitter_elem.setAttribute("sizes", sizes_str);
84 
85  for (int i = 0; i < splitter->count(); ++i)
86  {
87  auto child = saveChildNodesState(doc, splitter->widget(i));
88  splitter_elem.appendChild( child );
89  }
90  return splitter_elem;
91  }
92  else{
93  ads::CDockAreaWidget* dockArea = qobject_cast<ads::CDockAreaWidget*>(widget);
94  if (dockArea)
95  {
96  QDomElement area_elem = doc.createElement("DockArea");
97  for (int i = 0; i < dockArea->dockWidgetsCount(); ++i)
98  {
99  auto dock_widget = dynamic_cast<DockWidget*>( dockArea->dockWidget(i) );
100  if( dock_widget )
101  {
102  auto plotwidget_elem = dock_widget->plotWidget()->xmlSaveState(doc);
103  area_elem.appendChild( plotwidget_elem );
104  area_elem.setAttribute("name", dock_widget->toolBar()->label()->text());
105  }
106  }
107  return area_elem;
108  }
109  }
110  return {};
111 }
112 
113 QDomElement PlotDocker::xmlSaveState(QDomDocument &doc) const
114 {
115  QDomElement containers_elem = doc.createElement("Tab");
116 
117  containers_elem.setAttribute("containers", dockContainers().count());
118 
119  for (CDockContainerWidget* container : dockContainers())
120  {
121  QDomElement elem = doc.createElement("Container");
122  auto child = saveChildNodesState(doc, container->rootSplitter());
123  elem.appendChild(child);
124  containers_elem.appendChild(elem);
125  }
126  return containers_elem;
127 }
128 
129 void PlotDocker::restoreSplitter(QDomElement elem, DockWidget* widget)
130 {
131  QString orientation_str = elem.attribute("orientation");
132  int splitter_count = elem.attribute("count").toInt();
133 
134  // Check if the orientation string is right
135  if (!orientation_str.startsWith("|") && !orientation_str.startsWith("-"))
136  {
137  return;
138  }
139 
140  Qt::Orientation orientation = orientation_str.startsWith("|") ? Qt::Horizontal : Qt::Vertical;
141 
142  std::vector<DockWidget*> widgets(splitter_count);
143 
144  widgets[0] = widget;
145  for (int i=1; i<splitter_count; i++ )
146  {
147  widget = (orientation == Qt::Horizontal) ?
148  widget->splitHorizontal() : widget->splitVertical();
149  widgets[i] = widget;
150  }
151 
152  int tot_size = 0;
153 
154  for (int i=0; i<splitter_count; i++ )
155  {
156  tot_size += ( orientation == Qt::Horizontal ) ? widgets[i]->width() : widgets[i]->height();
157  }
158 
159  auto sizes_str = elem.attribute("sizes").splitRef(";", QString::SkipEmptyParts);
160  QList<int> sizes;
161 
162  for (int i=0; i<splitter_count; i++ )
163  {
164  sizes.push_back( static_cast<int>(sizes_str[i].toDouble() * tot_size) );
165  }
166 
167  auto splitter = ads::internal::findParent<ads::CDockSplitter*>(widget);
168  splitter->setSizes(sizes);
169 
170  int index = 0;
171 
172  QDomElement child_elem = elem.firstChildElement();
173  while (child_elem.isNull() == false)
174  {
175  if( child_elem.tagName() == "DockArea" )
176  {
177  auto plot_elem = child_elem.firstChildElement("plot");
178  widgets[index]->plotWidget()->xmlLoadState(plot_elem);
179  if( child_elem.hasAttribute("name") )
180  {
181  QString area_name = child_elem.attribute("name");
182  widgets[index]->toolBar()->label()->setText(area_name);
183  }
184  index++;
185  }
186  else if( child_elem.tagName() == "DockSplitter" )
187  {
188  restoreSplitter(child_elem, widgets[index++]);
189  }
190  else{
191  return;
192  }
193 
194  child_elem = child_elem.nextSiblingElement();
195  }
196 };
197 
198 bool PlotDocker::xmlLoadState(QDomElement &tab_element)
199 {
200  if (!isHidden())
201  {
202  hide();
203  }
204 
205  for (auto container_elem = tab_element.firstChildElement("Container");
206  !container_elem.isNull();
207  container_elem = container_elem.nextSiblingElement("Container"))
208  {
209  auto splitter_elem = container_elem.firstChildElement("DockSplitter");
210  if( !splitter_elem.isNull())
211  {
212  auto widget = dynamic_cast<DockWidget*>( dockArea(0)->currentDockWidget());
213  restoreSplitter(splitter_elem, widget );
214  }
215  }
216 
217  if (isHidden())
218  {
219  show();
220  }
221  return true;
222 }
223 
225 {
226  return dockAreaCount();
227 }
228 
230 {
231  return static_cast<PlotWidget*>( dockArea(index)->currentDockWidget()->widget() );
232 }
233 
235 {
236  // TODO
237 }
238 
240 {
241  for (int index = 0; index < plotCount(); index++)
242  {
243  plotAt(index)->zoomOut(false); // TODO is it false?
244  }
245 }
246 
248 {
249  for (int index = 0; index < plotCount(); index++)
250  {
251  plotAt(index)->replot();
252  }
253 }
254 
256 {
257  for (int index = 0; index < plotCount(); index++)
258  {
259  auto dock_widget = static_cast<DockWidget*>( dockArea(index)->currentDockWidget());
260  dock_widget->toolBar()->on_stylesheetChanged(theme);
261  }
262 }
263 
264 DockWidget::DockWidget(PlotDataMapRef& datamap, QWidget *parent):
265  ads::CDockWidget("Plot", parent), _datamap(datamap)
266 {
267  setFrameShape(QFrame::NoFrame);
268 
269  static int plot_count = 0;
270  QString plot_name = QString("_plot_%1_").arg(plot_count++);
271  auto plot_widget = new PlotWidget(datamap, this);
272  setWidget( plot_widget );
275 
276  _toolbar = new DraggableToolbar(this);
277  _toolbar->label()->setText("...");
278  qobject_cast<QBoxLayout*>(layout())->insertWidget(0, _toolbar);
279 
280  connect(_toolbar->buttonSplitHorizontal(), &QPushButton::clicked,
282 
283  connect(_toolbar->buttonSplitVertical(), &QPushButton::clicked,
285 
286  connect(plot_widget, &PlotWidget::splitHorizontal,
288 
289  connect(plot_widget, &PlotWidget::splitVertical,
291 
292  auto FullscreenAction = [=]() {
293  PlotDocker* parent_docker = static_cast<PlotDocker*>( dockManager() );
294 
295  this->toolBar()->toggleFullscreen();
296  bool fullscreen = this->toolBar()->isFullscreen();
297 
298  for(int i = 0; i < parent_docker->dockAreaCount(); i++ )
299  {
300  auto area = parent_docker->dockArea(i);
301  if (area != dockAreaWidget())
302  {
303  area->setVisible(!fullscreen);
304  }
305  this->toolBar()->buttonClose()->setHidden(fullscreen);
306  }
307  };
308 
309  QObject::connect(_toolbar->buttonFullscreen(), &QPushButton::clicked, FullscreenAction );
310 
311  QObject::connect(_toolbar->buttonClose(), &QPushButton::pressed, [=]()
312  {
314  this->undoableChange();
315  } );
316 
317  this->layout()->setMargin(10);
318 }
319 
321 {
322  // create a sibling (same parent)
323  auto new_widget = new DockWidget(_datamap, qobject_cast<QWidget*>(parent()));
324 
325  PlotDocker* parent_docker = static_cast<PlotDocker*>( dockManager() );
326  auto area = parent_docker->addDockWidget(ads::RightDockWidgetArea,
327  new_widget, dockAreaWidget());
328 
330 
331  parent_docker->plotWidgetAdded( new_widget->plotWidget() );
332 
333  connect(this, &DockWidget::undoableChange, parent_docker, &PlotDocker::undoableChange);
334 
335  this->undoableChange();
336 
337  return new_widget;
338 }
339 
341 {
342  auto new_widget = new DockWidget(_datamap, qobject_cast<QWidget*>(parent()));
343 
344  PlotDocker* parent_docker = static_cast<PlotDocker*>( dockManager() );
345 
346  auto area = parent_docker->addDockWidget(ads::BottomDockWidgetArea,
347  new_widget, dockAreaWidget());
348 
350  parent_docker->plotWidgetAdded( new_widget->plotWidget() );
351 
352  connect(this, &DockWidget::undoableChange, parent_docker, &PlotDocker::undoableChange);
353 
354  this->undoableChange();
355 
356  return new_widget;
357 }
358 
360 {
361  return static_cast<PlotWidget*>( widget() );
362 }
363 
365 {
366  return _toolbar;
367 }
368 
369 static void setButtonIcon(QPushButton* button, QIcon icon)
370 {
371  button->setIcon(icon);
372  button->setText("");
373 }
374 
376  QWidget(parent),
377  _parent(parent),
378  ui(new Ui::DraggableToolbar),
379  _fullscreen_mode(false)
380 {
381  ui->setupUi(this);
382 
383  QSettings settings;
384  QString theme = settings.value("StyleSheet::theme", "light").toString();
385  on_stylesheetChanged(theme);
386 
387  ui->buttonFullscreen->setVisible( false );
388  ui->buttonSplitHorizontal->setVisible( false );
389  ui->buttonSplitVertical->setVisible( false );
390 
391  setMouseTracking(true);
392  ui->widgetButtons->setMouseTracking(true);
393 
394  ui->label->installEventFilter(this);
395 }
396 
398 {
399  delete ui;
400 }
401 
403 {
405 
407 
408  ui->buttonClose->setHidden(_fullscreen_mode);
409  if( _fullscreen_mode ){
410  ui->buttonSplitHorizontal->setVisible( false );
411  ui->buttonSplitVertical->setVisible( false );
412  }
413 }
414 
416 {
418 }
419 
421 {
423 }
424 
425 void DraggableToolbar::mouseMoveEvent(QMouseEvent *ev)
426 {
427  ui->buttonFullscreen->setVisible( true );
428  ui->buttonSplitHorizontal->setVisible( !_fullscreen_mode );
429  ui->buttonSplitVertical->setVisible( !_fullscreen_mode );
431 
432  ev->accept();
433  QWidget::mouseMoveEvent(ev);
434 }
435 
437 {
438  ui->buttonFullscreen->setVisible( true );
439  ui->buttonSplitHorizontal->setVisible( !_fullscreen_mode );
440  ui->buttonSplitVertical->setVisible( !_fullscreen_mode );
441 
442  ev->accept();
443  QWidget::enterEvent(ev);
444 }
445 
446 bool DraggableToolbar::eventFilter(QObject *object, QEvent *event)
447 {
448  if(event->type() == QEvent::MouseButtonDblClick)
449  {
450  bool ok = true;
451  QString newName = QInputDialog::getText(this, tr("Change name of the Area"), tr("New name:"),
452  QLineEdit::Normal, ui->label->text(), &ok);
453  if (ok)
454  {
455  ui->label->setText(newName);
456  }
457  return true;
458  }
459  else{
460  return QObject::eventFilter(object,event);
461  }
462 }
463 
465 {
466  _expand_icon = LoadSvgIcon(":/resources/svg/expand.svg", theme);
467  _collapse_icon = LoadSvgIcon(":/resources/svg/collapse.svg", theme);
469  setButtonIcon(ui->buttonClose, LoadSvgIcon( ":/resources/svg/close-button.svg", theme));
470  setButtonIcon(ui->buttonSplitHorizontal, LoadSvgIcon(":/resources/svg/add_column.svg", theme));
471  setButtonIcon(ui->buttonSplitVertical, LoadSvgIcon(":/resources/svg/add_row.svg", theme));
472 }
473 
475 {
476  ui->buttonFullscreen->setVisible( _fullscreen_mode );
477  ui->buttonSplitHorizontal->setVisible( false );
478  ui->buttonSplitVertical->setVisible( false );
479  QWidget::leaveEvent(ev);
480 }
481 
482 
DockWidget(PlotDataMapRef &datamap, QWidget *parent=nullptr)
void mousePressEvent(QMouseEvent *ev) override
CDockWidget * currentDockWidget() const
void setWidget(QWidget *widget, eInsertMode InsertMode=AutoScrollArea)
Definition: DockWidget.cpp:266
QWidget * widget() const
Definition: DockWidget.cpp:321
CDockAreaTitleBar * titleBar() const
bool isFullscreen() const
Definition: plot_docker.h:33
DraggableToolbar(ads::CDockWidget *parent)
PlotWidget * plotAt(int index)
void replot() override
QDomElement xmlSaveState(QDomDocument &doc) const
Definition: plotwidget.cpp:765
void dockWidgetRemoved(ads::CDockWidget *DockWidget)
void setFeature(DockWidgetFeature flag, bool on)
Definition: DockWidget.cpp:350
void plotWidgetAdded(PlotWidget *)
QIcon LoadSvgIcon(QString filename, QString style_name="light")
Definition: svg_util.h:17
~DraggableToolbar() override
bool eventFilter(QObject *object, QEvent *event) override
deletes the dock widget when it is closed
Definition: DockWidget.h:153
CDockAreaWidget * addDockWidget(DockWidgetArea area, CDockWidget *Dockwidget, CDockAreaWidget *DockAreaWidget=nullptr)
Ui::DraggableToolbar * ui
Definition: plot_docker.h:51
virtual void setVisible(bool Visible) override
QPushButton * buttonClose()
Definition: plot_docker.h:27
void undoableChange()
void enterEvent(QEvent *) override
PlotDocker(QString name, PlotDataMapRef &datamap, QWidget *parent=nullptr)
Definition: plot_docker.cpp:25
QPushButton * buttonFullscreen()
Definition: plot_docker.h:26
friend class CDockContainerWidget
Definition: DockManager.h:77
int plotCount() const
void zoomOut()
PlotDataMapRef & _datamap
Definition: plot_docker.h:119
void setName(QString name)
Definition: plot_docker.cpp:56
DockWidget * splitVertical()
QLabel * label()
Definition: plot_docker.h:25
void splitVertical()
QPushButton * buttonSplitVertical()
Definition: plot_docker.h:29
dock widget can be dragged into a floating window
Definition: DockWidget.h:152
constexpr size_t count()
Definition: core.h:960
void mouseReleaseEvent(QMouseEvent *ev) override
QString _name
Definition: plot_docker.h:117
QIcon _collapse_icon
Definition: plot_docker.h:55
void zoomOut(bool emit_signal)
virtual void mouseReleaseEvent(QMouseEvent *ev) override
QDomElement saveChildNodesState(QDomDocument &doc, QWidget *widget)
Definition: plot_docker.cpp:62
CDockWidget * dockWidget(int Index) const
DockWidget * splitHorizontal()
QPushButton * buttonSplitHorizontal()
Definition: plot_docker.h:28
void setAllowedAreas(DockWidgetAreas areas)
virtual void mousePressEvent(QMouseEvent *ev) override
PlotDataMapRef & _datamap
Definition: plot_docker.h:77
CDockAreaWidget * dockArea(int Index) const
Declaration of CDockSplitter.
const QList< CDockContainerWidget * > dockContainers() const
ads::CDockAreaTitleBar * createDockAreaTitleBar(ads::CDockAreaWidget *dock_area) const override
Definition: plot_docker.cpp:16
DraggableToolbar * toolBar()
void restoreSplitter(QDomElement elem, DockWidget *widget)
virtual void mouseMoveEvent(QMouseEvent *ev) override
int dockWidgetsCount() const
const char * name
bool xmlLoadState(QDomElement &tab_element)
CDockManager * dockManager() const
Definition: DockWidget.cpp:366
static void setButtonIcon(QPushButton *button, QIcon icon)
QDomElement xmlSaveState(QDomDocument &doc) const
void leaveEvent(QEvent *) override
PlotWidget * plotWidget()
void on_stylesheetChanged(QString theme)
void replot()
void splitHorizontal()
void on_stylesheetChanged(QString theme)
QIcon icon() const
Definition: DockWidget.cpp:650
ads::CDockWidget * _parent
Definition: plot_docker.h:50
DraggableToolbar * _toolbar
Definition: plot_docker.h:75
QString name() const
Definition: plot_docker.cpp:52
CDockAreaWidget * dockAreaWidget() const
Definition: DockWidget.cpp:394
void setHorizontalLink(bool enabled)
void undoableChange()
void mouseMoveEvent(QMouseEvent *ev) override
static void setFactory(CDockComponentsFactory *Factory)


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10