annotate view/PaneStack.cpp @ 1447:8afea53332f3 single-point

Add option to make pane sizes auto-resize-only (i.e. remove user control via a splitter); also place alignment views above panes instead of below, meaning the extra bit of space that we currently have for the pane without one at least goes to the primary pane
author Chris Cannam
date Tue, 30 Apr 2019 15:53:21 +0100
parents 1ed6d666ec9e
children 4a6ca97ce783
rev   line source
Chris@127 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@127 2
Chris@127 3 /*
Chris@127 4 Sonic Visualiser
Chris@127 5 An audio file viewer and annotation editor.
Chris@127 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@127 8
Chris@127 9 This program is free software; you can redistribute it and/or
Chris@127 10 modify it under the terms of the GNU General Public License as
Chris@127 11 published by the Free Software Foundation; either version 2 of the
Chris@127 12 License, or (at your option) any later version. See the file
Chris@127 13 COPYING included with this distribution for more information.
Chris@127 14 */
Chris@127 15
Chris@127 16 #include "PaneStack.h"
Chris@127 17
Chris@128 18 #include "Pane.h"
Chris@127 19 #include "widgets/PropertyStack.h"
Chris@323 20 #include "widgets/IconLoader.h"
Chris@500 21 #include "widgets/ClickableLabel.h"
Chris@128 22 #include "layer/Layer.h"
Chris@128 23 #include "ViewManager.h"
Chris@867 24 #include "AlignmentView.h"
Chris@127 25
Chris@127 26 #include <QApplication>
Chris@127 27 #include <QHBoxLayout>
Chris@323 28 #include <QVBoxLayout>
Chris@127 29 #include <QPainter>
Chris@127 30 #include <QPalette>
Chris@127 31 #include <QLabel>
Chris@323 32 #include <QPushButton>
Chris@127 33 #include <QSplitter>
Chris@127 34 #include <QStackedWidget>
Chris@127 35
Chris@127 36 #include <iostream>
Chris@127 37
Chris@247 38 //#define DEBUG_PANE_STACK 1
Chris@247 39
Chris@127 40 PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) :
Chris@127 41 QFrame(parent),
Chris@1408 42 m_currentPane(nullptr),
Chris@712 43 m_showAccessories(true),
Chris@867 44 m_showAlignmentViews(false),
Chris@127 45 m_splitter(new QSplitter),
Chris@1447 46 m_autoResizeStack(new QWidget),
Chris@127 47 m_propertyStackStack(new QStackedWidget),
Chris@127 48 m_viewManager(viewManager),
Chris@615 49 m_propertyStackMinWidth(100),
Chris@1447 50 m_layoutStyle(PropertyStackPerPaneLayout),
Chris@1447 51 m_resizeMode(UserResizeable)
Chris@127 52 {
Chris@127 53 QHBoxLayout *layout = new QHBoxLayout;
Chris@127 54 layout->setMargin(0);
Chris@127 55 layout->setSpacing(0);
Chris@127 56
Chris@1447 57 m_autoResizeLayout = new QVBoxLayout;
Chris@1447 58 m_autoResizeLayout->setSpacing(0);
Chris@1447 59 m_autoResizeStack->setLayout(m_autoResizeLayout);
Chris@1447 60 m_autoResizeStack->hide();
Chris@1447 61 layout->addWidget(m_autoResizeStack);
Chris@1447 62 layout->setStretchFactor(m_autoResizeStack, 1);
Chris@1447 63
Chris@127 64 m_splitter->setOrientation(Qt::Vertical);
Chris@127 65 m_splitter->setOpaqueResize(false);
Chris@1447 66 m_splitter->show();
Chris@127 67 layout->addWidget(m_splitter);
Chris@127 68 layout->setStretchFactor(m_splitter, 1);
Chris@1447 69
Chris@1447 70 m_propertyStackStack->hide();
Chris@127 71 layout->addWidget(m_propertyStackStack);
Chris@127 72
Chris@127 73 setLayout(layout);
Chris@127 74 }
Chris@127 75
Chris@712 76 void
Chris@712 77 PaneStack::setShowPaneAccessories(bool show)
Chris@712 78 {
Chris@712 79 m_showAccessories = show;
Chris@712 80 }
Chris@712 81
Chris@867 82 void
Chris@867 83 PaneStack::setShowAlignmentViews(bool show)
Chris@867 84 {
Chris@867 85 m_showAlignmentViews = show;
Chris@1447 86 // each alignment view shows alignment between the pane above and
Chris@1447 87 // the pane it is attached to: so pane 0 doesn't have a visible one
Chris@1447 88 for (int i = 1; in_range_for(m_panes, i); ++i) {
Chris@1447 89 m_panes[i].alignmentView->setVisible(m_showAlignmentViews);
Chris@867 90 }
Chris@867 91 }
Chris@867 92
Chris@127 93 Pane *
Chris@127 94 PaneStack::addPane(bool suppressPropertyBox)
Chris@127 95 {
Chris@127 96 QFrame *frame = new QFrame;
Chris@495 97
Chris@495 98 QGridLayout *layout = new QGridLayout;
Chris@127 99 layout->setMargin(0);
Chris@1447 100 layout->setHorizontalSpacing(m_viewManager->scalePixelSize(2));
Chris@1447 101 if (m_showAlignmentViews) {
Chris@1447 102 layout->setVerticalSpacing(0);
Chris@1447 103 } else {
Chris@1447 104 layout->setVerticalSpacing(m_viewManager->scalePixelSize(2));
Chris@1447 105 }
Chris@1447 106
Chris@1447 107 AlignmentView *av = new AlignmentView(frame);
Chris@1447 108 av->setFixedHeight(ViewManager::scalePixelSize(20));
Chris@1447 109 av->setViewManager(m_viewManager);
Chris@1447 110 av->setVisible(false); // for now
Chris@1447 111 layout->addWidget(av, 0, 1);
Chris@127 112
Chris@323 113 QPushButton *xButton = new QPushButton(frame);
Chris@323 114 xButton->setIcon(IconLoader().load("cross"));
Chris@323 115 xButton->setFixedSize(QSize(16, 16));
Chris@497 116 xButton->setFlat(true);
Chris@712 117 xButton->setVisible(m_showAccessories);
Chris@1447 118 layout->addWidget(xButton, 1, 0);
Chris@323 119 connect(xButton, SIGNAL(clicked()), this, SLOT(paneDeleteButtonClicked()));
Chris@323 120
Chris@500 121 ClickableLabel *currentIndicator = new ClickableLabel(frame);
Chris@500 122 connect(currentIndicator, SIGNAL(clicked()), this, SLOT(indicatorClicked()));
Chris@1447 123 layout->addWidget(currentIndicator, 2, 0);
Chris@495 124 layout->setRowStretch(1, 20);
Chris@497 125 currentIndicator->setMinimumWidth(8);
Chris@127 126 currentIndicator->setScaledContents(true);
Chris@712 127 currentIndicator->setVisible(m_showAccessories);
Chris@127 128
Chris@908 129 sv_frame_t initialCentreFrame = -1;
Chris@855 130 if (!m_panes.empty()) {
Chris@855 131 initialCentreFrame = m_panes[0].pane->getCentreFrame();
Chris@516 132 }
Chris@516 133
Chris@127 134 Pane *pane = new Pane(frame);
Chris@516 135 if (initialCentreFrame >= 0) {
Chris@516 136 pane->setViewManager(m_viewManager, initialCentreFrame);
Chris@516 137 } else {
Chris@516 138 pane->setViewManager(m_viewManager);
Chris@516 139 }
Chris@1447 140 layout->addWidget(pane, 1, 1, 2, 1);
Chris@495 141 layout->setColumnStretch(1, 20);
Chris@127 142
Chris@1408 143 QWidget *properties = nullptr;
Chris@127 144 if (suppressPropertyBox) {
Chris@1266 145 properties = new QFrame();
Chris@127 146 } else {
Chris@1266 147 properties = new PropertyStack(frame, pane);
Chris@1266 148 connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
Chris@1266 149 this, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
Chris@190 150 connect(properties, SIGNAL(viewSelected(View *)),
Chris@190 151 this, SLOT(viewSelected(View *)));
Chris@189 152 connect(properties, SIGNAL(contextHelpChanged(const QString &)),
Chris@189 153 this, SIGNAL(contextHelpChanged(const QString &)));
Chris@127 154 }
Chris@127 155 if (m_layoutStyle == PropertyStackPerPaneLayout) {
Chris@1447 156 layout->addWidget(properties, 1, 2, 2, 1);
Chris@127 157 } else {
Chris@127 158 properties->setParent(m_propertyStackStack);
Chris@127 159 m_propertyStackStack->addWidget(properties);
Chris@127 160 }
Chris@606 161 layout->setColumnStretch(2, 0);
Chris@127 162
Chris@127 163 PaneRec rec;
Chris@127 164 rec.pane = pane;
Chris@127 165 rec.propertyStack = properties;
Chris@605 166 rec.xButton = xButton;
Chris@127 167 rec.currentIndicator = currentIndicator;
Chris@127 168 rec.frame = frame;
Chris@127 169 rec.layout = layout;
Chris@867 170 rec.alignmentView = av;
Chris@127 171 m_panes.push_back(rec);
Chris@127 172
Chris@127 173 frame->setLayout(layout);
Chris@1447 174
Chris@1447 175 if (m_resizeMode == UserResizeable) {
Chris@1447 176 m_splitter->addWidget(frame);
Chris@1447 177 } else {
Chris@1447 178 m_autoResizeLayout->addWidget(frame);
Chris@1447 179 frame->adjustSize();
Chris@1447 180 }
Chris@127 181
Chris@127 182 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@1266 183 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@127 184 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@1266 185 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@127 186 connect(pane, SIGNAL(paneInteractedWith()),
Chris@1266 187 this, SLOT(paneInteractedWith()));
Chris@127 188 connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)),
Chris@127 189 this, SLOT(rightButtonMenuRequested(QPoint)));
Chris@312 190 connect(pane, SIGNAL(dropAccepted(QStringList)),
Chris@312 191 this, SLOT(paneDropAccepted(QStringList)));
Chris@312 192 connect(pane, SIGNAL(dropAccepted(QString)),
Chris@312 193 this, SLOT(paneDropAccepted(QString)));
Chris@908 194 connect(pane, SIGNAL(doubleClickSelectInvoked(sv_frame_t)),
Chris@908 195 this, SIGNAL(doubleClickSelectInvoked(sv_frame_t)));
Chris@127 196
Chris@271 197 emit paneAdded(pane);
Chris@271 198 emit paneAdded();
Chris@271 199
Chris@127 200 if (!m_currentPane) {
Chris@1266 201 setCurrentPane(pane);
Chris@127 202 }
Chris@127 203
Chris@605 204 showOrHidePaneAccessories();
Chris@867 205 relinkAlignmentViews();
Chris@605 206
Chris@127 207 return pane;
Chris@127 208 }
Chris@127 209
Chris@127 210 void
Chris@867 211 PaneStack::relinkAlignmentViews()
Chris@867 212 {
Chris@1447 213 if (m_panes.empty()) return;
Chris@1447 214 m_panes[0].alignmentView->hide();
Chris@1447 215 for (int i = 1; in_range_for(m_panes, i); ++i) {
Chris@1447 216 m_panes[i].alignmentView->setViewAbove(m_panes[i-1].pane);
Chris@1447 217 m_panes[i].alignmentView->setViewBelow(m_panes[i].pane);
Chris@1447 218 m_panes[i].alignmentView->setVisible(true);
Chris@867 219 }
Chris@867 220 }
Chris@867 221
Chris@867 222 void
Chris@867 223 PaneStack::unlinkAlignmentViews()
Chris@867 224 {
Chris@1447 225 for (int i = 0; in_range_for(m_panes, i); ++i) {
Chris@1408 226 m_panes[i].alignmentView->setViewAbove(nullptr);
Chris@1408 227 m_panes[i].alignmentView->setViewBelow(nullptr);
Chris@867 228 }
Chris@867 229 }
Chris@867 230
Chris@867 231 void
Chris@235 232 PaneStack::setPropertyStackMinWidth(int mw)
Chris@235 233 {
Chris@235 234 for (std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@235 235 i != m_panes.end(); ++i) {
Chris@235 236 i->propertyStack->setMinimumWidth(mw);
Chris@235 237 }
Chris@235 238 m_propertyStackMinWidth = mw;
Chris@235 239 }
Chris@235 240
Chris@235 241 void
Chris@127 242 PaneStack::setLayoutStyle(LayoutStyle style)
Chris@127 243 {
Chris@127 244 if (style == m_layoutStyle) return;
Chris@127 245 m_layoutStyle = style;
Chris@127 246
Chris@127 247 std::vector<PaneRec>::iterator i;
Chris@127 248
Chris@127 249 switch (style) {
Chris@127 250
Chris@179 251 case NoPropertyStacks:
Chris@127 252 case SinglePropertyStackLayout:
Chris@127 253
Chris@127 254 for (i = m_panes.begin(); i != m_panes.end(); ++i) {
Chris@127 255 i->layout->removeWidget(i->propertyStack);
Chris@127 256 i->propertyStack->setParent(m_propertyStackStack);
Chris@127 257 m_propertyStackStack->addWidget(i->propertyStack);
Chris@127 258 }
Chris@179 259 m_propertyStackStack->setVisible(style != NoPropertyStacks);
Chris@127 260 break;
Chris@127 261
Chris@127 262 case PropertyStackPerPaneLayout:
Chris@127 263
Chris@127 264 for (i = m_panes.begin(); i != m_panes.end(); ++i) {
Chris@127 265 m_propertyStackStack->removeWidget(i->propertyStack);
Chris@127 266 i->propertyStack->setParent(i->frame);
Chris@495 267 i->layout->addWidget(i->propertyStack, 0, 2, 2, 1);
Chris@127 268 i->propertyStack->show();
Chris@127 269 }
Chris@127 270 m_propertyStackStack->hide();
Chris@127 271 break;
Chris@127 272 }
Chris@127 273 }
Chris@127 274
Chris@127 275 Pane *
Chris@127 276 PaneStack::getPane(int n)
Chris@127 277 {
Chris@806 278 if (n < (int)m_panes.size()) {
Chris@277 279 return m_panes[n].pane;
Chris@277 280 } else {
Chris@1408 281 return nullptr;
Chris@277 282 }
Chris@277 283 }
Chris@277 284
Chris@277 285 int
Chris@277 286 PaneStack::getPaneIndex(Pane *pane)
Chris@277 287 {
Chris@277 288 for (int i = 0; i < getPaneCount(); ++i) {
Chris@277 289 if (pane == getPane(i)) {
Chris@277 290 return i;
Chris@277 291 }
Chris@277 292 }
Chris@277 293 return -1;
Chris@127 294 }
Chris@127 295
Chris@127 296 Pane *
Chris@127 297 PaneStack::getHiddenPane(int n)
Chris@127 298 {
Chris@127 299 return m_hiddenPanes[n].pane;
Chris@127 300 }
Chris@127 301
Chris@127 302 void
Chris@127 303 PaneStack::deletePane(Pane *pane)
Chris@127 304 {
Chris@1362 305 #ifdef DEBUG_PANE_STACK
Chris@1362 306 SVCERR << "PaneStack::deletePane(" << pane << ")" << endl;
Chris@1362 307 #endif
Chris@729 308
Chris@127 309 std::vector<PaneRec>::iterator i;
Chris@127 310 bool found = false;
Chris@127 311
Chris@1408 312 QWidget *stack = nullptr;
Chris@729 313
Chris@127 314 for (i = m_panes.begin(); i != m_panes.end(); ++i) {
Chris@1266 315 if (i->pane == pane) {
Chris@729 316 stack = i->propertyStack;
Chris@1266 317 m_panes.erase(i);
Chris@1266 318 found = true;
Chris@1266 319 break;
Chris@1266 320 }
Chris@127 321 }
Chris@127 322
Chris@127 323 if (!found) {
Chris@127 324
Chris@1266 325 for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) {
Chris@1266 326 if (i->pane == pane) {
Chris@729 327 stack = i->propertyStack;
Chris@1266 328 m_hiddenPanes.erase(i);
Chris@1266 329 found = true;
Chris@1266 330 break;
Chris@1266 331 }
Chris@1266 332 }
Chris@127 333
Chris@1266 334 if (!found) {
Chris@1266 335 cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << endl;
Chris@1266 336 return;
Chris@1266 337 }
Chris@127 338 }
Chris@127 339
Chris@271 340 emit paneAboutToBeDeleted(pane);
Chris@867 341 unlinkAlignmentViews();
Chris@271 342
Chris@1362 343 #ifdef DEBUG_PANE_STACK
Chris@1362 344 SVCERR << "PaneStack::deletePane: about to delete parent " << pane->parent() << " of pane " << pane << endl;
Chris@1362 345 #endif
Chris@729 346
Chris@729 347 // The property stack associated with the parent was initially
Chris@729 348 // created with the same parent as it, so it would be deleted when
Chris@729 349 // we delete the pane's parent in a moment -- but it may have been
Chris@729 350 // reparented depending on the layout. We'd better delete it
Chris@729 351 // separately first. (This fixes a crash on opening a new layer
Chris@729 352 // with a new unit type in it, when a long-defunct property box
Chris@729 353 // could be signalled from the unit database to tell it that a new
Chris@729 354 // unit had appeared.)
Chris@729 355 delete stack;
Chris@729 356
Chris@127 357 delete pane->parent();
Chris@127 358
Chris@127 359 if (m_currentPane == pane) {
Chris@1266 360 if (m_panes.size() > 0) {
Chris@127 361 setCurrentPane(m_panes[0].pane);
Chris@1266 362 } else {
Chris@1408 363 setCurrentPane(nullptr);
Chris@1266 364 }
Chris@127 365 }
Chris@271 366
Chris@605 367 showOrHidePaneAccessories();
Chris@867 368 relinkAlignmentViews();
Chris@605 369
Chris@271 370 emit paneDeleted();
Chris@127 371 }
Chris@127 372
Chris@605 373 void
Chris@605 374 PaneStack::showOrHidePaneAccessories()
Chris@605 375 {
Chris@1362 376 #ifdef DEBUG_PANE_STACK
Chris@1362 377 SVCERR << "PaneStack::showOrHidePaneAccessories: count == " << getPaneCount() << endl;
Chris@1362 378 #endif
Chris@605 379
Chris@605 380 bool multi = (getPaneCount() > 1);
Chris@605 381 for (std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@605 382 i != m_panes.end(); ++i) {
Chris@712 383 i->xButton->setVisible(multi && m_showAccessories);
Chris@712 384 i->currentIndicator->setVisible(multi && m_showAccessories);
Chris@605 385 }
Chris@605 386 }
Chris@605 387
Chris@127 388 int
Chris@127 389 PaneStack::getPaneCount() const
Chris@127 390 {
Chris@908 391 return int(m_panes.size());
Chris@127 392 }
Chris@127 393
Chris@127 394 int
Chris@127 395 PaneStack::getHiddenPaneCount() const
Chris@127 396 {
Chris@908 397 return int(m_hiddenPanes.size());
Chris@127 398 }
Chris@127 399
Chris@127 400 void
Chris@127 401 PaneStack::hidePane(Pane *pane)
Chris@127 402 {
Chris@127 403 std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@127 404
Chris@127 405 while (i != m_panes.end()) {
Chris@1266 406 if (i->pane == pane) {
Chris@127 407
Chris@1266 408 m_hiddenPanes.push_back(*i);
Chris@1266 409 m_panes.erase(i);
Chris@127 410
Chris@1266 411 QWidget *pw = dynamic_cast<QWidget *>(pane->parent());
Chris@1266 412 if (pw) pw->hide();
Chris@127 413
Chris@1266 414 if (m_currentPane == pane) {
Chris@1266 415 if (m_panes.size() > 0) {
Chris@1266 416 setCurrentPane(m_panes[0].pane);
Chris@1266 417 } else {
Chris@1408 418 setCurrentPane(nullptr);
Chris@1266 419 }
Chris@1266 420 }
Chris@1266 421
Chris@605 422 showOrHidePaneAccessories();
Chris@605 423 emit paneHidden(pane);
Chris@605 424 emit paneHidden();
cannam@1444 425 relinkAlignmentViews();
Chris@1266 426 return;
Chris@1266 427 }
Chris@1266 428 ++i;
Chris@127 429 }
Chris@127 430
Chris@1362 431 SVCERR << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << endl;
Chris@127 432 }
Chris@127 433
Chris@127 434 void
Chris@127 435 PaneStack::showPane(Pane *pane)
Chris@127 436 {
Chris@127 437 std::vector<PaneRec>::iterator i = m_hiddenPanes.begin();
Chris@127 438
Chris@127 439 while (i != m_hiddenPanes.end()) {
Chris@1266 440 if (i->pane == pane) {
Chris@1266 441 m_panes.push_back(*i);
Chris@1266 442 m_hiddenPanes.erase(i);
Chris@1266 443 QWidget *pw = dynamic_cast<QWidget *>(pane->parent());
Chris@1266 444 if (pw) pw->show();
Chris@127 445
Chris@1266 446 //!!! update current pane
Chris@127 447
Chris@605 448 showOrHidePaneAccessories();
cannam@1444 449 relinkAlignmentViews();
Chris@605 450
Chris@1266 451 return;
Chris@1266 452 }
Chris@1266 453 ++i;
Chris@127 454 }
Chris@127 455
Chris@1362 456 SVCERR << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << endl;
Chris@127 457 }
Chris@127 458
Chris@127 459 void
Chris@127 460 PaneStack::setCurrentPane(Pane *pane) // may be null
Chris@127 461 {
Chris@127 462 if (m_currentPane == pane) return;
Chris@127 463
Chris@127 464 std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@127 465
Chris@127 466 // We used to do this by setting the foreground and background
Chris@127 467 // role, but it seems the background role is ignored and the
Chris@127 468 // background drawn transparent in Qt 4.1 -- I can't quite see why
Chris@127 469
Chris@127 470 QPixmap selectedMap(1, 1);
Chris@127 471 selectedMap.fill(QApplication::palette().color(QPalette::Foreground));
Chris@127 472
Chris@127 473 QPixmap unselectedMap(1, 1);
Chris@127 474 unselectedMap.fill(QApplication::palette().color(QPalette::Background));
Chris@127 475
Chris@127 476 bool found = false;
Chris@127 477
Chris@127 478 while (i != m_panes.end()) {
Chris@1266 479 if (i->pane == pane) {
Chris@1266 480 i->currentIndicator->setPixmap(selectedMap);
Chris@179 481 if (m_layoutStyle != PropertyStackPerPaneLayout) {
Chris@127 482 m_propertyStackStack->setCurrentWidget(i->propertyStack);
Chris@127 483 }
Chris@1266 484 found = true;
Chris@1266 485 } else {
Chris@1266 486 i->currentIndicator->setPixmap(unselectedMap);
Chris@1266 487 }
Chris@1266 488 ++i;
Chris@127 489 }
Chris@127 490
Chris@1408 491 if (found || pane == nullptr) {
Chris@1266 492 m_currentPane = pane;
Chris@1266 493 emit currentPaneChanged(m_currentPane);
Chris@127 494 } else {
Chris@1362 495 SVCERR << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << endl;
Chris@127 496 }
Chris@127 497 }
Chris@127 498
Chris@127 499 void
Chris@127 500 PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null
Chris@127 501 {
Chris@127 502 setCurrentPane(pane);
Chris@127 503
Chris@127 504 if (m_currentPane) {
Chris@127 505
Chris@1266 506 std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@127 507
Chris@1266 508 while (i != m_panes.end()) {
Chris@127 509
Chris@1266 510 if (i->pane == pane) {
Chris@1266 511 PropertyStack *stack = dynamic_cast<PropertyStack *>
Chris@1266 512 (i->propertyStack);
Chris@1266 513 if (stack) {
Chris@1266 514 if (stack->containsContainer(layer)) {
Chris@1266 515 stack->setCurrentIndex(stack->getContainerIndex(layer));
Chris@1266 516 emit currentLayerChanged(pane, layer);
Chris@1266 517 } else {
Chris@1266 518 stack->setCurrentIndex
Chris@1266 519 (stack->getContainerIndex
Chris@1266 520 (pane->getPropertyContainer(0)));
Chris@1408 521 emit currentLayerChanged(pane, nullptr);
Chris@1266 522 }
Chris@1266 523 }
Chris@1266 524 break;
Chris@1266 525 }
Chris@1266 526 ++i;
Chris@1266 527 }
Chris@127 528 }
Chris@127 529 }
Chris@127 530
Chris@127 531 Pane *
Chris@127 532 PaneStack::getCurrentPane()
Chris@127 533 {
Chris@127 534 return m_currentPane;
Chris@127 535 }
Chris@127 536
Chris@127 537 void
Chris@127 538 PaneStack::propertyContainerAdded(PropertyContainer *)
Chris@127 539 {
Chris@127 540 sizePropertyStacks();
Chris@127 541 }
Chris@127 542
Chris@127 543 void
Chris@127 544 PaneStack::propertyContainerRemoved(PropertyContainer *)
Chris@127 545 {
Chris@127 546 sizePropertyStacks();
Chris@127 547 }
Chris@127 548
Chris@127 549 void
Chris@127 550 PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc)
Chris@127 551 {
Chris@127 552 std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@127 553
Chris@127 554 while (i != m_panes.end()) {
Chris@1266 555 PropertyStack *stack = dynamic_cast<PropertyStack *>(i->propertyStack);
Chris@1266 556 if (stack &&
Chris@1266 557 stack->getClient() == client &&
Chris@1266 558 stack->containsContainer(pc)) {
Chris@1266 559 setCurrentPane(i->pane);
Chris@1266 560 break;
Chris@1266 561 }
Chris@1266 562 ++i;
Chris@127 563 }
Chris@127 564
Chris@127 565 Layer *layer = dynamic_cast<Layer *>(pc);
Chris@127 566 if (layer) emit currentLayerChanged(m_currentPane, layer);
Chris@1408 567 else emit currentLayerChanged(m_currentPane, nullptr);
Chris@127 568 }
Chris@127 569
Chris@127 570 void
Chris@190 571 PaneStack::viewSelected(View *v)
Chris@190 572 {
Chris@190 573 Pane *p = dynamic_cast<Pane *>(v);
Chris@190 574 if (p) setCurrentPane(p);
Chris@190 575 }
Chris@190 576
Chris@190 577 void
Chris@127 578 PaneStack::paneInteractedWith()
Chris@127 579 {
Chris@127 580 Pane *pane = dynamic_cast<Pane *>(sender());
Chris@127 581 if (!pane) return;
Chris@127 582 setCurrentPane(pane);
Chris@127 583 }
Chris@127 584
Chris@127 585 void
Chris@127 586 PaneStack::rightButtonMenuRequested(QPoint position)
Chris@127 587 {
Chris@127 588 Pane *pane = dynamic_cast<Pane *>(sender());
Chris@127 589 if (!pane) return;
Chris@127 590 emit rightButtonMenuRequested(pane, position);
Chris@127 591 }
Chris@127 592
Chris@127 593 void
Chris@127 594 PaneStack::sizePropertyStacks()
Chris@127 595 {
Chris@127 596 int maxMinWidth = 0;
Chris@127 597
Chris@235 598 if (m_propertyStackMinWidth > 0) maxMinWidth = m_propertyStackMinWidth;
Chris@235 599
Chris@806 600 for (int i = 0; i < (int)m_panes.size(); ++i) {
Chris@1266 601 if (!m_panes[i].propertyStack) continue;
Chris@247 602 #ifdef DEBUG_PANE_STACK
Chris@1266 603 SVDEBUG << "PaneStack::sizePropertyStacks: " << i << ": min "
Chris@1266 604 << m_panes[i].propertyStack->minimumSizeHint().width() << ", hint "
Chris@243 605 << m_panes[i].propertyStack->sizeHint().width() << ", current "
Chris@1266 606 << m_panes[i].propertyStack->width() << endl;
Chris@247 607 #endif
Chris@127 608
Chris@1266 609 if (m_panes[i].propertyStack->sizeHint().width() > maxMinWidth) {
Chris@1266 610 maxMinWidth = m_panes[i].propertyStack->sizeHint().width();
Chris@1266 611 }
Chris@127 612 }
Chris@127 613
Chris@247 614 #ifdef DEBUG_PANE_STACK
Chris@587 615 SVDEBUG << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << endl;
Chris@247 616 #endif
Chris@127 617
Chris@127 618 int setWidth = maxMinWidth;
Chris@127 619
Chris@127 620 m_propertyStackStack->setMaximumWidth(setWidth + 10);
Chris@127 621
Chris@806 622 for (int i = 0; i < (int)m_panes.size(); ++i) {
Chris@1266 623 if (!m_panes[i].propertyStack) continue;
Chris@1266 624 m_panes[i].propertyStack->setMinimumWidth(setWidth);
Chris@127 625 }
Chris@180 626
Chris@363 627 emit propertyStacksResized(setWidth);
Chris@180 628 emit propertyStacksResized();
Chris@127 629 }
Chris@127 630
Chris@312 631 void
Chris@312 632 PaneStack::paneDropAccepted(QStringList uriList)
Chris@312 633 {
Chris@312 634 Pane *pane = dynamic_cast<Pane *>(sender());
Chris@312 635 emit dropAccepted(pane, uriList);
Chris@312 636 }
Chris@312 637
Chris@312 638 void
Chris@312 639 PaneStack::paneDropAccepted(QString text)
Chris@312 640 {
Chris@312 641 Pane *pane = dynamic_cast<Pane *>(sender());
Chris@312 642 emit dropAccepted(pane, text);
Chris@312 643 }
Chris@127 644
Chris@320 645 void
Chris@323 646 PaneStack::paneDeleteButtonClicked()
Chris@323 647 {
Chris@323 648 QObject *s = sender();
Chris@806 649 for (int i = 0; i < (int)m_panes.size(); ++i) {
Chris@1266 650 if (m_panes[i].xButton == s) {
Chris@605 651 emit paneDeleteButtonClicked(m_panes[i].pane);
Chris@323 652 }
Chris@323 653 }
Chris@323 654 }
Chris@323 655
Chris@323 656 void
Chris@500 657 PaneStack::indicatorClicked()
Chris@500 658 {
Chris@500 659 QObject *s = sender();
Chris@500 660
Chris@806 661 for (int i = 0; i < (int)m_panes.size(); ++i) {
Chris@1266 662 if (m_panes[i].currentIndicator == s) {
Chris@500 663 setCurrentPane(m_panes[i].pane);
Chris@500 664 return;
Chris@500 665 }
Chris@500 666 }
Chris@500 667 }
Chris@500 668
Chris@500 669 void
Chris@320 670 PaneStack::sizePanesEqually()
Chris@320 671 {
Chris@1447 672 if (m_resizeMode == AutoResizeOnly) {
Chris@1447 673 return;
Chris@1447 674 }
Chris@1447 675
Chris@320 676 QList<int> sizes = m_splitter->sizes();
Chris@320 677 if (sizes.empty()) return;
Chris@320 678
Chris@320 679 int count = sizes.size();
Chris@320 680
Chris@687 681 int fixed = 0, variable = 0, total = 0;
Chris@687 682 int varicount = 0;
Chris@687 683
Chris@320 684 for (int i = 0; i < count; ++i) {
Chris@320 685 total += sizes[i];
Chris@320 686 }
Chris@320 687
Chris@687 688 variable = total;
Chris@687 689
Chris@687 690 for (int i = 0; i < count; ++i) {
Chris@687 691 int minh = m_panes[i].pane->minimumSize().height();
Chris@687 692 if (minh == m_panes[i].pane->maximumSize().height()) {
Chris@687 693 fixed += minh;
Chris@687 694 variable -= minh;
Chris@687 695 } else {
Chris@687 696 varicount++;
Chris@687 697 }
Chris@687 698 }
Chris@687 699
Chris@320 700 if (total == 0) return;
Chris@320 701
Chris@320 702 sizes.clear();
Chris@320 703
Chris@687 704 int each = (varicount > 0 ? (variable / varicount) : 0);
Chris@320 705 int remaining = total;
Chris@320 706
Chris@320 707 for (int i = 0; i < count; ++i) {
Chris@320 708 if (i == count - 1) {
Chris@320 709 sizes.push_back(remaining);
Chris@320 710 } else {
Chris@687 711 int minh = m_panes[i].pane->minimumSize().height();
Chris@687 712 if (minh == m_panes[i].pane->maximumSize().height()) {
Chris@687 713 sizes.push_back(minh);
Chris@687 714 remaining -= minh;
Chris@687 715 } else {
Chris@687 716 sizes.push_back(each);
Chris@687 717 remaining -= each;
Chris@687 718 }
Chris@320 719 }
Chris@320 720 }
Chris@320 721
Chris@320 722 /*
Chris@682 723 cerr << "sizes: ";
Chris@320 724 for (int i = 0; i < sizes.size(); ++i) {
Chris@682 725 cerr << sizes[i] << " ";
Chris@320 726 }
Chris@682 727 cerr << endl;
Chris@320 728 */
Chris@320 729
Chris@320 730 m_splitter->setSizes(sizes);
Chris@320 731 }
Chris@320 732
Chris@1447 733 void
Chris@1447 734 PaneStack::setResizeMode(ResizeMode mode)
Chris@1447 735 {
Chris@1447 736 if (mode == UserResizeable) {
Chris@1447 737 m_autoResizeStack->hide();
Chris@1447 738 m_splitter->show();
Chris@1447 739 } else {
Chris@1447 740 m_autoResizeStack->show();
Chris@1447 741 m_splitter->hide();
Chris@1447 742 }
Chris@1447 743 m_resizeMode = mode;
Chris@1447 744
Chris@1447 745 // we don't actually move any existing panes yet! let's do that
Chris@1447 746 // only if we turn out to need it, shall we?
Chris@1447 747 }
Chris@1447 748