annotate widgets/PropertyStack.cpp @ 1605:ae2d5f8ff005

When asked to render the whole view width, we need to wait for the layers to be ready before we can determine what the width is
author Chris Cannam
date Thu, 30 Apr 2020 14:47:13 +0100
parents 01a41a37bd26
children
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@1582 48 bar->setContextMenuPolicy(Qt::CustomContextMenu);
Chris@1582 49 connect(bar, SIGNAL(customContextMenuRequested(const QPoint &)),
Chris@1582 50 this, SLOT(tabBarContextMenuRequested(const QPoint &)));
Chris@1582 51
Chris@190 52 setTabBar(bar);
Chris@190 53
Chris@242 54 setElideMode(Qt::ElideNone);
Chris@241 55 tabBar()->setUsesScrollButtons(true);
Chris@1174 56 tabBar()->setIconSize(WidgetScale::scaleQSize(QSize(16, 16)));
Chris@980 57
Chris@0 58 repopulate();
Chris@0 59
Chris@0 60 connect(this, SIGNAL(currentChanged(int)),
Chris@1266 61 this, SLOT(selectedContainerChanged(int)));
Chris@0 62
Chris@0 63 connect(m_client, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@1266 64 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@0 65
Chris@0 66 connect(m_client, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@1266 67 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@0 68
Chris@0 69 connect(m_client, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
Chris@1266 70 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
Chris@0 71
Chris@197 72 connect(m_client, SIGNAL(propertyContainerPropertyRangeChanged(PropertyContainer *)),
Chris@1266 73 this, SLOT(propertyContainerPropertyRangeChanged(PropertyContainer *)));
Chris@197 74
Chris@0 75 connect(m_client, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
Chris@1266 76 this, SLOT(propertyContainerNameChanged(PropertyContainer *)));
Chris@0 77
Chris@52 78 connect(this, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
Chris@1266 79 m_client, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
Chris@0 80 }
Chris@0 81
Chris@729 82 PropertyStack::~PropertyStack()
Chris@729 83 {
Chris@729 84 }
Chris@729 85
Chris@0 86 void
Chris@0 87 PropertyStack::repopulate()
Chris@0 88 {
Chris@0 89 blockSignals(true);
Chris@0 90
Chris@0 91 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 92 SVDEBUG << "PropertyStack[" << this << "]::repopulate" << endl;
Chris@0 93 #endif
Chris@0 94
Chris@1525 95 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 96 SVDEBUG << "PropertyStack[" << this << "]::repopulate: removing tabs" << endl;
Chris@1525 97 #endif
Chris@0 98 while (count() > 0) {
Chris@1266 99 removeTab(0);
Chris@0 100 }
Chris@1525 101
Chris@1525 102 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 103 SVDEBUG << "PropertyStack[" << this << "]::repopulate: deleting boxes" << endl;
Chris@1525 104 #endif
Chris@0 105 for (size_t i = 0; i < m_boxes.size(); ++i) {
Chris@1525 106 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 107 SVDEBUG << "(" << i << " of " << m_boxes.size() << ": " << m_boxes[i]->getContainer()->getPropertyContainerName() << ")" << endl;
Chris@1525 108 #endif
Chris@1266 109 delete m_boxes[i];
Chris@0 110 }
Chris@1525 111
Chris@1525 112 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 113 SVDEBUG << "PropertyStack[" << this << "]::repopulate: done, clearing m_boxes" << endl;
Chris@1525 114 #endif
Chris@0 115 m_boxes.clear();
Chris@0 116
Chris@807 117 for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@0 118
Chris@1266 119 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@1266 120 QString name = container->getPropertyContainerName();
Chris@1266 121
Chris@835 122 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 123 SVDEBUG << "PropertyStack[" << this << "]::repopulate: client " << m_client
Chris@1525 124 << " returns container " << container << " (name " << name
Chris@1525 125 << ") at position " << i << endl;
Chris@835 126 #endif
Chris@835 127
Chris@1266 128 PropertyBox *box = new PropertyBox(container);
Chris@0 129
Chris@1266 130 connect(box, SIGNAL(showLayer(bool)), this, SLOT(showLayer(bool)));
Chris@189 131 connect(box, SIGNAL(contextHelpChanged(const QString &)),
Chris@189 132 this, SIGNAL(contextHelpChanged(const QString &)));
Chris@47 133
Chris@185 134 Layer *layer = dynamic_cast<Layer *>(container);
Chris@185 135 if (layer) {
Chris@185 136 box->layerVisibilityChanged(!layer->isLayerDormant(m_client));
Chris@185 137 }
Chris@185 138
Chris@242 139 QString shortName = name;
Chris@242 140
Chris@242 141 if (layer) {
Chris@242 142 shortName = LayerFactory::getInstance()->getLayerPresentationName
Chris@242 143 (LayerFactory::getInstance()->getLayerType(layer));
Chris@552 144 if (layer->getLayerPresentationName() != "") {
Chris@552 145 name = layer->getLayerPresentationName();
Chris@552 146 }
Chris@242 147 }
Chris@242 148
Chris@552 149 bool nameDiffers = (name != shortName);
Chris@242 150 shortName = QString("&%1 %2").arg(i + 1).arg(shortName);
Chris@242 151
Chris@1266 152 QString iconName = container->getPropertyContainerIconName();
Chris@242 153
Chris@289 154 QIcon icon(IconLoader().load(iconName));
Chris@1266 155 if (icon.isNull()) {
Chris@1266 156 addTab(box, shortName);
Chris@552 157 if (nameDiffers) {
Chris@552 158 setTabToolTip(i, name);
Chris@552 159 }
Chris@1266 160 } else {
Chris@1266 161 addTab(box, icon, QString("&%1").arg(i + 1));
Chris@1266 162 setTabToolTip(i, name);
Chris@1266 163 }
Chris@0 164
Chris@1266 165 m_boxes.push_back(box);
Chris@0 166 }
Chris@0 167
Chris@0 168 blockSignals(false);
Chris@0 169 }
Chris@0 170
Chris@1582 171 void
Chris@1582 172 PropertyStack::tabBarContextMenuRequested(const QPoint &pos)
Chris@1582 173 {
Chris@1582 174 int tab = tabBar()->tabAt(pos);
Chris@1582 175 if (!in_range_for(m_boxes, tab)) {
Chris@1582 176 return;
Chris@1582 177 }
Chris@1582 178
Chris@1582 179 emit propertyContainerContextMenuRequested(m_client,
Chris@1582 180 m_boxes[tab]->getContainer(),
Chris@1582 181 mapToGlobal(pos));
Chris@1582 182 }
Chris@1582 183
Chris@0 184 bool
Chris@0 185 PropertyStack::containsContainer(PropertyContainer *pc) const
Chris@0 186 {
Chris@807 187 for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
Chris@1266 188 PropertyContainer *container = m_client->getPropertyContainer(i);
Chris@1266 189 if (pc == container) return true;
Chris@0 190 }
Chris@0 191
Chris@0 192 return false;
Chris@0 193 }
Chris@0 194
Chris@19 195 int
Chris@19 196 PropertyStack::getContainerIndex(PropertyContainer *pc) const
Chris@19 197 {
Chris@723 198 // This is used to obtain an index to be passed to setCurrentIndex
Chris@723 199 // -- which is the index of the property container's box in our
Chris@723 200 // stack of boxes. That is not the same thing as the index of the
Chris@723 201 // container (i.e. the layer) in the view: the view reorders its
Chris@723 202 // containers whenever one is raised to the top, while our boxes
Chris@723 203 // remain in the same order. So we must find this container in the
Chris@723 204 // box list, not in the view.
Chris@723 205
Chris@908 206 for (int i = 0; in_range_for(m_boxes, i); ++i) {
Chris@1266 207 PropertyContainer *container = m_boxes[i]->getContainer();
Chris@1266 208 if (pc == container) {
Chris@723 209 return i;
Chris@723 210 }
Chris@19 211 }
Chris@19 212
Chris@19 213 return false;
Chris@19 214 }
Chris@19 215
Chris@0 216 void
Chris@1525 217 PropertyStack::propertyContainerAdded(PropertyContainer *
Chris@1525 218 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 219 c
Chris@1525 220 #endif
Chris@1525 221 )
Chris@0 222 {
Chris@0 223 if (sender() != m_client) return;
Chris@1525 224 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 225 SVDEBUG << "PropertyStack::propertyContainerAdded(" << (c ? c->getPropertyContainerName() : "(none)") << ")" << endl;
Chris@1525 226 #endif
Chris@0 227 repopulate();
Chris@0 228 }
Chris@0 229
Chris@0 230 void
Chris@1525 231 PropertyStack::propertyContainerRemoved(PropertyContainer *
Chris@1525 232 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 233 c
Chris@1525 234 #endif
Chris@1525 235 )
Chris@0 236 {
Chris@0 237 if (sender() != m_client) return;
Chris@1525 238 #ifdef DEBUG_PROPERTY_STACK
Chris@1525 239 SVDEBUG << "PropertyStack::propertyContainerAdded(" << (c ? c->getPropertyContainerName() : "(none)") << ")" << endl;
Chris@1525 240 #endif
Chris@0 241 repopulate();
Chris@0 242 }
Chris@0 243
Chris@0 244 void
Chris@0 245 PropertyStack::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 246 {
Chris@298 247 Layer *layer = dynamic_cast<Layer *>(pc);
Chris@0 248 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@1266 249 if (pc == m_boxes[i]->getContainer()) {
Chris@1266 250 m_boxes[i]->propertyContainerPropertyChanged(pc);
Chris@298 251 if (layer) {
Chris@298 252 m_boxes[i]->layerVisibilityChanged
Chris@298 253 (!layer->isLayerDormant(m_client));
Chris@298 254 }
Chris@1266 255 }
Chris@0 256 }
Chris@0 257 }
Chris@0 258
Chris@0 259 void
Chris@197 260 PropertyStack::propertyContainerPropertyRangeChanged(PropertyContainer *pc)
Chris@197 261 {
Chris@197 262 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@1266 263 if (pc == m_boxes[i]->getContainer()) {
Chris@1266 264 m_boxes[i]->propertyContainerPropertyRangeChanged(pc);
Chris@1266 265 }
Chris@197 266 }
Chris@197 267 }
Chris@197 268
Chris@197 269 void
Chris@249 270 PropertyStack::propertyContainerNameChanged(PropertyContainer *)
Chris@0 271 {
Chris@0 272 if (sender() != m_client) return;
Chris@0 273 repopulate();
Chris@0 274 }
Chris@0 275
Chris@0 276 void
Chris@47 277 PropertyStack::showLayer(bool show)
Chris@47 278 {
Chris@47 279 QObject *obj = sender();
Chris@47 280
Chris@47 281 for (unsigned int i = 0; i < m_boxes.size(); ++i) {
Chris@1266 282 if (obj == m_boxes[i]) {
Chris@1266 283 Layer *layer = dynamic_cast<Layer *>(m_boxes[i]->getContainer());
Chris@1266 284 if (layer) {
Chris@377 285 CommandHistory::getInstance()->addCommand
Chris@397 286 (new ShowLayerCommand(m_client, layer, show,
Chris@397 287 tr("Change Layer Visibility")));
Chris@1266 288 return;
Chris@1266 289 }
Chris@1266 290 }
Chris@47 291 }
Chris@47 292 }
Chris@47 293
Chris@47 294 void
Chris@0 295 PropertyStack::selectedContainerChanged(int n)
Chris@0 296 {
Chris@0 297 if (n >= int(m_boxes.size())) return;
Chris@52 298 emit propertyContainerSelected(m_client, m_boxes[n]->getContainer());
Chris@0 299 }
Chris@0 300
Chris@190 301 void
Chris@190 302 PropertyStack::mouseEnteredTabBar()
Chris@190 303 {
Chris@190 304 emit contextHelpChanged(tr("Click to change the current active layer"));
Chris@190 305 }
Chris@190 306
Chris@190 307 void
Chris@190 308 PropertyStack::mouseLeftTabBar()
Chris@190 309 {
Chris@190 310 emit contextHelpChanged("");
Chris@190 311 }
Chris@190 312
Chris@190 313 void
Chris@190 314 PropertyStack::activeTabClicked()
Chris@190 315 {
Chris@190 316 emit viewSelected(m_client);
Chris@190 317 }
Chris@190 318