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