svgui  1.9
PropertyStack.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "PropertyStack.h"
00017 #include "PropertyBox.h"
00018 #include "base/PropertyContainer.h"
00019 #include "view/View.h"
00020 #include "layer/Layer.h"
00021 #include "layer/LayerFactory.h"
00022 #include "widgets/NotifyingTabBar.h"
00023 #include "widgets/IconLoader.h"
00024 #include "base/Command.h"
00025 #include "widgets/CommandHistory.h"
00026 #include "layer/ShowLayerCommand.h"
00027 
00028 #include <QIcon>
00029 #include <QTabWidget>
00030 
00031 #include <iostream>
00032 
00033 #define DEBUG_PROPERTY_STACK 1
00034 
00035 PropertyStack::PropertyStack(QWidget *parent, View *client) :
00036     QTabWidget(parent),
00037     m_client(client)
00038 {
00039     NotifyingTabBar *bar = new NotifyingTabBar();
00040     bar->setDrawBase(false);
00041 
00042     connect(bar, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredTabBar()));
00043     connect(bar, SIGNAL(mouseLeft()), this, SLOT(mouseLeftTabBar()));
00044     connect(bar, SIGNAL(activeTabClicked()), this, SLOT(activeTabClicked()));
00045 
00046     setTabBar(bar);
00047 
00048 #if (QT_VERSION >= 0x0402)
00049     setElideMode(Qt::ElideNone); 
00050     tabBar()->setUsesScrollButtons(true); 
00051     tabBar()->setIconSize(QSize(16, 16));
00052 #endif
00053     
00054     repopulate();
00055 
00056     connect(this, SIGNAL(currentChanged(int)),
00057             this, SLOT(selectedContainerChanged(int)));
00058 
00059     connect(m_client, SIGNAL(propertyContainerAdded(PropertyContainer *)),
00060             this, SLOT(propertyContainerAdded(PropertyContainer *)));
00061 
00062     connect(m_client, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
00063             this, SLOT(propertyContainerRemoved(PropertyContainer *)));
00064 
00065     connect(m_client, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
00066             this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
00067 
00068     connect(m_client, SIGNAL(propertyContainerPropertyRangeChanged(PropertyContainer *)),
00069             this, SLOT(propertyContainerPropertyRangeChanged(PropertyContainer *)));
00070 
00071     connect(m_client, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
00072             this, SLOT(propertyContainerNameChanged(PropertyContainer *)));
00073 
00074     connect(this, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)),
00075             m_client, SLOT(propertyContainerSelected(View *, PropertyContainer *)));
00076 }
00077 
00078 PropertyStack::~PropertyStack()
00079 {
00080 }
00081 
00082 void
00083 PropertyStack::repopulate()
00084 {
00085     blockSignals(true);
00086 
00087 #ifdef DEBUG_PROPERTY_STACK
00088     cerr << "PropertyStack[" << this << "]::repopulate" << endl;
00089 #endif
00090     
00091     while (count() > 0) {
00092         removeTab(0);
00093     }
00094     for (size_t i = 0; i < m_boxes.size(); ++i) {
00095         delete m_boxes[i];
00096     }
00097     m_boxes.clear();
00098     
00099     for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
00100 
00101         PropertyContainer *container = m_client->getPropertyContainer(i);
00102         QString name = container->getPropertyContainerName();
00103         
00104 #ifdef DEBUG_PROPERTY_STACK
00105         cerr << "PropertyStack[" << this << "]::repopulate: client " << m_client
00106              << " returns container " << container << " (name " << name
00107              << ") at position " << i << endl;
00108 #endif
00109 
00110         PropertyBox *box = new PropertyBox(container);
00111 
00112         connect(box, SIGNAL(showLayer(bool)), this, SLOT(showLayer(bool)));
00113         connect(box, SIGNAL(contextHelpChanged(const QString &)),
00114                 this, SIGNAL(contextHelpChanged(const QString &)));
00115 
00116         Layer *layer = dynamic_cast<Layer *>(container);
00117         if (layer) {
00118             box->layerVisibilityChanged(!layer->isLayerDormant(m_client));
00119         }
00120 
00121         QString shortName = name;
00122 
00123         if (layer) {
00124             shortName = LayerFactory::getInstance()->getLayerPresentationName
00125                 (LayerFactory::getInstance()->getLayerType(layer));
00126             if (layer->getLayerPresentationName() != "") {
00127                 name = layer->getLayerPresentationName();
00128             }
00129         }
00130 
00131         bool nameDiffers = (name != shortName);
00132         shortName = QString("&%1 %2").arg(i + 1).arg(shortName);
00133 
00134         QString iconName = container->getPropertyContainerIconName();
00135 
00136         QIcon icon(IconLoader().load(iconName));
00137         if (icon.isNull()) {
00138             addTab(box, shortName);
00139             if (nameDiffers) {
00140                 setTabToolTip(i, name);
00141             }
00142         } else {
00143             addTab(box, icon, QString("&%1").arg(i + 1));
00144             setTabToolTip(i, name);
00145         }
00146 
00147         m_boxes.push_back(box);
00148     }    
00149 
00150     blockSignals(false);
00151 }
00152 
00153 bool
00154 PropertyStack::containsContainer(PropertyContainer *pc) const
00155 {
00156     for (int i = 0; i < m_client->getPropertyContainerCount(); ++i) {
00157         PropertyContainer *container = m_client->getPropertyContainer(i);
00158         if (pc == container) return true;
00159     }
00160 
00161     return false;
00162 }
00163 
00164 int
00165 PropertyStack::getContainerIndex(PropertyContainer *pc) const
00166 {
00167     // This is used to obtain an index to be passed to setCurrentIndex
00168     // -- which is the index of the property container's box in our
00169     // stack of boxes. That is not the same thing as the index of the
00170     // container (i.e. the layer) in the view: the view reorders its
00171     // containers whenever one is raised to the top, while our boxes
00172     // remain in the same order. So we must find this container in the
00173     // box list, not in the view.
00174 
00175     for (size_t i = 0; i < m_boxes.size(); ++i) {
00176         PropertyContainer *container = m_boxes[i]->getContainer();
00177         if (pc == container) {
00178             return i;
00179         }
00180     }
00181 
00182     return false;
00183 }
00184 
00185 void
00186 PropertyStack::propertyContainerAdded(PropertyContainer *)
00187 {
00188     if (sender() != m_client) return;
00189     repopulate();
00190 }
00191 
00192 void
00193 PropertyStack::propertyContainerRemoved(PropertyContainer *)
00194 {
00195     if (sender() != m_client) return;
00196     repopulate();
00197 }
00198 
00199 void
00200 PropertyStack::propertyContainerPropertyChanged(PropertyContainer *pc)
00201 {
00202     Layer *layer = dynamic_cast<Layer *>(pc);
00203     for (unsigned int i = 0; i < m_boxes.size(); ++i) {
00204         if (pc == m_boxes[i]->getContainer()) {
00205             m_boxes[i]->propertyContainerPropertyChanged(pc);
00206             if (layer) {
00207                 m_boxes[i]->layerVisibilityChanged
00208                     (!layer->isLayerDormant(m_client));
00209             }
00210         }
00211     }
00212 }
00213 
00214 void
00215 PropertyStack::propertyContainerPropertyRangeChanged(PropertyContainer *pc)
00216 {
00217     for (unsigned int i = 0; i < m_boxes.size(); ++i) {
00218         if (pc == m_boxes[i]->getContainer()) {
00219             m_boxes[i]->propertyContainerPropertyRangeChanged(pc);
00220         }
00221     }
00222 }
00223 
00224 void
00225 PropertyStack::propertyContainerNameChanged(PropertyContainer *)
00226 {
00227     if (sender() != m_client) return;
00228     repopulate();
00229 }
00230 
00231 void
00232 PropertyStack::showLayer(bool show)
00233 {
00234     QObject *obj = sender();
00235     
00236     for (unsigned int i = 0; i < m_boxes.size(); ++i) {
00237         if (obj == m_boxes[i]) {
00238             Layer *layer = dynamic_cast<Layer *>(m_boxes[i]->getContainer());
00239             if (layer) {
00240                 CommandHistory::getInstance()->addCommand
00241                     (new ShowLayerCommand(m_client, layer, show,
00242                                           tr("Change Layer Visibility")));
00243                 return;
00244             }
00245         }
00246     }
00247 }
00248 
00249 void
00250 PropertyStack::selectedContainerChanged(int n)
00251 {
00252     if (n >= int(m_boxes.size())) return;
00253     emit propertyContainerSelected(m_client, m_boxes[n]->getContainer());
00254 }
00255 
00256 void
00257 PropertyStack::mouseEnteredTabBar()
00258 {
00259     emit contextHelpChanged(tr("Click to change the current active layer"));
00260 }
00261 
00262 void
00263 PropertyStack::mouseLeftTabBar()
00264 {
00265     emit contextHelpChanged("");
00266 }
00267 
00268 void
00269 PropertyStack::activeTabClicked()
00270 {
00271     emit viewSelected(m_client);
00272 }
00273