Mercurial > hg > svgui
view view/PaneStack.cpp @ 288:e27f546f83ad
* Fix failure to auto-calculate bounds on time-value or note model loaded
from session file if min and max not specified in the model
* Attempt to work out why some points in time-value layer are not being
locally illuminated when expected, and why models are loaded from sv file
without their names -- both failed so far...
author | Chris Cannam |
---|---|
date | Thu, 12 Jul 2007 21:10:43 +0000 |
parents | 8acd30ed735c |
children | 6de6f78b13a1 |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Sonic Visualiser An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. This file copyright 2006 Chris Cannam and QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "PaneStack.h" #include "Pane.h" #include "widgets/PropertyStack.h" #include "layer/Layer.h" #include "ViewManager.h" #include <QApplication> #include <QHBoxLayout> #include <QPainter> #include <QPalette> #include <QLabel> #include <QSplitter> #include <QStackedWidget> #include <iostream> //#define DEBUG_PANE_STACK 1 PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) : QFrame(parent), m_currentPane(0), m_splitter(new QSplitter), m_propertyStackStack(new QStackedWidget), m_viewManager(viewManager), m_layoutStyle(PropertyStackPerPaneLayout) { QHBoxLayout *layout = new QHBoxLayout; layout->setMargin(0); layout->setSpacing(0); m_splitter->setOrientation(Qt::Vertical); m_splitter->setOpaqueResize(false); layout->addWidget(m_splitter); layout->setStretchFactor(m_splitter, 1); layout->addWidget(m_propertyStackStack); m_propertyStackStack->hide(); setLayout(layout); } Pane * PaneStack::addPane(bool suppressPropertyBox) { QFrame *frame = new QFrame; QHBoxLayout *layout = new QHBoxLayout; layout->setMargin(0); layout->setSpacing(2); QLabel *currentIndicator = new QLabel(frame); currentIndicator->setFixedWidth(QPainter(this).fontMetrics().width("x")); layout->addWidget(currentIndicator); layout->setStretchFactor(currentIndicator, 1); currentIndicator->setScaledContents(true); Pane *pane = new Pane(frame); pane->setViewManager(m_viewManager); layout->addWidget(pane); layout->setStretchFactor(pane, 10); QWidget *properties = 0; if (suppressPropertyBox) { properties = new QFrame(); } else { properties = new PropertyStack(frame, pane); connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); connect(properties, SIGNAL(viewSelected(View *)), this, SLOT(viewSelected(View *))); connect(properties, SIGNAL(contextHelpChanged(const QString &)), this, SIGNAL(contextHelpChanged(const QString &))); } if (m_layoutStyle == PropertyStackPerPaneLayout) { layout->addWidget(properties); } else { properties->setParent(m_propertyStackStack); m_propertyStackStack->addWidget(properties); } layout->setStretchFactor(properties, 1); PaneRec rec; rec.pane = pane; rec.propertyStack = properties; rec.currentIndicator = currentIndicator; rec.frame = frame; rec.layout = layout; m_panes.push_back(rec); frame->setLayout(layout); m_splitter->addWidget(frame); connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)), this, SLOT(propertyContainerAdded(PropertyContainer *))); connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)), this, SLOT(propertyContainerRemoved(PropertyContainer *))); connect(pane, SIGNAL(paneInteractedWith()), this, SLOT(paneInteractedWith())); connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)), this, SLOT(rightButtonMenuRequested(QPoint))); emit paneAdded(pane); emit paneAdded(); if (!m_currentPane) { setCurrentPane(pane); } return pane; } void PaneStack::setPropertyStackMinWidth(int mw) { for (std::vector<PaneRec>::iterator i = m_panes.begin(); i != m_panes.end(); ++i) { i->propertyStack->setMinimumWidth(mw); } m_propertyStackMinWidth = mw; } void PaneStack::setLayoutStyle(LayoutStyle style) { if (style == m_layoutStyle) return; m_layoutStyle = style; std::vector<PaneRec>::iterator i; switch (style) { case NoPropertyStacks: case SinglePropertyStackLayout: for (i = m_panes.begin(); i != m_panes.end(); ++i) { i->layout->removeWidget(i->propertyStack); i->propertyStack->setParent(m_propertyStackStack); m_propertyStackStack->addWidget(i->propertyStack); } m_propertyStackStack->setVisible(style != NoPropertyStacks); break; case PropertyStackPerPaneLayout: for (i = m_panes.begin(); i != m_panes.end(); ++i) { m_propertyStackStack->removeWidget(i->propertyStack); i->propertyStack->setParent(i->frame); i->layout->addWidget(i->propertyStack); i->propertyStack->show(); } m_propertyStackStack->hide(); break; } } Pane * PaneStack::getPane(int n) { if (n < m_panes.size()) { return m_panes[n].pane; } else { return 0; } } int PaneStack::getPaneIndex(Pane *pane) { for (int i = 0; i < getPaneCount(); ++i) { if (pane == getPane(i)) { return i; } } return -1; } Pane * PaneStack::getHiddenPane(int n) { return m_hiddenPanes[n].pane; } void PaneStack::deletePane(Pane *pane) { std::vector<PaneRec>::iterator i; bool found = false; for (i = m_panes.begin(); i != m_panes.end(); ++i) { if (i->pane == pane) { m_panes.erase(i); found = true; break; } } if (!found) { for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) { if (i->pane == pane) { m_hiddenPanes.erase(i); found = true; break; } } if (!found) { std::cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << std::endl; return; } } emit paneAboutToBeDeleted(pane); delete pane->parent(); if (m_currentPane == pane) { if (m_panes.size() > 0) { setCurrentPane(m_panes[0].pane); } else { setCurrentPane(0); } } emit paneDeleted(); } int PaneStack::getPaneCount() const { return m_panes.size(); } int PaneStack::getHiddenPaneCount() const { return m_hiddenPanes.size(); } void PaneStack::hidePane(Pane *pane) { std::vector<PaneRec>::iterator i = m_panes.begin(); while (i != m_panes.end()) { if (i->pane == pane) { m_hiddenPanes.push_back(*i); m_panes.erase(i); QWidget *pw = dynamic_cast<QWidget *>(pane->parent()); if (pw) pw->hide(); if (m_currentPane == pane) { if (m_panes.size() > 0) { setCurrentPane(m_panes[0].pane); } else { setCurrentPane(0); } } return; } ++i; } std::cerr << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << std::endl; } void PaneStack::showPane(Pane *pane) { std::vector<PaneRec>::iterator i = m_hiddenPanes.begin(); while (i != m_hiddenPanes.end()) { if (i->pane == pane) { m_panes.push_back(*i); m_hiddenPanes.erase(i); QWidget *pw = dynamic_cast<QWidget *>(pane->parent()); if (pw) pw->show(); //!!! update current pane return; } ++i; } std::cerr << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << std::endl; } void PaneStack::setCurrentPane(Pane *pane) // may be null { if (m_currentPane == pane) return; std::vector<PaneRec>::iterator i = m_panes.begin(); // We used to do this by setting the foreground and background // role, but it seems the background role is ignored and the // background drawn transparent in Qt 4.1 -- I can't quite see why QPixmap selectedMap(1, 1); selectedMap.fill(QApplication::palette().color(QPalette::Foreground)); QPixmap unselectedMap(1, 1); unselectedMap.fill(QApplication::palette().color(QPalette::Background)); bool found = false; while (i != m_panes.end()) { if (i->pane == pane) { i->currentIndicator->setPixmap(selectedMap); if (m_layoutStyle != PropertyStackPerPaneLayout) { m_propertyStackStack->setCurrentWidget(i->propertyStack); } found = true; } else { i->currentIndicator->setPixmap(unselectedMap); } ++i; } if (found || pane == 0) { m_currentPane = pane; emit currentPaneChanged(m_currentPane); } else { std::cerr << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << std::endl; } } void PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null { setCurrentPane(pane); if (m_currentPane) { std::vector<PaneRec>::iterator i = m_panes.begin(); while (i != m_panes.end()) { if (i->pane == pane) { PropertyStack *stack = dynamic_cast<PropertyStack *> (i->propertyStack); if (stack) { if (stack->containsContainer(layer)) { stack->setCurrentIndex(stack->getContainerIndex(layer)); emit currentLayerChanged(pane, layer); } else { stack->setCurrentIndex (stack->getContainerIndex (pane->getPropertyContainer(0))); emit currentLayerChanged(pane, 0); } } break; } ++i; } } } Pane * PaneStack::getCurrentPane() { return m_currentPane; } void PaneStack::propertyContainerAdded(PropertyContainer *) { sizePropertyStacks(); } void PaneStack::propertyContainerRemoved(PropertyContainer *) { sizePropertyStacks(); } void PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc) { std::vector<PaneRec>::iterator i = m_panes.begin(); while (i != m_panes.end()) { PropertyStack *stack = dynamic_cast<PropertyStack *>(i->propertyStack); if (stack && stack->getClient() == client && stack->containsContainer(pc)) { setCurrentPane(i->pane); break; } ++i; } Layer *layer = dynamic_cast<Layer *>(pc); if (layer) emit currentLayerChanged(m_currentPane, layer); else emit currentLayerChanged(m_currentPane, 0); } void PaneStack::viewSelected(View *v) { Pane *p = dynamic_cast<Pane *>(v); if (p) setCurrentPane(p); } void PaneStack::paneInteractedWith() { Pane *pane = dynamic_cast<Pane *>(sender()); if (!pane) return; setCurrentPane(pane); } void PaneStack::rightButtonMenuRequested(QPoint position) { Pane *pane = dynamic_cast<Pane *>(sender()); if (!pane) return; emit rightButtonMenuRequested(pane, position); } void PaneStack::sizePropertyStacks() { int maxMinWidth = 0; if (m_propertyStackMinWidth > 0) maxMinWidth = m_propertyStackMinWidth; for (size_t i = 0; i < m_panes.size(); ++i) { if (!m_panes[i].propertyStack) continue; #ifdef DEBUG_PANE_STACK std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min " << m_panes[i].propertyStack->minimumSizeHint().width() << ", hint " << m_panes[i].propertyStack->sizeHint().width() << ", current " << m_panes[i].propertyStack->width() << std::endl; #endif if (m_panes[i].propertyStack->sizeHint().width() > maxMinWidth) { maxMinWidth = m_panes[i].propertyStack->sizeHint().width(); } } #ifdef DEBUG_PANE_STACK std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl; #endif //#ifdef Q_WS_MAC // This is necessary to compensate for cb->setMinimumSize(10, 10) // in PropertyBox in the Mac version (to avoid a mysterious crash) // ... no longer necessary with qt4.2 // int setWidth = maxMinWidth * 3 / 2; //#else int setWidth = maxMinWidth; //#endif m_propertyStackStack->setMaximumWidth(setWidth + 10); for (size_t i = 0; i < m_panes.size(); ++i) { if (!m_panes[i].propertyStack) continue; m_panes[i].propertyStack->setMinimumWidth(setWidth); } emit propertyStacksResized(); }