annotate view/PaneStack.cpp @ 1617:cbbb411da977

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