annotate widgets/PropertyStack.cpp @ 1127:9fb8dfd7ce4c spectrogram-minor-refactor

Fix threshold in spectrogram -- it wasn't working in the last release. There is a new protocol for this. Formerly the threshold parameter had a range from -50dB to 0 with the default at -50, and -50 treated internally as "no threshold". However, there was a hardcoded, hidden internal threshold for spectrogram colour mapping at -80dB with anything below this being rounded to zero. Now the threshold parameter has range -81 to -1 with the default at -80, -81 is treated internally as "no threshold", and there is no hidden internal threshold. So the default behaviour is the same as before, an effective -80dB threshold, but it is now possible to change this in both directions. Sessions reloaded from prior versions may look slightly different because, if the session says there should be no threshold, there will now actually be no threshold instead of having the hidden internal one. Still need to do something in the UI to make it apparent that the -81dB setting removes the threshold entirely. This is at least no worse than the previous, also obscured, magic -50dB setting.
author Chris Cannam
date Mon, 01 Aug 2016 16:21:01 +0100
parents 66da6f009edd
children 3f5c82034f9b
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@377 24 #include "base/Command.h"
Chris@377 25 #include "widgets/CommandHistory.h"
Chris@732 26 #include "layer/ShowLayerCommand.h"
Chris@0 27
Chris@0 28 #include <QIcon>
Chris@0 29 #include <QTabWidget>
Chris@0 30
Chris@0 31 #include <iostream>
Chris@0 32
Chris@939 33 //#define DEBUG_PROPERTY_STACK 1
Chris@0 34
Chris@0 35 PropertyStack::PropertyStack(QWidget *parent, View *client) :
Chris@0 36 QTabWidget(parent),
Chris@0 37 m_client(client)
Chris@0 38 {
Chris@190 39 NotifyingTabBar *bar = new NotifyingTabBar();
Chris@190 40 bar->setDrawBase(false);
Chris@190 41
Chris@190 42 connect(bar, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredTabBar()));
Chris@190 43 connect(bar, SIGNAL(mouseLeft()), this, SLOT(mouseLeftTabBar()));
Chris@190 44 connect(bar, SIGNAL(activeTabClicked()), this, SLOT(activeTabClicked()));
Chris@190 45
Chris@190 46 setTabBar(bar);
Chris@190 47
Chris@242 48 #if (QT_VERSION >= 0x0402)
Chris@242 49 setElideMode(Qt::ElideNone);
Chris@241 50 tabBar()->setUsesScrollButtons(true);
Chris@241 51 tabBar()->setIconSize(QSize(16, 16));
Chris@242 52 #endif
Chris@980 53
Chris@0 54 repopulate();
Chris@0 55
Chris@0 56 connect(this, SIGNAL(currentChanged(int)),
Chris@0 57 this, SLOT(selectedContainerChanged(int)));
Chris@0 58
Chris@0 59 connect(m_client, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@0 60 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@0 61
Chris@0 62 connect(m_client, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@0 63 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@0 64
Chris@0 65 connect(m_client, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
Chris@0 66 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
Chris@0 67
Chris@197 68 connect(m_client, SIGNAL(propertyContainerPropertyRangeChanged(PropertyContainer *)),
Chris@197 69 this, SLOT(propertyContainerPropertyRangeChanged(PropertyContainer *)));
Chris@197 70
Chris@0 71 connect(m_client, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
Chris@0 72 this, SLOT(propertyContainerNameChanged(PropertyContainer *)));
Chris@0 73
Chris@52 74 connect(this, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
Chris@52 75 m_client, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
Chris@0 76 }
Chris@0 77
Chris@729 78 PropertyStack::~PropertyStack()
Chris@729 79 {
Chris@729 80 }
Chris@729 81
Chris@0 82 void
Chris@0 83 PropertyStack::repopulate()
Chris@0 84 {
Chris@0 85 blockSignals(true);
Chris@0 86
Chris@0 87 #ifdef DEBUG_PROPERTY_STACK
Chris@835 88 cerr << "PropertyStack[" << this << "]::repopulate" << endl;
Chris@0 89 #endif
Chris@0 90
Chris@0 91 while (count() > 0) {
Chris@0 92 removeTab(0);
Chris@0 93 }
Chris@0 94 for (size_t i = 0; i < m_boxes.size(); ++i) {
Chris@0 95 delete m_boxes[i];
Chris@0 96 }
Chris@0 97 m_boxes.clear();
Chris@0 98
Chris@807 99 for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@0 100
Chris@0 101 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@0 102 QString name = container->getPropertyContainerName();
Chris@0 103
Chris@835 104 #ifdef DEBUG_PROPERTY_STACK
Chris@835 105 cerr << "PropertyStack[" << this << "]::repopulate: client " << m_client
Chris@835 106 << " returns container " << container << " (name " << name
Chris@835 107 << ") at position " << i << endl;
Chris@835 108 #endif
Chris@835 109
Chris@0 110 PropertyBox *box = new PropertyBox(container);
Chris@0 111
Chris@47 112 connect(box, SIGNAL(showLayer(bool)), this, SLOT(showLayer(bool)));
Chris@189 113 connect(box, SIGNAL(contextHelpChanged(const QString &)),
Chris@189 114 this, SIGNAL(contextHelpChanged(const QString &)));
Chris@47 115
Chris@185 116 Layer *layer = dynamic_cast<Layer *>(container);
Chris@185 117 if (layer) {
Chris@185 118 box->layerVisibilityChanged(!layer->isLayerDormant(m_client));
Chris@185 119 }
Chris@185 120
Chris@242 121 QString shortName = name;
Chris@242 122
Chris@242 123 if (layer) {
Chris@242 124 shortName = LayerFactory::getInstance()->getLayerPresentationName
Chris@242 125 (LayerFactory::getInstance()->getLayerType(layer));
Chris@552 126 if (layer->getLayerPresentationName() != "") {
Chris@552 127 name = layer->getLayerPresentationName();
Chris@552 128 }
Chris@242 129 }
Chris@242 130
Chris@552 131 bool nameDiffers = (name != shortName);
Chris@242 132 shortName = QString("&%1 %2").arg(i + 1).arg(shortName);
Chris@242 133
Chris@242 134 QString iconName = container->getPropertyContainerIconName();
Chris@242 135
Chris@289 136 QIcon icon(IconLoader().load(iconName));
Chris@0 137 if (icon.isNull()) {
Chris@242 138 addTab(box, shortName);
Chris@552 139 if (nameDiffers) {
Chris@552 140 setTabToolTip(i, name);
Chris@552 141 }
Chris@0 142 } else {
Chris@0 143 addTab(box, icon, QString("&%1").arg(i + 1));
Chris@242 144 setTabToolTip(i, name);
Chris@0 145 }
Chris@0 146
Chris@0 147 m_boxes.push_back(box);
Chris@0 148 }
Chris@0 149
Chris@0 150 blockSignals(false);
Chris@0 151 }
Chris@0 152
Chris@0 153 bool
Chris@0 154 PropertyStack::containsContainer(PropertyContainer *pc) const
Chris@0 155 {
Chris@807 156 for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@0 157 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@0 158 if (pc == container) return true;
Chris@0 159 }
Chris@0 160
Chris@0 161 return false;
Chris@0 162 }
Chris@0 163
Chris@19 164 int
Chris@19 165 PropertyStack::getContainerIndex(PropertyContainer *pc) const
Chris@19 166 {
Chris@723 167 // This is used to obtain an index to be passed to setCurrentIndex
Chris@723 168 // -- which is the index of the property container's box in our
Chris@723 169 // stack of boxes. That is not the same thing as the index of the
Chris@723 170 // container (i.e. the layer) in the view: the view reorders its
Chris@723 171 // containers whenever one is raised to the top, while our boxes
Chris@723 172 // remain in the same order. So we must find this container in the
Chris@723 173 // box list, not in the view.
Chris@723 174
Chris@908 175 for (int i = 0; in_range_for(m_boxes, i); ++i) {
Chris@723 176 PropertyContainer *container = m_boxes[i]->getContainer();
Chris@723 177 if (pc == container) {
Chris@723 178 return i;
Chris@723 179 }
Chris@19 180 }
Chris@19 181
Chris@19 182 return false;
Chris@19 183 }
Chris@19 184
Chris@0 185 void
Chris@0 186 PropertyStack::propertyContainerAdded(PropertyContainer *)
Chris@0 187 {
Chris@0 188 if (sender() != m_client) return;
Chris@0 189 repopulate();
Chris@0 190 }
Chris@0 191
Chris@0 192 void
Chris@0 193 PropertyStack::propertyContainerRemoved(PropertyContainer *)
Chris@0 194 {
Chris@0 195 if (sender() != m_client) return;
Chris@0 196 repopulate();
Chris@0 197 }
Chris@0 198
Chris@0 199 void
Chris@0 200 PropertyStack::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 201 {
Chris@298 202 Layer *layer = dynamic_cast<Layer *>(pc);
Chris@0 203 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@0 204 if (pc == m_boxes[i]->getContainer()) {
Chris@0 205 m_boxes[i]->propertyContainerPropertyChanged(pc);
Chris@298 206 if (layer) {
Chris@298 207 m_boxes[i]->layerVisibilityChanged
Chris@298 208 (!layer->isLayerDormant(m_client));
Chris@298 209 }
Chris@0 210 }
Chris@0 211 }
Chris@0 212 }
Chris@0 213
Chris@0 214 void
Chris@197 215 PropertyStack::propertyContainerPropertyRangeChanged(PropertyContainer *pc)
Chris@197 216 {
Chris@197 217 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@197 218 if (pc == m_boxes[i]->getContainer()) {
Chris@197 219 m_boxes[i]->propertyContainerPropertyRangeChanged(pc);
Chris@197 220 }
Chris@197 221 }
Chris@197 222 }
Chris@197 223
Chris@197 224 void
Chris@249 225 PropertyStack::propertyContainerNameChanged(PropertyContainer *)
Chris@0 226 {
Chris@0 227 if (sender() != m_client) return;
Chris@0 228 repopulate();
Chris@0 229 }
Chris@0 230
Chris@0 231 void
Chris@47 232 PropertyStack::showLayer(bool show)
Chris@47 233 {
Chris@47 234 QObject *obj = sender();
Chris@47 235
Chris@47 236 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@47 237 if (obj == m_boxes[i]) {
Chris@47 238 Layer *layer = dynamic_cast<Layer *>(m_boxes[i]->getContainer());
Chris@47 239 if (layer) {
Chris@377 240 CommandHistory::getInstance()->addCommand
Chris@397 241 (new ShowLayerCommand(m_client, layer, show,
Chris@397 242 tr("Change Layer Visibility")));
Chris@47 243 return;
Chris@47 244 }
Chris@47 245 }
Chris@47 246 }
Chris@47 247 }
Chris@47 248
Chris@47 249 void
Chris@0 250 PropertyStack::selectedContainerChanged(int n)
Chris@0 251 {
Chris@0 252 if (n >= int(m_boxes.size())) return;
Chris@52 253 emit propertyContainerSelected(m_client, m_boxes[n]->getContainer());
Chris@0 254 }
Chris@0 255
Chris@190 256 void
Chris@190 257 PropertyStack::mouseEnteredTabBar()
Chris@190 258 {
Chris@190 259 emit contextHelpChanged(tr("Click to change the current active layer"));
Chris@190 260 }
Chris@190 261
Chris@190 262 void
Chris@190 263 PropertyStack::mouseLeftTabBar()
Chris@190 264 {
Chris@190 265 emit contextHelpChanged("");
Chris@190 266 }
Chris@190 267
Chris@190 268 void
Chris@190 269 PropertyStack::activeTabClicked()
Chris@190 270 {
Chris@190 271 emit viewSelected(m_client);
Chris@190 272 }
Chris@190 273