PropertyStack.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "PropertyStack.h"
17 #include "PropertyBox.h"
18 #include "base/PropertyContainer.h"
19 #include "view/View.h"
20 #include "layer/Layer.h"
21 #include "layer/LayerFactory.h"
23 #include "widgets/IconLoader.h"
24 #include "base/Command.h"
25 #include "widgets/CommandHistory.h"
26 #include "layer/ShowLayerCommand.h"
27 
28 #include "WidgetScale.h"
29 
30 #include <QIcon>
31 #include <QTabWidget>
32 
33 #include <iostream>
34 
35 //#define DEBUG_PROPERTY_STACK 1
36 
37 PropertyStack::PropertyStack(QWidget *parent, View *client) :
38  QTabWidget(parent),
39  m_client(client)
40 {
41  NotifyingTabBar *bar = new NotifyingTabBar();
42  bar->setDrawBase(false);
43 
44  connect(bar, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredTabBar()));
45  connect(bar, SIGNAL(mouseLeft()), this, SLOT(mouseLeftTabBar()));
46  connect(bar, SIGNAL(activeTabClicked()), this, SLOT(activeTabClicked()));
47 
48  bar->setContextMenuPolicy(Qt::CustomContextMenu);
49  connect(bar, SIGNAL(customContextMenuRequested(const QPoint &)),
50  this, SLOT(tabBarContextMenuRequested(const QPoint &)));
51 
52  setTabBar(bar);
53 
54  setElideMode(Qt::ElideNone);
55  tabBar()->setUsesScrollButtons(true);
56  tabBar()->setIconSize(WidgetScale::scaleQSize(QSize(16, 16)));
57 
58  repopulate();
59 
60  connect(this, SIGNAL(currentChanged(int)),
61  this, SLOT(selectedContainerChanged(int)));
62 
63  connect(m_client, SIGNAL(propertyContainerAdded(PropertyContainer *)),
64  this, SLOT(propertyContainerAdded(PropertyContainer *)));
65 
66  connect(m_client, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
67  this, SLOT(propertyContainerRemoved(PropertyContainer *)));
68 
69  connect(m_client, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
70  this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
71 
72  connect(m_client, SIGNAL(propertyContainerPropertyRangeChanged(PropertyContainer *)),
73  this, SLOT(propertyContainerPropertyRangeChanged(PropertyContainer *)));
74 
75  connect(m_client, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
76  this, SLOT(propertyContainerNameChanged(PropertyContainer *)));
77 
78  connect(this, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
79  m_client, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
80 }
81 
83 {
84 }
85 
86 void
88 {
89  blockSignals(true);
90 
91 #ifdef DEBUG_PROPERTY_STACK
92  SVDEBUG << "PropertyStack[" << this << "]::repopulate" << endl;
93 #endif
94 
95 #ifdef DEBUG_PROPERTY_STACK
96  SVDEBUG << "PropertyStack[" << this << "]::repopulate: removing tabs" << endl;
97 #endif
98  while (count() > 0) {
99  removeTab(0);
100  }
101 
102 #ifdef DEBUG_PROPERTY_STACK
103  SVDEBUG << "PropertyStack[" << this << "]::repopulate: deleting boxes" << endl;
104 #endif
105  for (size_t i = 0; i < m_boxes.size(); ++i) {
106 #ifdef DEBUG_PROPERTY_STACK
107  SVDEBUG << "(" << i << " of " << m_boxes.size() << ": " << m_boxes[i]->getContainer()->getPropertyContainerName() << ")" << endl;
108 #endif
109  delete m_boxes[i];
110  }
111 
112 #ifdef DEBUG_PROPERTY_STACK
113  SVDEBUG << "PropertyStack[" << this << "]::repopulate: done, clearing m_boxes" << endl;
114 #endif
115  m_boxes.clear();
116 
117  for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
118 
119  PropertyContainer *container = m_client->getPropertyContainer(i);
120  QString name = container->getPropertyContainerName();
121 
122 #ifdef DEBUG_PROPERTY_STACK
123  SVDEBUG << "PropertyStack[" << this << "]::repopulate: client " << m_client
124  << " returns container " << container << " (name " << name
125  << ") at position " << i << endl;
126 #endif
127 
128  PropertyBox *box = new PropertyBox(container);
129 
130  connect(box, SIGNAL(showLayer(bool)), this, SLOT(showLayer(bool)));
131  connect(box, SIGNAL(contextHelpChanged(const QString &)),
132  this, SIGNAL(contextHelpChanged(const QString &)));
133 
134  Layer *layer = dynamic_cast<Layer *>(container);
135  if (layer) {
137  }
138 
139  QString shortName = name;
140 
141  if (layer) {
143  (LayerFactory::getInstance()->getLayerType(layer));
144  if (layer->getLayerPresentationName() != "") {
145  name = layer->getLayerPresentationName();
146  }
147  }
148 
149  bool nameDiffers = (name != shortName);
150  shortName = QString("&%1 %2").arg(i + 1).arg(shortName);
151 
152  QString iconName = container->getPropertyContainerIconName();
153 
154  QIcon icon(IconLoader().load(iconName));
155  if (icon.isNull()) {
156  addTab(box, shortName);
157  if (nameDiffers) {
158  setTabToolTip(i, name);
159  }
160  } else {
161  addTab(box, icon, QString("&%1").arg(i + 1));
162  setTabToolTip(i, name);
163  }
164 
165  m_boxes.push_back(box);
166  }
167 
168  blockSignals(false);
169 }
170 
171 void
173 {
174  int tab = tabBar()->tabAt(pos);
175  if (!in_range_for(m_boxes, tab)) {
176  return;
177  }
178 
180  m_boxes[tab]->getContainer(),
181  mapToGlobal(pos));
182 }
183 
184 bool
185 PropertyStack::containsContainer(PropertyContainer *pc) const
186 {
187  for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
188  PropertyContainer *container = m_client->getPropertyContainer(i);
189  if (pc == container) return true;
190  }
191 
192  return false;
193 }
194 
195 int
196 PropertyStack::getContainerIndex(PropertyContainer *pc) const
197 {
198  // This is used to obtain an index to be passed to setCurrentIndex
199  // -- which is the index of the property container's box in our
200  // stack of boxes. That is not the same thing as the index of the
201  // container (i.e. the layer) in the view: the view reorders its
202  // containers whenever one is raised to the top, while our boxes
203  // remain in the same order. So we must find this container in the
204  // box list, not in the view.
205 
206  for (int i = 0; in_range_for(m_boxes, i); ++i) {
207  PropertyContainer *container = m_boxes[i]->getContainer();
208  if (pc == container) {
209  return i;
210  }
211  }
212 
213  return false;
214 }
215 
216 void
218 #ifdef DEBUG_PROPERTY_STACK
219  c
220 #endif
221  )
222 {
223  if (sender() != m_client) return;
224 #ifdef DEBUG_PROPERTY_STACK
225  SVDEBUG << "PropertyStack::propertyContainerAdded(" << (c ? c->getPropertyContainerName() : "(none)") << ")" << endl;
226 #endif
227  repopulate();
228 }
229 
230 void
232 #ifdef DEBUG_PROPERTY_STACK
233  c
234 #endif
235  )
236 {
237  if (sender() != m_client) return;
238 #ifdef DEBUG_PROPERTY_STACK
239  SVDEBUG << "PropertyStack::propertyContainerAdded(" << (c ? c->getPropertyContainerName() : "(none)") << ")" << endl;
240 #endif
241  repopulate();
242 }
243 
244 void
246 {
247  Layer *layer = dynamic_cast<Layer *>(pc);
248  for (unsigned int i = 0; i < m_boxes.size(); ++i) {
249  if (pc == m_boxes[i]->getContainer()) {
250  m_boxes[i]->propertyContainerPropertyChanged(pc);
251  if (layer) {
252  m_boxes[i]->layerVisibilityChanged
253  (!layer->isLayerDormant(m_client));
254  }
255  }
256  }
257 }
258 
259 void
261 {
262  for (unsigned int i = 0; i < m_boxes.size(); ++i) {
263  if (pc == m_boxes[i]->getContainer()) {
264  m_boxes[i]->propertyContainerPropertyRangeChanged(pc);
265  }
266  }
267 }
268 
269 void
271 {
272  if (sender() != m_client) return;
273  repopulate();
274 }
275 
276 void
278 {
279  QObject *obj = sender();
280 
281  for (unsigned int i = 0; i < m_boxes.size(); ++i) {
282  if (obj == m_boxes[i]) {
283  Layer *layer = dynamic_cast<Layer *>(m_boxes[i]->getContainer());
284  if (layer) {
286  (new ShowLayerCommand(m_client, layer, show,
287  tr("Change Layer Visibility")));
288  return;
289  }
290  }
291  }
292 }
293 
294 void
296 {
297  if (n >= int(m_boxes.size())) return;
298  emit propertyContainerSelected(m_client, m_boxes[n]->getContainer());
299 }
300 
301 void
303 {
304  emit contextHelpChanged(tr("Click to change the current active layer"));
305 }
306 
307 void
309 {
310  emit contextHelpChanged("");
311 }
312 
313 void
315 {
316  emit viewSelected(m_client);
317 }
318 
static LayerFactory * getInstance()
virtual bool isLayerDormant(const LayerGeometryProvider *v) const
Return whether the layer is dormant (i.e.
Definition: Layer.cpp:144
void tabBarContextMenuRequested(const QPoint &)
void propertyContainerPropertyChanged(PropertyContainer *)
virtual const PropertyContainer * getPropertyContainer(int i) const
Definition: View.cpp:183
The base class for visual representations of the data found in a Model.
Definition: Layer.h:54
void mouseLeftTabBar()
void propertyContainerAdded(PropertyContainer *)
void activeTabClicked()
std::vector< PropertyBox * > m_boxes
Definition: PropertyStack.h:67
int getContainerIndex(PropertyContainer *container) const
void viewSelected(View *client)
void showLayer(bool)
void addCommand(Command *command)
Add a command to the command history.
static QSize scaleQSize(QSize size)
Definition: WidgetScale.h:58
void selectedContainerChanged(int)
bool containsContainer(PropertyContainer *container) const
PropertyStack(QWidget *parent, View *client)
QString getLayerPresentationName(LayerType type)
void layerVisibilityChanged(bool)
virtual QString getLayerPresentationName() const
Definition: Layer.cpp:99
void contextHelpChanged(const QString &)
void propertyContainerRemoved(PropertyContainer *)
static CommandHistory * getInstance()
void propertyContainerPropertyRangeChanged(PropertyContainer *)
virtual int getPropertyContainerCount() const
Definition: View.cpp:177
void propertyContainerNameChanged(PropertyContainer *)
View is the base class of widgets that display one or more overlaid views of data against a horizonta...
Definition: View.h:55
void propertyContainerContextMenuRequested(View *client, PropertyContainer *container, QPoint pos)
void mouseEnteredTabBar()
void propertyContainerSelected(View *client, PropertyContainer *container)
virtual ~PropertyStack()