From cc3f817f58d4c9d33e03b2aafd9e53b352041028 Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Tue, 28 Nov 2006 11:38:56 +0000 Subject: part drag& drop --- muse/ChangeLog | 2 + muse/muse/arranger/canvas.cpp | 165 ++++++++++++++++++++++++---------------- muse/muse/arranger/canvas.h | 2 + muse/muse/arranger/partdrag.cpp | 50 +++++++++--- muse/muse/miditrack.cpp | 2 +- muse/muse/part.cpp | 8 +- muse/muse/part.h | 2 +- muse/muse/songfile.cpp | 1 - muse/muse/songpart.cpp | 2 +- muse/muse/wavetrack.cpp | 2 +- 10 files changed, 151 insertions(+), 85 deletions(-) diff --git a/muse/ChangeLog b/muse/ChangeLog index 08f9772c..f7abcbf7 100644 --- a/muse/ChangeLog +++ b/muse/ChangeLog @@ -1,3 +1,5 @@ +28.11 (ws) + - application spanning drag&drop of parts 24.11 (ws) - added new make target: "doxy" to generate doxygen source documentation diff --git a/muse/muse/arranger/canvas.cpp b/muse/muse/arranger/canvas.cpp index cd871963..1bcc3d71 100644 --- a/muse/muse/arranger/canvas.cpp +++ b/muse/muse/arranger/canvas.cpp @@ -760,14 +760,20 @@ void PartCanvas::mouseMove(QPoint pos) // // drag whole part // + srcPart = part; QDrag* d = 0; if (track->type() == Track::MIDI) - d = new MidiPartDrag(part, this); + d = new MidiPartDrag(srcPart, this); else if (track->type() == Track::WAVE) - d = new AudioPartDrag(part, this); + d = new AudioPartDrag(srcPart, this); if (d) { + Qt::KeyboardModifiers kb = QApplication::keyboardModifiers(); + Qt::DropActions da = kb ? (Qt::MoveAction | Qt::CopyAction | Qt::LinkAction) : Qt::MoveAction; + song->startUndo(); _dragOffset = startDrag.x() - rCanvasA.x() - ppos; - /* Qt::DropAction da =*/ d->start(Qt::CopyAction | Qt::LinkAction | Qt::MoveAction); + if (d->start(da) == Qt::MoveAction) + song->removePart(srcPart); + song->endUndo(0); update = true; } state = S_NORMAL; @@ -951,7 +957,13 @@ void PartCanvas::dragEnter(QDragEnterEvent* event) if (MidiPartDrag::canDecode(md) || AudioPartDrag::canDecode(md) || WavUriDrag::canDecode(md)) { - event->acceptProposedAction(); + Qt::KeyboardModifiers kb = event->keyboardModifiers(); + if (kb == 0 && (Qt::MoveAction & event->possibleActions())) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } + else + event->acceptProposedAction(); } else { QStringList formats = md->formats(); @@ -966,37 +978,32 @@ void PartCanvas::dragEnter(QDragEnterEvent* event) void PartCanvas::dragMove(QDragMoveEvent* event) { + QPoint p(event->pos() - rCanvasA.topLeft()); + searchPart(p); + if (!track) { + if (state != S_NORMAL) { + state = S_NORMAL; + widget()->update(); + } + event->ignore(); + return; + } + Part* srcPart = 0; QString filename; + bool srcIsMidi; const QMimeData* md = event->mimeData(); if (MidiPartDrag::canDecode(md)) { MidiPartDrag::decode(md, srcPart); + srcIsMidi = true; } else if (AudioPartDrag::canDecode(md)) { AudioPartDrag::decode(md, srcPart); + srcIsMidi = false; } else if (WavUriDrag::canDecode(md)) { WavUriDrag::decode(md, &filename); - } - else { - state = S_NORMAL; - event->ignore(); - return; - } - Track* srcTrack = srcPart ? srcPart->track() : 0; - - QPoint p(event->pos() - rCanvasA.topLeft()); - searchPart(p); - if (!track) { - if (state != S_NORMAL) { - state = S_NORMAL; - widget()->update(); - } - event->ignore(); - return; - } - if (srcTrack == 0) { // drag uri if (state != S_NORMAL) { state = S_NORMAL; widget()->update(); @@ -1007,7 +1014,14 @@ void PartCanvas::dragMove(QDragMoveEvent* event) event->ignore(); return; } - if (track->type() != srcTrack->type()) { + else { + state = S_NORMAL; + event->ignore(); + return; + } + + bool dstIsMidi = track->type() == Track::MIDI; + if (dstIsMidi != srcIsMidi) { if (state != S_NORMAL) { state = S_NORMAL; widget()->update(); @@ -1015,20 +1029,31 @@ void PartCanvas::dragMove(QDragMoveEvent* event) event->ignore(); return; } - event->acceptProposedAction(); + Qt::KeyboardModifiers kb = event->keyboardModifiers(); + if (kb == 0 && (Qt::MoveAction & event->possibleActions())) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } + else + event->acceptProposedAction(); state = S_DRAG4; ArrangerTrack* at = &(track->arrangerTrack); PartCanvas* cw = (PartCanvas*)event->source(); QRect updateRect(drag); - Pos pos(pix2pos(p.x() - cw->dragOffset()).snaped(raster())); + Pos pos; + if (cw) + pos = pix2pos(p.x() - cw->dragOffset()).snaped(raster()); + else + pos = pix2pos(p.x()).snaped(raster()); drag.setRect( pos2pix(pos), at->tw->y(), rmapx(srcPart->lenTick()), at->tw->height() - 1 - partBorderWidth ); + delete srcPart; updateRect |= drag; updateRect.adjust(-1, -1 + rCanvasA.y(), 1, 1 + rCanvasA.y()); widget()->update(updateRect); @@ -1041,54 +1066,66 @@ void PartCanvas::dragMove(QDragMoveEvent* event) void PartCanvas::drop(QDropEvent* event) { state = S_NORMAL; - Part* srcPart = 0; + Part* dstPart = 0; QString filename; + QPoint pos(event->pos() - rCanvasA.topLeft()); const QMimeData* md = event->mimeData(); - if (MidiPartDrag::canDecode(md)) { - MidiPartDrag::decode(md, srcPart); - } - else if (AudioPartDrag::canDecode(md)) { - AudioPartDrag::decode(md, srcPart); - } - else if (WavUriDrag::canDecode(md)) { + if (WavUriDrag::canDecode(md)) { WavUriDrag::decode(md, &filename); - } - else + int tick = AL::sigmap.raster(mapxDev(pos.x()), raster()); + Pos pos(tick); + muse->importWaveToTrack(filename, track, pos); + widget()->update(); return; + } + + bool isMidi = false; + if (MidiPartDrag::canDecode(md)) { + MidiPartDrag::decode(md, dstPart); + isMidi = true; + } + else if (AudioPartDrag::canDecode(md)) + AudioPartDrag::decode(md, dstPart); - QPoint pos(event->pos() - rCanvasA.topLeft()); searchPart(pos); - Track* srcTrack = srcPart ? srcPart->track() : 0; - if (track == 0 || (srcTrack && (track->type() != srcTrack->type()))) + if (!track || !dstPart || isMidi != track->isMidiTrack()) return; - if (srcPart == 0) { - int tick = AL::sigmap.raster(mapxDev(pos.x()), raster()); - Pos pos(tick); - muse->importWaveToTrack(filename, track, pos); - } - else { - PartCanvas* cw = (PartCanvas*)event->source(); - unsigned tick = AL::sigmap.raster(mapxDev(pos.x() - cw->dragOffset()), raster()); - if (srcPart->tick() != tick || srcTrack != track) { - Qt::KeyboardModifiers keyState = event->keyboardModifiers(); - - if (keyState & Qt::ShiftModifier) { - song->cmdCopyPart(srcPart, tick, track); - event->setDropAction(Qt::CopyAction); - } - else if (keyState & Qt::ControlModifier) { - song->cmdLinkPart(srcPart, tick, track); - event->setDropAction(Qt::LinkAction); - } - else { - song->cmdMovePart(srcPart, tick, track); - event->setDropAction(Qt::MoveAction); - } - } + dstPart->setTrack(track); + PartCanvas* cw = (PartCanvas*)event->source(); + + // + // cw == 0 means that we are dropping to + // another application + + unsigned tick; + if (cw) + tick = AL::sigmap.raster(mapxDev(pos.x() - cw->dragOffset()), raster()); + else + tick = AL::sigmap.raster(mapxDev(pos.x()), raster()); + + dstPart->setTick(tick); + + Qt::DropAction da = event->proposedAction(); + Qt::KeyboardModifiers kb = event->keyboardModifiers(); + if (kb == 0 && (Qt::MoveAction & event->possibleActions())) + da = Qt::MoveAction; + + if ((da == Qt::LinkAction) && (event->source() == this)) { + delete dstPart->events(); + dstPart->clone(srcPart->events()); + event->setDropAction(Qt::LinkAction); } - event->acceptProposedAction(); + else if (da == Qt::MoveAction) + event->setDropAction(Qt::MoveAction); + else + event->setDropAction(Qt::CopyAction); + event->accept(); + if (cw) + song->addPart(dstPart); + else + song->cmdAddPart(dstPart); widget()->update(); } diff --git a/muse/muse/arranger/canvas.h b/muse/muse/arranger/canvas.h index 8ecd3abe..032292af 100644 --- a/muse/muse/arranger/canvas.h +++ b/muse/muse/arranger/canvas.h @@ -63,6 +63,8 @@ class PartCanvas : public TimeCanvas { Part* part; ArrangerTrack* at; + Part* srcPart; // src part of a drag/drop operation + bool _drawBackground; int selected; int lselected; // in local coordinates diff --git a/muse/muse/arranger/partdrag.cpp b/muse/muse/arranger/partdrag.cpp index a09d9d3b..e497b613 100644 --- a/muse/muse/arranger/partdrag.cpp +++ b/muse/muse/arranger/partdrag.cpp @@ -19,8 +19,8 @@ //============================================================================= #include "partdrag.h" - -class Part; +#include "al/xml.h" +#include "part.h" const char MidiPartDrag::type[] = "application/muse/part/midi"; const char AudioPartDrag::type[] = "application/muse/part/audio"; @@ -36,9 +36,13 @@ const char WavUriDrag::type[] = "text/uri-list"; MidiPartDrag::MidiPartDrag(Part* part, QWidget* src) : QDrag(src) { - QByteArray a((const char*)&part, sizeof(part)); + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + AL::Xml xml(&buffer); + part->write(xml); + buffer.close(); QMimeData* mimeData = new QMimeData; - mimeData->setData(type, a); + mimeData->setData(type, buffer.buffer()); setMimeData(mimeData); } @@ -57,11 +61,31 @@ bool MidiPartDrag::canDecode(const QMimeData* s) bool MidiPartDrag::decode(const QMimeData* s, Part*& p) { - QByteArray a = s->data(type); - char* cp = (char*)(&p); - for (unsigned i = 0; i < sizeof(p); ++i) - *cp++ = a[i]; - return true; + p = 0; + QDomDocument doc; + int line, column; + QString err; + if (!doc.setContent(s->data(type), false, &err, &line, &column)) { + QString col, ln, error; + col.setNum(column); + ln.setNum(line); + error = err + "\n at line: " + ln + " col: " + col; + printf("error parsing part: %s\n", error.toLatin1().data()); + return false; + } + for (QDomNode node = doc.documentElement(); !node.isNull(); node = node.nextSibling()) { + QDomElement e = node.toElement(); + if (e.isNull()) + continue; + if (e.tagName() == "part") { + p = new Part(0); + p->ref(); + p->read(node, true); + } + else + printf("MusE: %s not supported\n", e.tagName().toLatin1().data()); + } + return (p != 0); } //--------------------------------------------------------- @@ -74,10 +98,14 @@ bool MidiPartDrag::decode(const QMimeData* s, Part*& p) AudioPartDrag::AudioPartDrag(Part* part, QWidget* src) : QDrag(src) { - QByteArray a((char*)&part, sizeof(part)); + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + Xml xml(&buffer); + part->write(xml); + buffer.close(); QMimeData* mimeData = new QMimeData; - mimeData->setData(type, a); + mimeData->setData(type, buffer.buffer()); setMimeData(mimeData); } diff --git a/muse/muse/miditrack.cpp b/muse/muse/miditrack.cpp index 742e24e1..e96f53ef 100644 --- a/muse/muse/miditrack.cpp +++ b/muse/muse/miditrack.cpp @@ -131,7 +131,7 @@ void MidiTrack::read(QDomNode node) _compression = i; else if (tag == "part") { Part* p = newPart(); - p->read(node); + p->read(node, true); parts()->add(p); } else if (tag == "locked") diff --git a/muse/muse/part.cpp b/muse/muse/part.cpp index e52b1309..30daed4f 100644 --- a/muse/muse/part.cpp +++ b/muse/muse/part.cpp @@ -63,7 +63,7 @@ Part::Part(Track* t) _fillLen = 0; _track = t; _events = 0; - if (_track->type() == Track::WAVE) + if (_track && _track->type() == Track::WAVE) setType(AL::FRAMES); } @@ -244,7 +244,7 @@ void Part::write(Xml& xml) // Part::read //--------------------------------------------------------- -void Part::read(QDomNode node) +void Part::read(QDomNode node, bool isMidiPart) { QDomElement e = node.toElement(); int id = e.attribute("cloneId", "-1").toInt(); @@ -280,9 +280,7 @@ void Part::read(QDomNode node) else if (tag == "fillLen") _fillLen = i; else if (tag == "event") { - EventType type = Wave; - if (_track->isMidiTrack()) - type = Note; + EventType type = isMidiPart ? Note : Wave; Event e(type); e.read(node); // tickpos is relative to start of part diff --git a/muse/muse/part.h b/muse/muse/part.h index 8a7c80f0..fd5fdd52 100644 --- a/muse/muse/part.h +++ b/muse/muse/part.h @@ -120,7 +120,7 @@ class Part : public AL::PosLen { int fillLen() const { return _fillLen; } void setFillLen(int val) { _fillLen = val; } - void read(QDomNode); + void read(QDomNode, bool isMidiPart); void write(Xml&); void dump(int n = 0) const; diff --git a/muse/muse/songfile.cpp b/muse/muse/songfile.cpp index 187132e3..fa62d4f2 100644 --- a/muse/muse/songfile.cpp +++ b/muse/muse/songfile.cpp @@ -26,7 +26,6 @@ #include "midiedit/drummap.h" #include "al/marker.h" #include "midictrl.h" -// #include "mixer/mixer.h" #include "conf.h" #include "midiseq.h" #include "al/tempo.h" diff --git a/muse/muse/songpart.cpp b/muse/muse/songpart.cpp index 6ad52f47..e561476b 100644 --- a/muse/muse/songpart.cpp +++ b/muse/muse/songpart.cpp @@ -117,7 +117,7 @@ void Song::removePart(Part* part) audio->sendMessage(&msg, false); undoOp(UndoOp::DeletePart, part); updateFlags |= SC_PART_REMOVED; -// part->deref(); + part->deref(); part->track()->partListChanged(); } diff --git a/muse/muse/wavetrack.cpp b/muse/muse/wavetrack.cpp index 47187364..750c805a 100644 --- a/muse/muse/wavetrack.cpp +++ b/muse/muse/wavetrack.cpp @@ -157,7 +157,7 @@ void WaveTrack::read(QDomNode node) if (e.tagName() == "part") { Part* p = newPart(); p->ref(); - p->read(node); + p->read(node, false); parts()->add(p); } else if (AudioTrack::readProperties(node)) -- cgit v1.2.3