annotate widgets/PropertyStack.cpp @ 349:369a197737c7

* Various fixes to object lifetime management, particularly in the spectrum layer and for notification of main model deletion. The main purpose of this is to improve the behaviour of the spectrum, but I think it may also help with #1840922 Various crashes in Layer Summary window.
author Chris Cannam
date Wed, 23 Jan 2008 15:43:27 +0000
parents 226cb289bdf4
children 25e72328a897 0895517bb2d1
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@59 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "PropertyStack.h"
Chris@0 17 #include "PropertyBox.h"
Chris@0 18 #include "base/PropertyContainer.h"
Chris@128 19 #include "view/View.h"
Chris@128 20 #include "layer/Layer.h"
Chris@242 21 #include "layer/LayerFactory.h"
Chris@190 22 #include "widgets/NotifyingTabBar.h"
Chris@289 23 #include "widgets/IconLoader.h"
Chris@0 24
Chris@0 25 #include <QIcon>
Chris@0 26 #include <QTabWidget>
Chris@0 27
Chris@0 28 #include <iostream>
Chris@0 29
Chris@36 30 //#define DEBUG_PROPERTY_STACK 1
Chris@0 31
Chris@0 32 PropertyStack::PropertyStack(QWidget *parent, View *client) :
Chris@0 33 QTabWidget(parent),
Chris@0 34 m_client(client)
Chris@0 35 {
Chris@190 36 NotifyingTabBar *bar = new NotifyingTabBar();
Chris@190 37 bar->setDrawBase(false);
Chris@190 38
Chris@190 39 connect(bar, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredTabBar()));
Chris@190 40 connect(bar, SIGNAL(mouseLeft()), this, SLOT(mouseLeftTabBar()));
Chris@190 41 connect(bar, SIGNAL(activeTabClicked()), this, SLOT(activeTabClicked()));
Chris@190 42
Chris@190 43 setTabBar(bar);
Chris@190 44
Chris@242 45 #if (QT_VERSION >= 0x0402)
Chris@242 46 setElideMode(Qt::ElideNone);
Chris@241 47 tabBar()->setUsesScrollButtons(true);
Chris@241 48 tabBar()->setIconSize(QSize(16, 16));
Chris@242 49 #endif
Chris@239 50
Chris@0 51 repopulate();
Chris@0 52
Chris@0 53 connect(this, SIGNAL(currentChanged(int)),
Chris@0 54 this, SLOT(selectedContainerChanged(int)));
Chris@0 55
Chris@0 56 connect(m_client, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@0 57 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@0 58
Chris@0 59 connect(m_client, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@0 60 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@0 61
Chris@0 62 connect(m_client, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
Chris@0 63 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
Chris@0 64
Chris@197 65 connect(m_client, SIGNAL(propertyContainerPropertyRangeChanged(PropertyContainer *)),
Chris@197 66 this, SLOT(propertyContainerPropertyRangeChanged(PropertyContainer *)));
Chris@197 67
Chris@0 68 connect(m_client, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
Chris@0 69 this, SLOT(propertyContainerNameChanged(PropertyContainer *)));
Chris@0 70
Chris@52 71 connect(this, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
Chris@52 72 m_client, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
Chris@0 73 }
Chris@0 74
Chris@0 75 void
Chris@0 76 PropertyStack::repopulate()
Chris@0 77 {
Chris@0 78 blockSignals(true);
Chris@0 79
Chris@0 80 #ifdef DEBUG_PROPERTY_STACK
Chris@0 81 std::cerr << "PropertyStack::repopulate" << std::endl;
Chris@0 82 #endif
Chris@0 83
Chris@0 84 while (count() > 0) {
Chris@0 85 removeTab(0);
Chris@0 86 }
Chris@0 87 for (size_t i = 0; i < m_boxes.size(); ++i) {
Chris@0 88 delete m_boxes[i];
Chris@0 89 }
Chris@0 90 m_boxes.clear();
Chris@0 91
Chris@0 92 for (size_t i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@0 93
Chris@0 94 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@0 95 QString name = container->getPropertyContainerName();
Chris@0 96
Chris@0 97 PropertyBox *box = new PropertyBox(container);
Chris@0 98
Chris@47 99 connect(box, SIGNAL(showLayer(bool)), this, SLOT(showLayer(bool)));
Chris@189 100 connect(box, SIGNAL(contextHelpChanged(const QString &)),
Chris@189 101 this, SIGNAL(contextHelpChanged(const QString &)));
Chris@47 102
Chris@185 103 Layer *layer = dynamic_cast<Layer *>(container);
Chris@185 104 if (layer) {
Chris@185 105 box->layerVisibilityChanged(!layer->isLayerDormant(m_client));
Chris@185 106 }
Chris@185 107
Chris@242 108 QString shortName = name;
Chris@242 109
Chris@242 110 if (layer) {
Chris@242 111 shortName = LayerFactory::getInstance()->getLayerPresentationName
Chris@242 112 (LayerFactory::getInstance()->getLayerType(layer));
Chris@242 113 }
Chris@242 114
Chris@242 115 shortName = QString("&%1 %2").arg(i + 1).arg(shortName);
Chris@242 116
Chris@242 117 #ifdef Q_WS_MAC
Chris@242 118
Chris@242 119 // Qt 4.2 on OS/X doesn't show the icons in the tab bar, and
Chris@242 120 // I'm not sure why -- use labels instead
Chris@242 121
Chris@242 122 addTab(box, shortName);
Chris@242 123
Chris@242 124 #else
Chris@242 125
Chris@242 126 // Icons on other platforms
Chris@242 127
Chris@242 128 QString iconName = container->getPropertyContainerIconName();
Chris@242 129
Chris@289 130 QIcon icon(IconLoader().load(iconName));
Chris@0 131 if (icon.isNull()) {
Chris@242 132 addTab(box, shortName);
Chris@0 133 } else {
Chris@0 134 addTab(box, icon, QString("&%1").arg(i + 1));
Chris@242 135 setTabToolTip(i, name);
Chris@0 136 }
Chris@0 137
Chris@242 138 #endif
Chris@242 139
Chris@0 140 m_boxes.push_back(box);
Chris@0 141 }
Chris@0 142
Chris@0 143 blockSignals(false);
Chris@0 144 }
Chris@0 145
Chris@0 146 bool
Chris@0 147 PropertyStack::containsContainer(PropertyContainer *pc) const
Chris@0 148 {
Chris@0 149 for (size_t i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@0 150 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@0 151 if (pc == container) return true;
Chris@0 152 }
Chris@0 153
Chris@0 154 return false;
Chris@0 155 }
Chris@0 156
Chris@19 157 int
Chris@19 158 PropertyStack::getContainerIndex(PropertyContainer *pc) const
Chris@19 159 {
Chris@19 160 for (size_t i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@19 161 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@19 162 if (pc == container) return i;
Chris@19 163 }
Chris@19 164
Chris@19 165 return false;
Chris@19 166 }
Chris@19 167
Chris@0 168 void
Chris@0 169 PropertyStack::propertyContainerAdded(PropertyContainer *)
Chris@0 170 {
Chris@0 171 if (sender() != m_client) return;
Chris@0 172 repopulate();
Chris@0 173 }
Chris@0 174
Chris@0 175 void
Chris@0 176 PropertyStack::propertyContainerRemoved(PropertyContainer *)
Chris@0 177 {
Chris@0 178 if (sender() != m_client) return;
Chris@0 179 repopulate();
Chris@0 180 }
Chris@0 181
Chris@0 182 void
Chris@0 183 PropertyStack::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 184 {
Chris@298 185 Layer *layer = dynamic_cast<Layer *>(pc);
Chris@0 186 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@0 187 if (pc == m_boxes[i]->getContainer()) {
Chris@0 188 m_boxes[i]->propertyContainerPropertyChanged(pc);
Chris@298 189 if (layer) {
Chris@298 190 m_boxes[i]->layerVisibilityChanged
Chris@298 191 (!layer->isLayerDormant(m_client));
Chris@298 192 }
Chris@0 193 }
Chris@0 194 }
Chris@0 195 }
Chris@0 196
Chris@0 197 void
Chris@197 198 PropertyStack::propertyContainerPropertyRangeChanged(PropertyContainer *pc)
Chris@197 199 {
Chris@197 200 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@197 201 if (pc == m_boxes[i]->getContainer()) {
Chris@197 202 m_boxes[i]->propertyContainerPropertyRangeChanged(pc);
Chris@197 203 }
Chris@197 204 }
Chris@197 205 }
Chris@197 206
Chris@197 207 void
Chris@249 208 PropertyStack::propertyContainerNameChanged(PropertyContainer *)
Chris@0 209 {
Chris@0 210 if (sender() != m_client) return;
Chris@0 211 repopulate();
Chris@0 212 }
Chris@0 213
Chris@0 214 void
Chris@47 215 PropertyStack::showLayer(bool show)
Chris@47 216 {
Chris@47 217 QObject *obj = sender();
Chris@47 218
Chris@47 219 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@47 220 if (obj == m_boxes[i]) {
Chris@47 221 Layer *layer = dynamic_cast<Layer *>(m_boxes[i]->getContainer());
Chris@47 222 if (layer) {
Chris@47 223 layer->showLayer(m_client, show);
Chris@47 224 return;
Chris@47 225 }
Chris@47 226 }
Chris@47 227 }
Chris@47 228 }
Chris@47 229
Chris@47 230 void
Chris@0 231 PropertyStack::selectedContainerChanged(int n)
Chris@0 232 {
Chris@0 233 if (n >= int(m_boxes.size())) return;
Chris@52 234 emit propertyContainerSelected(m_client, m_boxes[n]->getContainer());
Chris@0 235 }
Chris@0 236
Chris@190 237 void
Chris@190 238 PropertyStack::mouseEnteredTabBar()
Chris@190 239 {
Chris@190 240 emit contextHelpChanged(tr("Click to change the current active layer"));
Chris@190 241 }
Chris@190 242
Chris@190 243 void
Chris@190 244 PropertyStack::mouseLeftTabBar()
Chris@190 245 {
Chris@190 246 emit contextHelpChanged("");
Chris@190 247 }
Chris@190 248
Chris@190 249 void
Chris@190 250 PropertyStack::activeTabClicked()
Chris@190 251 {
Chris@190 252 emit viewSelected(m_client);
Chris@190 253 }
Chris@190 254