annotate widgets/PropertyStack.cpp @ 1544:2d4107270015

Return true from getValueExtents always, just with no unit in the case where we don't have a nice neat scale. This should preserve the property of preventing other layers auto-aligning to us, while also ensuring we don't get overlooked for the purposes of drawing our own scale in a situation where a scale-less layer is on top of us
author Chris Cannam
date Wed, 16 Oct 2019 13:02:52 +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