annotate widgets/PaneStack.cpp @ 101:0f36cdf407a6 sv1-v0.9rc1

* Make vertical scale alignment modes work in note layer as well as time-value layer, and several significant fixes to it * Make it possible to draw notes properly on the note layer * Show units (and frequencies etc in note layer's case) in the time-value and note layer description boxes * Minor fix to item edit dialog layout * Some minor menu rearrangement * Comment out a lot of debug output * Add SV website and reference URLs to Help menu, and add code to (attempt to) open them in the user's preferred browser
author Chris Cannam
date Fri, 12 May 2006 14:40:43 +0000
parents 803830f186ef
children 4772fc75ac7c
rev   line source
Chris@0 1
Chris@58 2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 3
Chris@0 4 /*
Chris@59 5 Sonic Visualiser
Chris@59 6 An audio file viewer and annotation editor.
Chris@59 7 Centre for Digital Music, Queen Mary, University of London.
Chris@59 8 This file copyright 2006 Chris Cannam.
Chris@0 9
Chris@59 10 This program is free software; you can redistribute it and/or
Chris@59 11 modify it under the terms of the GNU General Public License as
Chris@59 12 published by the Free Software Foundation; either version 2 of the
Chris@59 13 License, or (at your option) any later version. See the file
Chris@59 14 COPYING included with this distribution for more information.
Chris@0 15 */
Chris@0 16
Chris@0 17 #include "PaneStack.h"
Chris@0 18
Chris@0 19 #include "widgets/Pane.h"
Chris@0 20 #include "widgets/PropertyStack.h"
Chris@0 21 #include "base/Layer.h"
Chris@0 22 #include "base/ViewManager.h"
Chris@0 23
Chris@0 24 #include <QApplication>
Chris@0 25 #include <QHBoxLayout>
Chris@0 26 #include <QPainter>
Chris@0 27 #include <QPalette>
Chris@0 28 #include <QLabel>
Chris@0 29
Chris@0 30 #include <iostream>
Chris@0 31
Chris@0 32 PaneStack::PaneStack(QWidget *parent, ViewManager *viewManager) :
Chris@0 33 QSplitter(parent),
Chris@0 34 m_currentPane(0),
Chris@0 35 m_viewManager(viewManager)
Chris@0 36 {
Chris@0 37 setOrientation(Qt::Vertical);
Chris@0 38 setOpaqueResize(false);
Chris@0 39 }
Chris@0 40
Chris@0 41 Pane *
Chris@0 42 PaneStack::addPane(bool suppressPropertyBox)
Chris@0 43 {
Chris@0 44 QFrame *frame = new QFrame;
Chris@0 45 QHBoxLayout *layout = new QHBoxLayout;
Chris@0 46 layout->setMargin(0);
Chris@0 47 layout->setSpacing(2);
Chris@0 48
Chris@0 49 QLabel *currentIndicator = new QLabel(frame);
Chris@0 50 currentIndicator->setFixedWidth(QPainter(this).fontMetrics().width("x"));
Chris@0 51 layout->addWidget(currentIndicator);
Chris@0 52 layout->setStretchFactor(currentIndicator, 1);
Chris@0 53 currentIndicator->setScaledContents(true);
Chris@0 54
Chris@0 55 Pane *pane = new Pane(frame);
Chris@0 56 pane->setViewManager(m_viewManager);
Chris@0 57 layout->addWidget(pane);
Chris@0 58 layout->setStretchFactor(pane, 10);
Chris@0 59
Chris@0 60 QWidget *properties = 0;
Chris@0 61 if (suppressPropertyBox) {
Chris@0 62 properties = new QFrame();
Chris@0 63 } else {
Chris@0 64 properties = new PropertyStack(frame, pane);
Chris@52 65 connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
Chris@52 66 this, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
Chris@0 67 }
Chris@0 68 layout->addWidget(properties);
Chris@0 69 layout->setStretchFactor(properties, 1);
Chris@52 70
Chris@52 71 PaneRec rec;
Chris@52 72 rec.pane = pane;
Chris@52 73 rec.propertyStack = properties;
Chris@52 74 rec.currentIndicator = currentIndicator;
Chris@52 75 m_panes.push_back(rec);
Chris@0 76
Chris@0 77 frame->setLayout(layout);
Chris@0 78 addWidget(frame);
Chris@0 79
Chris@0 80 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@0 81 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@0 82 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@0 83 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@0 84 connect(pane, SIGNAL(paneInteractedWith()),
Chris@0 85 this, SLOT(paneInteractedWith()));
Chris@89 86 connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)),
Chris@89 87 this, SLOT(rightButtonMenuRequested(QPoint)));
Chris@0 88
Chris@0 89 if (!m_currentPane) {
Chris@0 90 setCurrentPane(pane);
Chris@0 91 }
Chris@0 92
Chris@0 93 return pane;
Chris@0 94 }
Chris@0 95
Chris@0 96 Pane *
Chris@0 97 PaneStack::getPane(int n)
Chris@0 98 {
Chris@52 99 return m_panes[n].pane;
Chris@52 100 }
Chris@52 101
Chris@52 102 Pane *
Chris@52 103 PaneStack::getHiddenPane(int n)
Chris@52 104 {
Chris@52 105 return m_hiddenPanes[n].pane;
Chris@0 106 }
Chris@0 107
Chris@0 108 void
Chris@0 109 PaneStack::deletePane(Pane *pane)
Chris@0 110 {
Chris@52 111 std::vector<PaneRec>::iterator i;
Chris@52 112 bool found = false;
Chris@0 113
Chris@52 114 for (i = m_panes.begin(); i != m_panes.end(); ++i) {
Chris@52 115 if (i->pane == pane) {
Chris@52 116 m_panes.erase(i);
Chris@52 117 found = true;
Chris@52 118 break;
Chris@52 119 }
Chris@0 120 }
Chris@0 121
Chris@52 122 if (!found) {
Chris@52 123
Chris@52 124 for (i = m_hiddenPanes.begin(); i != m_hiddenPanes.end(); ++i) {
Chris@52 125 if (i->pane == pane) {
Chris@52 126 m_hiddenPanes.erase(i);
Chris@52 127 found = true;
Chris@52 128 break;
Chris@52 129 }
Chris@52 130 }
Chris@52 131
Chris@52 132 if (!found) {
Chris@52 133 std::cerr << "WARNING: PaneStack::deletePane(" << pane << "): Pane not found in visible or hidden panes, not deleting" << std::endl;
Chris@52 134 return;
Chris@52 135 }
Chris@52 136 }
Chris@52 137
Chris@52 138 delete pane->parent();
Chris@0 139
Chris@0 140 if (m_currentPane == pane) {
Chris@0 141 if (m_panes.size() > 0) {
Chris@52 142 setCurrentPane(m_panes[0].pane);
Chris@0 143 } else {
Chris@0 144 setCurrentPane(0);
Chris@0 145 }
Chris@0 146 }
Chris@0 147 }
Chris@0 148
Chris@0 149 int
Chris@0 150 PaneStack::getPaneCount() const
Chris@0 151 {
Chris@0 152 return m_panes.size();
Chris@0 153 }
Chris@0 154
Chris@52 155 int
Chris@52 156 PaneStack::getHiddenPaneCount() const
Chris@52 157 {
Chris@52 158 return m_hiddenPanes.size();
Chris@52 159 }
Chris@52 160
Chris@52 161 void
Chris@52 162 PaneStack::hidePane(Pane *pane)
Chris@52 163 {
Chris@52 164 std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@52 165
Chris@52 166 while (i != m_panes.end()) {
Chris@52 167 if (i->pane == pane) {
Chris@52 168
Chris@52 169 m_hiddenPanes.push_back(*i);
Chris@52 170 m_panes.erase(i);
Chris@52 171
Chris@52 172 QWidget *pw = dynamic_cast<QWidget *>(pane->parent());
Chris@52 173 if (pw) pw->hide();
Chris@52 174
Chris@52 175 if (m_currentPane == pane) {
Chris@52 176 if (m_panes.size() > 0) {
Chris@52 177 setCurrentPane(m_panes[0].pane);
Chris@52 178 } else {
Chris@52 179 setCurrentPane(0);
Chris@52 180 }
Chris@52 181 }
Chris@52 182
Chris@52 183 return;
Chris@52 184 }
Chris@52 185 ++i;
Chris@52 186 }
Chris@52 187
Chris@52 188 std::cerr << "WARNING: PaneStack::hidePane(" << pane << "): Pane not found in visible panes" << std::endl;
Chris@52 189 }
Chris@52 190
Chris@52 191 void
Chris@52 192 PaneStack::showPane(Pane *pane)
Chris@52 193 {
Chris@52 194 std::vector<PaneRec>::iterator i = m_hiddenPanes.begin();
Chris@52 195
Chris@52 196 while (i != m_hiddenPanes.end()) {
Chris@52 197 if (i->pane == pane) {
Chris@52 198 m_panes.push_back(*i);
Chris@52 199 m_hiddenPanes.erase(i);
Chris@52 200 QWidget *pw = dynamic_cast<QWidget *>(pane->parent());
Chris@52 201 if (pw) pw->show();
Chris@52 202
Chris@52 203 //!!! update current pane
Chris@52 204
Chris@52 205 return;
Chris@52 206 }
Chris@52 207 ++i;
Chris@52 208 }
Chris@52 209
Chris@52 210 std::cerr << "WARNING: PaneStack::showPane(" << pane << "): Pane not found in hidden panes" << std::endl;
Chris@52 211 }
Chris@52 212
Chris@0 213 void
Chris@0 214 PaneStack::setCurrentPane(Pane *pane) // may be null
Chris@0 215 {
Chris@0 216 if (m_currentPane == pane) return;
Chris@0 217
Chris@52 218 std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@0 219
Chris@0 220 // We used to do this by setting the foreground and background
Chris@0 221 // role, but it seems the background role is ignored and the
Chris@0 222 // background drawn transparent in Qt 4.1 -- I can't quite see why
Chris@0 223
Chris@0 224 QPixmap selectedMap(1, 1);
Chris@0 225 selectedMap.fill(QApplication::palette().color(QPalette::Foreground));
Chris@0 226
Chris@0 227 QPixmap unselectedMap(1, 1);
Chris@0 228 unselectedMap.fill(QApplication::palette().color(QPalette::Background));
Chris@0 229
Chris@52 230 bool found = false;
Chris@52 231
Chris@0 232 while (i != m_panes.end()) {
Chris@52 233 if (i->pane == pane) {
Chris@52 234 i->currentIndicator->setPixmap(selectedMap);
Chris@52 235 found = true;
Chris@0 236 } else {
Chris@52 237 i->currentIndicator->setPixmap(unselectedMap);
Chris@0 238 }
Chris@0 239 ++i;
Chris@0 240 }
Chris@0 241
Chris@52 242 if (found || pane == 0) {
Chris@52 243 m_currentPane = pane;
Chris@52 244 emit currentPaneChanged(m_currentPane);
Chris@52 245 } else {
Chris@52 246 std::cerr << "WARNING: PaneStack::setCurrentPane(" << pane << "): pane is not a visible pane in this stack" << std::endl;
Chris@52 247 }
Chris@0 248 }
Chris@0 249
Chris@19 250 void
Chris@19 251 PaneStack::setCurrentLayer(Pane *pane, Layer *layer) // may be null
Chris@19 252 {
Chris@19 253 setCurrentPane(pane);
Chris@19 254
Chris@19 255 if (m_currentPane) {
Chris@19 256
Chris@52 257 std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@19 258
Chris@19 259 while (i != m_panes.end()) {
Chris@19 260
Chris@52 261 if (i->pane == pane) {
Chris@52 262 PropertyStack *stack = dynamic_cast<PropertyStack *>
Chris@52 263 (i->propertyStack);
Chris@19 264 if (stack) {
Chris@19 265 if (stack->containsContainer(layer)) {
Chris@19 266 stack->setCurrentIndex(stack->getContainerIndex(layer));
Chris@19 267 emit currentLayerChanged(pane, layer);
Chris@19 268 } else {
Chris@33 269 stack->setCurrentIndex
Chris@33 270 (stack->getContainerIndex
Chris@33 271 (pane->getPropertyContainer(0)));
Chris@19 272 emit currentLayerChanged(pane, 0);
Chris@19 273 }
Chris@19 274 }
Chris@19 275 break;
Chris@19 276 }
Chris@19 277 ++i;
Chris@19 278 }
Chris@19 279 }
Chris@19 280 }
Chris@19 281
Chris@0 282 Pane *
Chris@0 283 PaneStack::getCurrentPane()
Chris@0 284 {
Chris@0 285 return m_currentPane;
Chris@0 286 }
Chris@0 287
Chris@0 288 void
Chris@0 289 PaneStack::propertyContainerAdded(PropertyContainer *)
Chris@0 290 {
Chris@0 291 sizePropertyStacks();
Chris@0 292 }
Chris@0 293
Chris@0 294 void
Chris@0 295 PaneStack::propertyContainerRemoved(PropertyContainer *)
Chris@0 296 {
Chris@0 297 sizePropertyStacks();
Chris@0 298 }
Chris@0 299
Chris@0 300 void
Chris@52 301 PaneStack::propertyContainerSelected(View *client, PropertyContainer *pc)
Chris@0 302 {
Chris@52 303 std::vector<PaneRec>::iterator i = m_panes.begin();
Chris@0 304
Chris@0 305 while (i != m_panes.end()) {
Chris@52 306 PropertyStack *stack = dynamic_cast<PropertyStack *>(i->propertyStack);
Chris@52 307 if (stack &&
Chris@52 308 stack->getClient() == client &&
Chris@52 309 stack->containsContainer(pc)) {
Chris@52 310 setCurrentPane(i->pane);
Chris@0 311 break;
Chris@0 312 }
Chris@0 313 ++i;
Chris@0 314 }
Chris@17 315
Chris@17 316 Layer *layer = dynamic_cast<Layer *>(pc);
Chris@17 317 if (layer) emit currentLayerChanged(m_currentPane, layer);
Chris@17 318 else emit currentLayerChanged(m_currentPane, 0);
Chris@0 319 }
Chris@0 320
Chris@0 321 void
Chris@0 322 PaneStack::paneInteractedWith()
Chris@0 323 {
Chris@0 324 Pane *pane = dynamic_cast<Pane *>(sender());
Chris@0 325 if (!pane) return;
Chris@0 326 setCurrentPane(pane);
Chris@0 327 }
Chris@0 328
Chris@0 329 void
Chris@89 330 PaneStack::rightButtonMenuRequested(QPoint position)
Chris@89 331 {
Chris@89 332 Pane *pane = dynamic_cast<Pane *>(sender());
Chris@89 333 if (!pane) return;
Chris@89 334 emit rightButtonMenuRequested(pane, position);
Chris@89 335 }
Chris@89 336
Chris@89 337 void
Chris@0 338 PaneStack::sizePropertyStacks()
Chris@0 339 {
Chris@0 340 int maxMinWidth = 0;
Chris@0 341
Chris@52 342 for (size_t i = 0; i < m_panes.size(); ++i) {
Chris@52 343 if (!m_panes[i].propertyStack) continue;
Chris@79 344 // std::cerr << "PaneStack::sizePropertyStacks: " << i << ": min "
Chris@79 345 // << m_panes[i].propertyStack->minimumSizeHint().width() << ", current "
Chris@79 346 // << m_panes[i].propertyStack->width() << std::endl;
Chris@0 347
Chris@52 348 if (m_panes[i].propertyStack->minimumSizeHint().width() > maxMinWidth) {
Chris@52 349 maxMinWidth = m_panes[i].propertyStack->minimumSizeHint().width();
Chris@0 350 }
Chris@0 351 }
Chris@0 352
Chris@79 353 // std::cerr << "PaneStack::sizePropertyStacks: max min width " << maxMinWidth << std::endl;
Chris@0 354
Chris@0 355 #ifdef Q_WS_MAC
Chris@0 356 // This is necessary to compensate for cb->setMinimumSize(10, 10)
Chris@0 357 // in PropertyBox in the Mac version (to avoid a mysterious crash)
Chris@0 358 int setWidth = maxMinWidth * 3 / 2;
Chris@0 359 #else
Chris@0 360 int setWidth = maxMinWidth;
Chris@0 361 #endif
Chris@0 362
Chris@52 363 for (size_t i = 0; i < m_panes.size(); ++i) {
Chris@52 364 if (!m_panes[i].propertyStack) continue;
Chris@52 365 m_panes[i].propertyStack->setMinimumWidth(setWidth);
Chris@0 366 }
Chris@0 367 }
Chris@0 368
Chris@0 369
Chris@0 370 #ifdef INCLUDE_MOCFILES
Chris@0 371 #include "PaneStack.moc.cpp"
Chris@0 372 #endif
Chris@0 373