![]() |
Mixxx
|
00001 00002 #include <QtCore> 00003 #include <QLabel> 00004 #include "midimapping.h" 00005 #include "midiinputmappingtablemodel.h" 00006 00007 MidiInputMappingTableModel::MidiInputMappingTableModel(MidiMapping* mapping) : 00008 QAbstractTableModel(), 00009 m_pMapping(NULL) 00010 00011 { 00012 setMapping(mapping); //Save the mapping 00013 } 00014 00015 MidiInputMappingTableModel::~MidiInputMappingTableModel() 00016 { 00017 } 00018 00019 void MidiInputMappingTableModel::slotInputMappingChanged() { 00020 00021 // for now ask it to refresh the whole thing -- we can get fancy 00022 // with more complex signals later 00023 reset(); 00024 } 00025 00026 void MidiInputMappingTableModel::setMapping(MidiMapping* mapping) 00027 { 00028 if(m_pMapping != NULL) { 00029 disconnect(m_pMapping, SIGNAL(inputMappingChanged()), this, SLOT(slotInputMappingChanged())); 00030 } 00031 m_pMapping = mapping; 00032 connect(m_pMapping, SIGNAL(inputMappingChanged()), this, SLOT(slotInputMappingChanged())); 00033 } 00034 00035 QVariant MidiInputMappingTableModel::data(const QModelIndex &index, int role) const 00036 { 00037 if (!index.isValid()) 00038 return QVariant(); 00039 00040 if(!m_pMapping->isInputIndexValid(index.row())) 00041 return QVariant(); 00042 00043 if (role == Qt::DisplayRole || role == Qt::EditRole) { 00044 //This might be super slow, but that's the price of using a map/hash table (which give 00045 //us super fast lookups when MidiMessages come in). 00046 //Also note that QMaps are always sorted by key, whereas QHashes are not sorted and rearrange themselves. 00047 00048 MidiMessage message = m_pMapping->getInputMidiMessage(index.row()); 00049 MixxxControl control = m_pMapping->getInputMixxxControl(message); 00050 00051 switch (index.column()) 00052 { 00053 case MIDIINPUTTABLEINDEX_MIDISTATUS: 00054 return message.getMidiStatusByte(); 00055 break; 00056 00057 case MIDIINPUTTABLEINDEX_MIDINO: 00058 return message.getMidiNo(); 00059 break; 00060 00061 case MIDIINPUTTABLEINDEX_MIDICHANNEL: 00062 return message.getMidiChannel(); 00063 break; 00064 00065 case MIDIINPUTTABLEINDEX_CONTROLOBJECTGROUP: 00066 return control.getControlObjectGroup(); 00067 break; 00068 00069 case MIDIINPUTTABLEINDEX_CONTROLOBJECTVALUE: 00070 return control.getControlObjectValue(); 00071 break; 00072 00073 case MIDIINPUTTABLEINDEX_MIDIOPTION: 00074 return control.getMidiOption(); 00075 break; 00076 00077 case MIDIINPUTTABLEINDEX_CONTROLOBJECTDESCRIPTION: 00078 return control.getControlObjectDescription(); 00079 break; 00080 00081 default: 00082 return QVariant(); 00083 } 00084 } 00085 00086 return QVariant(); 00087 } 00088 00089 Qt::ItemFlags MidiInputMappingTableModel::flags(const QModelIndex &index) const 00090 { 00091 if (!index.isValid()) 00092 return Qt::ItemIsEnabled; 00093 00094 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; 00095 } 00096 00097 bool MidiInputMappingTableModel::setData(const QModelIndex &index, const QVariant &value, 00098 int role) 00099 { 00100 if (index.isValid() && role == Qt::EditRole) { 00101 MidiMessage message = m_pMapping->getInputMidiMessage(index.row()); 00102 MixxxControl control = m_pMapping->getInputMixxxControl(message); 00103 00104 //Now we actually need to remove the mapping we want to operate on, 00105 //because otherwise if we change the status or channel bits, we'll 00106 //end up inserting a new mapping instead of overwriting this one. 00107 //(This is because the mapping datastructure is a hash table that 00108 // hashes on the status byte.) 00109 m_pMapping->clearInputMidiMapping(message); 00110 00111 switch (index.column()) 00112 { 00113 case MIDIINPUTTABLEINDEX_MIDISTATUS: 00114 message.setMidiStatusByte((MidiStatusByte)value.toInt()); 00115 break; 00116 00117 case MIDIINPUTTABLEINDEX_MIDINO: 00118 message.setMidiNo(value.toInt()); 00119 break; 00120 00121 case MIDIINPUTTABLEINDEX_MIDICHANNEL: 00122 message.setMidiChannel(value.toInt()); 00123 break; 00124 00125 case MIDIINPUTTABLEINDEX_CONTROLOBJECTGROUP: 00126 control.setControlObjectGroup(value.toString()); 00127 break; 00128 00129 case MIDIINPUTTABLEINDEX_CONTROLOBJECTVALUE: 00130 control.setControlObjectValue(value.toString()); 00131 break; 00132 00133 case MIDIINPUTTABLEINDEX_MIDIOPTION: 00134 control.setMidiOption((MidiOption)value.toInt()); 00135 break; 00136 00137 case MIDIINPUTTABLEINDEX_CONTROLOBJECTDESCRIPTION: 00138 control.setControlObjectDescription(value.toString()); 00139 break; 00140 }; 00141 00142 //Insert the updated control into the map. 00143 m_pMapping->setInputMidiMapping(message, control); 00144 00145 emit dataChanged(index, index); 00146 return true; 00147 } 00148 return false; 00149 } 00150 00151 int MidiInputMappingTableModel::rowCount(const QModelIndex& parent) const 00152 { 00153 if (parent != QModelIndex()) //Some weird thing for table-based models. 00154 return 0; 00155 00156 return m_pMapping->numInputMidiMessages(); 00157 } 00158 00159 int MidiInputMappingTableModel::columnCount(const QModelIndex& parent) const 00160 { 00161 if (parent != QModelIndex()) //Some weird thing for table-based models. 00162 return 0; 00163 return MIDIINPUTTABLEINDEX_NUMCOLS; 00164 } 00165 00166 QVariant MidiInputMappingTableModel::headerData(int section, Qt::Orientation orientation, int role) const 00167 { 00168 //Column heading labels 00169 if (orientation == Qt::Horizontal) 00170 { 00171 switch (section) 00172 { 00173 case MIDIINPUTTABLEINDEX_MIDISTATUS: 00174 return QVariant(tr("Midi Status Type")); 00175 break; 00176 00177 case MIDIINPUTTABLEINDEX_MIDINO: 00178 return QVariant(tr("Midi Note")); 00179 break; 00180 00181 case MIDIINPUTTABLEINDEX_MIDICHANNEL: 00182 return QVariant(tr("Midi Channel")); 00183 break; 00184 00185 case MIDIINPUTTABLEINDEX_CONTROLOBJECTGROUP: 00186 return QVariant(tr("Control Group")); 00187 break; 00188 00189 case MIDIINPUTTABLEINDEX_CONTROLOBJECTVALUE: 00190 return QVariant(tr("Control Value")); 00191 break; 00192 00193 /* //WTF, why does the header disappear when I enable this? - Albert (1 AM) 00194 case MIDIINPUTTABLEINDEX_MIDIOPTION: 00195 return QVariant(tr("Midi Option")); 00196 break; 00197 */ 00198 00199 case MIDIINPUTTABLEINDEX_CONTROLOBJECTDESCRIPTION: 00200 return QVariant(tr("Description")); 00201 break; 00202 } 00203 } 00204 00205 return QVariant(); 00206 } 00207 00208 bool MidiInputMappingTableModel::removeRow(int row, const QModelIndex& parent) 00209 { 00210 //DO NOT CALL beginRemoveRows()/endRemoveRows() in this function! You're ONLY supposed to 00211 //do that for removeRows() (plural!!). It causes a bug if you do it here. 00212 00213 m_pMapping->clearInputMidiMapping(row); 00214 00215 return true; 00216 } 00217 00218 bool MidiInputMappingTableModel::removeRows(int row, int count, const QModelIndex& parent) 00219 { 00220 beginRemoveRows(parent, row, row+count); 00221 00222 m_pMapping->clearInputMidiMapping(row, count); 00223 00224 //TODO: Should probably handle an invalid selection and return false. 00225 00226 endRemoveRows(); 00227 00228 return true; 00229 }