HAL
dock_bar.cpp
Go to the documentation of this file.
6 #include "gui/gui_globals.h"
8 
9 #include <QApplication>
10 #include <QDrag>
11 #include <QDragEnterEvent>
12 #include <QDropEvent>
13 #include <QListIterator>
14 #include <QMimeData>
15 #include <QMouseEvent>
16 #include <QPainter>
17 #include <QPropertyAnimation>
18 
19 namespace hal
20 {
21  QPoint DockBar::sDragStartPosition;
22  DockButton* DockBar::sDragButton = nullptr;
23  int DockBar::sBeginDropRange = 0;
24  int DockBar::sEndDropRange = 0;
25  int DockBar::sDropSpacing = 0;
26  DockButton* DockBar::sMoveMarker = nullptr;
27 
28  DockBar::DockBar(Qt::Orientation orientation, button_orientation b_orientation, QWidget* parent) : QFrame(parent), mButtonOrientation(b_orientation)
29  {
30  mOrientation = orientation;
31 
32  setAcceptDrops(true);
33  }
34 
36  {
37  if (!(event->buttons() & Qt::LeftButton))
38  return;
39  if (!sDragButton)
40  return;
41  if ((event->pos() - sDragStartPosition).manhattanLength() < QApplication::startDragDistance())
42  return;
43 
44  QDrag* drag = new QDrag(this);
45  DockMimeData* mimeData = new DockMimeData(sDragButton->widget());
46  drag->setPixmap(sDragButton->grab());
47  drag->setHotSpot(QPoint(drag->pixmap().width() / 2, drag->pixmap().height() / 2));
48  sDragButton->hide();
49  sDragButton->setChecked(false);
50  sDragButton->widget()->close();
51  sDragButton->setAvailable(false);
52  sDropSpacing = sDragButton->relativeWidth();
53  drag->setMimeData(mimeData);
56  Qt::DropAction dropAction = drag->exec(Qt::MoveAction);
57  if (!(dropAction & Qt::MoveAction))
58  {
60  sDragButton->setAvailable(true);
62  sDragButton->show();
63  }
65  sDragButton = nullptr;
66  }
67 
69  {
70  const DockMimeData* mime_data = qobject_cast<const DockMimeData*>(event->mimeData());
71  if (mime_data)
72  {
73  event->acceptProposedAction();
74  sBeginDropRange = 0;
75  sEndDropRange = 0;
76  sMoveMarker = nullptr;
77  }
78  }
79 
81  {
82  int cursor_position;
83  if (mButtonOrientation == button_orientation::horizontal)
84  cursor_position = event->pos().x();
85  else
86  cursor_position = event->pos().y();
87 
88  if (cursor_position < sBeginDropRange || cursor_position > sEndDropRange)
89  {
90  int button_position = mButtonOffset;
91  QList<DockButton*>::iterator button_iterator;
92  QList<QPropertyAnimation*> animations;
93  bool already_executed = false;
94  bool move_marker_reached = false;
95 
96  for (button_iterator = mButtons.begin(); button_iterator != mButtons.end(); ++button_iterator)
97  {
98  if ((*button_iterator)->available())
99  {
100  if (button_position + (*button_iterator)->relativeWidth() < cursor_position)
101  {
102  if (*button_iterator == sMoveMarker)
103  move_marker_reached = true;
104 
105  if (move_marker_reached)
106  {
107  QPropertyAnimation* animation = new QPropertyAnimation(*button_iterator, "pos");
108  animation->setDuration(200);
109  animation->setStartValue((*button_iterator)->pos());
110  if (mButtonOrientation == button_orientation::horizontal)
111  {
112  animation->setEndValue(QPoint(button_position, 0));
113  }
114  else
115  {
116  animation->setEndValue(QPoint(0, button_position));
117  }
118  animation->start();
119  }
120  }
121  else
122  {
123  if (!already_executed)
124  {
125  sBeginDropRange = button_position;
126  sEndDropRange = button_position + (*button_iterator)->relativeWidth();
127  sMoveMarker = *button_iterator;
128  already_executed = true;
129  }
130 
131  QPropertyAnimation* animation = new QPropertyAnimation(*button_iterator, "pos");
132  animation->setDuration(200);
133  animation->setStartValue((*button_iterator)->pos());
134 
135  if (mButtonOrientation == button_orientation::horizontal)
136  {
137  animation->setEndValue(QPoint(button_position + sDropSpacing, 0));
138  }
139  else
140  {
141  animation->setEndValue(QPoint(0, button_position + sDropSpacing));
142  }
143  animations.append(animation);
144  }
145  button_position += (*button_iterator)->relativeWidth() + mButtonSpacing;
146  }
147  }
148  for (QPropertyAnimation* animation : animations)
149  {
150  animation->start();
151  }
152  if (already_executed)
153  return;
154  sBeginDropRange = 0;
155  sEndDropRange = 0;
156  sMoveMarker = nullptr;
157  }
158  }
159 
161  {
162  Q_UNUSED(event)
163  collapseButtons();
164  }
165 
167  {
168  const DockMimeData* mimedata = qobject_cast<const DockMimeData*>(event->mimeData());
169  if (mimedata)
170  {
171  event->acceptProposedAction();
172  ContentWidget* widget = mimedata->widget();
173  widget->remove();
174 
175  if (sMoveMarker == nullptr)
176  {
177  mAnchor->add(widget, count());
178  return;
179  }
180 
181  int index = 0;
182  for (DockButton* button : mButtons)
183  {
184  if (button == sMoveMarker)
185  {
186  mAnchor->add(widget, index);
187  return;
188  }
189  index++;
190  }
191  }
192  }
193 
194  bool DockBar::eventFilter(QObject* watched, QEvent* event)
195  {
196  if (event->type() == QEvent::MouseButtonPress)
197  {
198  QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
199  if (mouseEvent->buttons() & Qt::LeftButton)
200  {
201  sDragStartPosition = mapFromGlobal(mouseEvent->globalPos());
202  sDragButton = static_cast<DockButton*>(watched);
203  }
204  }
205  return false;
206  }
207 
209  {
210  if(mOrientation == Qt::Horizontal)
211  {
212  int width = 0;
213  for (DockButton* button : mButtons)
214  width += button->width();
215 
216  width += mButtons.size() * mButtonSpacing; //+ mButtonOffset
217  return QSize(width, height());
218  }
219  else
220  {
221  int height = 0;
222  for (DockButton* button : mButtons)
223  height += button->height();
224 
225  height += mButtons.size() * mButtonSpacing; //+ mButtonOffset
226  return QSize(width(), height);
227 
228  }
229  }
230 
232  {
233  if(mOrientation == Qt::Horizontal)
234  {
235  int width = 0;
236  for (DockButton* button : mButtons)
237  width += button->width();
238 
239  width += mButtons.size() * mButtonSpacing; //+ mButtonOffset
240  return QSize(width, height());
241  }
242  else
243  {
244  int height = 0;
245  for (DockButton* button : mButtons)
246  height += button->height();
247 
248  height += mButtons.size() * mButtonSpacing; //+ mButtonOffset
249  return QSize(width(), height);
250  }
251  }
252 
254  {
255  mAnchor = anchor;
256  }
257 
258  void DockBar::setAutohide(bool autohide)
259  {
260  mAutohide = autohide;
261  }
262 
264  {
265  bool no_button_visible = true;
266  for (DockButton* button : mButtons)
267  {
268  if (!button->hidden())
269  {
270  no_button_visible = false;
271  break;
272  }
273  }
274  if (no_button_visible)
275  return true;
276  return false;
277  }
278 
280  {
281  return mButtons.length();
282  }
283 
285  {
286  int index = 0;
287  for (DockButton* button : mButtons)
288  {
289  if (button->widget() == widget)
290  return index;
291  index++;
292  }
293  return -1;
294  }
295 
297  {
298  int position = mButtonOffset;
299  for (DockButton* button : mButtons)
300  {
301  if (button->available())
302  {
303  if (mButtonOrientation == button_orientation::horizontal)
304  {
305  button->move(position, 0);
306  position += button->relativeWidth() + mButtonSpacing;
307  }
308  else
309  {
310  button->move(0, position);
311  position += button->relativeWidth() + mButtonSpacing;
312  }
313  }
314  }
315  }
316 
318  {
319  int position = mButtonOffset;
320  for (DockButton* button : mButtons)
321  {
322  if (button->available())
323  {
324  QPropertyAnimation* animation = new QPropertyAnimation(button, "pos");
325  animation->setDuration(200);
326  animation->setStartValue(button->pos());
327 
328  if (mButtonOrientation == button_orientation::horizontal)
329  {
330  animation->setEndValue(QPoint(position, 0));
331  }
332  else
333  {
334  animation->setEndValue(QPoint(0, position));
335  }
336  position += button->relativeWidth() + mButtonSpacing;
337  connect(this, SIGNAL(stopAnimations()), animation, SLOT(stop()));
339  }
340  }
341  }
342 
343  void DockBar::addButton(ContentWidget* widget, int index)
344  {
345  DockButton* button = new DockButton(widget, mButtonOrientation, this, nullptr);
346  if (mButtonOrientation == button_orientation::horizontal)
347  button->setRelativeHeight(height());
348  else
349  button->setRelativeHeight(width());
350 
351  mButtons.insert(index, button);
353  button->setParent(this);
354  button->show();
355  show();
356  updateGeometry();
357  }
358 
360  {
361  for (DockButton* button : mButtons)
362  {
363  if (button->widget() == widget)
364  {
365  mButtons.removeOne(button);
366  button->hide();
368  delete button;
369 
370  if (mAutohide && unused())
371  hide();
372  updateGeometry();
373  return true;
374  }
375  }
376  return false;
377  }
378 
379  bool DockBar::removeButton(int index)
380  {
381  if (0 <= index && index < mButtons.size())
382  {
383  DockButton* button = mButtons.at(index);
384  button->hide();
385  mButtons.removeAt(index);
386  button->close();
388  if (mAutohide && unused())
389  hide();
390  updateGeometry();
391  return true;
392  }
393  return false;
394  }
395 
397  {
398  for (DockButton* button : mButtons)
399  {
400  if (button->widget() == widget)
401  {
402  button->hide();
403  button->setAvailable(false);
404  button->setChecked(false);
406 
407  if (mAutohide && unused())
408  hide();
409  break;
410  }
411  }
412  }
413 
415  {
416  for (DockButton* button : mButtons)
417  {
418  if (button->widget() == widget)
419  {
420  button->setAvailable(true);
422  button->show();
423  show();
424  break;
425  }
426  }
427  }
428 
430  {
431  for (DockButton* button : mButtons)
432  {
433  if (button->widget() == widget)
434  {
435  button->setChecked(true);
436  break;
437  }
438  }
439  }
440 
442  {
443  for (DockButton* button : mButtons)
444  {
445  if (button->widget() == widget)
446  {
447  button->setChecked(false);
448  break;
449  }
450  }
451  }
452 
454  {
455  if (0 <= index && index < mButtons.size())
456  return mButtons.at(index)->widget();
457  return nullptr;
458  }
459 
461  {
462  if (index < 0)
463  {
464  for (DockButton* button : mButtons)
465  {
466  if (!button->hidden())
467  return button->widget();
468  }
469  return nullptr;
470  }
471  if (index >= mButtons.size())
472  {
473  ContentWidget* widget = nullptr;
474  for (DockButton* button : mButtons)
475  {
476  if (!button->hidden())
477  widget = button->widget();
478  }
479  return widget;
480  }
481  int current_index = 0;
482  ContentWidget* widget = nullptr;
483  for (DockButton* button : mButtons)
484  {
485  if (!button->hidden())
486  {
487  widget = button->widget();
488  if (current_index >= index)
489  return widget;
490  }
491  current_index++;
492  }
493  return widget;
494  }
495 
497  {
498  for (DockButton* button : mButtons)
499  {
500  button->widget()->hide();
501  button->widget()->setParent(nullptr);
502 
503  button->hide();
504  button->setParent(nullptr);
505  delete button;
506  }
507 
508  mButtons.clear();
509 
511 
512  update();
513  }
514 
516  {
517  show();
518  }
519 
521  {
522  if (mAutohide && unused())
523  hide();
524  }
525 }
An abstract class that provides the interface for specific anchors (see SplitterAnchor or TabWidget )...
virtual void add(ContentWidget *widget, int index)=0
static ContentDragRelay * instance()
Abstract class for Widgets within HAL's ContentArea.
void clear()
Definition: dock_bar.cpp:496
void mouseMoveEvent(QMouseEvent *event) override
Definition: dock_bar.cpp:35
void dropEvent(QDropEvent *event) override
Definition: dock_bar.cpp:166
QSize sizeHint() const override
Definition: dock_bar.cpp:208
void dragEnterEvent(QDragEnterEvent *event) override
Definition: dock_bar.cpp:68
bool removeButton(ContentWidget *widget)
Definition: dock_bar.cpp:359
void setAnchor(ContentAnchor *anchor)
Definition: dock_bar.cpp:253
QSize minimumSizeHint() const override
Definition: dock_bar.cpp:231
void rearrangeButtons()
Definition: dock_bar.cpp:296
int index(ContentWidget *widget)
Definition: dock_bar.cpp:284
void checkButton(ContentWidget *widget)
Definition: dock_bar.cpp:429
bool eventFilter(QObject *watched, QEvent *event) override
Definition: dock_bar.cpp:194
void setAutohide(bool autohide)
Definition: dock_bar.cpp:258
void reattachButton(ContentWidget *widget)
Definition: dock_bar.cpp:414
DockBar(Qt::Orientation orientation, button_orientation b_orientation, QWidget *parent=nullptr)
Definition: dock_bar.cpp:28
void uncheckButton(ContentWidget *widget)
Definition: dock_bar.cpp:441
void dragLeaveEvent(QDragLeaveEvent *event) override
Definition: dock_bar.cpp:160
void handleDragEnd()
Definition: dock_bar.cpp:520
bool unused()
Definition: dock_bar.cpp:263
void stopAnimations()
ContentWidget * nextAvailableWidget(int index)
Definition: dock_bar.cpp:460
void detachButton(ContentWidget *widget)
Definition: dock_bar.cpp:396
void handleDragStart()
Definition: dock_bar.cpp:515
void dragMoveEvent(QDragMoveEvent *event) override
Definition: dock_bar.cpp:80
void addButton(ContentWidget *widget, int index)
Definition: dock_bar.cpp:343
ContentWidget * widgetAt(int index)
Definition: dock_bar.cpp:453
void collapseButtons()
Definition: dock_bar.cpp:317
A button of in the DockerBar.
Definition: dock_button.h:56
void setAvailable(bool available)
void setRelativeHeight(int height)
ContentWidget * widget()
QMineData to store and transfer information while dragging a DockButton.
ContentWidget * widget() const
button_orientation
Definition: dock_button.h:41
void start(QAbstractAnimation::DeletionPolicy policy)
void setChecked(bool)
Qt::DropAction exec(Qt::DropActions supportedActions)
QPixmap pixmap() const const
void setHotSpot(const QPoint &hotspot)
void setMimeData(QMimeData *data)
void setPixmap(const QPixmap &pixmap)
MouseButtonPress
virtual bool event(QEvent *e) override
void append(const T &value)
Qt::MouseButtons buttons() const const
QPoint globalPos() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int height() const const
int width() const const
DropAction
LeftButton
Orientation
void setDuration(int msecs)
void setEndValue(const QVariant &value)
void setStartValue(const QVariant &value)
void setAcceptDrops(bool on)
bool close()
QPixmap grab(const QRect &rectangle)
void hide()
QPoint mapFromGlobal(const QPoint &pos) const const
void setParent(QWidget *parent)
void show()
void update()
void updateGeometry()