annotate widgets/PropertyStack.cpp @ 1613:fe9a643b83bf

Merge from branch csv-import-headers
author Chris Cannam
date Thu, 18 Jun 2020 13:45:11 +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