annotate widgets/PaneStack.cpp @ 38:beb801473743

* Rearrange spectrogram cacheing so that gain, normalization, instantaneous frequency calculations etc can be done from the cached data (increasing the size of the cache, but also the usability).
author Chris Cannam
date Thu, 23 Feb 2006 18:01:31 +0000
parents 651e4e868bcc
children f2fe98a7c57e
rev   line source
Chris@0 1
Chris@0 2 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 3
Chris@0 4 /*
Chris@0 5 A waveform viewer and audio annotation editor.
Chris@5 6 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@0 7
Chris@0 8 This is experimental software. Not for distribution.
Chris@0 9 */
Chris@0 10
Chris@0 11 #include "PaneStack.h"
Chris@0 12
Chris@0 13 #include "widgets/Pane.h"
Chris@0 14 #include "widgets/PropertyStack.h"
Chris@0 15 #include "base/Layer.h"
Chris@0 16 #include "base/ViewManager.h"
Chris@0 17
Chris@0 18 #include <QApplication>
Chris@0 19 #include <QHBoxLayout>
Chris@0 20 #include <QPainter>
Chris@0 21 #include <QPalette>
Chris@0 22 #include <QLabel>
Chris@0 23
Chris@0 24 #include <iostream>
Chris@0 25
Chris@0 26 PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) :
Chris@0 27 QSplitter(parent),
Chris@0 28 m_currentPane(0),
Chris@0 29 m_viewManager(viewManager)
Chris@0 30 {
Chris@0 31 setOrientation(Qt::Vertical);
Chris@0 32 setOpaqueResize(false);
Chris@0 33 }
Chris@0 34
Chris@0 35 Pane *
Chris@0 36 PaneStack::addPane(bool suppressPropertyBox)
Chris@0 37 {
Chris@0 38 QFrame *frame = new QFrame;
Chris@0 39 QHBoxLayout *layout = new QHBoxLayout;
Chris@0 40 layout->setMargin(0);
Chris@0 41 layout->setSpacing(2);
Chris@0 42
Chris@0 43 QLabel *currentIndicator = new QLabel(frame);
Chris@0 44 currentIndicator->setFixedWidth(QPainter(this).fontMetrics().width("x"));
Chris@0 45 layout->addWidget(currentIndicator);
Chris@0 46 layout->setStretchFactor(currentIndicator, 1);
Chris@0 47 currentIndicator->setScaledContents(true);
Chris@0 48 m_currentIndicators.push_back(currentIndicator);
Chris@0 49
Chris@0 50 Pane *pane = new Pane(frame);
Chris@0 51 pane->setViewManager(m_viewManager);
Chris@0 52 layout->addWidget(pane);
Chris@0 53 layout->setStretchFactor(pane, 10);
Chris@0 54 m_panes.push_back(pane);
Chris@0 55
Chris@0 56 QWidget *properties = 0;
Chris@0 57 if (suppressPropertyBox) {
Chris@0 58 properties = new QFrame();
Chris@0 59 } else {
Chris@0 60 properties = new PropertyStack(frame, pane);
Chris@0 61 connect(properties, SIGNAL(propertyContainerSelected(PropertyContainer *)),
Chris@0 62 this, SLOT(propertyContainerSelected(PropertyContainer *)));
Chris@0 63 }
Chris@0 64 layout->addWidget(properties);
Chris@0 65 layout->setStretchFactor(properties, 1);
Chris@0 66 m_propertyStacks.push_back(properties);
Chris@0 67
Chris@0 68 frame->setLayout(layout);
Chris@0 69 addWidget(frame);
Chris@0 70
Chris@0 71 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@0 72 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@0 73 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@0 74 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@0 75 connect(pane, SIGNAL(paneInteractedWith()),
Chris@0 76 this, SLOT(paneInteractedWith()));
Chris@0 77
Chris@0 78 if (!m_currentPane) {
Chris@0 79 setCurrentPane(pane);
Chris@0 80 }
Chris@0 81
Chris@0 82 return pane;
Chris@0 83 }
Chris@0 84
Chris@0 85 Pane *
Chris@0 86 PaneStack::getPane(int n)
Chris@0 87 {
Chris@0 88 return m_panes[n];
Chris@0 89 }
Chris@0 90
Chris@0 91 void
Chris@0 92 PaneStack::deletePane(Pane *pane)
Chris@0 93 {
Chris@0 94 int n = 0;
Chris@0 95 std::vector<Pane *>::iterator i = m_panes.begin();
Chris@0 96 std::vector<QWidget *>::iterator j = m_propertyStacks.begin();
Chris@0 97 std::vector<QLabel *>::iterator k = m_currentIndicators.begin();
Chris@0 98
Chris@0 99 while (i != m_panes.end()) {
Chris@0 100 if (*i == pane) break;
Chris@0 101 ++i;
Chris@0 102 ++j;
Chris@0 103 ++k;
Chris@0 104 ++n;
Chris@0 105 }
Chris@0 106 if (n >= int(m_panes.size())) return;
Chris@0 107
Chris@0 108 m_panes.erase(i);
Chris@0 109 m_propertyStacks.erase(j);
Chris@0 110 m_currentIndicators.erase(k);
Chris@0 111 delete widget(n);
Chris@0 112
Chris@0 113 if (m_currentPane == pane) {
Chris@0 114 if (m_panes.size() > 0) {
Chris@0 115 setCurrentPane(m_panes[0]);
Chris@0 116 } else {
Chris@0 117 setCurrentPane(0);
Chris@0 118 }
Chris@0 119 }
Chris@0 120 }
Chris@0 121
Chris@0 122 int
Chris@0 123 PaneStack::getPaneCount() const
Chris@0 124 {
Chris@0 125 return m_panes.size();
Chris@0 126 }
Chris@0 127
Chris@0 128 void
Chris@0 129 PaneStack::setCurrentPane(Pane *pane) // may be null
Chris@0 130 {
Chris@0 131 if (m_currentPane == pane) return;
Chris@0 132
Chris@0 133 std::vector<Pane *>::iterator i = m_panes.begin();
Chris@0 134 std::vector<QLabel *>::iterator k = m_currentIndicators.begin();
Chris@0 135
Chris@0 136 // We used to do this by setting the foreground and background
Chris@0 137 // role, but it seems the background role is ignored and the
Chris@0 138 // background drawn transparent in Qt 4.1 -- I can't quite see why
Chris@0 139
Chris@0 140 QPixmap selectedMap(1, 1);
Chris@0 141 selectedMap.fill(QApplication::palette().color(QPalette::Foreground));
Chris@0 142
Chris@0 143 QPixmap unselectedMap(1, 1);
Chris@0 144 unselectedMap.fill(QApplication::palette().color(QPalette::Background));
Chris@0 145
Chris@0 146 while (i != m_panes.end()) {
Chris@0 147 if (*i == pane) {
Chris@0 148 (*k)->setPixmap(selectedMap);
Chris@0 149 } else {
Chris@0 150 (*k)->setPixmap(unselectedMap);
Chris@0 151 }
Chris@0 152 ++i;
Chris@0 153 ++k;
Chris@0 154 }
Chris@0 155 m_currentPane = pane;
Chris@0 156
Chris@0 157 emit currentPaneChanged(m_currentPane);
Chris@0 158 }
Chris@0 159
Chris@19 160 void
Chris@19 161 PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null
Chris@19 162 {
Chris@19 163 setCurrentPane(pane);
Chris@19 164
Chris@19 165 if (m_currentPane) {
Chris@19 166
Chris@19 167 std::vector<Pane *>::iterator i = m_panes.begin();
Chris@19 168 std::vector<QWidget *>::iterator j = m_propertyStacks.begin();
Chris@19 169
Chris@19 170 while (i != m_panes.end()) {
Chris@19 171
Chris@19 172 if (*i == pane) {
Chris@19 173 PropertyStack *stack = dynamic_cast<PropertyStack *>(*j);
Chris@19 174 if (stack) {
Chris@19 175 if (stack->containsContainer(layer)) {
Chris@19 176 stack->setCurrentIndex(stack->getContainerIndex(layer));
Chris@19 177 emit currentLayerChanged(pane, layer);
Chris@19 178 } else {
Chris@33 179 stack->setCurrentIndex
Chris@33 180 (stack->getContainerIndex
Chris@33 181 (pane->getPropertyContainer(0)));
Chris@19 182 emit currentLayerChanged(pane, 0);
Chris@19 183 }
Chris@19 184 }
Chris@19 185 break;
Chris@19 186 }
Chris@19 187 ++i;
Chris@19 188 ++j;
Chris@19 189 }
Chris@19 190 }
Chris@19 191 }
Chris@19 192
Chris@0 193 Pane *
Chris@0 194 PaneStack::getCurrentPane()
Chris@0 195 {
Chris@0 196 return m_currentPane;
Chris@0 197 }
Chris@0 198
Chris@0 199 void
Chris@0 200 PaneStack::propertyContainerAdded(PropertyContainer *)
Chris@0 201 {
Chris@0 202 sizePropertyStacks();
Chris@0 203 }
Chris@0 204
Chris@0 205 void
Chris@0 206 PaneStack::propertyContainerRemoved(PropertyContainer *)
Chris@0 207 {
Chris@0 208 sizePropertyStacks();
Chris@0 209 }
Chris@0 210
Chris@0 211 void
Chris@0 212 PaneStack::propertyContainerSelected(PropertyContainer *pc)
Chris@0 213 {
Chris@0 214 std::vector<Pane *>::iterator i = m_panes.begin();
Chris@0 215 std::vector<QWidget *>::iterator j = m_propertyStacks.begin();
Chris@0 216
Chris@0 217 while (i != m_panes.end()) {
Chris@0 218 PropertyStack *stack = dynamic_cast<PropertyStack *>(*j);
Chris@0 219 if (stack && stack->containsContainer(pc)) {
Chris@0 220 setCurrentPane(*i);
Chris@0 221 break;
Chris@0 222 }
Chris@0 223 ++i;
Chris@0 224 ++j;
Chris@0 225 }
Chris@17 226
Chris@17 227 Layer *layer = dynamic_cast<Layer *>(pc);
Chris@17 228 if (layer) emit currentLayerChanged(m_currentPane, layer);
Chris@17 229 else emit currentLayerChanged(m_currentPane, 0);
Chris@0 230 }
Chris@0 231
Chris@0 232 void
Chris@0 233 PaneStack::paneInteractedWith()
Chris@0 234 {
Chris@0 235 Pane *pane = dynamic_cast<Pane *>(sender());
Chris@0 236 if (!pane) return;
Chris@0 237 setCurrentPane(pane);
Chris@0 238 }
Chris@0 239
Chris@0 240 void
Chris@0 241 PaneStack::sizePropertyStacks()
Chris@0 242 {
Chris@0 243 int maxMinWidth = 0;
Chris@0 244
Chris@0 245 for (unsigned int i = 0; i < m_propertyStacks.size(); ++i) {
Chris@0 246 if (!m_propertyStacks[i]) continue;
Chris@0 247 std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min "
Chris@0 248 << m_propertyStacks[i]->minimumSizeHint().width() << ", current "
Chris@0 249 << m_propertyStacks[i]->width() << std::endl;
Chris@0 250
Chris@0 251 if (m_propertyStacks[i]->minimumSizeHint().width() > maxMinWidth) {
Chris@0 252 maxMinWidth = m_propertyStacks[i]->minimumSizeHint().width();
Chris@0 253 }
Chris@0 254 }
Chris@0 255
Chris@0 256 std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl;
Chris@0 257
Chris@0 258 #ifdef Q_WS_MAC
Chris@0 259 // This is necessary to compensate for cb->setMinimumSize(10, 10)
Chris@0 260 // in PropertyBox in the Mac version (to avoid a mysterious crash)
Chris@0 261 int setWidth = maxMinWidth * 3 / 2;
Chris@0 262 #else
Chris@0 263 int setWidth = maxMinWidth;
Chris@0 264 #endif
Chris@0 265
Chris@0 266 for (unsigned int i = 0; i < m_propertyStacks.size(); ++i) {
Chris@0 267 if (!m_propertyStacks[i]) continue;
Chris@0 268 m_propertyStacks[i]->setMinimumWidth(setWidth);
Chris@0 269 }
Chris@0 270 }
Chris@0 271
Chris@0 272
Chris@0 273 #ifdef INCLUDE_MOCFILES
Chris@0 274 #include "PaneStack.moc.cpp"
Chris@0 275 #endif
Chris@0 276