changeset 1196:b1e3ee5f1be6 levelpanwidget

Introduce colour combobox class, to replace ad-hoc code in property box
author Chris Cannam
date Fri, 16 Dec 2016 13:08:33 +0000
parents 51bb2582c2cc
children ff77b7707c95
files files.pri widgets/ColourComboBox.cpp widgets/ColourComboBox.h widgets/NotifyingComboBox.h widgets/PropertyBox.cpp widgets/PropertyBox.h
diffstat 6 files changed, 208 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/files.pri	Thu Dec 15 16:29:27 2016 +0000
+++ b/files.pri	Fri Dec 16 13:08:33 2016 +0000
@@ -44,6 +44,7 @@
 	   widgets/ActivityLog.h \
            widgets/AudioDial.h \
            widgets/ClickableLabel.h \
+           widgets/ColourComboBox.h \
            widgets/ColourNameDialog.h \
            widgets/CommandHistory.h \
            widgets/CSVFormatDialog.h \
@@ -123,6 +124,7 @@
            view/ViewManager.cpp \
 	   widgets/ActivityLog.cpp \
            widgets/AudioDial.cpp \
+           widgets/ColourComboBox.cpp \
            widgets/ColourNameDialog.cpp \
            widgets/CommandHistory.cpp \
            widgets/CSVFormatDialog.cpp \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/ColourComboBox.cpp	Fri Dec 16 13:08:33 2016 +0000
@@ -0,0 +1,101 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2007-2016 QMUL.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "ColourComboBox.h"
+
+#include "ColourNameDialog.h"
+
+#include "layer/ColourDatabase.h"
+
+#include "base/Debug.h"
+
+#include <QFontMetrics>
+#include <QColorDialog>
+
+#include <iostream>
+
+using namespace std;
+
+ColourComboBox::ColourComboBox(bool withAddNewColourEntry, QWidget *parent) :
+    NotifyingComboBox(parent),
+    m_withAddNewColourEntry(withAddNewColourEntry)
+{
+    setEditable(false);
+    rebuild();
+
+    connect(this, SIGNAL(activated(int)), this, SLOT(comboActivated(int)));
+    connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()),
+            this, SLOT(rebuild()));
+
+    if (count() < 20 && count() > maxVisibleItems()) {
+	setMaxVisibleItems(count());
+    }
+}
+
+void
+ColourComboBox::comboActivated(int index)
+{
+    if (!m_withAddNewColourEntry ||
+	index < int(ColourDatabase::getInstance()->getColourCount())) {
+	emit colourChanged(index);
+	return;
+    }
+    
+    QColor newColour = QColorDialog::getColor();
+    if (!newColour.isValid()) return;
+
+    ColourNameDialog dialog(tr("Name New Colour"),
+                            tr("Enter a name for the new colour:"),
+                            newColour, newColour.name(), this);
+    dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
+    if (dialog.exec() == QDialog::Accepted) {
+        //!!! command
+        ColourDatabase *db = ColourDatabase::getInstance();
+        int index = db->addColour(newColour, dialog.getColourName());
+        db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
+	// addColour will have called back on rebuild(), and the new
+	// colour will be at the index previously occupied by Add New
+	// Colour, which is our current index
+	emit colourChanged(currentIndex());
+    }
+}
+
+void
+ColourComboBox::rebuild()
+{
+    blockSignals(true);
+
+    int ix = currentIndex();
+    
+    clear();
+
+    int size = (QFontMetrics(QFont()).height() * 2) / 3;
+    if (size < 12) size = 12;
+    
+    ColourDatabase *db = ColourDatabase::getInstance();
+    for (int i = 0; i < db->getColourCount(); ++i) {
+	QString name = db->getColourName(i);
+	addItem(db->getExamplePixmap(i, QSize(size, size)), name);
+    }
+
+    if (m_withAddNewColourEntry) {
+	addItem(tr("Add New Colour..."));
+    }
+
+    setCurrentIndex(ix);
+    
+    blockSignals(false);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/ColourComboBox.h	Fri Dec 16 13:08:33 2016 +0000
@@ -0,0 +1,44 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2007-2016 QMUL.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef SV_COLOUR_COMBO_BOX_H
+#define SV_COLOUR_COMBO_BOX_H
+
+#include "NotifyingComboBox.h"
+
+/**
+ * Colour-picker combo box with swatches, optionally including "Add
+ * New Colour..." entry to invoke a QColorDialog/ColourNameDialog
+ */
+class ColourComboBox : public NotifyingComboBox
+{
+    Q_OBJECT
+
+public:
+    ColourComboBox(bool withAddNewColourEntry, QWidget *parent = 0);
+
+signals:
+    void colourChanged(int colourIndex);
+
+private slots:
+    void rebuild();
+    void comboActivated(int);
+    
+private:
+    bool m_withAddNewColourEntry;
+};
+
+#endif
+
--- a/widgets/NotifyingComboBox.h	Thu Dec 15 16:29:27 2016 +0000
+++ b/widgets/NotifyingComboBox.h	Fri Dec 16 13:08:33 2016 +0000
@@ -13,8 +13,8 @@
     COPYING included with this distribution for more information.
 */
 
-#ifndef _NOTIFYING_COMBO_BOX_H_
-#define _NOTIFYING_COMBO_BOX_H_
+#ifndef SV_NOTIFYING_COMBO_BOX_H
+#define SV_NOTIFYING_COMBO_BOX_H
 
 #include <QComboBox>
 
@@ -26,8 +26,8 @@
 class NotifyingComboBox : public QComboBox
 {
     Q_OBJECT
+
 public:
-
     NotifyingComboBox(QWidget *parent = 0) :
         QComboBox(parent) { }
 
--- a/widgets/PropertyBox.cpp	Thu Dec 15 16:29:27 2016 +0000
+++ b/widgets/PropertyBox.cpp	Fri Dec 16 13:08:33 2016 +0000
@@ -20,7 +20,6 @@
 #include "base/PlayParameters.h"
 #include "base/PlayParameterRepository.h"
 #include "layer/Layer.h"
-#include "layer/ColourDatabase.h"
 #include "base/UnitDatabase.h"
 #include "base/RangeMapper.h"
 
@@ -35,7 +34,7 @@
 #include "NotifyingComboBox.h"
 #include "NotifyingPushButton.h"
 #include "NotifyingToolButton.h"
-#include "ColourNameDialog.h"
+#include "ColourComboBox.h"
 
 #include <QGridLayout>
 #include <QHBoxLayout>
@@ -108,9 +107,6 @@
     connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()),
             this, SLOT(unitDatabaseChanged()));
 
-    connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()),
-            this, SLOT(colourDatabaseChanged()));
-
 #ifdef DEBUG_PROPERTY_BOX
     cerr << "PropertyBox[" << this << "]::PropertyBox returning" << endl;
 #endif
@@ -303,7 +299,7 @@
         QAbstractButton *button = 0;
 
 	if (have) {
-            button = dynamic_cast<QAbstractButton *>(m_propertyControllers[name]);
+            button = qobject_cast<QAbstractButton *>(m_propertyControllers[name]);
             assert(button);
 	} else {
 #ifdef DEBUG_PROPERTY_BOX 
@@ -349,7 +345,7 @@
 	AudioDial *dial;
 
 	if (have) {
-	    dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]);
+	    dial = qobject_cast<AudioDial *>(m_propertyControllers[name]);
 	    assert(dial);
             if (rangeChanged) {
                 dial->blockSignals(true);
@@ -408,14 +404,60 @@
 	break;
     }
 
+    case PropertyContainer::ColourProperty:
+    {
+        ColourComboBox *cb;
+        
+	if (have) {
+	    cb = qobject_cast<ColourComboBox *>(m_propertyControllers[name]);
+	    assert(cb);
+	} else {
+#ifdef DEBUG_PROPERTY_BOX 
+	    cerr << "PropertyBox: creating new colour combobox" << endl;
+#endif
+            cb = new ColourComboBox(true);
+            cb->setObjectName(name);
+
+	    connect(cb, SIGNAL(colourChanged(int)),
+		    this, SLOT(propertyControllerChanged(int)));
+            connect(cb, SIGNAL(mouseEntered()),
+                    this, SLOT(mouseEnteredWidget()));
+            connect(cb, SIGNAL(mouseLeft()),
+                    this, SLOT(mouseLeftWidget()));
+
+	    if (inGroup) {
+		cb->setToolTip(propertyLabel);
+		m_groupLayouts[groupName]->addWidget
+                    (cb, 0, m_groupLayouts[groupName]->columnCount());
+	    } else {
+		m_layout->addWidget(cb, row, 1, 1, 2);
+	    }
+	    m_propertyControllers[name] = cb;
+	}
+
+        if (cb->currentIndex() != value) {
+            cb->blockSignals(true);
+            cb->setCurrentIndex(value);
+            cb->blockSignals(false);
+        }
+
+#ifdef Q_OS_MAC
+	// Crashes on startup without this, for some reason; also
+	// prevents combo boxes from getting weirdly squished
+	// vertically
+	cb->setMinimumSize(QSize(10, cb->font().pixelSize() * 2));
+#endif
+
+        break;
+    }        
+
     case PropertyContainer::ValueProperty:
     case PropertyContainer::UnitsProperty:
-    case PropertyContainer::ColourProperty:
     {
 	NotifyingComboBox *cb;
 
 	if (have) {
-	    cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]);
+	    cb = qobject_cast<NotifyingComboBox *>(m_propertyControllers[name]);
 	    assert(cb);
 	} else {
 #ifdef DEBUG_PROPERTY_BOX 
@@ -448,7 +490,7 @@
                     }
                 }
 
-            } else if (type == PropertyContainer::UnitsProperty) {
+            } else { // PropertyContainer::UnitsProperty
 
                 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
                 for (int i = 0; i < units.size(); ++i) {
@@ -456,26 +498,6 @@
                 }
 
                 cb->setEditable(true);
-
-            } else { // ColourProperty
-
-                //!!! should be a proper colour combobox class that
-                // manages its own Add New Colour entry...
-
-                int size = (QFontMetrics(QFont()).height() * 2) / 3;
-                if (size < 12) size = 12;
-                
-                ColourDatabase *db = ColourDatabase::getInstance();
-                for (int i = 0; i < db->getColourCount(); ++i) {
-                    QString name = db->getColourName(i);
-                    cb->addItem(db->getExamplePixmap(i, QSize(size, size)), name);
-                }
-                cb->addItem(tr("Add New Colour..."));
-            }                
-                
-            cb->blockSignals(false);
-            if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) {
-                cb->setMaxVisibleItems(cb->count());
             }
         }
 
@@ -498,8 +520,7 @@
 	}
 
         cb->blockSignals(true);
-        if (type == PropertyContainer::ValueProperty ||
-            type == PropertyContainer::ColourProperty) {
+        if (type == PropertyContainer::ValueProperty) {
             if (cb->currentIndex() != value) {
                 cb->setCurrentIndex(value);
             }
@@ -590,22 +611,6 @@
 }    
 
 void
-PropertyBox::colourDatabaseChanged()
-{
-    blockSignals(true);
-
-    PropertyContainer::PropertyList properties = m_container->getProperties();
-    for (size_t i = 0; i < properties.size(); ++i) {
-        if (m_container->getPropertyType(properties[i]) ==
-            PropertyContainer::ColourProperty) {
-            updatePropertyEditor(properties[i], true);
-        }
-    }
-
-    blockSignals(false);
-}    
-
-void
 PropertyBox::propertyControllerChanged(bool on)
 {
     propertyControllerChanged(on ? 1 : 0);
@@ -627,24 +632,13 @@
 
     if (type == PropertyContainer::UnitsProperty) {
 
-        NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj);
+        NotifyingComboBox *cb = qobject_cast<NotifyingComboBox *>(obj);
         if (cb) {
             QString unit = cb->currentText();
             c = m_container->getSetPropertyCommand
                 (name, UnitDatabase::getInstance()->getUnitId(unit));
         }
 
-    } else if (type == PropertyContainer::ColourProperty) {
-
-        if (value == int(ColourDatabase::getInstance()->getColourCount())) {
-            addNewColour();
-            if (value == int(ColourDatabase::getInstance()->getColourCount())) {
-                propertyContainerPropertyChanged(m_container);
-                return;
-            }
-        }
-        c = m_container->getSetPropertyCommand(name, value);
-
     } else if (type != PropertyContainer::InvalidProperty) {
 
 	c = m_container->getSetPropertyCommand(name, value);
@@ -656,24 +650,6 @@
 }
 
 void
-PropertyBox::addNewColour()
-{
-    QColor newColour = QColorDialog::getColor();
-    if (!newColour.isValid()) return;
-
-    ColourNameDialog dialog(tr("Name New Colour"),
-                            tr("Enter a name for the new colour:"),
-                            newColour, newColour.name(), this);
-    dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
-    if (dialog.exec() == QDialog::Accepted) {
-        //!!! command
-        ColourDatabase *db = ColourDatabase::getInstance();
-        int index = db->addColour(newColour, dialog.getColourName());
-        db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
-    }
-}
-
-void
 PropertyBox::playAudibleChanged(bool audible)
 {
     m_playButton->setChecked(audible);
@@ -803,7 +779,7 @@
 void
 PropertyBox::updateContextHelp(QObject *o)
 {
-    QWidget *w = dynamic_cast<QWidget *>(o);
+    QWidget *w = qobject_cast<QWidget *>(o);
     if (!w) return;
 
     if (!m_container) return;
@@ -848,7 +824,7 @@
         emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
     } else if (wname == "") {
         return;
-    } else if (dynamic_cast<QAbstractButton *>(w)) {
+    } else if (qobject_cast<QAbstractButton *>(w)) {
         emit contextHelpChanged(tr("Toggle %1 property of %2")
                                 .arg(wname).arg(cname));
     } else {
--- a/widgets/PropertyBox.h	Thu Dec 15 16:29:27 2016 +0000
+++ b/widgets/PropertyBox.h	Fri Dec 16 13:08:33 2016 +0000
@@ -13,8 +13,8 @@
     COPYING included with this distribution for more information.
 */
 
-#ifndef _PROPERTY_BOX_H_
-#define _PROPERTY_BOX_H_
+#ifndef SV_PROPERTY_BOX_H
+#define SV_PROPERTY_BOX_H
 
 #include "base/PropertyContainer.h"
 
@@ -62,7 +62,6 @@
     void populateViewPlayFrame();
 
     void unitDatabaseChanged();
-    void colourDatabaseChanged();
 
     void editPlayParameters();
 
@@ -73,7 +72,6 @@
     void updatePropertyEditor(PropertyContainer::PropertyName,
                               bool rangeChanged = false);
     void updateContextHelp(QObject *o);
-    void addNewColour();
 
     QLabel *m_nameWidget;
     QWidget *m_mainWidget;