annotate view/PaneStack.cpp @ 1509:8145a9c4c253

The default key frame map is not working well at the moment, because its extents are not being properly updated as the models they depend on are loaded. Leave it empty for now.
author Chris Cannam
date Tue, 17 Sep 2019 12:50:34 +0100
parents 6bd413aff85c
children 0f1601d870db
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@1460 44 m_showCloseButtonOnFirstPane(true),
Chris@867 45 m_showAlignmentViews(false),
Chris@127 46 m_splitter(new QSplitter),
Chris@1447 47 m_autoResizeStack(new QWidget),
Chris@127 48 m_propertyStackStack(new QStackedWidget),
Chris@127 49 m_viewManager(viewManager),
Chris@615 50 m_propertyStackMinWidth(100),
Chris@1447 51 m_layoutStyle(PropertyStackPerPaneLayout),
Chris@1447 52 m_resizeMode(UserResizeable)
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@1447 58 m_autoResizeLayout = new QVBoxLayout;
Chris@1454 59 m_autoResizeLayout->setMargin(0);
Chris@1447 60 m_autoResizeLayout->setSpacing(0);
Chris@1447 61 m_autoResizeStack->setLayout(m_autoResizeLayout);
Chris@1447 62 m_autoResizeStack->hide();
Chris@1447 63 layout->addWidget(m_autoResizeStack);
Chris@1447 64 layout->setStretchFactor(m_autoResizeStack, 1);
Chris@1447 65
Chris@127 66 m_splitter->setOrientation(Qt::Vertical);
Chris@127 67 m_splitter->setOpaqueResize(false);
Chris@1447 68 m_splitter->show();
Chris@127 69 layout->addWidget(m_splitter);
Chris@127 70 layout->setStretchFactor(m_splitter, 1);
Chris@1447 71
Chris@1447 72 m_propertyStackStack->hide();
Chris@127 73 layout->addWidget(m_propertyStackStack);
Chris@127 74
Chris@127 75 setLayout(layout);
Chris@127 76 }
Chris@127 77
Chris@712 78 void
Chris@712 79 PaneStack::setShowPaneAccessories(bool show)
Chris@712 80 {
Chris@712 81 m_showAccessories = show;
Chris@712 82 }
Chris@712 83
Chris@867 84 void
Chris@1460 85 PaneStack::setShowCloseButtonOnFirstPane(bool show)
Chris@1460 86 {
Chris@1460 87 m_showCloseButtonOnFirstPane = show;
Chris@1460 88 }
Chris@1460 89
Chris@1460 90 void
Chris@867 91 PaneStack::setShowAlignmentViews(bool show)
Chris@867 92 {
Chris@867 93 m_showAlignmentViews = show;
Chris@1447 94 // each alignment view shows alignment between the pane above and
Chris@1447 95 // the pane it is attached to: so pane 0 doesn't have a visible one
Chris@1447 96 for (int i = 1; in_range_for(m_panes, i); ++i) {
Chris@1447 97 m_panes[i].alignmentView->setVisible(m_showAlignmentViews);
Chris@867 98 }
Chris@867 99 }
Chris@867 100
Chris@127 101 Pane *
Chris@127 102 PaneStack::addPane(bool suppressPropertyBox)
Chris@127 103 {
Chris@127 104 QFrame *frame = new QFrame;
Chris@495 105
Chris@495 106 QGridLayout *layout = new QGridLayout;
Chris@127 107 layout->setMargin(0);
Chris@1447 108 layout->setHorizontalSpacing(m_viewManager->scalePixelSize(2));
Chris@1447 109 if (m_showAlignmentViews) {
Chris@1447 110 layout->setVerticalSpacing(0);
Chris@1447 111 } else {
Chris@1447 112 layout->setVerticalSpacing(m_viewManager->scalePixelSize(2));
Chris@1447 113 }
Chris@1447 114
Chris@1447 115 AlignmentView *av = new AlignmentView(frame);
Chris@1447 116 av->setFixedHeight(ViewManager::scalePixelSize(20));
Chris@1447 117 av->setViewManager(m_viewManager);
Chris@1447 118 av->setVisible(false); // for now
Chris@1447 119 layout->addWidget(av, 0, 1);
Chris@127 120
Chris@323 121 QPushButton *xButton = new QPushButton(frame);
Chris@323 122 xButton->setIcon(IconLoader().load("cross"));
Chris@323 123 xButton->setFixedSize(QSize(16, 16));
Chris@497 124 xButton->setFlat(true);
Chris@712 125 xButton->setVisible(m_showAccessories);
Chris@1460 126 if (m_panes.empty() && !m_showCloseButtonOnFirstPane) {
Chris@1460 127 xButton->setVisible(false);
Chris@1460 128 }
Chris@1447 129 layout->addWidget(xButton, 1, 0);
Chris@323 130 connect(xButton, SIGNAL(clicked()), this, SLOT(paneDeleteButtonClicked()));
Chris@323 131
Chris@500 132 ClickableLabel *currentIndicator = new ClickableLabel(frame);
Chris@500 133 connect(currentIndicator, SIGNAL(clicked()), this, SLOT(indicatorClicked()));
Chris@1447 134 layout->addWidget(currentIndicator, 2, 0);
Chris@1462 135 layout->setRowStretch(2, 20);
Chris@1460 136 currentIndicator->setMinimumWidth(16);
Chris@1460 137 currentIndicator->setMinimumHeight(16);
Chris@127 138 currentIndicator->setScaledContents(true);
Chris@712 139 currentIndicator->setVisible(m_showAccessories);
Chris@127 140
Chris@908 141 sv_frame_t initialCentreFrame = -1;
Chris@855 142 if (!m_panes.empty()) {
Chris@855 143 initialCentreFrame = m_panes[0].pane->getCentreFrame();
Chris@516 144 }
Chris@516 145
Chris@127 146 Pane *pane = new Pane(frame);
Chris@516 147 if (initialCentreFrame >= 0) {
Chris@516 148 pane->setViewManager(m_viewManager, initialCentreFrame);
Chris@516 149 } else {
Chris@516 150 pane->setViewManager(m_viewManager);
Chris@516 151 }
Chris@1447 152 layout->addWidget(pane, 1, 1, 2, 1);
Chris@495 153 layout->setColumnStretch(1, 20);
Chris@127 154
Chris@1408 155 QWidget *properties = nullptr;
Chris@127 156 if (suppressPropertyBox) {
Chris@1266 157 properties = new QFrame();
Chris@127 158 } else {
Chris@1266 159 properties = new PropertyStack(frame, pane);
Chris@1266 160 connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
Chris@1266 161 this, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
Chris@190 162 connect(properties, SIGNAL(viewSelected(View *)),
Chris@190 163 this, SLOT(viewSelected(View *)));
Chris@189 164 connect(properties, SIGNAL(contextHelpChanged(const QString &)),
Chris@189 165 this, SIGNAL(contextHelpChanged(const QString &)));
Chris@127 166 }
Chris@127 167 if (m_layoutStyle == PropertyStackPerPaneLayout) {
Chris@1447 168 layout->addWidget(properties, 1, 2, 2, 1);
Chris@127 169 } else {
Chris@127 170 properties->setParent(m_propertyStackStack);
Chris@127 171 m_propertyStackStack->addWidget(properties);
Chris@127 172 }
Chris@606 173 layout->setColumnStretch(2, 0);
Chris@127 174
Chris@127 175 PaneRec rec;
Chris@127 176 rec.pane = pane;
Chris@127 177 rec.propertyStack = properties;
Chris@605 178 rec.xButton = xButton;
Chris@127 179 rec.currentIndicator = currentIndicator;
Chris@127 180 rec.frame = frame;
Chris@127 181 rec.layout = layout;
Chris@867 182 rec.alignmentView = av;
Chris@127 183 m_panes.push_back(rec);
Chris@127 184
Chris@127 185 frame->setLayout(layout);
Chris@1447 186
Chris@1447 187 if (m_resizeMode == UserResizeable) {
Chris@1447 188 m_splitter->addWidget(frame);
Chris@1447 189 } else {
Chris@1447 190 m_autoResizeLayout->addWidget(frame);
Chris@1447 191 frame->adjustSize();
Chris@1447 192 }
Chris@127 193
Chris@127 194 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@1266 195 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@127 196 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@1266 197 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@127 198 connect(pane, SIGNAL(paneInteractedWith()),
Chris@1266 199 this, SLOT(paneInteractedWith()));
Chris@127 200 connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)),
Chris@127 201 this, SLOT(rightButtonMenuRequested(QPoint)));
Chris@312 202 connect(pane, SIGNAL(dropAccepted(QStringList)),
Chris@312 203 this, SLOT(paneDropAccepted(QStringList)));
Chris@312 204 connect(pane, SIGNAL(dropAccepted(QString)),
Chris@312 205 this, SLOT(paneDropAccepted(QString)));
Chris@908 206 connect(pane, SIGNAL(doubleClickSelectInvoked(sv_frame_t)),
Chris@908 207 this, SIGNAL(doubleClickSelectInvoked(sv_frame_t)));
Chris@127 208
Chris@271 209 emit paneAdded(pane);
Chris@271 210 emit paneAdded();
Chris@271 211
Chris@127 212 if (!m_currentPane) {
Chris@1266 213 setCurrentPane(pane);
Chris@127 214 }
Chris@127 215
Chris@605 216 showOrHidePaneAccessories();
Chris@867 217 relinkAlignmentViews();
Chris@605 218
Chris@127 219 return pane;
Chris@127 220 }
Chris@127 221
Chris@127 222 void
Chris@867 223 PaneStack::relinkAlignmentViews()
Chris@867 224 {
Chris@1447 225 if (m_panes.empty()) return;
Chris@1462 226 if (!m_showAlignmentViews) return;
Chris@1447 227 m_panes[0].alignmentView->hide();
Chris@1447 228 for (int i = 1; in_range_for(m_panes, i); ++i) {
Chris@1447 229 m_panes[i].alignmentView->setViewAbove(m_panes[i-1].pane);
Chris@1447 230 m_panes[i].alignmentView->setViewBelow(m_panes[i].pane);
Chris@1447 231 m_panes[i].alignmentView->setVisible(true);
Chris@867 232 }
Chris@867 233 }
Chris@867 234
Chris@867 235 void
Chris@867 236 PaneStack::unlinkAlignmentViews()
Chris@867 237 {
Chris@1447 238 for (int i = 0; in_range_for(m_panes, i); ++i) {
Chris@1408 239 m_panes[i].alignmentView->setViewAbove(nullptr);
Chris@1408 240 m_panes[i].alignmentView->setViewBelow(nullptr);
Chris@867 241 }
Chris@867 242 }
Chris@867 243
Chris@867 244 void
Chris@235 245 PaneStack::setPropertyStackMinWidth(int mw)
Chris@235 246 {
Chris@235 247 for (std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@235 248 i != m_panes.end(); ++i) {
Chris@235 249 i->propertyStack->setMinimumWidth(mw);
Chris@235 250 }
Chris@235 251 m_propertyStackMinWidth = mw;
Chris@235 252 }
Chris@235 253
Chris@235 254 void
Chris@127 255 PaneStack::setLayoutStyle(LayoutStyle style)
Chris@127 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@179 264 case NoPropertyStacks:
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@179 272 m_propertyStackStack->setVisible(style != NoPropertyStacks);
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@495 280 i->layout->addWidget(i->propertyStack, 0, 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@1460 396 bool visible = (multi && m_showAccessories);
Chris@1460 397 bool xvisible = visible;
Chris@1460 398 if (i == m_panes.begin()) {
Chris@1460 399 if (!m_showCloseButtonOnFirstPane) {
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@1447 692 if (m_resizeMode == AutoResizeOnly) {
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
Chris@1447 753 void
Chris@1447 754 PaneStack::setResizeMode(ResizeMode mode)
Chris@1447 755 {
Chris@1447 756 if (mode == UserResizeable) {
Chris@1447 757 m_autoResizeStack->hide();
Chris@1447 758 m_splitter->show();
Chris@1447 759 } else {
Chris@1447 760 m_autoResizeStack->show();
Chris@1447 761 m_splitter->hide();
Chris@1447 762 }
Chris@1447 763 m_resizeMode = mode;
Chris@1447 764
Chris@1447 765 // we don't actually move any existing panes yet! let's do that
Chris@1447 766 // only if we turn out to need it, shall we?
Chris@1447 767 }
Chris@1447 768