QtCanpool 3.3.0
载入中...
搜索中...
未找到
docksidebar.cpp
浏览该文件的文档.
1
5#include "docksidebar.h"
6#include "dockcontainer.h"
8#include "dockwindow.h"
10#include "docksidetab.h"
11
12#include <QBoxLayout>
13#include <QXmlStreamWriter>
14#include <QApplication>
15
17
18class SideTabsWidget;
19
20class DockSideBarPrivate
21{
22public:
23 QX_DECLARE_PUBLIC(DockSideBar)
24public:
25 DockSideBarPrivate();
26 void init();
27 inline bool isHorizontal() const;
28 void handleViewportEvent(QEvent *e);
29public:
30 DockContainer *m_container;
31 QBoxLayout *m_tabsLayout;
33 Qt::Orientation m_orientation;
34 SideTabsWidget *m_tabsContainerWidget;
35};
36
37class SideTabsWidget : public QWidget
38{
39public:
40 using QWidget::QWidget;
41 using Super = QWidget;
42 DockSideBarPrivate *eventHandler;
43
44 virtual QSize minimumSizeHint() const override
45 {
46 return Super::sizeHint();
47 }
48
49 virtual bool event(QEvent *e) override
50 {
51 eventHandler->handleViewportEvent(e);
52 return Super::event(e);
53 }
54};
55
56DockSideBarPrivate::DockSideBarPrivate()
57{
58}
59
60void DockSideBarPrivate::init()
61{
62 Q_Q(DockSideBar);
63
64 m_tabsContainerWidget = new SideTabsWidget();
65 m_tabsContainerWidget->eventHandler = this;
66 m_tabsContainerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
67 m_tabsContainerWidget->setObjectName("sideTabsContainerWidget");
68
69 m_tabsLayout = new QBoxLayout(m_orientation == Qt::Vertical ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight);
70 m_tabsLayout->setContentsMargins(0, 0, 0, 0);
71 m_tabsLayout->setSpacing(12);
72 m_tabsLayout->addStretch(1);
73 m_tabsContainerWidget->setLayout(m_tabsLayout);
74 q->setWidget(m_tabsContainerWidget);
75}
76
77bool DockSideBarPrivate::isHorizontal() const
78{
79 return Qt::Horizontal == m_orientation;
80}
81
82void DockSideBarPrivate::handleViewportEvent(QEvent *e)
83{
84 Q_Q(DockSideBar);
85 switch (e->type()) {
86 case QEvent::ChildRemoved:
87 if (m_tabsLayout->isEmpty()) {
88 q->hide();
89 }
90 break;
91
92 default:
93 break;
94 }
95}
96
97DockSideBar::DockSideBar(DockContainer *parent, Qx::DockSideBarArea area)
98 : QScrollArea(parent)
99{
101 Q_D(DockSideBar);
102 d->m_container = parent;
103 d->m_sideTabArea = area;
104 d->m_orientation = (area == Qx::DockSideBarBottom || area == Qx::DockSideBarTop) ? Qt::Horizontal : Qt::Vertical;
105
106 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
107 setFrameStyle(QFrame::NoFrame);
108 setWidgetResizable(true);
109 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
110 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
111
112 d->init();
113
114 setFocusPolicy(Qt::NoFocus);
115 if (d->isHorizontal()) {
116 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
117 } else {
118 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
119 }
120
121 hide();
122}
123
125{
126 auto tabs = findChildren<DockSideTab *>(QString(), Qt::FindDirectChildrenOnly);
127 for (auto tab : tabs) {
128 tab->setParent(nullptr);
129 }
131}
132
134{
135 Q_D(DockSideBar);
136 sideTab->removeEventFilter(this);
137 d->m_tabsLayout->removeWidget(sideTab);
138 if (d->m_tabsLayout->isEmpty()) {
139 hide();
140 }
141}
142
149{
150 Q_D(DockSideBar);
151 auto autoHideContainer = new DockAutoHideContainer(w, d->m_sideTabArea, d->m_container);
152 // The focus controller only exists when DockManager::FocusHighlighting is
153 // enabled, and that is not the default, so this is a real null case rather
154 // than a theoretical one. Every other caller checks before using it.
155 if (auto *focusController = w->dockWindow()->dockFocusController()) {
156 focusController->clearDockWidgetFocus(w);
157 }
158 auto tab = autoHideContainer->autoHideTab();
159 w->setSideTab(tab);
160 insertTab(index, tab);
161 return autoHideContainer;
162}
163
170{
171 Q_D(DockSideBar);
172 auto sideBar = autoHideWidget->autoHideTab()->sideBar();
173 if (sideBar == this) {
174 // If we move to the same tab index or if we insert before the next
175 // tab index, then we will end at the same tab position and can leave
176 if (autoHideWidget->tabIndex() == index || (autoHideWidget->tabIndex() + 1) == index) {
177 return;
178 }
179
180 // We remove this auto hide widget from the sidebar in the code below
181 // and therefore need to correct the TabIndex here
182 if (autoHideWidget->tabIndex() < index) {
183 --index;
184 }
185 }
186
187 if (sideBar) {
188 sideBar->removeAutoHideWidget(autoHideWidget);
189 }
190 autoHideWidget->setParent(d->m_container);
191 autoHideWidget->setSideBarArea(d->m_sideTabArea);
192 d->m_container->registerAutoHideWidget(autoHideWidget);
193 insertTab(index, autoHideWidget->autoHideTab());
194}
195
197{
198 autoHideWidget->autoHideTab()->removeFromSideBar();
199 auto dockContainer = autoHideWidget->dockContainer();
200 if (dockContainer) {
201 dockContainer->removeAutoHideWidget(autoHideWidget);
202 }
203 autoHideWidget->setParent(nullptr);
204}
205
206Qt::Orientation DockSideBar::orientation() const
207{
208 Q_D(const DockSideBar);
209 return d->m_orientation;
210}
211
213{
214 Q_D(const DockSideBar);
215 return qobject_cast<DockSideTab *>(d->m_tabsLayout->itemAt(index)->widget());
216}
217
224int DockSideBar::tabAt(const QPoint &pos) const
225{
226 if (!isVisible()) {
228 }
229
230 if (orientation() == Qt::Horizontal) {
231 if (pos.x() < tab(0)->geometry().x()) {
232 return -1;
233 }
234 } else {
235 if (pos.y() < tab(0)->geometry().y()) {
236 return -1;
237 }
238 }
239
240 for (int i = 0; i < count(); ++i) {
241 if (tab(i)->geometry().contains(pos)) {
242 return i;
243 }
244 }
245
246 return count();
247}
248
249int DockSideBar::tabInsertIndexAt(const QPoint &pos) const
250{
251 int index = tabAt(pos);
252 if (index == Qx::DockTabInvalidIndex) {
254 } else {
255 return (index < 0) ? 0 : index;
256 }
257}
258
260{
261 for (auto i = 0; i < count(); i++) {
262 if (this->tab(i) == &tab) {
263 return i;
264 }
265 }
266
267 return -1;
268}
269
271{
272 Q_D(const DockSideBar);
273 return d->m_tabsLayout->count() - 1;
274}
275
277{
278 int visibleTabCount = 0;
279 auto parentWidget = this->parentWidget();
280 for (auto i = 0; i < count(); i++) {
281 if (tab(i)->isVisibleTo(parentWidget)) {
283 }
284 }
285
286 return visibleTabCount;
287}
288
296{
297 auto parentWidget = this->parentWidget();
298 for (auto i = 0; i < count(); i++) {
299 if (tab(i)->isVisibleTo(parentWidget)) {
300 return true;
301 }
302 }
303
304 return false;
305}
306
308{
309 Q_D(const DockSideBar);
310 return d->m_sideTabArea;
311}
312
321{
322 Q_D(const DockSideBar);
323 QSize size = sizeHint();
324 if (d->isHorizontal()) {
325 size.setWidth(0);
326 } else {
327 size.setHeight(0);
328 }
329 return size;
330}
331
333{
334 Q_D(const DockSideBar);
335 return d->m_tabsContainerWidget->sizeHint();
336}
337
339{
340 Q_D(const DockSideBar);
341 return d->m_tabsLayout->spacing();
342}
343
344void DockSideBar::setSpacing(int spacing)
345{
346 Q_D(DockSideBar);
347 d->m_tabsLayout->setSpacing(spacing);
348}
349
350void DockSideBar::insertTab(int index, DockSideTab *sideTab)
351{
352 Q_D(DockSideBar);
353 sideTab->setSideBar(this);
354 sideTab->installEventFilter(this);
355 // Default insertion is append
356 if (index < 0) {
357 d->m_tabsLayout->insertWidget(d->m_tabsLayout->count() - 1, sideTab);
358 } else {
359 d->m_tabsLayout->insertWidget(index, sideTab);
360 }
361 show();
362}
363
364void DockSideBar::saveState(QXmlStreamWriter &s) const
365{
366 if (!count()) {
367 return;
368 }
369
370 s.writeStartElement("SideBar");
371 s.writeAttribute("Area", QString::number(sideBarArea()));
372 s.writeAttribute("Tabs", QString::number(count()));
373
374 for (auto i = 0; i < count(); ++i) {
375 auto t = tab(i);
376 if (!t) {
377 continue;
378 }
379 t->dockWidget()->autoHideContainer()->saveState(s);
380 }
381
382 s.writeEndElement();
383}
384
385bool DockSideBar::eventFilter(QObject *watched, QEvent *event)
386{
387 auto tab = qobject_cast<DockSideTab *>(watched);
388 if (!tab) {
389 return false;
390 }
391
392 switch (event->type()) {
393 case QEvent::ShowToParent:
394 show();
395 break;
396
397 case QEvent::HideToParent:
398 if (!hasVisibleTabs()) {
399 hide();
400 }
401 break;
402
403 default:
404 break;
405 }
406
407 return false;
408}
409
Auto hide container for hosting an auto hide dock widget
int tabIndex() const
Returns the index of this container in the sidebar
Container that manages a number of dock panels with single dock widgets or tabyfied dock widgets in e...
void removeAutoHideWidget(DockAutoHideContainer *autoHideWidget)
Side tab bar widget that is shown at the edges of a dock container.
Definition docksidebar.h:32
Qt::Orientation orientation() const
void setSpacing(int spacing)
void addAutoHideWidget(DockAutoHideContainer *autoHideWidget, int index=Qx::DockTabDefaultInsertIndex)
Adds the given autoHideWidget to this sidebar.
DockAutoHideContainer * insertDockWidget(int index, DockWidget *w)
Insert dock widget into the side bar.
void saveState(QXmlStreamWriter &s) const
virtual QSize minimumSizeHint() const override
Overrides the minimumSizeHint() function of QScrollArea The minimumSizeHint() is bigger than the size...
virtual bool eventFilter(QObject *watched, QEvent *event) override
virtual QSize sizeHint() const override
void insertTab(int index, DockSideTab *sideTab)
int indexOfTab(const DockSideTab &tab) const
int visibleTabCount() const
int tabAt(const QPoint &pos) const
Returns the tab at the given position.
DockSideTab * tab(int index) const
bool hasVisibleTabs() const
Returns true, if the sidebar contains visible tabs to its parent widget.
void removeAutoHideWidget(DockAutoHideContainer *autoHideWidget)
int tabInsertIndexAt(const QPoint &pos) const
Qx::DockSideBarArea sideBarArea() const
void removeTab(DockSideTab *sideTab)
A dock widget Side tab that shows a title or an icon.
Definition docksidetab.h:23
DockSideBar * sideBar() const
Returns the side bar that contains this tab or a nullptr if the tab is not in a side bar
void setSideBar(DockSideBar *sideBar)
The DockWidget class provides a widget that can be docked inside a DockWindow or floated as a top-lev...
Definition dockwidget.h:31
DockWindow * dockWindow() const
Returns the dock window that manages the dock widget or 0 if the widget has not been assigned to any ...
void setSideTab(DockSideTab *sideTab)
Assign a side tab widget if this dock widget is an auto hide container
DockFocusController * dockFocusController() const
DockSideBarArea
@ DockSideBarTop
@ DockSideBarBottom
@ DockSideBarLeft
@ DockTabInvalidIndex
@ DockTabDefaultInsertIndex
#define QX_INIT_PRIVATE(Class)
#define QX_DECLARE_PUBLIC(Class)
#define QX_FINI_PRIVATE()
#define QX_DOCK_END_NAMESPACE
#define QX_DOCK_BEGIN_NAMESPACE