Mercurial > hg > svgui
comparison view/PaneStack.cpp @ 1526:0f1601d870db
Rework PaneStack so that the options that generally aren't (or can't be) changed after construction are supplied to the constructor instead of being set through setter methods.
This is a more sensible way of doing things in general, but also a workaround for https://code.soundsoftware.ac.uk/issues/1930, a problem that arises when reinitialising hidden property boxes in a context in which they will never be visible at all.
author | Chris Cannam |
---|---|
date | Fri, 04 Oct 2019 13:51:24 +0100 |
parents | 6bd413aff85c |
children | 88fcbc4d93dd |
comparison
equal
deleted
inserted
replaced
1525:284a38c43721 | 1526:0f1601d870db |
---|---|
35 | 35 |
36 #include <iostream> | 36 #include <iostream> |
37 | 37 |
38 //#define DEBUG_PANE_STACK 1 | 38 //#define DEBUG_PANE_STACK 1 |
39 | 39 |
40 PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) : | 40 PaneStack::PaneStack(QWidget *parent, |
41 ViewManager *viewManager, | |
42 int options) : | |
41 QFrame(parent), | 43 QFrame(parent), |
42 m_currentPane(nullptr), | 44 m_currentPane(nullptr), |
43 m_showAccessories(true), | 45 m_options(options), |
44 m_showCloseButtonOnFirstPane(true), | 46 m_splitter(nullptr), |
45 m_showAlignmentViews(false), | 47 m_autoResizeStack(nullptr), |
46 m_splitter(new QSplitter), | |
47 m_autoResizeStack(new QWidget), | |
48 m_propertyStackStack(new QStackedWidget), | 48 m_propertyStackStack(new QStackedWidget), |
49 m_viewManager(viewManager), | 49 m_viewManager(viewManager), |
50 m_propertyStackMinWidth(100), | 50 m_propertyStackMinWidth(100), |
51 m_layoutStyle(PropertyStackPerPaneLayout), | 51 m_layoutStyle(PropertyStackPerPaneLayout) |
52 m_resizeMode(UserResizeable) | |
53 { | 52 { |
54 QHBoxLayout *layout = new QHBoxLayout; | 53 QHBoxLayout *layout = new QHBoxLayout; |
55 layout->setMargin(0); | 54 layout->setMargin(0); |
56 layout->setSpacing(0); | 55 layout->setSpacing(0); |
57 | 56 |
58 m_autoResizeLayout = new QVBoxLayout; | 57 if (m_options & int(Option::NoUserResize)) { |
59 m_autoResizeLayout->setMargin(0); | 58 |
60 m_autoResizeLayout->setSpacing(0); | 59 m_autoResizeStack = new QWidget; |
61 m_autoResizeStack->setLayout(m_autoResizeLayout); | 60 m_autoResizeLayout = new QVBoxLayout; |
62 m_autoResizeStack->hide(); | 61 m_autoResizeLayout->setMargin(0); |
63 layout->addWidget(m_autoResizeStack); | 62 m_autoResizeLayout->setSpacing(0); |
64 layout->setStretchFactor(m_autoResizeStack, 1); | 63 m_autoResizeStack->setLayout(m_autoResizeLayout); |
65 | 64 m_autoResizeStack->hide(); |
66 m_splitter->setOrientation(Qt::Vertical); | 65 layout->addWidget(m_autoResizeStack); |
67 m_splitter->setOpaqueResize(false); | 66 layout->setStretchFactor(m_autoResizeStack, 1); |
68 m_splitter->show(); | 67 |
69 layout->addWidget(m_splitter); | 68 } else { |
70 layout->setStretchFactor(m_splitter, 1); | 69 |
70 m_splitter = new QSplitter; | |
71 m_splitter->setOrientation(Qt::Vertical); | |
72 m_splitter->setOpaqueResize(false); | |
73 m_splitter->show(); | |
74 layout->addWidget(m_splitter); | |
75 layout->setStretchFactor(m_splitter, 1); | |
76 } | |
77 | |
78 if (m_options & int(Option::NoPropertyStacks)) { | |
79 m_layoutStyle = HiddenPropertyStacksLayout; | |
80 } | |
71 | 81 |
72 m_propertyStackStack->hide(); | 82 m_propertyStackStack->hide(); |
73 layout->addWidget(m_propertyStackStack); | 83 layout->addWidget(m_propertyStackStack); |
74 | 84 |
75 setLayout(layout); | 85 setLayout(layout); |
76 } | 86 } |
77 | 87 |
78 void | |
79 PaneStack::setShowPaneAccessories(bool show) | |
80 { | |
81 m_showAccessories = show; | |
82 } | |
83 | |
84 void | |
85 PaneStack::setShowCloseButtonOnFirstPane(bool show) | |
86 { | |
87 m_showCloseButtonOnFirstPane = show; | |
88 } | |
89 | |
90 void | |
91 PaneStack::setShowAlignmentViews(bool show) | |
92 { | |
93 m_showAlignmentViews = show; | |
94 // each alignment view shows alignment between the pane above and | |
95 // the pane it is attached to: so pane 0 doesn't have a visible one | |
96 for (int i = 1; in_range_for(m_panes, i); ++i) { | |
97 m_panes[i].alignmentView->setVisible(m_showAlignmentViews); | |
98 } | |
99 } | |
100 | |
101 Pane * | 88 Pane * |
102 PaneStack::addPane(bool suppressPropertyBox) | 89 PaneStack::addPane() |
103 { | 90 { |
104 QFrame *frame = new QFrame; | 91 QFrame *frame = new QFrame; |
105 | 92 |
106 QGridLayout *layout = new QGridLayout; | 93 QGridLayout *layout = new QGridLayout; |
107 layout->setMargin(0); | 94 layout->setMargin(0); |
108 layout->setHorizontalSpacing(m_viewManager->scalePixelSize(2)); | 95 layout->setHorizontalSpacing(m_viewManager->scalePixelSize(2)); |
109 if (m_showAlignmentViews) { | 96 if (m_options & int(Option::ShowAlignmentViews)) { |
110 layout->setVerticalSpacing(0); | 97 layout->setVerticalSpacing(0); |
111 } else { | 98 } else { |
112 layout->setVerticalSpacing(m_viewManager->scalePixelSize(2)); | 99 layout->setVerticalSpacing(m_viewManager->scalePixelSize(2)); |
113 } | 100 } |
114 | 101 |
120 | 107 |
121 QPushButton *xButton = new QPushButton(frame); | 108 QPushButton *xButton = new QPushButton(frame); |
122 xButton->setIcon(IconLoader().load("cross")); | 109 xButton->setIcon(IconLoader().load("cross")); |
123 xButton->setFixedSize(QSize(16, 16)); | 110 xButton->setFixedSize(QSize(16, 16)); |
124 xButton->setFlat(true); | 111 xButton->setFlat(true); |
125 xButton->setVisible(m_showAccessories); | 112 xButton->setVisible(!(m_options & int(Option::NoPaneAccessories))); |
126 if (m_panes.empty() && !m_showCloseButtonOnFirstPane) { | 113 if (m_panes.empty() && (m_options & int(Option::NoCloseOnFirstPane))) { |
127 xButton->setVisible(false); | 114 xButton->setVisible(false); |
128 } | 115 } |
129 layout->addWidget(xButton, 1, 0); | 116 layout->addWidget(xButton, 1, 0); |
130 connect(xButton, SIGNAL(clicked()), this, SLOT(paneDeleteButtonClicked())); | 117 connect(xButton, SIGNAL(clicked()), this, SLOT(paneDeleteButtonClicked())); |
131 | 118 |
134 layout->addWidget(currentIndicator, 2, 0); | 121 layout->addWidget(currentIndicator, 2, 0); |
135 layout->setRowStretch(2, 20); | 122 layout->setRowStretch(2, 20); |
136 currentIndicator->setMinimumWidth(16); | 123 currentIndicator->setMinimumWidth(16); |
137 currentIndicator->setMinimumHeight(16); | 124 currentIndicator->setMinimumHeight(16); |
138 currentIndicator->setScaledContents(true); | 125 currentIndicator->setScaledContents(true); |
139 currentIndicator->setVisible(m_showAccessories); | 126 currentIndicator->setVisible(!(m_options & int(Option::NoPaneAccessories))); |
140 | 127 |
141 sv_frame_t initialCentreFrame = -1; | 128 sv_frame_t initialCentreFrame = -1; |
142 if (!m_panes.empty()) { | 129 if (!m_panes.empty()) { |
143 initialCentreFrame = m_panes[0].pane->getCentreFrame(); | 130 initialCentreFrame = m_panes[0].pane->getCentreFrame(); |
144 } | 131 } |
151 } | 138 } |
152 layout->addWidget(pane, 1, 1, 2, 1); | 139 layout->addWidget(pane, 1, 1, 2, 1); |
153 layout->setColumnStretch(1, 20); | 140 layout->setColumnStretch(1, 20); |
154 | 141 |
155 QWidget *properties = nullptr; | 142 QWidget *properties = nullptr; |
156 if (suppressPropertyBox) { | 143 if (m_options & int(Option::NoPropertyStacks)) { |
157 properties = new QFrame(); | 144 properties = new QFrame(); |
158 } else { | 145 } else { |
159 properties = new PropertyStack(frame, pane); | 146 properties = new PropertyStack(frame, pane); |
160 connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), | 147 connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), |
161 this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); | 148 this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); |
182 rec.alignmentView = av; | 169 rec.alignmentView = av; |
183 m_panes.push_back(rec); | 170 m_panes.push_back(rec); |
184 | 171 |
185 frame->setLayout(layout); | 172 frame->setLayout(layout); |
186 | 173 |
187 if (m_resizeMode == UserResizeable) { | 174 if (m_options & int(Option::NoUserResize)) { |
188 m_splitter->addWidget(frame); | |
189 } else { | |
190 m_autoResizeLayout->addWidget(frame); | 175 m_autoResizeLayout->addWidget(frame); |
191 frame->adjustSize(); | 176 frame->adjustSize(); |
177 } else { | |
178 m_splitter->addWidget(frame); | |
192 } | 179 } |
193 | 180 |
194 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)), | 181 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)), |
195 this, SLOT(propertyContainerAdded(PropertyContainer *))); | 182 this, SLOT(propertyContainerAdded(PropertyContainer *))); |
196 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)), | 183 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)), |
221 | 208 |
222 void | 209 void |
223 PaneStack::relinkAlignmentViews() | 210 PaneStack::relinkAlignmentViews() |
224 { | 211 { |
225 if (m_panes.empty()) return; | 212 if (m_panes.empty()) return; |
226 if (!m_showAlignmentViews) return; | |
227 m_panes[0].alignmentView->hide(); | 213 m_panes[0].alignmentView->hide(); |
228 for (int i = 1; in_range_for(m_panes, i); ++i) { | 214 for (int i = 1; in_range_for(m_panes, i); ++i) { |
229 m_panes[i].alignmentView->setViewAbove(m_panes[i-1].pane); | 215 if (!(m_options & int(Option::ShowAlignmentViews))) { |
230 m_panes[i].alignmentView->setViewBelow(m_panes[i].pane); | 216 m_panes[i].alignmentView->hide(); |
231 m_panes[i].alignmentView->setVisible(true); | 217 } else { |
218 m_panes[i].alignmentView->setViewAbove(m_panes[i-1].pane); | |
219 m_panes[i].alignmentView->setViewBelow(m_panes[i].pane); | |
220 m_panes[i].alignmentView->show(); | |
221 } | |
232 } | 222 } |
233 } | 223 } |
234 | 224 |
235 void | 225 void |
236 PaneStack::unlinkAlignmentViews() | 226 PaneStack::unlinkAlignmentViews() |
252 } | 242 } |
253 | 243 |
254 void | 244 void |
255 PaneStack::setLayoutStyle(LayoutStyle style) | 245 PaneStack::setLayoutStyle(LayoutStyle style) |
256 { | 246 { |
247 if (m_options & int(Option::NoPropertyStacks)) { | |
248 SVCERR << "NOTE: PaneStack::setLayoutStyle called on PaneStack with NoPropertyStacks option set - this does nothing, its style is always equivalent to HiddenPropertyStacksLayout" << endl; | |
249 return; | |
250 } | |
251 | |
257 if (style == m_layoutStyle) return; | 252 if (style == m_layoutStyle) return; |
258 m_layoutStyle = style; | 253 m_layoutStyle = style; |
259 | 254 |
260 std::vector<PaneRec>::iterator i; | 255 std::vector<PaneRec>::iterator i; |
261 | 256 |
262 switch (style) { | 257 switch (style) { |
263 | 258 |
264 case NoPropertyStacks: | 259 case HiddenPropertyStacksLayout: |
265 case SinglePropertyStackLayout: | 260 case SinglePropertyStackLayout: |
266 | 261 |
267 for (i = m_panes.begin(); i != m_panes.end(); ++i) { | 262 for (i = m_panes.begin(); i != m_panes.end(); ++i) { |
268 i->layout->removeWidget(i->propertyStack); | 263 i->layout->removeWidget(i->propertyStack); |
269 i->propertyStack->setParent(m_propertyStackStack); | 264 i->propertyStack->setParent(m_propertyStackStack); |
270 m_propertyStackStack->addWidget(i->propertyStack); | 265 m_propertyStackStack->addWidget(i->propertyStack); |
271 } | 266 } |
272 m_propertyStackStack->setVisible(style != NoPropertyStacks); | 267 m_propertyStackStack->setVisible(style != HiddenPropertyStacksLayout); |
273 break; | 268 break; |
274 | 269 |
275 case PropertyStackPerPaneLayout: | 270 case PropertyStackPerPaneLayout: |
276 | 271 |
277 for (i = m_panes.begin(); i != m_panes.end(); ++i) { | 272 for (i = m_panes.begin(); i != m_panes.end(); ++i) { |
391 #endif | 386 #endif |
392 | 387 |
393 bool multi = (getPaneCount() > 1); | 388 bool multi = (getPaneCount() > 1); |
394 for (std::vector<PaneRec>::iterator i = m_panes.begin(); | 389 for (std::vector<PaneRec>::iterator i = m_panes.begin(); |
395 i != m_panes.end(); ++i) { | 390 i != m_panes.end(); ++i) { |
396 bool visible = (multi && m_showAccessories); | 391 bool visible = (multi && !(m_options & int(Option::NoPaneAccessories))); |
397 bool xvisible = visible; | 392 bool xvisible = visible; |
398 if (i == m_panes.begin()) { | 393 if (i == m_panes.begin()) { |
399 if (!m_showCloseButtonOnFirstPane) { | 394 if (m_options & int(Option::NoCloseOnFirstPane)) { |
400 xvisible = false; | 395 xvisible = false; |
401 } | 396 } |
402 } | 397 } |
403 i->xButton->setVisible(xvisible); | 398 i->xButton->setVisible(xvisible); |
404 i->currentIndicator->setVisible(visible); | 399 i->currentIndicator->setVisible(visible); |
687 } | 682 } |
688 | 683 |
689 void | 684 void |
690 PaneStack::sizePanesEqually() | 685 PaneStack::sizePanesEqually() |
691 { | 686 { |
692 if (m_resizeMode == AutoResizeOnly) { | 687 if (m_options & int(Option::NoUserResize)) { |
693 return; | 688 return; |
694 } | 689 } |
695 | 690 |
696 QList<int> sizes = m_splitter->sizes(); | 691 QList<int> sizes = m_splitter->sizes(); |
697 if (sizes.empty()) return; | 692 if (sizes.empty()) return; |
748 */ | 743 */ |
749 | 744 |
750 m_splitter->setSizes(sizes); | 745 m_splitter->setSizes(sizes); |
751 } | 746 } |
752 | 747 |
753 void | |
754 PaneStack::setResizeMode(ResizeMode mode) | |
755 { | |
756 if (mode == UserResizeable) { | |
757 m_autoResizeStack->hide(); | |
758 m_splitter->show(); | |
759 } else { | |
760 m_autoResizeStack->show(); | |
761 m_splitter->hide(); | |
762 } | |
763 m_resizeMode = mode; | |
764 | |
765 // we don't actually move any existing panes yet! let's do that | |
766 // only if we turn out to need it, shall we? | |
767 } | |
768 |