1 /***************************************************************************
2 **                                                                        **
3 **  Polyphone, a soundfont editor                                         **
4 **  Copyright (C) 2013-2020 Davy Triponney                                **
5 **                2014      Andrea Celani                                 **
6 **                                                                        **
7 **  This program is free software: you can redistribute it and/or modify  **
8 **  it under the terms of the GNU General Public License as published by  **
9 **  the Free Software Foundation, either version 3 of the License, or     **
10 **  (at your option) any later version.                                   **
11 **                                                                        **
12 **  This program is distributed in the hope that it will be useful,       **
13 **  but WITHOUT ANY WARRANTY; without even the implied warranty of        **
14 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the          **
15 **  GNU General Public License for more details.                          **
16 **                                                                        **
17 **  You should have received a copy of the GNU General Public License     **
18 **  along with this program. If not, see http://www.gnu.org/licenses/.    **
19 **                                                                        **
20 ****************************************************************************
21 **           Author: Davy Triponney                                       **
22 **  Website/Contact: https://www.polyphone-soundfonts.com                 **
23 **             Date: 01.01.2013                                           **
24 ***************************************************************************/
25 
26 #include "modulatorcombocurve.h"
27 #include "contextmanager.h"
28 #include <QMouseEvent>
29 #include <QTableView>
30 #include <QStandardItemModel>
31 #include <QHeaderView>
32 #include "soundfontmanager.h"
33 
34 static const QChar unicodeArrow[] = { 0xfeff, 0x279c };
35 const QString ModulatorComboCurve::s_rightArrow = " " + QString::fromRawData(unicodeArrow, 2) + " ";
36 
ModulatorComboCurve(QWidget * parent)37 ModulatorComboCurve::ModulatorComboCurve(QWidget* parent) : QComboBox(parent)
38 {
39     // New view
40     QTableView * view = new QTableView();
41     view->viewport()->installEventFilter(this);
42     view->horizontalHeader()->setVisible(false);
43     view->verticalHeader()->setVisible(false);
44     view->setShowGrid(false);
45     this->setView(view);
46 
47     // Prepare the model
48     QStandardItemModel * model = new QStandardItemModel();
49     this->setModel(model);
50     model->setColumnCount(4);
51     model->setRowCount(4);
52 
53     // Icons
54     int iconWidth = 48;
55     int margin = 6;
56     QMap<QString, QString> replacement;
57     replacement["currentColor"] = ContextManager::theme()->getColor(ThemeManager::LIST_TEXT).name();
58     replacement["secondColor"] = ContextManager::theme()->getColor(ThemeManager::HIGHLIGHTED_BACKGROUND).name();
59     for (int i = 0; i < 4; i++)
60     {
61         for (int j = 0; j < 4; j++)
62         {
63             QString iconName = QString(":/icons/courbe%1.svg").arg(4*j+i+1, 2, 10, QChar('0'));
64             QStandardItem * item = new QStandardItem("");
65             item->setData(ContextManager::theme()->getColoredSvg(iconName, QSize(iconWidth, iconWidth), replacement), Qt::DecorationRole);
66             model->setItem(i, j, item);
67         }
68     }
69 
70     // Size
71     for (int i = 0; i < 4; i++)
72     {
73         view->setColumnWidth(i, iconWidth + margin);
74         view->setRowHeight(i, iconWidth + margin);
75     }
76     view->setFixedSize(4 * (iconWidth + margin), 4 * (iconWidth + margin));
77 
78     // Highlight color
79     QPalette p = view->palette();
80     p.setColor(QPalette::Highlight, ContextManager::theme()->getColor(ThemeManager::LIST_ALTERNATIVE_BACKGROUND));
81     view->setPalette(p);
82 }
83 
~ModulatorComboCurve()84 ModulatorComboCurve::~ModulatorComboCurve()
85 {
86     delete this->model();
87 }
88 
eventFilter(QObject * object,QEvent * event)89 bool ModulatorComboCurve::eventFilter(QObject* object, QEvent* event)
90 {
91     if (event->type() == QEvent::MouseButtonPress && object == view()->viewport())
92     {
93         this->setCurrentIndex(view()->currentIndex().row());
94         this->setModelColumn(view()->currentIndex().column());
95 
96         // Store the result
97         valueSelected(view()->currentIndex().row(), view()->currentIndex().column());
98     }
99     return false;
100 }
101 
initialize(EltID id,bool source1)102 void ModulatorComboCurve::initialize(EltID id, bool source1)
103 {
104     _id = id;
105     _source1 = source1;
106 
107     loadValue();
108 }
109 
initialize(SFModulator mod)110 void ModulatorComboCurve::initialize(SFModulator mod)
111 {
112     _id.typeElement = elementUnknown;
113 
114     _isBipolar = mod.isBipolar;
115     _isDescending = mod.isDescending;
116     _type = mod.Type;
117 
118     this->setCurrentIndex(_type);
119     this->setModelColumn((_isDescending ? 1 : 0) + (_isBipolar ? 2 : 0));
120 }
121 
loadValue()122 void ModulatorComboCurve::loadValue()
123 {
124     SoundfontManager * sm = SoundfontManager::getInstance();
125     SFModulator mod = sm->get(_id, _source1 ? champ_sfModSrcOper : champ_sfModAmtSrcOper).sfModValue;
126 
127     _isBipolar = mod.isBipolar;
128     _isDescending = mod.isDescending;
129     _type = mod.Type;
130 
131     this->setCurrentIndex(_type);
132     this->setModelColumn((_isDescending ? 1 : 0) + (_isBipolar ? 2 : 0));
133 }
134 
valueSelected(int row,int column)135 void ModulatorComboCurve::valueSelected(int row, int column)
136 {
137     if (_id.typeElement == elementUnknown)
138         return;
139 
140     _isDescending = (column % 2 > 0);
141     _isBipolar = (column / 2 > 0);
142     _type = static_cast<quint8>(row);
143 
144     // Compare with the old value
145     SoundfontManager * sm = SoundfontManager::getInstance();
146     AttributeValue val;
147     val.sfModValue = sm->get(_id, _source1 ? champ_sfModSrcOper : champ_sfModAmtSrcOper).sfModValue;
148     if (val.sfModValue.isDescending != _isDescending || val.sfModValue.isBipolar != _isBipolar || val.sfModValue.Type != _type)
149     {
150         val.sfModValue.isDescending = _isDescending;
151         val.sfModValue.isBipolar = _isBipolar;
152         val.sfModValue.Type = static_cast<quint8>(_type);
153 
154         sm->set(_id, _source1 ? champ_sfModSrcOper : champ_sfModAmtSrcOper, val);
155         sm->endEditing("modulatorEditor");
156     }
157 }
158 
getEvolution()159 QString ModulatorComboCurve::getEvolution()
160 {
161     QString result = "";
162     if (_isDescending)
163         result = _isBipolar ? "1" + s_rightArrow + "-1" : "1" + s_rightArrow + "0";
164     else
165         result = _isBipolar ? "-1" + s_rightArrow + "1" : "0" + s_rightArrow + "1";
166     return result;
167 }
168