annotate widgets/PropertyStack.cpp @ 1363:bbeffb29bf09

Fix inconsistency between centre frame actually set and centre frame notified as set, which caused the start frame location to creep out of place gradually as you page through
author Chris Cannam
date Tue, 30 Oct 2018 14:00:20 +0000
parents a34a2a25907c
children 284a38c43721
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@835 88 cerr << "PropertyStack[" << this << "]::repopulate" << endl;
Chris@0 89 #endif
Chris@0 90
Chris@0 91 while (count() > 0) {
Chris@1266 92 removeTab(0);
Chris@0 93 }
Chris@0 94 for (size_t i = 0; i < m_boxes.size(); ++i) {
Chris@1266 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@1266 101 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@1266 102 QString name = container->getPropertyContainerName();
Chris@1266 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@1266 110 PropertyBox *box = new PropertyBox(container);
Chris@0 111
Chris@1266 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@1266 134 QString iconName = container->getPropertyContainerIconName();
Chris@242 135
Chris@289 136 QIcon icon(IconLoader().load(iconName));
Chris@1266 137 if (icon.isNull()) {
Chris@1266 138 addTab(box, shortName);
Chris@552 139 if (nameDiffers) {
Chris@552 140 setTabToolTip(i, name);
Chris@552 141 }
Chris@1266 142 } else {
Chris@1266 143 addTab(box, icon, QString("&%1").arg(i + 1));
Chris@1266 144 setTabToolTip(i, name);
Chris@1266 145 }
Chris@0 146
Chris@1266 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@1266 157 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@1266 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@1266 176 PropertyContainer *container = m_boxes[i]->getContainer();
Chris@1266 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@1266 204 if (pc == m_boxes[i]->getContainer()) {
Chris@1266 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@1266 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@1266 218 if (pc == m_boxes[i]->getContainer()) {
Chris@1266 219 m_boxes[i]->propertyContainerPropertyRangeChanged(pc);
Chris@1266 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@1266 237 if (obj == m_boxes[i]) {
Chris@1266 238 Layer *layer = dynamic_cast<Layer *>(m_boxes[i]->getContainer());
Chris@1266 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@1266 243 return;
Chris@1266 244 }
Chris@1266 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