Chris@127: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@127: Chris@127: /* Chris@127: Sonic Visualiser Chris@127: An audio file viewer and annotation editor. Chris@127: Centre for Digital Music, Queen Mary, University of London. Chris@182: This file copyright 2006 Chris Cannam and QMUL. Chris@127: Chris@127: This program is free software; you can redistribute it and/or Chris@127: modify it under the terms of the GNU General Public License as Chris@127: published by the Free Software Foundation; either version 2 of the Chris@127: License, or (at your option) any later version. See the file Chris@127: COPYING included with this distribution for more information. Chris@127: */ Chris@127: Chris@127: #include "PaneStack.h" Chris@127: Chris@128: #include "Pane.h" Chris@127: #include "widgets/PropertyStack.h" Chris@323: #include "widgets/IconLoader.h" Chris@500: #include "widgets/ClickableLabel.h" Chris@128: #include "layer/Layer.h" Chris@128: #include "ViewManager.h" Chris@867: #include "AlignmentView.h" Chris@127: Chris@127: #include Chris@127: #include Chris@323: #include Chris@127: #include Chris@127: #include Chris@127: #include Chris@323: #include Chris@127: #include Chris@127: #include Chris@1606: #include Chris@127: Chris@127: #include Chris@127: Chris@247: //#define DEBUG_PANE_STACK 1 Chris@247: Chris@1526: PaneStack::PaneStack(QWidget *parent, Chris@1526: ViewManager *viewManager, Chris@1526: int options) : Chris@127: QFrame(parent), Chris@1408: m_currentPane(nullptr), Chris@1526: m_options(options), Chris@1526: m_splitter(nullptr), Chris@1526: m_autoResizeStack(nullptr), Chris@127: m_propertyStackStack(new QStackedWidget), Chris@127: m_viewManager(viewManager), Chris@615: m_propertyStackMinWidth(100), Chris@1526: m_layoutStyle(PropertyStackPerPaneLayout) Chris@127: { Chris@127: QHBoxLayout *layout = new QHBoxLayout; Chris@127: layout->setMargin(0); Chris@127: layout->setSpacing(0); Chris@127: Chris@1526: if (m_options & int(Option::NoUserResize)) { Chris@1447: Chris@1526: m_autoResizeStack = new QWidget; Chris@1526: m_autoResizeLayout = new QVBoxLayout; Chris@1526: m_autoResizeLayout->setMargin(0); Chris@1526: m_autoResizeLayout->setSpacing(0); Chris@1526: m_autoResizeStack->setLayout(m_autoResizeLayout); Chris@1526: layout->addWidget(m_autoResizeStack); Chris@1526: layout->setStretchFactor(m_autoResizeStack, 1); Chris@1526: Chris@1526: } else { Chris@1526: Chris@1526: m_splitter = new QSplitter; Chris@1526: m_splitter->setOrientation(Qt::Vertical); Chris@1526: m_splitter->setOpaqueResize(false); Chris@1526: layout->addWidget(m_splitter); Chris@1526: layout->setStretchFactor(m_splitter, 1); Chris@1526: } Chris@1526: Chris@1526: if (m_options & int(Option::NoPropertyStacks)) { Chris@1526: m_layoutStyle = HiddenPropertyStacksLayout; Chris@1526: } Chris@1447: Chris@1447: m_propertyStackStack->hide(); Chris@127: layout->addWidget(m_propertyStackStack); Chris@127: Chris@127: setLayout(layout); Chris@127: } Chris@127: Chris@127: Pane * Chris@1526: PaneStack::addPane() Chris@127: { Chris@127: QFrame *frame = new QFrame; Chris@495: Chris@495: QGridLayout *layout = new QGridLayout; Chris@127: layout->setMargin(0); Chris@1447: layout->setHorizontalSpacing(m_viewManager->scalePixelSize(2)); Chris@1530: Chris@1530: AlignmentView *av = nullptr; Chris@1530: Chris@1526: if (m_options & int(Option::ShowAlignmentViews)) { Chris@1447: layout->setVerticalSpacing(0); Chris@1530: av = new AlignmentView(frame); Chris@1530: av->setFixedHeight(ViewManager::scalePixelSize(20)); Chris@1530: av->setViewManager(m_viewManager); Chris@1530: av->setVisible(false); // for now Chris@1530: layout->addWidget(av, 0, 1); Chris@1447: } else { Chris@1447: layout->setVerticalSpacing(m_viewManager->scalePixelSize(2)); Chris@1447: } Chris@1447: Chris@323: QPushButton *xButton = new QPushButton(frame); Chris@323: xButton->setIcon(IconLoader().load("cross")); Chris@323: xButton->setFixedSize(QSize(16, 16)); Chris@497: xButton->setFlat(true); Chris@1526: xButton->setVisible(!(m_options & int(Option::NoPaneAccessories))); Chris@1526: if (m_panes.empty() && (m_options & int(Option::NoCloseOnFirstPane))) { Chris@1460: xButton->setVisible(false); Chris@1460: } Chris@1447: layout->addWidget(xButton, 1, 0); Chris@323: connect(xButton, SIGNAL(clicked()), this, SLOT(paneDeleteButtonClicked())); Chris@323: Chris@500: ClickableLabel *currentIndicator = new ClickableLabel(frame); Chris@500: connect(currentIndicator, SIGNAL(clicked()), this, SLOT(indicatorClicked())); Chris@1447: layout->addWidget(currentIndicator, 2, 0); Chris@1462: layout->setRowStretch(2, 20); Chris@1460: currentIndicator->setMinimumWidth(16); Chris@1460: currentIndicator->setMinimumHeight(16); Chris@127: currentIndicator->setScaledContents(true); Chris@1526: currentIndicator->setVisible(!(m_options & int(Option::NoPaneAccessories))); Chris@127: Chris@908: sv_frame_t initialCentreFrame = -1; Chris@855: if (!m_panes.empty()) { Chris@855: initialCentreFrame = m_panes[0].pane->getCentreFrame(); Chris@516: } Chris@516: Chris@127: Pane *pane = new Pane(frame); Chris@516: if (initialCentreFrame >= 0) { Chris@516: pane->setViewManager(m_viewManager, initialCentreFrame); Chris@516: } else { Chris@516: pane->setViewManager(m_viewManager); Chris@516: } Chris@1447: layout->addWidget(pane, 1, 1, 2, 1); Chris@495: layout->setColumnStretch(1, 20); Chris@127: Chris@1408: QWidget *properties = nullptr; Chris@1526: if (m_options & int(Option::NoPropertyStacks)) { Chris@1266: properties = new QFrame(); Chris@127: } else { Chris@1266: properties = new PropertyStack(frame, pane); Chris@1266: connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), Chris@1266: this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); Chris@1582: connect(properties, SIGNAL(propertyContainerContextMenuRequested(View *, PropertyContainer *, QPoint)), Chris@1582: this, SLOT(propertyContainerContextMenuRequested(View *, PropertyContainer *, QPoint))); Chris@190: connect(properties, SIGNAL(viewSelected(View *)), Chris@190: this, SLOT(viewSelected(View *))); Chris@189: connect(properties, SIGNAL(contextHelpChanged(const QString &)), Chris@189: this, SIGNAL(contextHelpChanged(const QString &))); Chris@127: } Chris@127: if (m_layoutStyle == PropertyStackPerPaneLayout) { Chris@1447: layout->addWidget(properties, 1, 2, 2, 1); Chris@127: } else { Chris@127: properties->setParent(m_propertyStackStack); Chris@127: m_propertyStackStack->addWidget(properties); Chris@127: } Chris@606: layout->setColumnStretch(2, 0); Chris@127: Chris@127: PaneRec rec; Chris@127: rec.pane = pane; Chris@127: rec.propertyStack = properties; Chris@605: rec.xButton = xButton; Chris@127: rec.currentIndicator = currentIndicator; Chris@127: rec.frame = frame; Chris@127: rec.layout = layout; Chris@867: rec.alignmentView = av; Chris@127: m_panes.push_back(rec); Chris@127: Chris@127: frame->setLayout(layout); Chris@1447: Chris@1526: if (m_options & int(Option::NoUserResize)) { Chris@1447: m_autoResizeLayout->addWidget(frame); Chris@1447: frame->adjustSize(); Chris@1526: } else { Chris@1526: m_splitter->addWidget(frame); Chris@1447: } Chris@127: Chris@127: connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)), Chris@1266: this, SLOT(propertyContainerAdded(PropertyContainer *))); Chris@127: connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)), Chris@1266: this, SLOT(propertyContainerRemoved(PropertyContainer *))); Chris@127: connect(pane, SIGNAL(paneInteractedWith()), Chris@1266: this, SLOT(paneInteractedWith())); Chris@127: connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)), Chris@127: this, SLOT(rightButtonMenuRequested(QPoint))); Chris@312: connect(pane, SIGNAL(dropAccepted(QStringList)), Chris@312: this, SLOT(paneDropAccepted(QStringList))); Chris@312: connect(pane, SIGNAL(dropAccepted(QString)), Chris@312: this, SLOT(paneDropAccepted(QString))); Chris@908: connect(pane, SIGNAL(doubleClickSelectInvoked(sv_frame_t)), Chris@908: this, SIGNAL(doubleClickSelectInvoked(sv_frame_t))); Chris@127: Chris@271: emit paneAdded(pane); Chris@271: emit paneAdded(); Chris@271: Chris@127: if (!m_currentPane) { Chris@1266: setCurrentPane(pane); Chris@127: } Chris@127: Chris@605: showOrHidePaneAccessories(); Chris@867: relinkAlignmentViews(); Chris@605: Chris@127: return pane; Chris@127: } Chris@127: Chris@127: void Chris@867: PaneStack::relinkAlignmentViews() Chris@867: { Chris@1447: if (m_panes.empty()) return; Chris@1530: auto av = m_panes[0].alignmentView; Chris@1530: if (av) av->hide(); Chris@1447: for (int i = 1; in_range_for(m_panes, i); ++i) { Chris@1530: av = m_panes[i].alignmentView; Chris@1530: if (!av) continue; Chris@1526: if (!(m_options & int(Option::ShowAlignmentViews))) { Chris@1530: av->hide(); Chris@1526: } else { Chris@1615: av->setAboveView(m_panes[i-1].pane); Chris@1615: av->setBelowView(m_panes[i].pane); Chris@1615: av->setReferenceView(m_panes[0].pane); Chris@1530: av->show(); Chris@1526: } Chris@867: } Chris@1606: Chris@1606: adjustAlignmentViewHeights(size().height()); Chris@867: } Chris@867: Chris@867: void Chris@867: PaneStack::unlinkAlignmentViews() Chris@867: { Chris@1447: for (int i = 0; in_range_for(m_panes, i); ++i) { Chris@1530: auto av = m_panes[i].alignmentView; Chris@1530: if (!av) continue; Chris@1615: av->setAboveView(nullptr); Chris@1615: av->setBelowView(nullptr); Chris@1615: av->setReferenceView(nullptr); Chris@867: } Chris@867: } Chris@867: Chris@867: void Chris@1606: PaneStack::resizeEvent(QResizeEvent *ev) Chris@1606: { Chris@1606: adjustAlignmentViewHeights(ev->size().height()); Chris@1606: } Chris@1606: Chris@1606: void Chris@1606: PaneStack::adjustAlignmentViewHeights(int forMyHeight) Chris@1606: { Chris@1606: if (!(m_options & int(Option::ShowAlignmentViews))) return; Chris@1606: if (!(m_options & int(Option::NoUserResize))) return; Chris@1606: if (!isVisible()) return; Chris@1614: if (m_panes.empty()) return; Chris@1606: Chris@1606: int heightPerPane = forMyHeight / int(m_panes.size()); Chris@1606: Chris@1606: SVCERR << "heightPerPane = " << heightPerPane << " (" Chris@1606: << forMyHeight << "/" << m_panes.size() << ")" << endl; Chris@1606: Chris@1606: int roomForAlignmentView = heightPerPane / 4; Chris@1606: int min = ViewManager::scalePixelSize(6); Chris@1606: int max = ViewManager::scalePixelSize(25); Chris@1606: int alignmentHeight = roomForAlignmentView; Chris@1606: if (alignmentHeight < min) { Chris@1606: alignmentHeight = min; Chris@1606: } Chris@1606: if (alignmentHeight > max) { Chris@1606: alignmentHeight = max; Chris@1606: } Chris@1606: Chris@1606: SVCERR << "alignmentHeight = " << alignmentHeight << endl; Chris@1606: Chris@1606: for (int i = 0; in_range_for(m_panes, i); ++i) { Chris@1606: auto av = m_panes[i].alignmentView; Chris@1606: if (!av) continue; Chris@1606: av->setFixedHeight(alignmentHeight); Chris@1606: } Chris@1606: } Chris@1606: Chris@1606: void Chris@235: PaneStack::setPropertyStackMinWidth(int mw) Chris@235: { Chris@235: for (std::vector::iterator i = m_panes.begin(); Chris@235: i != m_panes.end(); ++i) { Chris@235: i->propertyStack->setMinimumWidth(mw); Chris@235: } Chris@235: m_propertyStackMinWidth = mw; Chris@235: } Chris@235: Chris@235: void Chris@127: PaneStack::setLayoutStyle(LayoutStyle style) Chris@127: { Chris@1526: if (m_options & int(Option::NoPropertyStacks)) { Chris@1526: SVCERR << "NOTE: PaneStack::setLayoutStyle called on PaneStack with NoPropertyStacks option set - this does nothing, its style is always equivalent to HiddenPropertyStacksLayout" << endl; Chris@1526: return; Chris@1526: } Chris@1526: Chris@127: if (style == m_layoutStyle) return; Chris@127: m_layoutStyle = style; Chris@127: Chris@127: std::vector::iterator i; Chris@127: Chris@127: switch (style) { Chris@127: Chris@1526: case HiddenPropertyStacksLayout: Chris@127: case SinglePropertyStackLayout: Chris@127: Chris@127: for (i = m_panes.begin(); i != m_panes.end(); ++i) { Chris@127: i->layout->removeWidget(i->propertyStack); Chris@127: i->propertyStack->setParent(m_propertyStackStack); Chris@127: m_propertyStackStack->addWidget(i->propertyStack); Chris@127: } Chris@1526: m_propertyStackStack->setVisible(style != HiddenPropertyStacksLayout); Chris@127: break; Chris@127: Chris@127: case PropertyStackPerPaneLayout: Chris@127: Chris@127: for (i = m_panes.begin(); i != m_panes.end(); ++i) { Chris@127: m_propertyStackStack->removeWidget(i->propertyStack); Chris@127: i->propertyStack->setParent(i->frame); Chris@1529: i->layout->addWidget(i->propertyStack, 1, 2, 2, 1); Chris@127: i->propertyStack->show(); Chris@127: } Chris@127: m_propertyStackStack->hide(); Chris@127: break; Chris@127: } Chris@127: } Chris@127: Chris@127: Pane * Chris@127: PaneStack::getPane(int n) Chris@127: { Chris@806: if (n < (int)m_panes.size()) { Chris@277: return m_panes[n].pane; Chris@277: } else { Chris@1408: return nullptr; Chris@277: } Chris@277: } Chris@277: Chris@277: int Chris@277: PaneStack::getPaneIndex(Pane *pane) Chris@277: { Chris@277: for (int i = 0; i < getPaneCount(); ++i) { Chris@277: if (pane == getPane(i)) { Chris@277: return i; Chris@277: } Chris@277: } Chris@277: return -1; Chris@127: } Chris@127: Chris@127: Pane * Chris@127: PaneStack::getHiddenPane(int n) Chris@127: { Chris@127: return m_hiddenPanes[n].pane; Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::deletePane(Pane *pane) Chris@127: { Chris@1362: #ifdef DEBUG_PANE_STACK Chris@1362: SVCERR << "PaneStack::deletePane(" << pane << ")" << endl; Chris@1362: #endif Chris@729: Chris@127: std::vector::iterator i; Chris@127: bool found = false; Chris@127: Chris@1408: QWidget *stack = nullptr; Chris@729: Chris@127: for (i = m_panes.begin(); i != m_panes.end(); ++i) { Chris@1266: if (i->pane == pane) { Chris@729: stack = i->propertyStack; Chris@1266: m_panes.erase(i); Chris@1266: found = true; Chris@1266: break; Chris@1266: } Chris@127: } Chris@127: Chris@127: if (!found) { Chris@127: Chris@1266: for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) { Chris@1266: if (i->pane == pane) { Chris@729: stack = i->propertyStack; Chris@1266: m_hiddenPanes.erase(i); Chris@1266: found = true; Chris@1266: break; Chris@1266: } Chris@1266: } Chris@127: Chris@1266: if (!found) { Chris@1266: cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << endl; Chris@1266: return; Chris@1266: } Chris@127: } Chris@127: Chris@271: emit paneAboutToBeDeleted(pane); Chris@867: unlinkAlignmentViews(); Chris@271: Chris@1362: #ifdef DEBUG_PANE_STACK Chris@1362: SVCERR << "PaneStack::deletePane: about to delete parent " << pane->parent() << " of pane " << pane << endl; Chris@1362: #endif Chris@729: Chris@729: // The property stack associated with the parent was initially Chris@729: // created with the same parent as it, so it would be deleted when Chris@729: // we delete the pane's parent in a moment -- but it may have been Chris@729: // reparented depending on the layout. We'd better delete it Chris@729: // separately first. (This fixes a crash on opening a new layer Chris@729: // with a new unit type in it, when a long-defunct property box Chris@729: // could be signalled from the unit database to tell it that a new Chris@729: // unit had appeared.) Chris@729: delete stack; Chris@729: Chris@127: delete pane->parent(); Chris@127: Chris@127: if (m_currentPane == pane) { Chris@1266: if (m_panes.size() > 0) { Chris@127: setCurrentPane(m_panes[0].pane); Chris@1266: } else { Chris@1408: setCurrentPane(nullptr); Chris@1266: } Chris@127: } Chris@271: Chris@605: showOrHidePaneAccessories(); Chris@867: relinkAlignmentViews(); Chris@605: Chris@271: emit paneDeleted(); Chris@127: } Chris@127: Chris@605: void Chris@605: PaneStack::showOrHidePaneAccessories() Chris@605: { Chris@1362: #ifdef DEBUG_PANE_STACK Chris@1362: SVCERR << "PaneStack::showOrHidePaneAccessories: count == " << getPaneCount() << endl; Chris@1362: #endif Chris@605: Chris@605: bool multi = (getPaneCount() > 1); Chris@605: for (std::vector::iterator i = m_panes.begin(); Chris@605: i != m_panes.end(); ++i) { Chris@1526: bool visible = (multi && !(m_options & int(Option::NoPaneAccessories))); Chris@1460: bool xvisible = visible; Chris@1460: if (i == m_panes.begin()) { Chris@1526: if (m_options & int(Option::NoCloseOnFirstPane)) { Chris@1460: xvisible = false; Chris@1460: } Chris@1460: } Chris@1460: i->xButton->setVisible(xvisible); Chris@1460: i->currentIndicator->setVisible(visible); Chris@605: } Chris@605: } Chris@605: Chris@127: int Chris@127: PaneStack::getPaneCount() const Chris@127: { Chris@908: return int(m_panes.size()); Chris@127: } Chris@127: Chris@127: int Chris@127: PaneStack::getHiddenPaneCount() const Chris@127: { Chris@908: return int(m_hiddenPanes.size()); Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::hidePane(Pane *pane) Chris@127: { Chris@127: std::vector::iterator i = m_panes.begin(); Chris@127: Chris@127: while (i != m_panes.end()) { Chris@1266: if (i->pane == pane) { Chris@127: Chris@1266: m_hiddenPanes.push_back(*i); Chris@1266: m_panes.erase(i); Chris@127: Chris@1266: QWidget *pw = dynamic_cast(pane->parent()); Chris@1266: if (pw) pw->hide(); Chris@127: Chris@1266: if (m_currentPane == pane) { Chris@1266: if (m_panes.size() > 0) { Chris@1266: setCurrentPane(m_panes[0].pane); Chris@1266: } else { Chris@1408: setCurrentPane(nullptr); Chris@1266: } Chris@1266: } Chris@1266: Chris@605: showOrHidePaneAccessories(); Chris@605: emit paneHidden(pane); Chris@605: emit paneHidden(); cannam@1444: relinkAlignmentViews(); Chris@1266: return; Chris@1266: } Chris@1266: ++i; Chris@127: } Chris@127: Chris@1362: SVCERR << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << endl; Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::showPane(Pane *pane) Chris@127: { Chris@127: std::vector::iterator i = m_hiddenPanes.begin(); Chris@127: Chris@127: while (i != m_hiddenPanes.end()) { Chris@1266: if (i->pane == pane) { Chris@1266: m_panes.push_back(*i); Chris@1266: m_hiddenPanes.erase(i); Chris@1266: QWidget *pw = dynamic_cast(pane->parent()); Chris@1266: if (pw) pw->show(); Chris@127: Chris@1266: //!!! update current pane Chris@127: Chris@605: showOrHidePaneAccessories(); cannam@1444: relinkAlignmentViews(); Chris@605: Chris@1266: return; Chris@1266: } Chris@1266: ++i; Chris@127: } Chris@127: Chris@1362: SVCERR << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << endl; Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::setCurrentPane(Pane *pane) // may be null Chris@127: { Chris@127: if (m_currentPane == pane) return; Chris@127: Chris@127: std::vector::iterator i = m_panes.begin(); Chris@127: Chris@127: // We used to do this by setting the foreground and background Chris@127: // role, but it seems the background role is ignored and the Chris@127: // background drawn transparent in Qt 4.1 -- I can't quite see why Chris@127: Chris@127: QPixmap selectedMap(1, 1); Chris@127: selectedMap.fill(QApplication::palette().color(QPalette::Foreground)); Chris@127: Chris@127: QPixmap unselectedMap(1, 1); Chris@127: unselectedMap.fill(QApplication::palette().color(QPalette::Background)); Chris@127: Chris@127: bool found = false; Chris@127: Chris@127: while (i != m_panes.end()) { Chris@1266: if (i->pane == pane) { Chris@1266: i->currentIndicator->setPixmap(selectedMap); Chris@179: if (m_layoutStyle != PropertyStackPerPaneLayout) { Chris@127: m_propertyStackStack->setCurrentWidget(i->propertyStack); Chris@127: } Chris@1266: found = true; Chris@1266: } else { Chris@1266: i->currentIndicator->setPixmap(unselectedMap); Chris@1266: } Chris@1266: ++i; Chris@127: } Chris@127: Chris@1408: if (found || pane == nullptr) { Chris@1266: m_currentPane = pane; Chris@1266: emit currentPaneChanged(m_currentPane); Chris@127: } else { Chris@1362: SVCERR << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << endl; Chris@127: } Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null Chris@127: { Chris@127: setCurrentPane(pane); Chris@127: Chris@127: if (m_currentPane) { Chris@127: Chris@1266: std::vector::iterator i = m_panes.begin(); Chris@127: Chris@1266: while (i != m_panes.end()) { Chris@127: Chris@1266: if (i->pane == pane) { Chris@1266: PropertyStack *stack = dynamic_cast Chris@1266: (i->propertyStack); Chris@1266: if (stack) { Chris@1266: if (stack->containsContainer(layer)) { Chris@1266: stack->setCurrentIndex(stack->getContainerIndex(layer)); Chris@1266: emit currentLayerChanged(pane, layer); Chris@1266: } else { Chris@1266: stack->setCurrentIndex Chris@1266: (stack->getContainerIndex Chris@1266: (pane->getPropertyContainer(0))); Chris@1408: emit currentLayerChanged(pane, nullptr); Chris@1266: } Chris@1266: } Chris@1266: break; Chris@1266: } Chris@1266: ++i; Chris@1266: } Chris@127: } Chris@127: } Chris@127: Chris@127: Pane * Chris@127: PaneStack::getCurrentPane() Chris@127: { Chris@127: return m_currentPane; Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::propertyContainerAdded(PropertyContainer *) Chris@127: { Chris@127: sizePropertyStacks(); Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::propertyContainerRemoved(PropertyContainer *) Chris@127: { Chris@127: sizePropertyStacks(); Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc) Chris@127: { Chris@127: std::vector::iterator i = m_panes.begin(); Chris@127: Chris@127: while (i != m_panes.end()) { Chris@1266: PropertyStack *stack = dynamic_cast(i->propertyStack); Chris@1266: if (stack && Chris@1266: stack->getClient() == client && Chris@1266: stack->containsContainer(pc)) { Chris@1266: setCurrentPane(i->pane); Chris@1266: break; Chris@1266: } Chris@1266: ++i; Chris@127: } Chris@127: Chris@127: Layer *layer = dynamic_cast(pc); Chris@127: if (layer) emit currentLayerChanged(m_currentPane, layer); Chris@1408: else emit currentLayerChanged(m_currentPane, nullptr); Chris@127: } Chris@127: Chris@127: void Chris@1582: PaneStack::propertyContainerContextMenuRequested(View *client, Chris@1582: PropertyContainer *pc, Chris@1582: QPoint pos) Chris@1582: { Chris@1582: Pane *pane = dynamic_cast(client); Chris@1582: Layer *layer = dynamic_cast(pc); Chris@1582: Chris@1582: if (pane) { Chris@1582: if (layer) { Chris@1582: emit layerPropertiesRightButtonMenuRequested(pane, layer, pos); Chris@1582: } else { Chris@1582: emit panePropertiesRightButtonMenuRequested(pane, pos); Chris@1582: } Chris@1582: } Chris@1582: } Chris@1582: Chris@1582: void Chris@190: PaneStack::viewSelected(View *v) Chris@190: { Chris@190: Pane *p = dynamic_cast(v); Chris@190: if (p) setCurrentPane(p); Chris@190: } Chris@190: Chris@190: void Chris@127: PaneStack::paneInteractedWith() Chris@127: { Chris@127: Pane *pane = dynamic_cast(sender()); Chris@127: if (!pane) return; Chris@127: setCurrentPane(pane); Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::rightButtonMenuRequested(QPoint position) Chris@127: { Chris@127: Pane *pane = dynamic_cast(sender()); Chris@127: if (!pane) return; Chris@1582: emit paneRightButtonMenuRequested(pane, position); Chris@127: } Chris@127: Chris@127: void Chris@127: PaneStack::sizePropertyStacks() Chris@127: { Chris@127: int maxMinWidth = 0; Chris@127: Chris@235: if (m_propertyStackMinWidth > 0) maxMinWidth = m_propertyStackMinWidth; Chris@235: Chris@806: for (int i = 0; i < (int)m_panes.size(); ++i) { Chris@1266: if (!m_panes[i].propertyStack) continue; Chris@247: #ifdef DEBUG_PANE_STACK Chris@1266: SVDEBUG << "PaneStack::sizePropertyStacks: " << i << ": min " Chris@1266: << m_panes[i].propertyStack->minimumSizeHint().width() << ", hint " Chris@243: << m_panes[i].propertyStack->sizeHint().width() << ", current " Chris@1266: << m_panes[i].propertyStack->width() << endl; Chris@247: #endif Chris@127: Chris@1266: if (m_panes[i].propertyStack->sizeHint().width() > maxMinWidth) { Chris@1266: maxMinWidth = m_panes[i].propertyStack->sizeHint().width(); Chris@1266: } Chris@127: } Chris@127: Chris@247: #ifdef DEBUG_PANE_STACK Chris@587: SVDEBUG << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << endl; Chris@247: #endif Chris@127: Chris@127: int setWidth = maxMinWidth; Chris@127: Chris@127: m_propertyStackStack->setMaximumWidth(setWidth + 10); Chris@127: Chris@806: for (int i = 0; i < (int)m_panes.size(); ++i) { Chris@1266: if (!m_panes[i].propertyStack) continue; Chris@1266: m_panes[i].propertyStack->setMinimumWidth(setWidth); Chris@127: } Chris@180: Chris@363: emit propertyStacksResized(setWidth); Chris@180: emit propertyStacksResized(); Chris@127: } Chris@127: Chris@312: void Chris@312: PaneStack::paneDropAccepted(QStringList uriList) Chris@312: { Chris@312: Pane *pane = dynamic_cast(sender()); Chris@312: emit dropAccepted(pane, uriList); Chris@312: } Chris@312: Chris@312: void Chris@312: PaneStack::paneDropAccepted(QString text) Chris@312: { Chris@312: Pane *pane = dynamic_cast(sender()); Chris@312: emit dropAccepted(pane, text); Chris@312: } Chris@127: Chris@320: void Chris@323: PaneStack::paneDeleteButtonClicked() Chris@323: { Chris@323: QObject *s = sender(); Chris@806: for (int i = 0; i < (int)m_panes.size(); ++i) { Chris@1266: if (m_panes[i].xButton == s) { Chris@605: emit paneDeleteButtonClicked(m_panes[i].pane); Chris@323: } Chris@323: } Chris@323: } Chris@323: Chris@323: void Chris@500: PaneStack::indicatorClicked() Chris@500: { Chris@500: QObject *s = sender(); Chris@500: Chris@806: for (int i = 0; i < (int)m_panes.size(); ++i) { Chris@1266: if (m_panes[i].currentIndicator == s) { Chris@500: setCurrentPane(m_panes[i].pane); Chris@500: return; Chris@500: } Chris@500: } Chris@500: } Chris@500: Chris@500: void Chris@320: PaneStack::sizePanesEqually() Chris@320: { Chris@1526: if (m_options & int(Option::NoUserResize)) { Chris@1447: return; Chris@1447: } Chris@1447: Chris@320: QList sizes = m_splitter->sizes(); Chris@320: if (sizes.empty()) return; Chris@320: Chris@320: int count = sizes.size(); Chris@320: Chris@687: int fixed = 0, variable = 0, total = 0; Chris@687: int varicount = 0; Chris@687: Chris@320: for (int i = 0; i < count; ++i) { Chris@320: total += sizes[i]; Chris@320: } Chris@320: Chris@687: variable = total; Chris@687: Chris@687: for (int i = 0; i < count; ++i) { Chris@687: int minh = m_panes[i].pane->minimumSize().height(); Chris@687: if (minh == m_panes[i].pane->maximumSize().height()) { Chris@687: fixed += minh; Chris@687: variable -= minh; Chris@687: } else { Chris@687: varicount++; Chris@687: } Chris@687: } Chris@687: Chris@320: if (total == 0) return; Chris@320: Chris@320: sizes.clear(); Chris@320: Chris@687: int each = (varicount > 0 ? (variable / varicount) : 0); Chris@320: int remaining = total; Chris@320: Chris@320: for (int i = 0; i < count; ++i) { Chris@320: if (i == count - 1) { Chris@320: sizes.push_back(remaining); Chris@320: } else { Chris@687: int minh = m_panes[i].pane->minimumSize().height(); Chris@687: if (minh == m_panes[i].pane->maximumSize().height()) { Chris@687: sizes.push_back(minh); Chris@687: remaining -= minh; Chris@687: } else { Chris@687: sizes.push_back(each); Chris@687: remaining -= each; Chris@687: } Chris@320: } Chris@320: } Chris@320: Chris@320: /* Chris@682: cerr << "sizes: "; Chris@320: for (int i = 0; i < sizes.size(); ++i) { Chris@682: cerr << sizes[i] << " "; Chris@320: } Chris@682: cerr << endl; Chris@320: */ Chris@320: Chris@320: m_splitter->setSizes(sizes); Chris@320: } Chris@320: