annotate view/PaneStack.cpp @ 1615:911330a28a7c

Where the "below" view represents only a subset of the "above" view, cut off the feature mappings at the outer edges of the "below" view - don't map everything outside this (it would all just map onto the same single points at beginning and end, which is excessive, confusing and not useful)
author Chris Cannam
date Thu, 02 Jul 2020 15:37:43 +0100
parents c6f5c822b10d
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