annotate view/PaneStack.cpp @ 1534:bfd8b22fd67c

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