lbajardsilogic@0: lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: This file copyright 2006 Chris Cannam and QMUL. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #include "PaneStack.h" lbajardsilogic@0: lbajardsilogic@0: #include "Pane.h" lbajardsilogic@0: #include "widgets/PropertyStack.h" lbajardsilogic@0: #include "layer/Layer.h" lbajardsilogic@0: #include "ViewManager.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include benoitrigolleau@102: #include lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: //#define DEBUG_PANE_STACK 1 lbajardsilogic@0: lbajardsilogic@0: PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) : lbajardsilogic@0: QFrame(parent), lbajardsilogic@0: m_currentPane(0), lbajardsilogic@0: m_splitter(new QSplitter), lbajardsilogic@0: m_propertyStackStack(new QStackedWidget), lbajardsilogic@204: m_viewManager(viewManager) lbajardsilogic@0: { lbajardsilogic@0: QHBoxLayout *layout = new QHBoxLayout; lbajardsilogic@0: layout->setMargin(0); lbajardsilogic@0: layout->setSpacing(0); lbajardsilogic@0: lbajardsilogic@0: m_splitter->setOrientation(Qt::Vertical); lbajardsilogic@0: m_splitter->setOpaqueResize(false); lbajardsilogic@0: lbajardsilogic@0: layout->addWidget(m_splitter); lbajardsilogic@0: layout->setStretchFactor(m_splitter, 1); lbajardsilogic@0: layout->addWidget(m_propertyStackStack); lbajardsilogic@0: m_propertyStackStack->hide(); lbajardsilogic@0: lbajardsilogic@0: setLayout(layout); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Pane * lbajardsilogic@0: PaneStack::addPane(bool suppressPropertyBox) lbajardsilogic@0: { lbajardsilogic@0: QFrame *frame = new QFrame; lbajardsilogic@0: QHBoxLayout *layout = new QHBoxLayout; lbajardsilogic@0: layout->setMargin(0); lbajardsilogic@0: layout->setSpacing(2); lbajardsilogic@0: lbajardsilogic@0: QLabel *currentIndicator = new QLabel(frame); lbajardsilogic@0: currentIndicator->setFixedWidth(QPainter(this).fontMetrics().width("x")); lbajardsilogic@0: layout->addWidget(currentIndicator); lbajardsilogic@0: layout->setStretchFactor(currentIndicator, 1); lbajardsilogic@0: currentIndicator->setScaledContents(true); lbajardsilogic@0: lbajardsilogic@0: Pane *pane = new Pane(frame); lbajardsilogic@0: pane->setViewManager(m_viewManager); lbajardsilogic@0: layout->addWidget(pane); lbajardsilogic@0: layout->setStretchFactor(pane, 10); lbajardsilogic@0: lbajardsilogic@0: PaneRec rec; lbajardsilogic@0: rec.pane = pane; lbajardsilogic@13: rec.propertyStack = 0; lbajardsilogic@0: rec.currentIndicator = currentIndicator; lbajardsilogic@0: rec.frame = frame; lbajardsilogic@0: rec.layout = layout; lbajardsilogic@0: m_panes.push_back(rec); lbajardsilogic@0: benoitrigolleau@102: //for the panel's border benoitrigolleau@102: frame->setFrameStyle(QFrame::Box | QFrame::Raised); benoitrigolleau@102: frame->setLineWidth(0); benoitrigolleau@102: benoitrigolleau@102: frame->setLayout(layout); lbajardsilogic@0: m_splitter->addWidget(frame); lbajardsilogic@0: lbajardsilogic@101: resizePane(); lbajardsilogic@101: lbajardsilogic@0: connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)), lbajardsilogic@0: this, SLOT(propertyContainerAdded(PropertyContainer *))); lbajardsilogic@0: connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)), lbajardsilogic@0: this, SLOT(propertyContainerRemoved(PropertyContainer *))); lbajardsilogic@0: connect(pane, SIGNAL(paneInteractedWith()), lbajardsilogic@0: this, SLOT(paneInteractedWith())); lbajardsilogic@0: connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)), lbajardsilogic@0: this, SLOT(rightButtonMenuRequested(QPoint))); lbajardsilogic@0: lbajardsilogic@0: if (!m_currentPane) { lbajardsilogic@0: setCurrentPane(pane); lbajardsilogic@0: } benoitrigolleau@66: emit newPaneAdded(pane); lbajardsilogic@0: return pane; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::setPropertyStackMinWidth(int mw) lbajardsilogic@0: { lbajardsilogic@0: for (std::vector::iterator i = m_panes.begin(); lbajardsilogic@0: i != m_panes.end(); ++i) { lbajardsilogic@0: i->propertyStack->setMinimumWidth(mw); lbajardsilogic@0: } lbajardsilogic@0: m_propertyStackMinWidth = mw; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Pane * lbajardsilogic@0: PaneStack::getPane(int n) lbajardsilogic@0: { lbajardsilogic@0: return m_panes[n].pane; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Pane * lbajardsilogic@0: PaneStack::getHiddenPane(int n) lbajardsilogic@0: { lbajardsilogic@0: return m_hiddenPanes[n].pane; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::deletePane(Pane *pane) lbajardsilogic@0: { lbajardsilogic@0: std::vector::iterator i; lbajardsilogic@0: bool found = false; lbajardsilogic@0: lbajardsilogic@0: for (i = m_panes.begin(); i != m_panes.end(); ++i) { lbajardsilogic@0: if (i->pane == pane) { lbajardsilogic@0: m_panes.erase(i); lbajardsilogic@0: found = true; lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!found) { lbajardsilogic@0: lbajardsilogic@0: for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) { lbajardsilogic@0: if (i->pane == pane) { lbajardsilogic@0: m_hiddenPanes.erase(i); lbajardsilogic@0: found = true; lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!found) { lbajardsilogic@0: std::cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: delete pane->parent(); lbajardsilogic@0: lbajardsilogic@0: if (m_currentPane == pane) { lbajardsilogic@0: if (m_panes.size() > 0) { lbajardsilogic@0: setCurrentPane(m_panes[0].pane); lbajardsilogic@0: } else { lbajardsilogic@0: setCurrentPane(0); lbajardsilogic@0: } lbajardsilogic@0: } benoitrigolleau@66: emit paneDeleted(pane); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: int lbajardsilogic@0: PaneStack::getPaneCount() const lbajardsilogic@0: { lbajardsilogic@0: return m_panes.size(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: int lbajardsilogic@0: PaneStack::getHiddenPaneCount() const lbajardsilogic@0: { lbajardsilogic@0: return m_hiddenPanes.size(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::hidePane(Pane *pane) lbajardsilogic@0: { lbajardsilogic@0: std::vector::iterator i = m_panes.begin(); lbajardsilogic@0: lbajardsilogic@0: while (i != m_panes.end()) { lbajardsilogic@0: if (i->pane == pane) { lbajardsilogic@0: lbajardsilogic@0: m_hiddenPanes.push_back(*i); lbajardsilogic@0: m_panes.erase(i); lbajardsilogic@0: lbajardsilogic@0: QWidget *pw = dynamic_cast(pane->parent()); lbajardsilogic@0: if (pw) pw->hide(); lbajardsilogic@0: lbajardsilogic@0: if (m_currentPane == pane) { lbajardsilogic@0: if (m_panes.size() > 0) { lbajardsilogic@0: setCurrentPane(m_panes[0].pane); lbajardsilogic@0: } else { lbajardsilogic@0: setCurrentPane(0); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: ++i; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: std::cerr << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::showPane(Pane *pane) lbajardsilogic@0: { lbajardsilogic@0: std::vector::iterator i = m_hiddenPanes.begin(); lbajardsilogic@0: lbajardsilogic@0: while (i != m_hiddenPanes.end()) { lbajardsilogic@0: if (i->pane == pane) { lbajardsilogic@0: m_panes.push_back(*i); lbajardsilogic@0: m_hiddenPanes.erase(i); lbajardsilogic@0: QWidget *pw = dynamic_cast(pane->parent()); lbajardsilogic@0: if (pw) pw->show(); lbajardsilogic@0: lbajardsilogic@0: //!!! update current pane lbajardsilogic@0: lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: ++i; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: std::cerr << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::setCurrentPane(Pane *pane) // may be null lbajardsilogic@0: { lbajardsilogic@0: if (m_currentPane == pane) return; lbajardsilogic@0: lbajardsilogic@0: std::vector::iterator i = m_panes.begin(); lbajardsilogic@0: lbajardsilogic@0: // We used to do this by setting the foreground and background lbajardsilogic@0: // role, but it seems the background role is ignored and the lbajardsilogic@0: // background drawn transparent in Qt 4.1 -- I can't quite see why lbajardsilogic@0: lbajardsilogic@0: QPixmap selectedMap(1, 1); lbajardsilogic@0: selectedMap.fill(QApplication::palette().color(QPalette::Foreground)); lbajardsilogic@0: lbajardsilogic@0: QPixmap unselectedMap(1, 1); lbajardsilogic@0: unselectedMap.fill(QApplication::palette().color(QPalette::Background)); lbajardsilogic@0: lbajardsilogic@0: bool found = false; lbajardsilogic@0: lbajardsilogic@0: while (i != m_panes.end()) { lbajardsilogic@0: if (i->pane == pane) { lbajardsilogic@0: i->currentIndicator->setPixmap(selectedMap); lbajardsilogic@204: m_propertyStackStack->setCurrentWidget(i->propertyStack); lbajardsilogic@204: found = true; benoitrigolleau@102: benoitrigolleau@102: QFrame* frame = (QFrame*) (i->pane->parentWidget()); benoitrigolleau@102: if(frame!=0){ benoitrigolleau@102: frame->setLineWidth(2); benoitrigolleau@102: } benoitrigolleau@102: lbajardsilogic@0: } else { lbajardsilogic@0: i->currentIndicator->setPixmap(unselectedMap); benoitrigolleau@102: QFrame* frame = (QFrame*) (i->pane->parentWidget()); benoitrigolleau@102: if(frame!=0){ benoitrigolleau@102: frame->setLineWidth(0); benoitrigolleau@102: } lbajardsilogic@0: } lbajardsilogic@0: ++i; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (found || pane == 0) { benoitrigolleau@102: m_currentPane = pane; benoitrigolleau@102: emit currentPaneChanged(m_currentPane); lbajardsilogic@0: } else { lbajardsilogic@0: std::cerr << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null lbajardsilogic@0: { lbajardsilogic@0: setCurrentPane(pane); lbajardsilogic@0: lbajardsilogic@0: if (m_currentPane) { lbajardsilogic@0: lbajardsilogic@0: std::vector::iterator i = m_panes.begin(); lbajardsilogic@0: lbajardsilogic@0: while (i != m_panes.end()) { lbajardsilogic@0: lbajardsilogic@0: if (i->pane == pane) { lbajardsilogic@0: PropertyStack *stack = dynamic_cast lbajardsilogic@0: (i->propertyStack); lbajardsilogic@0: if (stack) { lbajardsilogic@0: if (stack->containsContainer(layer)) { lbajardsilogic@0: stack->setCurrentIndex(stack->getContainerIndex(layer)); lbajardsilogic@0: emit currentLayerChanged(pane, layer); lbajardsilogic@0: } else { lbajardsilogic@0: stack->setCurrentIndex lbajardsilogic@0: (stack->getContainerIndex lbajardsilogic@0: (pane->getPropertyContainer(0))); lbajardsilogic@0: emit currentLayerChanged(pane, 0); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: ++i; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Pane * lbajardsilogic@0: PaneStack::getCurrentPane() lbajardsilogic@0: { lbajardsilogic@0: return m_currentPane; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::propertyContainerAdded(PropertyContainer *) lbajardsilogic@0: { lbajardsilogic@0: sizePropertyStacks(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::propertyContainerRemoved(PropertyContainer *) lbajardsilogic@0: { lbajardsilogic@0: sizePropertyStacks(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc) lbajardsilogic@0: { lbajardsilogic@0: std::vector::iterator i = m_panes.begin(); lbajardsilogic@0: lbajardsilogic@0: while (i != m_panes.end()) { lbajardsilogic@0: PropertyStack *stack = dynamic_cast(i->propertyStack); lbajardsilogic@0: if (stack && lbajardsilogic@0: stack->getClient() == client && lbajardsilogic@0: stack->containsContainer(pc)) { lbajardsilogic@0: setCurrentPane(i->pane); lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: ++i; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Layer *layer = dynamic_cast(pc); lbajardsilogic@0: if (layer) emit currentLayerChanged(m_currentPane, layer); lbajardsilogic@0: else emit currentLayerChanged(m_currentPane, 0); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::viewSelected(View *v) lbajardsilogic@0: { lbajardsilogic@0: Pane *p = dynamic_cast(v); lbajardsilogic@0: if (p) setCurrentPane(p); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::paneInteractedWith() lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = dynamic_cast(sender()); lbajardsilogic@0: if (!pane) return; lbajardsilogic@0: setCurrentPane(pane); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::rightButtonMenuRequested(QPoint position) lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = dynamic_cast(sender()); lbajardsilogic@0: if (!pane) return; lbajardsilogic@0: emit rightButtonMenuRequested(pane, position); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: PaneStack::sizePropertyStacks() lbajardsilogic@0: { lbajardsilogic@0: int maxMinWidth = 0; lbajardsilogic@0: lbajardsilogic@0: if (m_propertyStackMinWidth > 0) maxMinWidth = m_propertyStackMinWidth; lbajardsilogic@0: lbajardsilogic@0: for (size_t i = 0; i < m_panes.size(); ++i) { lbajardsilogic@0: if (!m_panes[i].propertyStack) continue; lbajardsilogic@0: #ifdef DEBUG_PANE_STACK lbajardsilogic@0: std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min " lbajardsilogic@0: << m_panes[i].propertyStack->minimumSizeHint().width() << ", hint " lbajardsilogic@0: << m_panes[i].propertyStack->sizeHint().width() << ", current " lbajardsilogic@0: << m_panes[i].propertyStack->width() << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: if (m_panes[i].propertyStack->sizeHint().width() > maxMinWidth) { lbajardsilogic@0: maxMinWidth = m_panes[i].propertyStack->sizeHint().width(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_PANE_STACK lbajardsilogic@0: std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: //#ifdef Q_WS_MAC lbajardsilogic@0: // This is necessary to compensate for cb->setMinimumSize(10, 10) lbajardsilogic@0: // in PropertyBox in the Mac version (to avoid a mysterious crash) lbajardsilogic@0: // ... no longer necessary with qt4.2 lbajardsilogic@0: // int setWidth = maxMinWidth * 3 / 2; lbajardsilogic@0: //#else lbajardsilogic@0: int setWidth = maxMinWidth; lbajardsilogic@0: //#endif lbajardsilogic@0: lbajardsilogic@0: m_propertyStackStack->setMaximumWidth(setWidth + 10); lbajardsilogic@0: lbajardsilogic@0: for (size_t i = 0; i < m_panes.size(); ++i) { lbajardsilogic@0: if (!m_panes[i].propertyStack) continue; lbajardsilogic@0: m_panes[i].propertyStack->setMinimumWidth(setWidth); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: emit propertyStacksResized(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@101: void PaneStack::resizePane() lbajardsilogic@101: { lbajardsilogic@101: int totalSize = m_splitter->size().height(); lbajardsilogic@101: int nbPane = getPaneCount(); lbajardsilogic@0: lbajardsilogic@101: if (nbPane == 0) lbajardsilogic@101: return; lbajardsilogic@101: lbajardsilogic@101: QList newSizes; lbajardsilogic@101: lbajardsilogic@101: for (int i = 0; i< nbPane; i++) lbajardsilogic@101: { lbajardsilogic@101: newSizes.push_back(totalSize/nbPane); lbajardsilogic@101: } lbajardsilogic@101: lbajardsilogic@101: m_splitter->setSizes(newSizes); lbajardsilogic@101: }