summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2012-02-14 17:26:03 +0000
committerFlorian Jung <flo@windfisch.org>2012-02-14 17:26:03 +0000
commit3ffd0dacdd7447c6c377f95c1fa7fc45a2612d98 (patch)
treec8fa5ba7569d3001f3304f16f2f4a5c2546db8df
parentbca65ae96031f8d6828cb0038ee768ae11c7cff8 (diff)
- 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)
-rw-r--r--muse2/muse/app.h1
-rw-r--r--muse2/muse/arranger/arranger.cpp213
-rw-r--r--muse2/muse/arranger/arranger.h23
-rw-r--r--muse2/muse/arranger/arrangerview.cpp3
-rw-r--r--muse2/muse/arranger/arrangerview.h2
-rw-r--r--muse2/muse/arranger/tlist.cpp309
-rw-r--r--muse2/muse/arranger/tlist.h8
-rw-r--r--muse2/muse/conf.cpp2
-rw-r--r--muse2/muse/widgets/header.cpp90
-rw-r--r--muse2/muse/widgets/header.h3
-rw-r--r--muse2/muse/widgets/spinbox.cpp6
-rw-r--r--muse2/muse/widgets/utils.h3
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_col_t> Arranger::custom_columns;
+QString Arranger::header_state;
+
+void Arranger::writeCustomColumns(int level, MusECore::Xml& xml)
+{
+ xml.tag(level++, "custom_columns");
+
+ for (unsigned i=0;i<custom_columns.size();i++)
+ {
+ xml.tag(level++, "column");
+ xml.strTag(level, "name", custom_columns[i].name);
+ xml.intTag(level, "ctrl", custom_columns[i].ctrl);
+ xml.etag(--level, "column");
+ }
+
+ xml.etag(--level, "custom_columns");
+}
+
+void Arranger::readCustomColumns(MusECore::Xml& xml)
+{
+ custom_columns.clear();
+
+ 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 == "column")
+ custom_columns.push_back(readOneCustomColumn(xml));
+ else
+ xml.unknown("Arranger::readCustomColumns");
+ break;
+ case MusECore::Xml::TagEnd:
+ if (tag == "custom_columns")
+ return;
+ default:
+ break;
+ }
+ }
+}
+
+Arranger::custom_col_t Arranger::readOneCustomColumn(MusECore::Xml& xml)
+{
+ custom_col_t temp(0, "-");
+
+ for (;;) {
+ MusECore::Xml::Token token(xml.parse());
+ const QString& tag(xml.s1());
+ switch (token) {
+ case MusECore::Xml::Error:
+ case MusECore::Xml::End:
+ return temp;
+ case MusECore::Xml::TagStart:
+ if (tag == "name")
+ temp.name=xml.parse1();
+ else if (tag == "ctrl")
+ temp.ctrl=xml.parseInt();
+ else
+ xml.unknown("Arranger::readOneCustomColumn");
+ break;
+ case MusECore::Xml::TagEnd:
+ if (tag == "column")
+ return temp;
+ default:
+ break;
+ }
+ }
+ return temp;
+}
+
+
+
//---------------------------------------------------------
// Arranger::setHeaderToolTips
//---------------------------------------------------------
@@ -258,7 +333,7 @@ Arranger::Arranger(ArrangerView* parent, const char* name)
box->addWidget(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;i<custom_columns.size();i++)
+ header->setColumnLabel(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;i<custom_columns.size();i++)
+ header->setResizeMode(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 <vector>
+#include <QString>
#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_col_t> 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<MusECore::MidiTrack*>(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<MusECore::MidiTrack*>(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<MusECore::MidiTrack*>(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<MusECore::MidiTrack*>(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<MusECore::MidiTrack*>(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("</%s>", name());
+ xml.nput("%s", getStatus().toLatin1().constData());
xml.put("</%s>", 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 <QHeaderView>
#include <QAction>
+#include <QString>
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;