annotate view/PaneStack.cpp @ 1457:160e6d010141 single-point

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