Chris@0: Chris@0: /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: A waveform viewer and audio annotation editor. Chris@0: Chris Cannam, Queen Mary University of London, 2005 Chris@0: Chris@0: This is experimental software. Not for distribution. Chris@0: */ Chris@0: Chris@0: #include "PaneStack.h" Chris@0: Chris@0: #include "widgets/Pane.h" Chris@0: #include "widgets/PropertyStack.h" Chris@0: #include "base/Layer.h" Chris@0: #include "base/ViewManager.h" Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: Chris@0: #include Chris@0: Chris@0: PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) : Chris@0: QSplitter(parent), Chris@0: m_currentPane(0), Chris@0: m_viewManager(viewManager) Chris@0: { Chris@0: setOrientation(Qt::Vertical); Chris@0: setOpaqueResize(false); Chris@0: } Chris@0: Chris@0: Pane * Chris@0: PaneStack::addPane(bool suppressPropertyBox) Chris@0: { Chris@0: QFrame *frame = new QFrame; Chris@0: QHBoxLayout *layout = new QHBoxLayout; Chris@0: layout->setMargin(0); Chris@0: layout->setSpacing(2); Chris@0: Chris@0: QLabel *currentIndicator = new QLabel(frame); Chris@0: currentIndicator->setFixedWidth(QPainter(this).fontMetrics().width("x")); Chris@0: layout->addWidget(currentIndicator); Chris@0: layout->setStretchFactor(currentIndicator, 1); Chris@0: currentIndicator->setScaledContents(true); Chris@0: m_currentIndicators.push_back(currentIndicator); Chris@0: Chris@0: Pane *pane = new Pane(frame); Chris@0: pane->setViewManager(m_viewManager); Chris@0: layout->addWidget(pane); Chris@0: layout->setStretchFactor(pane, 10); Chris@0: m_panes.push_back(pane); Chris@0: Chris@0: QWidget *properties = 0; Chris@0: if (suppressPropertyBox) { Chris@0: properties = new QFrame(); Chris@0: } else { Chris@0: properties = new PropertyStack(frame, pane); Chris@0: connect(properties, SIGNAL(propertyContainerSelected(PropertyContainer *)), Chris@0: this, SLOT(propertyContainerSelected(PropertyContainer *))); Chris@0: } Chris@0: layout->addWidget(properties); Chris@0: layout->setStretchFactor(properties, 1); Chris@0: m_propertyStacks.push_back(properties); Chris@0: Chris@0: frame->setLayout(layout); Chris@0: addWidget(frame); Chris@0: Chris@0: connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)), Chris@0: this, SLOT(propertyContainerAdded(PropertyContainer *))); Chris@0: connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)), Chris@0: this, SLOT(propertyContainerRemoved(PropertyContainer *))); Chris@0: connect(pane, SIGNAL(paneInteractedWith()), Chris@0: this, SLOT(paneInteractedWith())); Chris@0: Chris@0: if (!m_currentPane) { Chris@0: setCurrentPane(pane); Chris@0: } Chris@0: Chris@0: return pane; Chris@0: } Chris@0: Chris@0: Pane * Chris@0: PaneStack::getPane(int n) Chris@0: { Chris@0: return m_panes[n]; Chris@0: } Chris@0: Chris@0: void Chris@0: PaneStack::deletePane(Pane *pane) Chris@0: { Chris@0: int n = 0; Chris@0: std::vector::iterator i = m_panes.begin(); Chris@0: std::vector::iterator j = m_propertyStacks.begin(); Chris@0: std::vector::iterator k = m_currentIndicators.begin(); Chris@0: Chris@0: while (i != m_panes.end()) { Chris@0: if (*i == pane) break; Chris@0: ++i; Chris@0: ++j; Chris@0: ++k; Chris@0: ++n; Chris@0: } Chris@0: if (n >= int(m_panes.size())) return; Chris@0: Chris@0: m_panes.erase(i); Chris@0: m_propertyStacks.erase(j); Chris@0: m_currentIndicators.erase(k); Chris@0: delete widget(n); Chris@0: Chris@0: if (m_currentPane == pane) { Chris@0: if (m_panes.size() > 0) { Chris@0: setCurrentPane(m_panes[0]); Chris@0: } else { Chris@0: setCurrentPane(0); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: int Chris@0: PaneStack::getPaneCount() const Chris@0: { Chris@0: return m_panes.size(); Chris@0: } Chris@0: Chris@0: void Chris@0: PaneStack::setCurrentPane(Pane *pane) // may be null Chris@0: { Chris@0: if (m_currentPane == pane) return; Chris@0: Chris@0: std::vector::iterator i = m_panes.begin(); Chris@0: std::vector::iterator k = m_currentIndicators.begin(); Chris@0: Chris@0: // We used to do this by setting the foreground and background Chris@0: // role, but it seems the background role is ignored and the Chris@0: // background drawn transparent in Qt 4.1 -- I can't quite see why Chris@0: Chris@0: QPixmap selectedMap(1, 1); Chris@0: selectedMap.fill(QApplication::palette().color(QPalette::Foreground)); Chris@0: Chris@0: QPixmap unselectedMap(1, 1); Chris@0: unselectedMap.fill(QApplication::palette().color(QPalette::Background)); Chris@0: Chris@0: while (i != m_panes.end()) { Chris@0: if (*i == pane) { Chris@0: (*k)->setPixmap(selectedMap); Chris@0: } else { Chris@0: (*k)->setPixmap(unselectedMap); Chris@0: } Chris@0: ++i; Chris@0: ++k; Chris@0: } Chris@0: m_currentPane = pane; Chris@0: Chris@0: emit currentPaneChanged(m_currentPane); Chris@0: } Chris@0: Chris@0: Pane * Chris@0: PaneStack::getCurrentPane() Chris@0: { Chris@0: return m_currentPane; Chris@0: } Chris@0: Chris@0: void Chris@0: PaneStack::propertyContainerAdded(PropertyContainer *) Chris@0: { Chris@0: sizePropertyStacks(); Chris@0: } Chris@0: Chris@0: void Chris@0: PaneStack::propertyContainerRemoved(PropertyContainer *) Chris@0: { Chris@0: sizePropertyStacks(); Chris@0: } Chris@0: Chris@0: void Chris@0: PaneStack::propertyContainerSelected(PropertyContainer *pc) Chris@0: { Chris@0: std::vector::iterator i = m_panes.begin(); Chris@0: std::vector::iterator j = m_propertyStacks.begin(); Chris@0: Chris@0: while (i != m_panes.end()) { Chris@0: PropertyStack *stack = dynamic_cast(*j); Chris@0: if (stack && stack->containsContainer(pc)) { Chris@0: setCurrentPane(*i); Chris@0: break; Chris@0: } Chris@0: ++i; Chris@0: ++j; Chris@0: } Chris@0: } Chris@0: Chris@0: void Chris@0: PaneStack::paneInteractedWith() Chris@0: { Chris@0: Pane *pane = dynamic_cast(sender()); Chris@0: if (!pane) return; Chris@0: setCurrentPane(pane); Chris@0: } Chris@0: Chris@0: void Chris@0: PaneStack::sizePropertyStacks() Chris@0: { Chris@0: int maxMinWidth = 0; Chris@0: Chris@0: for (unsigned int i = 0; i < m_propertyStacks.size(); ++i) { Chris@0: if (!m_propertyStacks[i]) continue; Chris@0: std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min " Chris@0: << m_propertyStacks[i]->minimumSizeHint().width() << ", current " Chris@0: << m_propertyStacks[i]->width() << std::endl; Chris@0: Chris@0: if (m_propertyStacks[i]->minimumSizeHint().width() > maxMinWidth) { Chris@0: maxMinWidth = m_propertyStacks[i]->minimumSizeHint().width(); Chris@0: } Chris@0: } Chris@0: Chris@0: std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl; Chris@0: Chris@0: #ifdef Q_WS_MAC Chris@0: // This is necessary to compensate for cb->setMinimumSize(10, 10) Chris@0: // in PropertyBox in the Mac version (to avoid a mysterious crash) Chris@0: int setWidth = maxMinWidth * 3 / 2; Chris@0: #else Chris@0: int setWidth = maxMinWidth; Chris@0: #endif Chris@0: Chris@0: for (unsigned int i = 0; i < m_propertyStacks.size(); ++i) { Chris@0: if (!m_propertyStacks[i]) continue; Chris@0: m_propertyStacks[i]->setMinimumWidth(setWidth); Chris@0: } Chris@0: } Chris@0: Chris@0: Chris@0: #ifdef INCLUDE_MOCFILES Chris@0: #include "PaneStack.moc.cpp" Chris@0: #endif Chris@0: