annotate widgets/PropertyStack.cpp @ 1534:bfd8b22fd67c

Fix #1904 Scrolling colour 3d plot does not always work when in View normalisation mode. We shouldn't imagine we've just invalidated the cache if the truth is that we've only just created the renderer
author Chris Cannam
date Wed, 09 Oct 2019 13:45:17 +0100
parents 284a38c43721
children 01a41a37bd26
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@1174 28 #include "WidgetScale.h"
Chris@1174 29
Chris@0 30 #include <QIcon>
Chris@0 31 #include <QTabWidget>
Chris@0 32
Chris@0 33 #include <iostream>
Chris@0 34
Chris@939 35 //#define DEBUG_PROPERTY_STACK 1
Chris@0 36
Chris@0 37 PropertyStack::PropertyStack(QWidget *parent, View *client) :
Chris@0 38 QTabWidget(parent),
Chris@0 39 m_client(client)
Chris@0 40 {
Chris@190 41 NotifyingTabBar *bar = new NotifyingTabBar();
Chris@190 42 bar->setDrawBase(false);
Chris@190 43
Chris@190 44 connect(bar, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredTabBar()));
Chris@190 45 connect(bar, SIGNAL(mouseLeft()), this, SLOT(mouseLeftTabBar()));
Chris@190 46 connect(bar, SIGNAL(activeTabClicked()), this, SLOT(activeTabClicked()));
Chris@190 47
Chris@190 48 setTabBar(bar);
Chris@190 49
Chris@242 50 setElideMode(Qt::ElideNone);
Chris@241 51 tabBar()->setUsesScrollButtons(true);
Chris@1174 52 tabBar()->setIconSize(WidgetScale::scaleQSize(QSize(16, 16)));
Chris@980 53
Chris@0 54 repopulate();
Chris@0 55
Chris@0 56 connect(this, SIGNAL(currentChanged(int)),
Chris@1266 57 this, SLOT(selectedContainerChanged(int)));
Chris@0 58
Chris@0 59 connect(m_client, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@1266 60 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@0 61
Chris@0 62 connect(m_client, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@1266 63 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@0 64
Chris@0 65 connect(m_client, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
Chris@1266 66 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
Chris@0 67
Chris@197 68 connect(m_client, SIGNAL(propertyContainerPropertyRangeChanged(PropertyContainer *)),
Chris@1266 69 this, SLOT(propertyContainerPropertyRangeChanged(PropertyContainer *)));
Chris@197 70
Chris@0 71 connect(m_client, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
Chris@1266 72 this, SLOT(propertyContainerNameChanged(PropertyContainer *)));
Chris@0 73
Chris@52 74 connect(this, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
Chris@1266 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@1525 88 SVDEBUG << "PropertyStack[" << this << "]::repopulate" << endl;
Chris@0 89 #endif
Chris@0 90
Chris@1525 91 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 92 SVDEBUG << "PropertyStack[" << this << "]::repopulate: removing tabs" << endl;
Chris@1525 93 #endif
Chris@0 94 while (count() > 0) {
Chris@1266 95 removeTab(0);
Chris@0 96 }
Chris@1525 97
Chris@1525 98 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 99 SVDEBUG << "PropertyStack[" << this << "]::repopulate: deleting boxes" << endl;
Chris@1525 100 #endif
Chris@0 101 for (size_t i = 0; i < m_boxes.size(); ++i) {
Chris@1525 102 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 103 SVDEBUG << "(" << i << " of " << m_boxes.size() << ": " << m_boxes[i]->getContainer()->getPropertyContainerName() << ")" << endl;
Chris@1525 104 #endif
Chris@1266 105 delete m_boxes[i];
Chris@0 106 }
Chris@1525 107
Chris@1525 108 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 109 SVDEBUG << "PropertyStack[" << this << "]::repopulate: done, clearing m_boxes" << endl;
Chris@1525 110 #endif
Chris@0 111 m_boxes.clear();
Chris@0 112
Chris@807 113 for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@0 114
Chris@1266 115 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@1266 116 QString name = container->getPropertyContainerName();
Chris@1266 117
Chris@835 118 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 119 SVDEBUG << "PropertyStack[" << this << "]::repopulate: client " << m_client
Chris@1525 120 << " returns container " << container << " (name " << name
Chris@1525 121 << ") at position " << i << endl;
Chris@835 122 #endif
Chris@835 123
Chris@1266 124 PropertyBox *box = new PropertyBox(container);
Chris@0 125
Chris@1266 126 connect(box, SIGNAL(showLayer(bool)), this, SLOT(showLayer(bool)));
Chris@189 127 connect(box, SIGNAL(contextHelpChanged(const QString &)),
Chris@189 128 this, SIGNAL(contextHelpChanged(const QString &)));
Chris@47 129
Chris@185 130 Layer *layer = dynamic_cast<Layer *>(container);
Chris@185 131 if (layer) {
Chris@185 132 box->layerVisibilityChanged(!layer->isLayerDormant(m_client));
Chris@185 133 }
Chris@185 134
Chris@242 135 QString shortName = name;
Chris@242 136
Chris@242 137 if (layer) {
Chris@242 138 shortName = LayerFactory::getInstance()->getLayerPresentationName
Chris@242 139 (LayerFactory::getInstance()->getLayerType(layer));
Chris@552 140 if (layer->getLayerPresentationName() != "") {
Chris@552 141 name = layer->getLayerPresentationName();
Chris@552 142 }
Chris@242 143 }
Chris@242 144
Chris@552 145 bool nameDiffers = (name != shortName);
Chris@242 146 shortName = QString("&%1 %2").arg(i + 1).arg(shortName);
Chris@242 147
Chris@1266 148 QString iconName = container->getPropertyContainerIconName();
Chris@242 149
Chris@289 150 QIcon icon(IconLoader().load(iconName));
Chris@1266 151 if (icon.isNull()) {
Chris@1266 152 addTab(box, shortName);
Chris@552 153 if (nameDiffers) {
Chris@552 154 setTabToolTip(i, name);
Chris@552 155 }
Chris@1266 156 } else {
Chris@1266 157 addTab(box, icon, QString("&%1").arg(i + 1));
Chris@1266 158 setTabToolTip(i, name);
Chris@1266 159 }
Chris@0 160
Chris@1266 161 m_boxes.push_back(box);
Chris@0 162 }
Chris@0 163
Chris@0 164 blockSignals(false);
Chris@0 165 }
Chris@0 166
Chris@0 167 bool
Chris@0 168 PropertyStack::containsContainer(PropertyContainer *pc) const
Chris@0 169 {
Chris@807 170 for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@1266 171 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@1266 172 if (pc == container) return true;
Chris@0 173 }
Chris@0 174
Chris@0 175 return false;
Chris@0 176 }
Chris@0 177
Chris@19 178 int
Chris@19 179 PropertyStack::getContainerIndex(PropertyContainer *pc) const
Chris@19 180 {
Chris@723 181 // This is used to obtain an index to be passed to setCurrentIndex
Chris@723 182 // -- which is the index of the property container's box in our
Chris@723 183 // stack of boxes. That is not the same thing as the index of the
Chris@723 184 // container (i.e. the layer) in the view: the view reorders its
Chris@723 185 // containers whenever one is raised to the top, while our boxes
Chris@723 186 // remain in the same order. So we must find this container in the
Chris@723 187 // box list, not in the view.
Chris@723 188
Chris@908 189 for (int i = 0; in_range_for(m_boxes, i); ++i) {
Chris@1266 190 PropertyContainer *container = m_boxes[i]->getContainer();
Chris@1266 191 if (pc == container) {
Chris@723 192 return i;
Chris@723 193 }
Chris@19 194 }
Chris@19 195
Chris@19 196 return false;
Chris@19 197 }
Chris@19 198
Chris@0 199 void
Chris@1525 200 PropertyStack::propertyContainerAdded(PropertyContainer *
Chris@1525 201 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 202 c
Chris@1525 203 #endif
Chris@1525 204 )
Chris@0 205 {
Chris@0 206 if (sender() != m_client) return;
Chris@1525 207 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 208 SVDEBUG << "PropertyStack::propertyContainerAdded(" << (c ? c->getPropertyContainerName() : "(none)") << ")" << endl;
Chris@1525 209 #endif
Chris@0 210 repopulate();
Chris@0 211 }
Chris@0 212
Chris@0 213 void
Chris@1525 214 PropertyStack::propertyContainerRemoved(PropertyContainer *
Chris@1525 215 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 216 c
Chris@1525 217 #endif
Chris@1525 218 )
Chris@0 219 {
Chris@0 220 if (sender() != m_client) return;
Chris@1525 221 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 222 SVDEBUG << "PropertyStack::propertyContainerAdded(" << (c ? c->getPropertyContainerName() : "(none)") << ")" << endl;
Chris@1525 223 #endif
Chris@0 224 repopulate();
Chris@0 225 }
Chris@0 226
Chris@0 227 void
Chris@0 228 PropertyStack::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 229 {
Chris@298 230 Layer *layer = dynamic_cast<Layer *>(pc);
Chris@0 231 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@1266 232 if (pc == m_boxes[i]->getContainer()) {
Chris@1266 233 m_boxes[i]->propertyContainerPropertyChanged(pc);
Chris@298 234 if (layer) {
Chris@298 235 m_boxes[i]->layerVisibilityChanged
Chris@298 236 (!layer->isLayerDormant(m_client));
Chris@298 237 }
Chris@1266 238 }
Chris@0 239 }
Chris@0 240 }
Chris@0 241
Chris@0 242 void
Chris@197 243 PropertyStack::propertyContainerPropertyRangeChanged(PropertyContainer *pc)
Chris@197 244 {
Chris@197 245 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@1266 246 if (pc == m_boxes[i]->getContainer()) {
Chris@1266 247 m_boxes[i]->propertyContainerPropertyRangeChanged(pc);
Chris@1266 248 }
Chris@197 249 }
Chris@197 250 }
Chris@197 251
Chris@197 252 void
Chris@249 253 PropertyStack::propertyContainerNameChanged(PropertyContainer *)
Chris@0 254 {
Chris@0 255 if (sender() != m_client) return;
Chris@0 256 repopulate();
Chris@0 257 }
Chris@0 258
Chris@0 259 void
Chris@47 260 PropertyStack::showLayer(bool show)
Chris@47 261 {
Chris@47 262 QObject *obj = sender();
Chris@47 263
Chris@47 264 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@1266 265 if (obj == m_boxes[i]) {
Chris@1266 266 Layer *layer = dynamic_cast<Layer *>(m_boxes[i]->getContainer());
Chris@1266 267 if (layer) {
Chris@377 268 CommandHistory::getInstance()->addCommand
Chris@397 269 (new ShowLayerCommand(m_client, layer, show,
Chris@397 270 tr("Change Layer Visibility")));
Chris@1266 271 return;
Chris@1266 272 }
Chris@1266 273 }
Chris@47 274 }
Chris@47 275 }
Chris@47 276
Chris@47 277 void
Chris@0 278 PropertyStack::selectedContainerChanged(int n)
Chris@0 279 {
Chris@0 280 if (n >= int(m_boxes.size())) return;
Chris@52 281 emit propertyContainerSelected(m_client, m_boxes[n]->getContainer());
Chris@0 282 }
Chris@0 283
Chris@190 284 void
Chris@190 285 PropertyStack::mouseEnteredTabBar()
Chris@190 286 {
Chris@190 287 emit contextHelpChanged(tr("Click to change the current active layer"));
Chris@190 288 }
Chris@190 289
Chris@190 290 void
Chris@190 291 PropertyStack::mouseLeftTabBar()
Chris@190 292 {
Chris@190 293 emit contextHelpChanged("");
Chris@190 294 }
Chris@190 295
Chris@190 296 void
Chris@190 297 PropertyStack::activeTabClicked()
Chris@190 298 {
Chris@190 299 emit viewSelected(m_client);
Chris@190 300 }
Chris@190 301