scide: DocManager - report warnings via the status bar
[supercollider.git] / editors / sc-ide / widgets / util / multi_splitter.hpp
blob6fb4828552486a73de2fadc37e3354616ca113ed
1 /*
2 SuperCollider Qt IDE
3 Copyright (c) 2012 Jakob Leben & Tim Blechmann
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef SCIDE_WIDGETS_UTIL_MULTI_SPLITTER_HPP_INCLUDED
22 #define SCIDE_WIDGETS_UTIL_MULTI_SPLITTER_HPP_INCLUDED
24 #include <QSplitter>
26 namespace ScIDE {
28 class MultiSplitter : public QSplitter
30 public:
31 explicit MultiSplitter(QWidget *parent = 0):
32 QSplitter(parent)
34 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
37 void insertWidget( QWidget *widget, QWidget *neighbour, Qt::Orientation direction )
39 if (!neighbour || !widgetIsChild(neighbour)) {
40 qWarning("MultiSplitter: neighbour widget invalid");
41 return;
44 QSplitter *parentSplitter = parentSplitterOf(neighbour);
45 Q_ASSERT(parentSplitter);
46 int posInParent = parentSplitter->indexOf(neighbour);
47 Q_ASSERT(posInParent != -1);
49 if (parentSplitter->orientation() == direction) {
50 parentSplitter->insertWidget(posInParent + 1, widget);
52 else if (parentSplitter->count() < 2)
54 parentSplitter->setOrientation(direction);
55 parentSplitter->addWidget(widget);
57 else {
58 // store parent's current distribution:
59 QList<int> parentsSizes = parentSplitter->sizes();
60 QSplitter * splitter = new QSplitter(direction);
61 // move the neighbour to the new splitter, and add the new widget:
62 splitter->addWidget(neighbour);
63 splitter->addWidget(widget);
64 // insert the new splitter at the neighbour's old position:
65 parentSplitter->insertWidget(posInParent, splitter);
66 // restore parent's old distribution, affected by operations above:
67 parentSplitter->setSizes(parentsSizes);
68 // change the parent to the new splitter, for operations below:
69 parentSplitter = splitter;
72 setEqualSizes(parentSplitter);
75 void removeWidget( QWidget *widget )
77 if (!widget || !widgetIsChild(widget)) {
78 qWarning("MultiSplitter: widget invalid");
79 return;
82 QSplitter *parent = parentSplitterOf(widget);
83 if (parent == this && parent->count() < 2) {
84 qWarning("MultiSplitter: can not remove last widget");
85 return;
88 delete widget;
90 Q_ASSERT(parent->count());
92 if (parent->count() == 1) {
93 QWidget *neighbour = parent->widget(0);
94 if (parent != this) {
95 // replace parent splitter with it's only child
96 QSplitter *grandParent = parentSplitterOf(parent);
97 QList<int> grandParentsSizes = grandParent->sizes();
98 int posInParent = grandParent->indexOf(parent);
99 Q_ASSERT(posInParent != -1);
100 grandParent->insertWidget(posInParent, neighbour);
101 delete parent;
102 grandParent->setSizes(grandParentsSizes);
104 else {
105 // replace child splitter with it's own children
106 QSplitter *splitter = qobject_cast<QSplitter*>(neighbour);
107 if (splitter) {
108 QList<int> childSizes = splitter->sizes();
109 Qt::Orientation childOrientation = splitter->orientation();
110 int childCount = splitter->count();
111 while(childCount--)
112 parent->addWidget(splitter->widget(0)); // 0 is always another widget
113 delete splitter;
114 parent->setOrientation(childOrientation);
115 parent->setSizes(childSizes);
121 template<typename T> T* findChild()
123 return MultiSplitter::findChild<T>(this);
126 private:
127 template<typename T> static T* findChild( QSplitter * splitter ) {
128 int childCount = splitter->count();
129 for (int idx = 0; idx < childCount; ++idx) {
130 QWidget *child = splitter->widget(idx);
131 T* typedChild = qobject_cast<T*>(child);
132 if (typedChild)
133 return typedChild;
134 QSplitter *childSplitter = qobject_cast<QSplitter*>(child);
135 if (childSplitter) {
136 typedChild = findChild<T>( childSplitter );
137 if (typedChild)
138 return typedChild;
141 return 0;
144 QSplitter *parentSplitterOf( QWidget *widget )
146 return qobject_cast<QSplitter*>( widget->parent() );
149 void setEqualSizes(QSplitter *splitter)
151 int widgetCount = splitter->count();
152 int splitterSize = splitter->orientation() == Qt::Horizontal ?
153 splitter->size().width() : splitter->size().height();
154 QList<int> newWidgetSizes;
155 int singleWidgetSize = splitterSize / widgetCount;
156 for( int idx = 0; idx < widgetCount; ++idx )
157 newWidgetSizes << singleWidgetSize;
158 splitter->setSizes( newWidgetSizes );
161 bool widgetIsChild( QWidget *widget )
163 QObject *object = widget->parent();
164 while (object) {
165 if (object == this)
166 return true;
167 object = object->parent();
169 return false;
173 } // namespace ScIDE
175 #endif // SCIDE_WIDGETS_UTIL_MULTI_SPLITTER_HPP_INCLUDED