annotate view/PaneStack.cpp @ 1587:2108af725460

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