comparison widgets/PropertyBox.cpp @ 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
comparison
equal deleted inserted replaced
1195:51bb2582c2cc 1196:b1e3ee5f1be6
18 18
19 #include "base/PropertyContainer.h" 19 #include "base/PropertyContainer.h"
20 #include "base/PlayParameters.h" 20 #include "base/PlayParameters.h"
21 #include "base/PlayParameterRepository.h" 21 #include "base/PlayParameterRepository.h"
22 #include "layer/Layer.h" 22 #include "layer/Layer.h"
23 #include "layer/ColourDatabase.h"
24 #include "base/UnitDatabase.h" 23 #include "base/UnitDatabase.h"
25 #include "base/RangeMapper.h" 24 #include "base/RangeMapper.h"
26 25
27 #include "AudioDial.h" 26 #include "AudioDial.h"
28 #include "LEDButton.h" 27 #include "LEDButton.h"
33 32
34 #include "NotifyingCheckBox.h" 33 #include "NotifyingCheckBox.h"
35 #include "NotifyingComboBox.h" 34 #include "NotifyingComboBox.h"
36 #include "NotifyingPushButton.h" 35 #include "NotifyingPushButton.h"
37 #include "NotifyingToolButton.h" 36 #include "NotifyingToolButton.h"
38 #include "ColourNameDialog.h" 37 #include "ColourComboBox.h"
39 38
40 #include <QGridLayout> 39 #include <QGridLayout>
41 #include <QHBoxLayout> 40 #include <QHBoxLayout>
42 #include <QVBoxLayout> 41 #include <QVBoxLayout>
43 #include <QPushButton> 42 #include <QPushButton>
105 104
106 m_layout->setRowStretch(m_layout->rowCount(), 10); 105 m_layout->setRowStretch(m_layout->rowCount(), 10);
107 106
108 connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()), 107 connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()),
109 this, SLOT(unitDatabaseChanged())); 108 this, SLOT(unitDatabaseChanged()));
110
111 connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()),
112 this, SLOT(colourDatabaseChanged()));
113 109
114 #ifdef DEBUG_PROPERTY_BOX 110 #ifdef DEBUG_PROPERTY_BOX
115 cerr << "PropertyBox[" << this << "]::PropertyBox returning" << endl; 111 cerr << "PropertyBox[" << this << "]::PropertyBox returning" << endl;
116 #endif 112 #endif
117 } 113 }
301 case PropertyContainer::ToggleProperty: 297 case PropertyContainer::ToggleProperty:
302 { 298 {
303 QAbstractButton *button = 0; 299 QAbstractButton *button = 0;
304 300
305 if (have) { 301 if (have) {
306 button = dynamic_cast<QAbstractButton *>(m_propertyControllers[name]); 302 button = qobject_cast<QAbstractButton *>(m_propertyControllers[name]);
307 assert(button); 303 assert(button);
308 } else { 304 } else {
309 #ifdef DEBUG_PROPERTY_BOX 305 #ifdef DEBUG_PROPERTY_BOX
310 cerr << "PropertyBox: creating new checkbox" << endl; 306 cerr << "PropertyBox: creating new checkbox" << endl;
311 #endif 307 #endif
347 case PropertyContainer::RangeProperty: 343 case PropertyContainer::RangeProperty:
348 { 344 {
349 AudioDial *dial; 345 AudioDial *dial;
350 346
351 if (have) { 347 if (have) {
352 dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]); 348 dial = qobject_cast<AudioDial *>(m_propertyControllers[name]);
353 assert(dial); 349 assert(dial);
354 if (rangeChanged) { 350 if (rangeChanged) {
355 dial->blockSignals(true); 351 dial->blockSignals(true);
356 dial->setMinimum(min); 352 dial->setMinimum(min);
357 dial->setMaximum(max); 353 dial->setMaximum(max);
406 dial->blockSignals(false); 402 dial->blockSignals(false);
407 } 403 }
408 break; 404 break;
409 } 405 }
410 406
411 case PropertyContainer::ValueProperty:
412 case PropertyContainer::UnitsProperty:
413 case PropertyContainer::ColourProperty: 407 case PropertyContainer::ColourProperty:
414 { 408 {
415 NotifyingComboBox *cb; 409 ColourComboBox *cb;
416 410
417 if (have) { 411 if (have) {
418 cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]); 412 cb = qobject_cast<ColourComboBox *>(m_propertyControllers[name]);
419 assert(cb); 413 assert(cb);
420 } else { 414 } else {
421 #ifdef DEBUG_PROPERTY_BOX 415 #ifdef DEBUG_PROPERTY_BOX
422 cerr << "PropertyBox: creating new combobox" << endl; 416 cerr << "PropertyBox: creating new colour combobox" << endl;
423 #endif 417 #endif
424 418 cb = new ColourComboBox(true);
425 cb = new NotifyingComboBox(); 419 cb->setObjectName(name);
426 cb->setObjectName(name); 420
427 cb->setDuplicatesEnabled(false); 421 connect(cb, SIGNAL(colourChanged(int)),
428 }
429
430 if (!have || rangeChanged) {
431
432 cb->blockSignals(true);
433 cb->clear();
434 cb->setEditable(false);
435
436 if (type == PropertyContainer::ValueProperty) {
437
438 for (int i = min; i <= max; ++i) {
439
440 QString label = m_container->getPropertyValueLabel(name, i);
441 QString iname = m_container->getPropertyValueIconName(name, i);
442
443 if (iname != "") {
444 QIcon icon(IconLoader().load(iname));
445 cb->addItem(icon, label);
446 } else {
447 cb->addItem(label);
448 }
449 }
450
451 } else if (type == PropertyContainer::UnitsProperty) {
452
453 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
454 for (int i = 0; i < units.size(); ++i) {
455 cb->addItem(units[i]);
456 }
457
458 cb->setEditable(true);
459
460 } else { // ColourProperty
461
462 //!!! should be a proper colour combobox class that
463 // manages its own Add New Colour entry...
464
465 int size = (QFontMetrics(QFont()).height() * 2) / 3;
466 if (size < 12) size = 12;
467
468 ColourDatabase *db = ColourDatabase::getInstance();
469 for (int i = 0; i < db->getColourCount(); ++i) {
470 QString name = db->getColourName(i);
471 cb->addItem(db->getExamplePixmap(i, QSize(size, size)), name);
472 }
473 cb->addItem(tr("Add New Colour..."));
474 }
475
476 cb->blockSignals(false);
477 if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) {
478 cb->setMaxVisibleItems(cb->count());
479 }
480 }
481
482 if (!have) {
483 connect(cb, SIGNAL(activated(int)),
484 this, SLOT(propertyControllerChanged(int))); 422 this, SLOT(propertyControllerChanged(int)));
485 connect(cb, SIGNAL(mouseEntered()), 423 connect(cb, SIGNAL(mouseEntered()),
486 this, SLOT(mouseEnteredWidget())); 424 this, SLOT(mouseEnteredWidget()));
487 connect(cb, SIGNAL(mouseLeft()), 425 connect(cb, SIGNAL(mouseLeft()),
488 this, SLOT(mouseLeftWidget())); 426 this, SLOT(mouseLeftWidget()));
495 m_layout->addWidget(cb, row, 1, 1, 2); 433 m_layout->addWidget(cb, row, 1, 1, 2);
496 } 434 }
497 m_propertyControllers[name] = cb; 435 m_propertyControllers[name] = cb;
498 } 436 }
499 437
438 if (cb->currentIndex() != value) {
439 cb->blockSignals(true);
440 cb->setCurrentIndex(value);
441 cb->blockSignals(false);
442 }
443
444 #ifdef Q_OS_MAC
445 // Crashes on startup without this, for some reason; also
446 // prevents combo boxes from getting weirdly squished
447 // vertically
448 cb->setMinimumSize(QSize(10, cb->font().pixelSize() * 2));
449 #endif
450
451 break;
452 }
453
454 case PropertyContainer::ValueProperty:
455 case PropertyContainer::UnitsProperty:
456 {
457 NotifyingComboBox *cb;
458
459 if (have) {
460 cb = qobject_cast<NotifyingComboBox *>(m_propertyControllers[name]);
461 assert(cb);
462 } else {
463 #ifdef DEBUG_PROPERTY_BOX
464 cerr << "PropertyBox: creating new combobox" << endl;
465 #endif
466
467 cb = new NotifyingComboBox();
468 cb->setObjectName(name);
469 cb->setDuplicatesEnabled(false);
470 }
471
472 if (!have || rangeChanged) {
473
474 cb->blockSignals(true);
475 cb->clear();
476 cb->setEditable(false);
477
478 if (type == PropertyContainer::ValueProperty) {
479
480 for (int i = min; i <= max; ++i) {
481
482 QString label = m_container->getPropertyValueLabel(name, i);
483 QString iname = m_container->getPropertyValueIconName(name, i);
484
485 if (iname != "") {
486 QIcon icon(IconLoader().load(iname));
487 cb->addItem(icon, label);
488 } else {
489 cb->addItem(label);
490 }
491 }
492
493 } else { // PropertyContainer::UnitsProperty
494
495 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
496 for (int i = 0; i < units.size(); ++i) {
497 cb->addItem(units[i]);
498 }
499
500 cb->setEditable(true);
501 }
502 }
503
504 if (!have) {
505 connect(cb, SIGNAL(activated(int)),
506 this, SLOT(propertyControllerChanged(int)));
507 connect(cb, SIGNAL(mouseEntered()),
508 this, SLOT(mouseEnteredWidget()));
509 connect(cb, SIGNAL(mouseLeft()),
510 this, SLOT(mouseLeftWidget()));
511
512 if (inGroup) {
513 cb->setToolTip(propertyLabel);
514 m_groupLayouts[groupName]->addWidget
515 (cb, 0, m_groupLayouts[groupName]->columnCount());
516 } else {
517 m_layout->addWidget(cb, row, 1, 1, 2);
518 }
519 m_propertyControllers[name] = cb;
520 }
521
500 cb->blockSignals(true); 522 cb->blockSignals(true);
501 if (type == PropertyContainer::ValueProperty || 523 if (type == PropertyContainer::ValueProperty) {
502 type == PropertyContainer::ColourProperty) {
503 if (cb->currentIndex() != value) { 524 if (cb->currentIndex() != value) {
504 cb->setCurrentIndex(value); 525 cb->setCurrentIndex(value);
505 } 526 }
506 } else { 527 } else {
507 QString unit = UnitDatabase::getInstance()->getUnitById(value); 528 QString unit = UnitDatabase::getInstance()->getUnitById(value);
588 609
589 blockSignals(false); 610 blockSignals(false);
590 } 611 }
591 612
592 void 613 void
593 PropertyBox::colourDatabaseChanged()
594 {
595 blockSignals(true);
596
597 PropertyContainer::PropertyList properties = m_container->getProperties();
598 for (size_t i = 0; i < properties.size(); ++i) {
599 if (m_container->getPropertyType(properties[i]) ==
600 PropertyContainer::ColourProperty) {
601 updatePropertyEditor(properties[i], true);
602 }
603 }
604
605 blockSignals(false);
606 }
607
608 void
609 PropertyBox::propertyControllerChanged(bool on) 614 PropertyBox::propertyControllerChanged(bool on)
610 { 615 {
611 propertyControllerChanged(on ? 1 : 0); 616 propertyControllerChanged(on ? 1 : 0);
612 } 617 }
613 618
625 630
626 Command *c = 0; 631 Command *c = 0;
627 632
628 if (type == PropertyContainer::UnitsProperty) { 633 if (type == PropertyContainer::UnitsProperty) {
629 634
630 NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj); 635 NotifyingComboBox *cb = qobject_cast<NotifyingComboBox *>(obj);
631 if (cb) { 636 if (cb) {
632 QString unit = cb->currentText(); 637 QString unit = cb->currentText();
633 c = m_container->getSetPropertyCommand 638 c = m_container->getSetPropertyCommand
634 (name, UnitDatabase::getInstance()->getUnitId(unit)); 639 (name, UnitDatabase::getInstance()->getUnitId(unit));
635 } 640 }
636 641
637 } else if (type == PropertyContainer::ColourProperty) {
638
639 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
640 addNewColour();
641 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
642 propertyContainerPropertyChanged(m_container);
643 return;
644 }
645 }
646 c = m_container->getSetPropertyCommand(name, value);
647
648 } else if (type != PropertyContainer::InvalidProperty) { 642 } else if (type != PropertyContainer::InvalidProperty) {
649 643
650 c = m_container->getSetPropertyCommand(name, value); 644 c = m_container->getSetPropertyCommand(name, value);
651 } 645 }
652 646
653 if (c) CommandHistory::getInstance()->addCommand(c, true, true); 647 if (c) CommandHistory::getInstance()->addCommand(c, true, true);
654 648
655 updateContextHelp(obj); 649 updateContextHelp(obj);
656 }
657
658 void
659 PropertyBox::addNewColour()
660 {
661 QColor newColour = QColorDialog::getColor();
662 if (!newColour.isValid()) return;
663
664 ColourNameDialog dialog(tr("Name New Colour"),
665 tr("Enter a name for the new colour:"),
666 newColour, newColour.name(), this);
667 dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
668 if (dialog.exec() == QDialog::Accepted) {
669 //!!! command
670 ColourDatabase *db = ColourDatabase::getInstance();
671 int index = db->addColour(newColour, dialog.getColourName());
672 db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
673 }
674 } 650 }
675 651
676 void 652 void
677 PropertyBox::playAudibleChanged(bool audible) 653 PropertyBox::playAudibleChanged(bool audible)
678 { 654 {
801 } 777 }
802 778
803 void 779 void
804 PropertyBox::updateContextHelp(QObject *o) 780 PropertyBox::updateContextHelp(QObject *o)
805 { 781 {
806 QWidget *w = dynamic_cast<QWidget *>(o); 782 QWidget *w = qobject_cast<QWidget *>(o);
807 if (!w) return; 783 if (!w) return;
808 784
809 if (!m_container) return; 785 if (!m_container) return;
810 QString cname = m_container->getPropertyContainerName(); 786 QString cname = m_container->getPropertyContainerName();
811 if (cname == "") return; 787 if (cname == "") return;
846 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname)); 822 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname));
847 } else if (w == m_playButton) { 823 } else if (w == m_playButton) {
848 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname)); 824 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
849 } else if (wname == "") { 825 } else if (wname == "") {
850 return; 826 return;
851 } else if (dynamic_cast<QAbstractButton *>(w)) { 827 } else if (qobject_cast<QAbstractButton *>(w)) {
852 emit contextHelpChanged(tr("Toggle %1 property of %2") 828 emit contextHelpChanged(tr("Toggle %1 property of %2")
853 .arg(wname).arg(cname)); 829 .arg(wname).arg(cname));
854 } else { 830 } else {
855 emit contextHelpChanged(tr("Adjust %1 property of %2%3") 831 emit contextHelpChanged(tr("Adjust %1 property of %2%3")
856 .arg(wname).arg(cname).arg(extraText)); 832 .arg(wname).arg(cname).arg(extraText));