Mercurial > hg > svgui
diff view/PaneStack.cpp @ 127:89c625dda204
* Reorganising code base. This revision will not compile.
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 11:44:37 +0000 |
parents | |
children | 33929e0c3c6b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/view/PaneStack.cpp Mon Jul 31 11:44:37 2006 +0000 @@ -0,0 +1,434 @@ + +/* -*- 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. + + 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 "widgets/Pane.h" +#include "widgets/PropertyStack.h" +#include "base/Layer.h" +#include "base/ViewManager.h" + +#include <QApplication> +#include <QHBoxLayout> +#include <QPainter> +#include <QPalette> +#include <QLabel> +#include <QSplitter> +#include <QStackedWidget> + +#include <iostream> + +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 *))); + } + 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))); + + if (!m_currentPane) { + setCurrentPane(pane); + } + + return pane; +} + +void +PaneStack::setLayoutStyle(LayoutStyle style) +{ + if (style == m_layoutStyle) return; + m_layoutStyle = style; + + std::vector<PaneRec>::iterator i; + + switch (style) { + + 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->show(); + 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) +{ + return m_panes[n].pane; +} + +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; + } + } + + delete pane->parent(); + + if (m_currentPane == pane) { + if (m_panes.size() > 0) { + setCurrentPane(m_panes[0].pane); + } else { + setCurrentPane(0); + } + } +} + +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 == SinglePropertyStackLayout) { + 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::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; + + for (size_t i = 0; i < m_panes.size(); ++i) { + if (!m_panes[i].propertyStack) continue; +// std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min " +// << m_panes[i].propertyStack->minimumSizeHint().width() << ", current " +// << m_panes[i].propertyStack->width() << std::endl; + + if (m_panes[i].propertyStack->minimumSizeHint().width() > maxMinWidth) { + maxMinWidth = m_panes[i].propertyStack->minimumSizeHint().width(); + } + } + +// std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl; + +#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) + 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); + } +} + + +#ifdef INCLUDE_MOCFILES +#include "PaneStack.moc.cpp" +#endif +