From 3ffd0dacdd7447c6c377f95c1fa7fc45a2612d98 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Tue, 14 Feb 2012 17:26:03 +0000 Subject: - added support for custom controller columns in the tracklist they are stored in and read from the global config file. - tracklist header is now saved into global config, not in songfile. TODO: - allow the user to customize the custom columns - make recreating the Header work (graphical glitches currently) --- muse2/muse/app.h | 1 + muse2/muse/arranger/arranger.cpp | 213 ++++++++++++++++++++---- muse2/muse/arranger/arranger.h | 23 +++ muse2/muse/arranger/arrangerview.cpp | 3 + muse2/muse/arranger/arrangerview.h | 2 +- muse2/muse/arranger/tlist.cpp | 309 ++++++++++++++++++++++++++++++----- muse2/muse/arranger/tlist.h | 8 +- muse2/muse/conf.cpp | 2 +- muse2/muse/widgets/header.cpp | 90 +++++----- muse2/muse/widgets/header.h | 3 + muse2/muse/widgets/spinbox.cpp | 6 +- muse2/muse/widgets/utils.h | 3 + 12 files changed, 538 insertions(+), 125 deletions(-) diff --git a/muse2/muse/app.h b/muse2/muse/app.h index 2e62db1a..7b2c1431 100644 --- a/muse2/muse/app.h +++ b/muse2/muse/app.h @@ -380,6 +380,7 @@ class MusE : public QMainWindow ~MusE(); void loadDefaultSong(int argc, char** argv); Arranger* arranger() const { return _arranger; } + ArrangerView* getArrangerView() const { return arrangerView; } QRect configGeometryMain; QProgressDialog *progress; bool importMidi(const QString name, bool merge); diff --git a/muse2/muse/arranger/arranger.cpp b/muse2/muse/arranger/arranger.cpp index af5c9785..d572aadd 100644 --- a/muse2/muse/arranger/arranger.cpp +++ b/muse2/muse/arranger/arranger.cpp @@ -72,6 +72,81 @@ namespace MusEGui { +std::vector Arranger::custom_columns; +QString Arranger::header_state; + +void Arranger::writeCustomColumns(int level, MusECore::Xml& xml) +{ + xml.tag(level++, "custom_columns"); + + for (unsigned i=0;iaddWidget(split, 1000); //split->setHandleWidth(10); - QWidget* tracklist = new QWidget(split); + tracklist = new QWidget(split); split->setStretchFactor(split->indexOf(tracklist), 0); //tracklist->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding, 0, 100)); @@ -294,38 +369,11 @@ Arranger::Arranger(ArrangerView* parent, const char* name) ib->setChecked(showTrackinfoFlag); ib->setFocusPolicy(Qt::NoFocus); connect(ib, SIGNAL(toggled(bool)), SLOT(showTrackInfo(bool))); - - header = new Header(tracklist, "header"); - header->setFixedHeight(30); - - QFontMetrics fm1(header->font()); - int fw = 8; - - header->setColumnLabel(tr("R"), COL_RECORD, fm1.width('R')+fw); - header->setColumnLabel(tr("M"), COL_MUTE, fm1.width('M')+fw); - header->setColumnLabel(tr("S"), COL_SOLO, fm1.width('S')+fw); - header->setColumnLabel(tr("C"), COL_CLASS, fm1.width('C')+fw); - header->setColumnLabel(tr("Track"), COL_NAME, 100); - header->setColumnLabel(tr("Port"), COL_OPORT, 60); - header->setColumnLabel(tr("Ch"), COL_OCHANNEL, 30); - header->setColumnLabel(tr("T"), COL_TIMELOCK, fm1.width('T')+fw); - header->setColumnLabel(tr("Automation"), COL_AUTOMATION, 75); - header->setColumnLabel(tr("Clef"), COL_CLEF, 75); - header->setResizeMode(COL_RECORD, QHeaderView::Fixed); - header->setResizeMode(COL_MUTE, QHeaderView::Fixed); - header->setResizeMode(COL_SOLO, QHeaderView::Fixed); - header->setResizeMode(COL_CLASS, QHeaderView::Fixed); - header->setResizeMode(COL_NAME, QHeaderView::Interactive); - header->setResizeMode(COL_OPORT, QHeaderView::Interactive); - header->setResizeMode(COL_OCHANNEL, QHeaderView::Fixed); - header->setResizeMode(COL_TIMELOCK, QHeaderView::Fixed); - header->setResizeMode(COL_AUTOMATION, QHeaderView::Interactive); - header->setResizeMode(COL_CLEF, QHeaderView::Interactive); - - setHeaderToolTips(); - setHeaderWhatsThis(); - header->setMovable (true ); + list=NULL; + header=NULL; + tgrid=NULL; + updateTListHeader(); list = new TList(header, tracklist, "tracklist"); // Do this now that the list is available. @@ -467,6 +515,66 @@ Arranger::Arranger(ArrangerView* parent, const char* name) //setTabOrder(ib, hscroll); } + +void Arranger::updateTListHeader() +{ + if (header) + { + header_state=header->getStatus(); + delete header; + } + + header = new Header(tracklist, "header"); + + header->setFixedHeight(30); + + QFontMetrics fm1(header->font()); + int fw = 8; + + header->setColumnLabel(tr("R"), COL_RECORD, fm1.width('R')+fw); + header->setColumnLabel(tr("M"), COL_MUTE, fm1.width('M')+fw); + header->setColumnLabel(tr("S"), COL_SOLO, fm1.width('S')+fw); + header->setColumnLabel(tr("C"), COL_CLASS, fm1.width('C')+fw); + header->setColumnLabel(tr("Track"), COL_NAME, 100); + header->setColumnLabel(tr("Port"), COL_OPORT, 60); + header->setColumnLabel(tr("Ch"), COL_OCHANNEL, 30); + header->setColumnLabel(tr("T"), COL_TIMELOCK, fm1.width('T')+fw); + header->setColumnLabel(tr("Automation"), COL_AUTOMATION, 75); + header->setColumnLabel(tr("Clef"), COL_CLEF, 75); + for (unsigned i=0;isetColumnLabel(custom_columns[i].name, COL_CUSTOM_MIDICTRL_OFFSET+i, MAX(fm1.width(custom_columns[i].name)+fw, 30)); + header->setResizeMode(COL_RECORD, QHeaderView::Fixed); + header->setResizeMode(COL_MUTE, QHeaderView::Fixed); + header->setResizeMode(COL_SOLO, QHeaderView::Fixed); + header->setResizeMode(COL_CLASS, QHeaderView::Fixed); + header->setResizeMode(COL_NAME, QHeaderView::Interactive); + header->setResizeMode(COL_OPORT, QHeaderView::Interactive); + header->setResizeMode(COL_OCHANNEL, QHeaderView::Fixed); + header->setResizeMode(COL_TIMELOCK, QHeaderView::Fixed); + header->setResizeMode(COL_AUTOMATION, QHeaderView::Interactive); + header->setResizeMode(COL_CLEF, QHeaderView::Interactive); + for (unsigned i=0;isetResizeMode(COL_CUSTOM_MIDICTRL_OFFSET+i, QHeaderView::Fixed); + + setHeaderToolTips(); + setHeaderWhatsThis(); + header->setMovable (true); + header->setStatus(header_state); + + if (list) + { + list->setHeader(header); + connect(header, SIGNAL(sectionResized(int,int,int)), list, SLOT(redraw())); + connect(header, SIGNAL(sectionMoved(int,int,int)), list, SLOT(redraw())); + connect(header, SIGNAL(sectionMoved(int,int,int)), this, SLOT(headerMoved())); + } + + if (tgrid) + { + tgrid->wadd(2, header); + } +} + //--------------------------------------------------------- // updateHScrollRange //--------------------------------------------------------- @@ -693,7 +801,6 @@ void Arranger::writeStatus(int level, MusECore::Xml& xml) xml.tag(level++, "arranger"); xml.intTag(level, "info", ib->isChecked()); split->writeStatus(level, xml); - list->writeStatus(level, xml, "list"); xml.intTag(level, "xpos", hscroll->pos()); xml.intTag(level, "xmag", hscroll->mag()); @@ -701,6 +808,44 @@ void Arranger::writeStatus(int level, MusECore::Xml& xml) xml.etag(level, "arranger"); } +void Arranger::writeConfiguration(int level, MusECore::Xml& xml) + { + xml.tag(level++, "arranger"); + writeCustomColumns(level, xml); + xml.strTag(level, "tlist_header", header->getStatus()); + xml.etag(level, "arranger"); + } + +//--------------------------------------------------------- +// readConfiguration +//--------------------------------------------------------- + +void Arranger::readConfiguration(MusECore::Xml& xml) + { + for (;;) { + MusECore::Xml::Token token(xml.parse()); + const QString& tag(xml.s1()); + switch (token) { + case MusECore::Xml::Error: + case MusECore::Xml::End: + return; + case MusECore::Xml::TagStart: + if (tag == "tlist_header") + header_state = xml.parse1(); + else if (tag == "custom_columns") + readCustomColumns(xml); + else + xml.unknown("Arranger"); + break; + case MusECore::Xml::TagEnd: + if (tag == "arranger") + return; + default: + break; + } + } + } + //--------------------------------------------------------- // readStatus //--------------------------------------------------------- @@ -719,8 +864,6 @@ void Arranger::readStatus(MusECore::Xml& xml) showTrackinfoFlag = xml.parseInt(); else if (tag == split->objectName()) split->readStatus(xml); - else if (tag == "list") - list->readStatus(xml, "list"); else if (tag == "xmag") hscroll->setMag(xml.parseInt()); else if (tag == "xpos") { diff --git a/muse2/muse/arranger/arranger.h b/muse2/muse/arranger/arranger.h index 35a3fe36..a49829c8 100644 --- a/muse2/muse/arranger/arranger.h +++ b/muse2/muse/arranger/arranger.h @@ -24,6 +24,7 @@ #define __ARRANGER_H__ #include +#include #include "midieditor.h" #include "pcanvas.h" @@ -87,6 +88,8 @@ class WidgetStack : public QWidget { class Arranger : public QWidget { Q_OBJECT + static QString header_state; + int _quant, _raster; PartCanvas* canvas; ScrollScale* hscroll; @@ -103,6 +106,7 @@ class Arranger : public QWidget { MidiTrackInfo* midiTrackInfo; AudioStrip* waveTrackInfo; QWidget* noTrackInfo; + QWidget* tracklist; TLLayout* tgrid; MusECore::Track* selected; @@ -167,10 +171,24 @@ class Arranger : public QWidget { void updateTrackInfo(int flags); void configChanged(); void controllerChanged(MusECore::Track *t); + void updateTListHeader(); public: enum { CMD_CUT_PART, CMD_COPY_PART, CMD_COPY_PART_IN_RANGE, CMD_PASTE_PART, CMD_PASTE_CLONE_PART, CMD_PASTE_DIALOG, CMD_PASTE_CLONE_DIALOG, CMD_INSERT_EMPTYMEAS }; + + struct custom_col_t + { + int ctrl; + QString name; + + custom_col_t(int c, QString n) + { + ctrl=c; + name=n; + } + }; + static std::vector custom_columns; Arranger(ArrangerView* parent, const char* name = 0); @@ -180,6 +198,11 @@ class Arranger : public QWidget { void writeStatus(int level, MusECore::Xml&); void readStatus(MusECore::Xml&); + void writeConfiguration(int level, MusECore::Xml&); + static void readConfiguration(MusECore::Xml&); + static void writeCustomColumns(int level, MusECore::Xml&); + static void readCustomColumns(MusECore::Xml&); + static custom_col_t readOneCustomColumn(MusECore::Xml&); MusECore::Track* curTrack() const { return selected; } void cmd(int); diff --git a/muse2/muse/arranger/arrangerview.cpp b/muse2/muse/arranger/arrangerview.cpp index 36658903..afc0da8c 100644 --- a/muse2/muse/arranger/arrangerview.cpp +++ b/muse2/muse/arranger/arrangerview.cpp @@ -435,6 +435,8 @@ void ArrangerView::readConfiguration(MusECore::Xml& xml) case MusECore::Xml::TagStart: if (tag == "topwin") TopWin::readConfiguration(ARRANGER, xml); + else if (tag == "arranger") + Arranger::readConfiguration(xml); else xml.unknown("ArrangerView"); break; @@ -455,6 +457,7 @@ void ArrangerView::writeConfiguration(int level, MusECore::Xml& xml) { xml.tag(level++, "arrangerview"); TopWin::writeConfiguration(ARRANGER, level, xml); + arranger->writeConfiguration(level,xml); xml.tag(level, "/arrangerview"); } diff --git a/muse2/muse/arranger/arrangerview.h b/muse2/muse/arranger/arrangerview.h index 5407c2ab..2e128c1d 100644 --- a/muse2/muse/arranger/arrangerview.h +++ b/muse2/muse/arranger/arrangerview.h @@ -153,7 +153,7 @@ class ArrangerView : public TopWin void writeStatus(int level, MusECore::Xml& xml) const; void readStatus(MusECore::Xml& xml); static void readConfiguration(MusECore::Xml&); - static void writeConfiguration(int, MusECore::Xml&); + void writeConfiguration(int, MusECore::Xml&); }; } // namespace MusEGui diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index fe8b4731..2a1e1d72 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -46,6 +46,7 @@ #include "xml.h" #include "mididev.h" #include "midiport.h" +#include "midictrl.h" #include "midiseq.h" #include "comment.h" #include "track.h" @@ -64,6 +65,8 @@ #include "popupmenu.h" #include "filedialog.h" #include "menutitleitem.h" +#include "arranger.h" +#include "undo.h" #ifdef DSSI_SUPPORT #include "dssihost.h" @@ -92,6 +95,7 @@ TList::TList(Header* hdr, QWidget* parent, const char* name) setObjectName(name); ypos = 0; editMode = false; + editJustFinished=false; setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); header = hdr; @@ -100,6 +104,7 @@ TList::TList(Header* hdr, QWidget* parent, const char* name) editTrack = 0; editor = 0; chan_edit = NULL; + ctrl_edit = NULL; mode = NORMAL; //setBackgroundMode(Qt::NoBackground); // ORCAN - FIXME @@ -117,7 +122,9 @@ TList::TList(Header* hdr, QWidget* parent, const char* name) void TList::songChanged(int flags) { if (flags & (SC_MUTE | SC_SOLO | SC_RECFLAG | SC_TRACK_INSERTED - | SC_TRACK_REMOVED | SC_TRACK_MODIFIED | SC_ROUTE | SC_CHANNELS | SC_MIDI_TRACK_PROP)) + | SC_TRACK_REMOVED | SC_TRACK_MODIFIED | SC_ROUTE | SC_CHANNELS | SC_MIDI_TRACK_PROP + | SC_PART_INSERTED | SC_PART_REMOVED | SC_PART_MODIFIED + | SC_EVENT_INSERTED | SC_EVENT_REMOVED | SC_EVENT_MODIFIED )) redraw(); if (flags & (SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED)) adjustScrollbar(); @@ -416,6 +423,22 @@ void TList::paint(const QRect& r) } break; default: + if (section>=COL_CUSTOM_MIDICTRL_OFFSET) + { + if (track->isMidiTrack()) + { + int col_ctrl_no=Arranger::custom_columns[section-COL_CUSTOM_MIDICTRL_OFFSET].ctrl; + MusECore::MidiTrack* mt=dynamic_cast(track); + MusECore::MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; + MusECore::MidiController* mctl = mp->midiController(col_ctrl_no); + int val=mt->getFirstControllerValue(col_ctrl_no,MusECore::CTRL_VAL_UNKNOWN); + if (val!=MusECore::CTRL_VAL_UNKNOWN) + val-=mctl->bias(); + + p.drawText(r, Qt::AlignVCenter|Qt::AlignHCenter, + (val!=MusECore::CTRL_VAL_UNKNOWN)?QString::number(val):tr("off")); + } + } break; } x += header->sectionSize(section); @@ -495,6 +518,7 @@ void TList::returnPressed() } editMode = false; + editJustFinished = true; if(editor->isVisible()) { editor->blockSignals(true); @@ -519,7 +543,6 @@ void TList::chanValueFinished() { MusECore::MidiTrack* mt = dynamic_cast(editTrack); if (mt && mt->type() != MusECore::Track::DRUM) - //if (mt && !mt->isDrumTrack()) // For Flo later with new drum tracks. { int channel = chan_edit->value() - 1; if(channel >= MIDI_CHANNELS) @@ -579,6 +602,7 @@ void TList::chanValueFinished() } editMode = false; + editJustFinished=true; if(chan_edit->isVisible()) { chan_edit->blockSignals(true); @@ -588,6 +612,67 @@ void TList::chanValueFinished() setFocus(); } +void TList::ctrlValueFinished() +{ + if(editTrack && editTrack->isMidiTrack()) + { + MusECore::MidiTrack* mt = dynamic_cast(editTrack); + if (mt && mt->type() != MusECore::Track::DRUM) + { + int val = ctrl_edit->value(); + MusECore::MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; + MusECore::MidiController* mctl = mp->midiController(ctrl_num); + + if (val==ctrl_edit->minimum()) + val=MusECore::CTRL_VAL_UNKNOWN; + else + val+=mctl->bias(); + + if (val!=MusECore::CTRL_VAL_UNKNOWN) + { + MusECore::Event a(MusECore::Controller); + a.setTick(0); + a.setA(ctrl_num); + a.setB(val); + MusEGlobal::song->recordEvent(mt, a); + } + else + { + MusECore::Undo operations; + for (MusECore::iPart p = mt->parts()->begin(); p!=mt->parts()->end(); p++) + { + if (p->second->tick()==0) + { + for (MusECore::iEvent ev=p->second->events()->begin(); ev!=p->second->events()->end(); ev++) + { + if (ev->second.tick()!=0) break; + else if (ev->second.type()==MusECore::Controller && ev->second.dataA()==ctrl_num) + { + using MusECore::UndoOp; + operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, p->second, false, false)); + break; + } + } + } + } + MusEGlobal::song->applyOperationGroup(operations); + } + } + + editTrack = 0; + } + + editMode = false; + editJustFinished=true; + if(ctrl_edit->isVisible()) + { + ctrl_edit->blockSignals(true); + ctrl_edit->hide(); + ctrl_edit->blockSignals(false); + } + setFocus(); +} + //--------------------------------------------------------- // adjustScrollbar //--------------------------------------------------------- @@ -704,6 +789,34 @@ void TList::mouseDoubleClickEvent(QMouseEvent* ev) ev->accept(); } } + else if (section >= COL_CUSTOM_MIDICTRL_OFFSET) + { + if (t->isMidiTrack()) + { + editTrack=t; + if (ctrl_edit==0) { + ctrl_edit=new QSpinBox(this); + ctrl_edit->setSpecialValueText(tr("off")); + connect(ctrl_edit, SIGNAL(editingFinished()), SLOT(ctrlValueFinished())); + } + + ctrl_num=Arranger::custom_columns[section-COL_CUSTOM_MIDICTRL_OFFSET].ctrl; + + MusECore::MidiTrack* mt=(MusECore::MidiTrack*)t; + MusECore::MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; + MusECore::MidiController* mctl = mp->midiController(ctrl_num); + ctrl_edit->setMinimum(mctl->minVal()-1); // -1 because of the specialValueText + ctrl_edit->setMaximum(mctl->maxVal()); + ctrl_edit->setValue(((MusECore::MidiTrack*)editTrack)->getFirstControllerValue(ctrl_num)-mctl->bias()); + int w=colw; + if (w < ctrl_edit->sizeHint().width()) w=ctrl_edit->sizeHint().width(); + ctrl_edit->setGeometry(colx, coly, w, colh); + editMode = true; + ctrl_edit->show(); + ctrl_edit->setFocus(); + ev->accept(); + } + } else mousePressEvent(ev); } @@ -1110,14 +1223,26 @@ void TList::keyPressEvent(QKeyEvent* e) chan_edit->hide(); chan_edit->blockSignals(false); } + if(ctrl_edit && ctrl_edit->isVisible()) + { + ctrl_edit->blockSignals(true); + ctrl_edit->hide(); + ctrl_edit->blockSignals(false); + } editTrack = 0; editMode = false; setFocus(); return; } } - emit keyPressExt(e); //redirect keypress events to main app - + else if (!editJustFinished) + { + emit keyPressExt(e); //redirect keypress events to main app. don't call this when confirming an editor + } + else + editJustFinished=false; + + // p4.0.10 Removed by Tim. keyPressExt are sent to part canvas, where they are // ignored *only* if necessary. //e->ignore(); @@ -1748,7 +1873,74 @@ void TList::mousePressEvent(QMouseEvent* ev) break; default: - mode = START_DRAG; + if (col>=COL_CUSTOM_MIDICTRL_OFFSET) + { + mode = START_DRAG; + + int delta = 0; + if (button == Qt::RightButton) + delta = 1; + else if (button == Qt::MidButton) + delta = -1; + + if (delta!=0 && t->isMidiTrack()) + { + MusECore::MidiTrack* mt = dynamic_cast(t); + if (mt == 0) + break; + + int ctrl_num = Arranger::custom_columns[col-COL_CUSTOM_MIDICTRL_OFFSET].ctrl; + + MusECore::MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; + MusECore::MidiController* mctl = mp->midiController(ctrl_num); + + int minval=mctl->minVal()+mctl->bias(); + int maxval=mctl->maxVal()+mctl->bias(); + + int val = mt->getFirstControllerValue(ctrl_num); + int oldval=val; + val += delta; + if(val > maxval) + val = maxval; + if(val < minval-1) // "-1" because of "off" + val = minval-1; + + if (val != oldval) + { + if (val!=minval-1) + { + MusECore::Event a(MusECore::Controller); + a.setTick(0); + a.setA(ctrl_num); + a.setB(val); + MusEGlobal::song->recordEvent(mt, a); + } + else + { + MusECore::Undo operations; + for (MusECore::iPart p = mt->parts()->begin(); p!=mt->parts()->end(); p++) + { + if (p->second->tick()==0) + { + for (MusECore::iEvent ev=p->second->events()->begin(); ev!=p->second->events()->end(); ev++) + { + if (ev->second.tick()!=0) break; + else if (ev->second.type()==MusECore::Controller && ev->second.dataA()==ctrl_num) + { + using MusECore::UndoOp; + operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, p->second, false, false)); + break; + } + } + } + } + MusEGlobal::song->applyOperationGroup(operations); + } + } + } + } + else + mode = START_DRAG; } redraw(); } @@ -2006,7 +2198,7 @@ void TList::mouseReleaseEvent(QMouseEvent* ev) } if (editTrack && editor && editor->isVisible()) editor->setFocus(); - //else + //else // DELETETHIS or add the same for ctrl_edit! //if (editTrack && chan_edit && chan_edit->isVisible()) // p4.0.46 // chan_edit->setFocus(); adjustScrollbar(); @@ -2122,49 +2314,74 @@ void TList::wheelEvent(QWheelEvent* ev) } break; default: - break; - } - } - -//--------------------------------------------------------- -// writeStatus -//--------------------------------------------------------- - -void TList::writeStatus(int level, MusECore::Xml& xml, const char* name) const - { - xml.tag(level++, name); - header->writeStatus(level, xml); - xml.etag(level, name); - } - -//--------------------------------------------------------- -// readStatus -//--------------------------------------------------------- + if (col>=COL_CUSTOM_MIDICTRL_OFFSET) + { + mode = START_DRAG; -void TList::readStatus(MusECore::Xml& xml, const char* name) - { - for (;;) { - MusECore::Xml::Token token(xml.parse()); - const QString& tag(xml.s1()); - switch (token) { - case MusECore::Xml::Error: - case MusECore::Xml::End: - return; - case MusECore::Xml::TagStart: - if (tag == header->objectName()) - header->readStatus(xml); - else - xml.unknown("Tlist"); - break; - case MusECore::Xml::TagEnd: - if (tag == name) - return; - default: + if (t->isMidiTrack()) + { + MusECore::MidiTrack* mt = dynamic_cast(t); + if (mt == 0) break; + + int ctrl_num = Arranger::custom_columns[col-COL_CUSTOM_MIDICTRL_OFFSET].ctrl; + + MusECore::MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; + MusECore::MidiController* mctl = mp->midiController(ctrl_num); + + int minval=mctl->minVal()+mctl->bias(); + int maxval=mctl->maxVal()+mctl->bias(); + + int val = mt->getFirstControllerValue(ctrl_num); + int oldval=val; + val += delta; + if(val > maxval) + val = maxval; + if(val < minval-1) // "-1" because of "off" + val = minval-1; + + if (val != oldval) + { + if (val!=minval-1) + { + MusECore::Event a(MusECore::Controller); + a.setTick(0); + a.setA(ctrl_num); + a.setB(val); + MusEGlobal::song->recordEvent(mt, a); + } + else + { + MusECore::Undo operations; + for (MusECore::iPart p = mt->parts()->begin(); p!=mt->parts()->end(); p++) + { + if (p->second->tick()==0) + { + for (MusECore::iEvent ev=p->second->events()->begin(); ev!=p->second->events()->end(); ev++) + { + if (ev->second.tick()!=0) break; + else if (ev->second.type()==MusECore::Controller && ev->second.dataA()==ctrl_num) + { + using MusECore::UndoOp; + operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, p->second, false, false)); + break; + } + } + } + } + MusEGlobal::song->applyOperationGroup(operations); + } + } + } } + else + mode = START_DRAG; + + break; } } + //--------------------------------------------------------- // setYPos //--------------------------------------------------------- @@ -2308,4 +2525,10 @@ void TList::classesPopupMenu(MusECore::Track* t, int x, int y) } } +void TList::setHeader(Header* h) +{ + header=h; + redraw(); +} + } // namespace MusEGui diff --git a/muse2/muse/arranger/tlist.h b/muse2/muse/arranger/tlist.h index 53f708e7..5ea6edb9 100644 --- a/muse2/muse/arranger/tlist.h +++ b/muse2/muse/arranger/tlist.h @@ -59,6 +59,7 @@ enum TrackColumn { COL_TIMELOCK, COL_AUTOMATION, COL_CLEF, + COL_CUSTOM_MIDICTRL_OFFSET, COL_NONE = -1 }; @@ -71,6 +72,7 @@ class TList : public QWidget { int ypos; bool editMode; + bool editJustFinished; QPixmap bgPixmap; // background Pixmap bool resizeFlag; // true if resize cursor is shown @@ -79,6 +81,8 @@ class TList : public QWidget { QScrollBar* _scroll; QLineEdit* editor; QSpinBox* chan_edit; + QSpinBox* ctrl_edit; + int ctrl_num; MusECore::Track* editTrack; MusECore::Track* editAutomation; @@ -116,6 +120,7 @@ class TList : public QWidget { void returnPressed(); void chanValueChanged(int); void chanValueFinished(); + void ctrlValueFinished(); void songChanged(int flags); void changeAutomation(QAction*); void changeAutomationColor(QAction*); @@ -136,13 +141,12 @@ class TList : public QWidget { void selectTrack(MusECore::Track*); void selectTrackAbove(); void selectTrackBelow(); + void setHeader(Header*); public: TList(Header*, QWidget* parent, const char* name); void setScroll(QScrollBar* s) { _scroll = s; } MusECore::Track* track() const { return editTrack; } - void writeStatus(int level, MusECore::Xml&, const char* name) const; - void readStatus(MusECore::Xml&, const char* name); }; } // namespace MusEGui diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp index b1481f60..638f591b 100644 --- a/muse2/muse/conf.cpp +++ b/muse2/muse/conf.cpp @@ -1438,7 +1438,7 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const MusEGui::ClipListEdit::writeConfiguration(level, xml); MusEGui::LMaster::writeConfiguration(level, xml); MusEGui::MarkerView::writeConfiguration(level, xml); - MusEGui::ArrangerView::writeConfiguration(level, xml); + arrangerView->writeConfiguration(level, xml); MusEGui::write_function_dialog_config(level, xml); diff --git a/muse2/muse/widgets/header.cpp b/muse2/muse/widgets/header.cpp index 968e7f73..a8e98ab5 100644 --- a/muse2/muse/widgets/header.cpp +++ b/muse2/muse/widgets/header.cpp @@ -36,7 +36,6 @@ namespace MusEGui { void Header::readStatus(MusECore::Xml& xml) { - for (;;) { MusECore::Xml::Token token = xml.parse(); const QString& tag = xml.s1(); @@ -45,36 +44,7 @@ void Header::readStatus(MusECore::Xml& xml) case MusECore::Xml::End: return; case MusECore::Xml::Text: - { - QStringList l = tag.split(QString(" "), QString::SkipEmptyParts); - int index = count() -1; - for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) { - int logialIdx=abs((*it).toInt()); - bool isHidden = (*it).toInt() < 0 ? true:false; - int section = visualIndex(logialIdx - (isHidden? 1:0)); - moveSection(section, index); - if (isHidden) - hideSection(logialIdx-1); - else - showSection(logialIdx); - --index; - } - - // loop again looking for missing indexes - for (int i =0; i < count(); i++) { - bool foundIt=false; - for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) { - int id=((*it).toInt()); - if ( id == i || i == -1 - id ) - foundIt=true; - } - if (foundIt == false) { - int section = visualIndex(i); - moveSection(section, i); - //printf("Adding missing i %d index %d section %d!\n", i, index, section); - } - } - } + setStatus(tag); break; case MusECore::Xml::TagStart: xml.unknown("Header"); @@ -88,25 +58,65 @@ void Header::readStatus(MusECore::Xml& xml) } } +void Header::setStatus(QString status) +{ + QStringList l = status.split(QString(" "), QString::SkipEmptyParts); + int index = count() -1; + for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + int logialIdx=abs((*it).toInt()); + bool isHidden = ((*it).toInt() < 0); + int section = visualIndex(logialIdx - (isHidden? 1:0)); + moveSection(section, index); + if (isHidden) + hideSection(logialIdx-1); + else + showSection(logialIdx); + --index; + } + + // loop again looking for missing indexes + for (int i =0; i < count(); i++) { + bool foundIt=false; + for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + int id=((*it).toInt()); + if ( id == i || i == -1 - id ) + foundIt=true; + } + if (foundIt == false) { + int section = visualIndex(i); + moveSection(section, i); + //printf("Adding missing i %d index %d section %d!\n", i, index, section); + } + } +} + //--------------------------------------------------------- // writeStatus //--------------------------------------------------------- void Header::writeStatus(int level, MusECore::Xml& xml) const { - //xml.nput(level, "<%s> ", name()); xml.nput(level, "<%s> ", MusECore::Xml::xmlString(objectName()).toLatin1().constData()); - int n = count(); - for (int i = n-1; i >= 0; --i) { - if (isSectionHidden(logicalIndex(i))) - xml.nput("%d ", -logicalIndex(i)-1); // hidden is stored as negative value starting from -1 - else - xml.nput("%d ", logicalIndex(i)); - } - //xml.put("", name()); + xml.nput("%s", getStatus().toLatin1().constData()); xml.put("", MusECore::Xml::xmlString(objectName()).toLatin1().constData()); } +QString Header::getStatus() const +{ + QString temp=""; + + int n = count(); + for (int i = n-1; i >= 0; --i) + { + if (isSectionHidden(logicalIndex(i))) + temp+=QString::number(-logicalIndex(i)-1)+" "; // hidden is stored as negative value starting from -1 + else + temp+=QString::number(logicalIndex(i))+" "; + } + + return temp; +} + //--------------------------------------------------------- // Header //--------------------------------------------------------- diff --git a/muse2/muse/widgets/header.h b/muse2/muse/widgets/header.h index f88ba750..047f4f28 100644 --- a/muse2/muse/widgets/header.h +++ b/muse2/muse/widgets/header.h @@ -25,6 +25,7 @@ #include #include +#include class QStandardItemModel; @@ -42,7 +43,9 @@ class Header : public QHeaderView { public: Header(QWidget* parent=0, const char* name=0); void writeStatus(int level, MusECore::Xml&) const; + QString getStatus() const; void readStatus(MusECore::Xml&); + void setStatus(QString status); void setColumnLabel( const QString & s, int col, int width = -1 ); void setToolTip(int col, const QString &text); void setWhatsThis(int col, const QString &text); diff --git a/muse2/muse/widgets/spinbox.cpp b/muse2/muse/widgets/spinbox.cpp index a763eea1..730e4828 100644 --- a/muse2/muse/widgets/spinbox.cpp +++ b/muse2/muse/widgets/spinbox.cpp @@ -49,7 +49,7 @@ bool SpinBox::eventFilter(QObject* o, QEvent* ev) // if (o != (QObject*)editor()) ddskrjo can't find editor() // return QSpinBox::eventFilter(o,ev); - bool retval = FALSE; + bool retval = false; if(ev->type() == QEvent::KeyPress) { QKeyEvent* k = (QKeyEvent*)ev; @@ -65,7 +65,7 @@ bool SpinBox::eventFilter(QObject* o, QEvent* ev) //if(!editor()->isModified()) { clearFocus(); - return TRUE; + return true; } } } @@ -73,7 +73,7 @@ bool SpinBox::eventFilter(QObject* o, QEvent* ev) if(ev->type() == QEvent::MouseButtonDblClick) { emit doubleClicked(); - return TRUE; + return true; } retval = QSpinBox::eventFilter(o, ev); diff --git a/muse2/muse/widgets/utils.h b/muse2/muse/widgets/utils.h index 95b9a133..07899a84 100644 --- a/muse2/muse/widgets/utils.h +++ b/muse2/muse/widgets/utils.h @@ -23,6 +23,9 @@ #ifndef __UTILS_H__ #define __UTILS_H__ +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) + class QFrame; class QString; class QWidget; -- cgit v1.2.3