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