annotate view/PaneStack.cpp @ 1605:ae2d5f8ff005

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