Mercurial > hg > easaier-soundaccess
comparison view/PaneStack.cpp @ 0:fc9323a41f5a
start base : Sonic Visualiser sv1-1.0rc1
author | lbajardsilogic |
---|---|
date | Fri, 11 May 2007 09:08:14 +0000 |
parents | |
children | 7a9e35f51c7a |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:fc9323a41f5a |
---|---|
1 | |
2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
3 | |
4 /* | |
5 Sonic Visualiser | |
6 An audio file viewer and annotation editor. | |
7 Centre for Digital Music, Queen Mary, University of London. | |
8 This file copyright 2006 Chris Cannam and QMUL. | |
9 | |
10 This program is free software; you can redistribute it and/or | |
11 modify it under the terms of the GNU General Public License as | |
12 published by the Free Software Foundation; either version 2 of the | |
13 License, or (at your option) any later version. See the file | |
14 COPYING included with this distribution for more information. | |
15 */ | |
16 | |
17 #include "PaneStack.h" | |
18 | |
19 #include "Pane.h" | |
20 #include "widgets/PropertyStack.h" | |
21 #include "layer/Layer.h" | |
22 #include "ViewManager.h" | |
23 | |
24 #include <QApplication> | |
25 #include <QHBoxLayout> | |
26 #include <QPainter> | |
27 #include <QPalette> | |
28 #include <QLabel> | |
29 #include <QSplitter> | |
30 #include <QStackedWidget> | |
31 | |
32 #include <iostream> | |
33 | |
34 //#define DEBUG_PANE_STACK 1 | |
35 | |
36 PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) : | |
37 QFrame(parent), | |
38 m_currentPane(0), | |
39 m_splitter(new QSplitter), | |
40 m_propertyStackStack(new QStackedWidget), | |
41 m_viewManager(viewManager), | |
42 m_layoutStyle(PropertyStackPerPaneLayout) | |
43 { | |
44 QHBoxLayout *layout = new QHBoxLayout; | |
45 layout->setMargin(0); | |
46 layout->setSpacing(0); | |
47 | |
48 m_splitter->setOrientation(Qt::Vertical); | |
49 m_splitter->setOpaqueResize(false); | |
50 | |
51 layout->addWidget(m_splitter); | |
52 layout->setStretchFactor(m_splitter, 1); | |
53 layout->addWidget(m_propertyStackStack); | |
54 m_propertyStackStack->hide(); | |
55 | |
56 setLayout(layout); | |
57 } | |
58 | |
59 Pane * | |
60 PaneStack::addPane(bool suppressPropertyBox) | |
61 { | |
62 QFrame *frame = new QFrame; | |
63 QHBoxLayout *layout = new QHBoxLayout; | |
64 layout->setMargin(0); | |
65 layout->setSpacing(2); | |
66 | |
67 QLabel *currentIndicator = new QLabel(frame); | |
68 currentIndicator->setFixedWidth(QPainter(this).fontMetrics().width("x")); | |
69 layout->addWidget(currentIndicator); | |
70 layout->setStretchFactor(currentIndicator, 1); | |
71 currentIndicator->setScaledContents(true); | |
72 | |
73 Pane *pane = new Pane(frame); | |
74 pane->setViewManager(m_viewManager); | |
75 layout->addWidget(pane); | |
76 layout->setStretchFactor(pane, 10); | |
77 | |
78 QWidget *properties = 0; | |
79 if (suppressPropertyBox) { | |
80 properties = new QFrame(); | |
81 } else { | |
82 properties = new PropertyStack(frame, pane); | |
83 connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), | |
84 this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); | |
85 connect(properties, SIGNAL(viewSelected(View *)), | |
86 this, SLOT(viewSelected(View *))); | |
87 connect(properties, SIGNAL(contextHelpChanged(const QString &)), | |
88 this, SIGNAL(contextHelpChanged(const QString &))); | |
89 } | |
90 if (m_layoutStyle == PropertyStackPerPaneLayout) { | |
91 layout->addWidget(properties); | |
92 } else { | |
93 properties->setParent(m_propertyStackStack); | |
94 m_propertyStackStack->addWidget(properties); | |
95 } | |
96 layout->setStretchFactor(properties, 1); | |
97 | |
98 PaneRec rec; | |
99 rec.pane = pane; | |
100 rec.propertyStack = properties; | |
101 rec.currentIndicator = currentIndicator; | |
102 rec.frame = frame; | |
103 rec.layout = layout; | |
104 m_panes.push_back(rec); | |
105 | |
106 frame->setLayout(layout); | |
107 m_splitter->addWidget(frame); | |
108 | |
109 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)), | |
110 this, SLOT(propertyContainerAdded(PropertyContainer *))); | |
111 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)), | |
112 this, SLOT(propertyContainerRemoved(PropertyContainer *))); | |
113 connect(pane, SIGNAL(paneInteractedWith()), | |
114 this, SLOT(paneInteractedWith())); | |
115 connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)), | |
116 this, SLOT(rightButtonMenuRequested(QPoint))); | |
117 | |
118 if (!m_currentPane) { | |
119 setCurrentPane(pane); | |
120 } | |
121 | |
122 return pane; | |
123 } | |
124 | |
125 void | |
126 PaneStack::setPropertyStackMinWidth(int mw) | |
127 { | |
128 for (std::vector<PaneRec>::iterator i = m_panes.begin(); | |
129 i != m_panes.end(); ++i) { | |
130 i->propertyStack->setMinimumWidth(mw); | |
131 } | |
132 m_propertyStackMinWidth = mw; | |
133 } | |
134 | |
135 void | |
136 PaneStack::setLayoutStyle(LayoutStyle style) | |
137 { | |
138 if (style == m_layoutStyle) return; | |
139 m_layoutStyle = style; | |
140 | |
141 std::vector<PaneRec>::iterator i; | |
142 | |
143 switch (style) { | |
144 | |
145 case NoPropertyStacks: | |
146 case SinglePropertyStackLayout: | |
147 | |
148 for (i = m_panes.begin(); i != m_panes.end(); ++i) { | |
149 i->layout->removeWidget(i->propertyStack); | |
150 i->propertyStack->setParent(m_propertyStackStack); | |
151 m_propertyStackStack->addWidget(i->propertyStack); | |
152 } | |
153 m_propertyStackStack->setVisible(style != NoPropertyStacks); | |
154 break; | |
155 | |
156 case PropertyStackPerPaneLayout: | |
157 | |
158 for (i = m_panes.begin(); i != m_panes.end(); ++i) { | |
159 m_propertyStackStack->removeWidget(i->propertyStack); | |
160 i->propertyStack->setParent(i->frame); | |
161 i->layout->addWidget(i->propertyStack); | |
162 i->propertyStack->show(); | |
163 } | |
164 m_propertyStackStack->hide(); | |
165 break; | |
166 } | |
167 } | |
168 | |
169 Pane * | |
170 PaneStack::getPane(int n) | |
171 { | |
172 return m_panes[n].pane; | |
173 } | |
174 | |
175 Pane * | |
176 PaneStack::getHiddenPane(int n) | |
177 { | |
178 return m_hiddenPanes[n].pane; | |
179 } | |
180 | |
181 void | |
182 PaneStack::deletePane(Pane *pane) | |
183 { | |
184 std::vector<PaneRec>::iterator i; | |
185 bool found = false; | |
186 | |
187 for (i = m_panes.begin(); i != m_panes.end(); ++i) { | |
188 if (i->pane == pane) { | |
189 m_panes.erase(i); | |
190 found = true; | |
191 break; | |
192 } | |
193 } | |
194 | |
195 if (!found) { | |
196 | |
197 for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) { | |
198 if (i->pane == pane) { | |
199 m_hiddenPanes.erase(i); | |
200 found = true; | |
201 break; | |
202 } | |
203 } | |
204 | |
205 if (!found) { | |
206 std::cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << std::endl; | |
207 return; | |
208 } | |
209 } | |
210 | |
211 delete pane->parent(); | |
212 | |
213 if (m_currentPane == pane) { | |
214 if (m_panes.size() > 0) { | |
215 setCurrentPane(m_panes[0].pane); | |
216 } else { | |
217 setCurrentPane(0); | |
218 } | |
219 } | |
220 } | |
221 | |
222 int | |
223 PaneStack::getPaneCount() const | |
224 { | |
225 return m_panes.size(); | |
226 } | |
227 | |
228 int | |
229 PaneStack::getHiddenPaneCount() const | |
230 { | |
231 return m_hiddenPanes.size(); | |
232 } | |
233 | |
234 void | |
235 PaneStack::hidePane(Pane *pane) | |
236 { | |
237 std::vector<PaneRec>::iterator i = m_panes.begin(); | |
238 | |
239 while (i != m_panes.end()) { | |
240 if (i->pane == pane) { | |
241 | |
242 m_hiddenPanes.push_back(*i); | |
243 m_panes.erase(i); | |
244 | |
245 QWidget *pw = dynamic_cast<QWidget *>(pane->parent()); | |
246 if (pw) pw->hide(); | |
247 | |
248 if (m_currentPane == pane) { | |
249 if (m_panes.size() > 0) { | |
250 setCurrentPane(m_panes[0].pane); | |
251 } else { | |
252 setCurrentPane(0); | |
253 } | |
254 } | |
255 | |
256 return; | |
257 } | |
258 ++i; | |
259 } | |
260 | |
261 std::cerr << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << std::endl; | |
262 } | |
263 | |
264 void | |
265 PaneStack::showPane(Pane *pane) | |
266 { | |
267 std::vector<PaneRec>::iterator i = m_hiddenPanes.begin(); | |
268 | |
269 while (i != m_hiddenPanes.end()) { | |
270 if (i->pane == pane) { | |
271 m_panes.push_back(*i); | |
272 m_hiddenPanes.erase(i); | |
273 QWidget *pw = dynamic_cast<QWidget *>(pane->parent()); | |
274 if (pw) pw->show(); | |
275 | |
276 //!!! update current pane | |
277 | |
278 return; | |
279 } | |
280 ++i; | |
281 } | |
282 | |
283 std::cerr << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << std::endl; | |
284 } | |
285 | |
286 void | |
287 PaneStack::setCurrentPane(Pane *pane) // may be null | |
288 { | |
289 if (m_currentPane == pane) return; | |
290 | |
291 std::vector<PaneRec>::iterator i = m_panes.begin(); | |
292 | |
293 // We used to do this by setting the foreground and background | |
294 // role, but it seems the background role is ignored and the | |
295 // background drawn transparent in Qt 4.1 -- I can't quite see why | |
296 | |
297 QPixmap selectedMap(1, 1); | |
298 selectedMap.fill(QApplication::palette().color(QPalette::Foreground)); | |
299 | |
300 QPixmap unselectedMap(1, 1); | |
301 unselectedMap.fill(QApplication::palette().color(QPalette::Background)); | |
302 | |
303 bool found = false; | |
304 | |
305 while (i != m_panes.end()) { | |
306 if (i->pane == pane) { | |
307 i->currentIndicator->setPixmap(selectedMap); | |
308 if (m_layoutStyle != PropertyStackPerPaneLayout) { | |
309 m_propertyStackStack->setCurrentWidget(i->propertyStack); | |
310 } | |
311 found = true; | |
312 } else { | |
313 i->currentIndicator->setPixmap(unselectedMap); | |
314 } | |
315 ++i; | |
316 } | |
317 | |
318 if (found || pane == 0) { | |
319 m_currentPane = pane; | |
320 emit currentPaneChanged(m_currentPane); | |
321 } else { | |
322 std::cerr << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << std::endl; | |
323 } | |
324 } | |
325 | |
326 void | |
327 PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null | |
328 { | |
329 setCurrentPane(pane); | |
330 | |
331 if (m_currentPane) { | |
332 | |
333 std::vector<PaneRec>::iterator i = m_panes.begin(); | |
334 | |
335 while (i != m_panes.end()) { | |
336 | |
337 if (i->pane == pane) { | |
338 PropertyStack *stack = dynamic_cast<PropertyStack *> | |
339 (i->propertyStack); | |
340 if (stack) { | |
341 if (stack->containsContainer(layer)) { | |
342 stack->setCurrentIndex(stack->getContainerIndex(layer)); | |
343 emit currentLayerChanged(pane, layer); | |
344 } else { | |
345 stack->setCurrentIndex | |
346 (stack->getContainerIndex | |
347 (pane->getPropertyContainer(0))); | |
348 emit currentLayerChanged(pane, 0); | |
349 } | |
350 } | |
351 break; | |
352 } | |
353 ++i; | |
354 } | |
355 } | |
356 } | |
357 | |
358 Pane * | |
359 PaneStack::getCurrentPane() | |
360 { | |
361 return m_currentPane; | |
362 } | |
363 | |
364 void | |
365 PaneStack::propertyContainerAdded(PropertyContainer *) | |
366 { | |
367 sizePropertyStacks(); | |
368 } | |
369 | |
370 void | |
371 PaneStack::propertyContainerRemoved(PropertyContainer *) | |
372 { | |
373 sizePropertyStacks(); | |
374 } | |
375 | |
376 void | |
377 PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc) | |
378 { | |
379 std::vector<PaneRec>::iterator i = m_panes.begin(); | |
380 | |
381 while (i != m_panes.end()) { | |
382 PropertyStack *stack = dynamic_cast<PropertyStack *>(i->propertyStack); | |
383 if (stack && | |
384 stack->getClient() == client && | |
385 stack->containsContainer(pc)) { | |
386 setCurrentPane(i->pane); | |
387 break; | |
388 } | |
389 ++i; | |
390 } | |
391 | |
392 Layer *layer = dynamic_cast<Layer *>(pc); | |
393 if (layer) emit currentLayerChanged(m_currentPane, layer); | |
394 else emit currentLayerChanged(m_currentPane, 0); | |
395 } | |
396 | |
397 void | |
398 PaneStack::viewSelected(View *v) | |
399 { | |
400 Pane *p = dynamic_cast<Pane *>(v); | |
401 if (p) setCurrentPane(p); | |
402 } | |
403 | |
404 void | |
405 PaneStack::paneInteractedWith() | |
406 { | |
407 Pane *pane = dynamic_cast<Pane *>(sender()); | |
408 if (!pane) return; | |
409 setCurrentPane(pane); | |
410 } | |
411 | |
412 void | |
413 PaneStack::rightButtonMenuRequested(QPoint position) | |
414 { | |
415 Pane *pane = dynamic_cast<Pane *>(sender()); | |
416 if (!pane) return; | |
417 emit rightButtonMenuRequested(pane, position); | |
418 } | |
419 | |
420 void | |
421 PaneStack::sizePropertyStacks() | |
422 { | |
423 int maxMinWidth = 0; | |
424 | |
425 if (m_propertyStackMinWidth > 0) maxMinWidth = m_propertyStackMinWidth; | |
426 | |
427 for (size_t i = 0; i < m_panes.size(); ++i) { | |
428 if (!m_panes[i].propertyStack) continue; | |
429 #ifdef DEBUG_PANE_STACK | |
430 std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min " | |
431 << m_panes[i].propertyStack->minimumSizeHint().width() << ", hint " | |
432 << m_panes[i].propertyStack->sizeHint().width() << ", current " | |
433 << m_panes[i].propertyStack->width() << std::endl; | |
434 #endif | |
435 | |
436 if (m_panes[i].propertyStack->sizeHint().width() > maxMinWidth) { | |
437 maxMinWidth = m_panes[i].propertyStack->sizeHint().width(); | |
438 } | |
439 } | |
440 | |
441 #ifdef DEBUG_PANE_STACK | |
442 std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl; | |
443 #endif | |
444 | |
445 //#ifdef Q_WS_MAC | |
446 // This is necessary to compensate for cb->setMinimumSize(10, 10) | |
447 // in PropertyBox in the Mac version (to avoid a mysterious crash) | |
448 // ... no longer necessary with qt4.2 | |
449 // int setWidth = maxMinWidth * 3 / 2; | |
450 //#else | |
451 int setWidth = maxMinWidth; | |
452 //#endif | |
453 | |
454 m_propertyStackStack->setMaximumWidth(setWidth + 10); | |
455 | |
456 for (size_t i = 0; i < m_panes.size(); ++i) { | |
457 if (!m_panes[i].propertyStack) continue; | |
458 m_panes[i].propertyStack->setMinimumWidth(setWidth); | |
459 } | |
460 | |
461 emit propertyStacksResized(); | |
462 } | |
463 | |
464 |