1 //=============================================================================
2 //  MusE Score
3 //  Linux Music Score Editor
4 //
5 //  Copyright (C) 2002-2009 Werner Schweer and others
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 version 2.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19 
20 #include "editstringdata.h"
21 #include "editpitch.h"
22 #include "musescore.h"
23 
24 namespace Ms {
25 
26 //---------------------------------------------------------
27 //   EditStringData
28 //    To edit the string data (tuning and number of frets) for an instrument
29 //---------------------------------------------------------
30 
EditStringData(QWidget * parent,QList<instrString> * strings,int * frets)31 EditStringData::EditStringData(QWidget *parent, QList<instrString> * strings, int * frets)
32    : QDialog(parent)
33       {
34       setObjectName("EditStringData");
35       setupUi(this);
36       setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
37       _strings = strings;
38       QStringList hdrLabels;
39       int         numOfStrings = _strings->size();
40       hdrLabels << tr("Open", "string data") << tr("Pitch", "string data");
41       stringList->setHorizontalHeaderLabels(hdrLabels);
42       stringList->setRowCount(numOfStrings);
43       // if any string, insert into string list control and select the first one
44 
45       if(numOfStrings > 0) {
46             int   i;
47             instrString strg;
48             // insert into local working copy and into string list dlg control
49             // IN REVERSED ORDER
50             for(i=0; i < numOfStrings; i++) {
51                   strg = (*_strings)[numOfStrings - i - 1];
52                   _stringsLoc.append(strg);
53                   QTableWidgetItem *newCheck = new QTableWidgetItem();
54                   newCheck->setFlags(Qt::ItemFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled));
55                   newCheck->setCheckState(strg.open ? Qt::Checked : Qt::Unchecked);
56                   stringList->setItem(i, 0, newCheck);
57                   QTableWidgetItem *newPitch = new QTableWidgetItem(midiCodeToStr(strg.pitch));
58                   stringList->setItem(i, 1, newPitch);
59                   }
60             stringList->setCurrentCell(0, 1);
61             }
62       // if no string yet, disable buttons acting on individual string
63       else {
64             editString->setEnabled(false);
65             deleteString->setEnabled(false);
66             }
67 
68       _frets = frets;
69       numOfFrets->setValue(*_frets);
70 
71       connect(deleteString, SIGNAL(clicked()), SLOT(deleteStringClicked()));
72       connect(editString,   SIGNAL(clicked()), SLOT(editStringClicked()));
73       connect(newString,    SIGNAL(clicked()), SLOT(newStringClicked()));
74       connect(stringList,   SIGNAL(doubleClicked(QModelIndex)),     SLOT(editStringClicked()));
75       connect(stringList,   SIGNAL(itemClicked(QTableWidgetItem*)), SLOT(listItemClicked(QTableWidgetItem *)));
76       _modified = false;
77 
78       MuseScore::restoreGeometry(this);
79       }
80 
~EditStringData()81 EditStringData::~EditStringData()
82 {
83 }
84 
85 //---------------------------------------------------------
86 //   hideEvent
87 //---------------------------------------------------------
88 
hideEvent(QHideEvent * ev)89 void EditStringData::hideEvent(QHideEvent* ev)
90       {
91       MuseScore::saveGeometry(this);
92       QWidget::hideEvent(ev);
93       }
94 
95 //---------------------------------------------------------
96 //   deleteStringClicked
97 //---------------------------------------------------------
98 
deleteStringClicked()99 void EditStringData::deleteStringClicked()
100       {
101       int         i = stringList->currentRow();
102 
103       // remove item from local string list and from dlg list control
104       _stringsLoc.removeAt(i);
105       stringList->model()->removeRow(i);
106       // if no more items, disable buttons acting on individual string
107       if (stringList->rowCount() == 0) {
108             editString->setEnabled(false);
109             deleteString->setEnabled(false);
110             }
111       _modified = true;
112       }
113 
114 //---------------------------------------------------------
115 //   editStringClicked
116 //---------------------------------------------------------
117 
editStringClicked()118 void EditStringData::editStringClicked()
119       {
120       int         i = stringList->currentRow();
121       int         newCode;
122 
123       EditPitch* ep = new EditPitch(this, _stringsLoc[i].pitch);
124       if ( (newCode=ep->exec()) != -1) {
125             // update item value in local string list and item text in dlg list control
126             _stringsLoc[i].pitch = newCode;
127             QTableWidgetItem * item = stringList->item(i, 1);
128             item->setText(midiCodeToStr(newCode));
129             _modified = true;
130             }
131       }
132 
133 //---------------------------------------------------------
134 //   listItemClicked
135 //---------------------------------------------------------
136 
listItemClicked(QTableWidgetItem * item)137 void EditStringData::listItemClicked(QTableWidgetItem * item)
138       {
139       int col = item->column();
140       if (col != 0)                 // ignore clicks not on check boxes
141             return;
142       int row = item->row();
143 
144       // flip openness in local string list, then sync dlg list ctrl
145       bool open = !_stringsLoc[row].open;
146       _stringsLoc[row].open = open;
147       stringList->item(row, col)->setCheckState(open ? Qt::Checked : Qt::Unchecked);
148       _modified = true;
149       }
150 
151 //---------------------------------------------------------
152 //   newStringClicked
153 //---------------------------------------------------------
154 
newStringClicked()155 void EditStringData::newStringClicked()
156       {
157       int         i, newCode;
158 
159       EditPitch* ep = new EditPitch(this);
160       if ( (newCode=ep->exec()) != -1) {
161             // add below selected string or at the end if no selected string
162             i = stringList->currentRow() + 1;
163             if(i <= 0)
164                   i = stringList->rowCount();
165             // insert in local string list and in dlg list control
166             instrString strg = {newCode, 0};
167             _stringsLoc.insert(i, strg);
168             stringList->insertRow(i);
169             QTableWidgetItem *newCheck = new QTableWidgetItem();
170             newCheck->setFlags(Qt::ItemFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled));
171             newCheck->setCheckState(strg.open ? Qt::Checked : Qt::Unchecked);
172             stringList->setItem(i, 0, newCheck);
173             QTableWidgetItem *newPitch = new QTableWidgetItem(midiCodeToStr(strg.pitch));
174             stringList->setItem(i, 1, newPitch);
175             // select last added item and ensure buttons are active
176             stringList->setCurrentCell(i, 1);
177             editString->setEnabled(true);
178             deleteString->setEnabled(true);
179             _modified = true;
180             }
181       }
182 
183 //---------------------------------------------------------
184 //   accept
185 //---------------------------------------------------------
186 
accept()187 void EditStringData::accept()
188       {
189       // store data back into original variables
190       // string tunings are copied in reversed order (from lowest to highest)
191       if(_modified) {
192             _strings->clear();
193             for(int i=_stringsLoc.size()-1; i >= 0; i--)
194                   _strings->append(_stringsLoc[i]);
195             }
196       if(*_frets != numOfFrets->value()) {
197             *_frets = numOfFrets->value();
198             _modified = true;
199             }
200 
201       if(_modified)
202             QDialog::accept();
203       else
204             QDialog::reject();            // if no data change, no need to trigger changes downward the caller chain
205       }
206 
207 //---------------------------------------------------------
208 //   midiCodeToStr
209 //    Converts a MIDI numeric pitch code to human-readable note name
210 //---------------------------------------------------------
211 
212 static const char* g_cNoteName[] = {
213       QT_TRANSLATE_NOOP("editstringdata", "C"),
214       QT_TRANSLATE_NOOP("editstringdata", "C♯"),
215       QT_TRANSLATE_NOOP("editstringdata", "D"),
216       QT_TRANSLATE_NOOP("editstringdata", "E♭"),
217       QT_TRANSLATE_NOOP("editstringdata", "E"),
218       QT_TRANSLATE_NOOP("editstringdata", "F"),
219       QT_TRANSLATE_NOOP("editstringdata", "F♯"),
220       QT_TRANSLATE_NOOP("editstringdata", "G"),
221       QT_TRANSLATE_NOOP("editstringdata", "A♭"),
222       QT_TRANSLATE_NOOP("editstringdata", "A"),
223       QT_TRANSLATE_NOOP("editstringdata", "B♭"),
224       QT_TRANSLATE_NOOP("editstringdata", "B")
225       };
226 
midiCodeToStr(int midiCode)227 QString EditStringData::midiCodeToStr(int midiCode)
228       {
229       return QString("%1 %2").arg(qApp->translate("editstringdata", g_cNoteName[midiCode % 12])).arg(midiCode / 12 - 1);
230       }
231 }
232