summaryrefslogtreecommitdiffstats
path: root/src/gui/editors/segment/TriggerSegmentManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/editors/segment/TriggerSegmentManager.cpp')
-rw-r--r--src/gui/editors/segment/TriggerSegmentManager.cpp576
1 files changed, 576 insertions, 0 deletions
diff --git a/src/gui/editors/segment/TriggerSegmentManager.cpp b/src/gui/editors/segment/TriggerSegmentManager.cpp
new file mode 100644
index 0000000..3fb1732
--- /dev/null
+++ b/src/gui/editors/segment/TriggerSegmentManager.cpp
@@ -0,0 +1,576 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "TriggerSegmentManager.h"
+#include "TriggerManagerItem.h"
+#include <qlayout.h>
+#include <kapplication.h>
+
+#include "base/BaseProperties.h"
+#include <klocale.h>
+#include <kstddirs.h>
+#include "misc/Debug.h"
+#include "misc/Strings.h"
+#include "base/Clipboard.h"
+#include "base/Composition.h"
+#include "base/CompositionTimeSliceAdapter.h"
+#include "base/RealTime.h"
+#include "base/Segment.h"
+#include "base/TriggerSegment.h"
+#include "commands/segment/AddTriggerSegmentCommand.h"
+#include "commands/segment/DeleteTriggerSegmentCommand.h"
+#include "commands/segment/PasteToTriggerSegmentCommand.h"
+#include "document/MultiViewCommandHistory.h"
+#include "document/RosegardenGUIDoc.h"
+#include "document/ConfigGroups.h"
+#include "gui/dialogs/TimeDialog.h"
+#include "gui/general/MidiPitchLabel.h"
+#include <kaction.h>
+#include <kcommand.h>
+#include <kglobal.h>
+#include <klistview.h>
+#include <kmainwindow.h>
+#include <kmessagebox.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+#include <kconfig.h>
+#include <qaccel.h>
+#include <qdialog.h>
+#include <qframe.h>
+#include <qiconset.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qsizepolicy.h>
+#include <qstring.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+#include <qwidget.h>
+#include <qcanvas.h>
+
+
+namespace Rosegarden
+{
+
+TriggerSegmentManager::TriggerSegmentManager(QWidget *parent,
+ RosegardenGUIDoc *doc):
+ KMainWindow(parent, "triggereditordialog"),
+ m_doc(doc),
+ m_modified(false)
+{
+ QVBox* mainFrame = new QVBox(this);
+ setCentralWidget(mainFrame);
+
+ setCaption(i18n("Manage Triggered Segments"));
+
+ m_listView = new KListView(mainFrame);
+ m_listView->addColumn("Index");
+ m_listView->addColumn(i18n("ID"));
+ m_listView->addColumn(i18n("Label"));
+ m_listView->addColumn(i18n("Duration"));
+ m_listView->addColumn(i18n("Base pitch"));
+ m_listView->addColumn(i18n("Base velocity"));
+ m_listView->addColumn(i18n("Triggers"));
+
+ // Align centrally
+ for (int i = 0; i < 2; ++i)
+ m_listView->setColumnAlignment(i, Qt::AlignHCenter);
+
+ QFrame* btnBox = new QFrame(mainFrame);
+
+ btnBox->setSizePolicy(
+ QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed));
+
+ QHBoxLayout* layout = new QHBoxLayout(btnBox, 4, 10);
+
+ m_addButton = new QPushButton(i18n("Add"), btnBox);
+ m_deleteButton = new QPushButton(i18n("Delete"), btnBox);
+ m_deleteAllButton = new QPushButton(i18n("Delete All"), btnBox);
+
+ m_closeButton = new QPushButton(i18n("Close"), btnBox);
+
+ QToolTip::add
+ (m_addButton,
+ i18n("Add a Triggered Segment"));
+
+ QToolTip::add
+ (m_deleteButton,
+ i18n("Delete a Triggered Segment"));
+
+ QToolTip::add
+ (m_deleteAllButton,
+ i18n("Delete All Triggered Segments"));
+
+ QToolTip::add
+ (m_closeButton,
+ i18n("Close the Triggered Segment Manager"));
+
+ layout->addStretch(10);
+ layout->addWidget(m_addButton);
+ layout->addWidget(m_deleteButton);
+ layout->addWidget(m_deleteAllButton);
+ layout->addSpacing(30);
+
+ layout->addWidget(m_closeButton);
+ layout->addSpacing(5);
+
+ connect(m_addButton, SIGNAL(released()),
+ SLOT(slotAdd()));
+
+ connect(m_deleteButton, SIGNAL(released()),
+ SLOT(slotDelete()));
+
+ connect(m_closeButton, SIGNAL(released()),
+ SLOT(slotClose()));
+
+ connect(m_deleteAllButton, SIGNAL(released()),
+ SLOT(slotDeleteAll()));
+
+ setupActions();
+
+ m_doc->getCommandHistory()->attachView(actionCollection());
+ connect(m_doc->getCommandHistory(), SIGNAL(commandExecuted()),
+ this, SLOT(slotUpdate()));
+
+ connect(m_listView, SIGNAL(doubleClicked(QListViewItem *)),
+ SLOT(slotEdit(QListViewItem *)));
+
+ connect(m_listView, SIGNAL(pressed(QListViewItem *)),
+ this, SLOT(slotItemClicked(QListViewItem *)));
+
+ // Highlight all columns - enable extended selection mode
+ //
+ m_listView->setAllColumnsShowFocus(true);
+ m_listView->setSelectionMode(QListView::Extended);
+ m_listView->setItemsRenameable(true);
+
+ initDialog();
+
+ setAutoSaveSettings(TriggerManagerConfigGroup, true);
+
+ m_accelerators = new QAccel(this);
+}
+
+TriggerSegmentManager::~TriggerSegmentManager()
+{
+ RG_DEBUG << "TriggerSegmentManager::~TriggerSegmentManager" << endl;
+
+ m_listView->saveLayout(kapp->config(), TriggerManagerConfigGroup);
+
+ if (m_doc)
+ m_doc->getCommandHistory()->detachView(actionCollection());
+}
+
+void
+TriggerSegmentManager::initDialog()
+{
+ RG_DEBUG << "TriggerSegmentManager::initDialog" << endl;
+ slotUpdate();
+}
+
+void
+TriggerSegmentManager::slotUpdate()
+{
+ RG_DEBUG << "TriggerSegmentManager::slotUpdate" << endl;
+
+ TriggerManagerItem *item;
+
+ m_listView->clear();
+
+ Composition &comp = m_doc->getComposition();
+
+ const Composition::triggersegmentcontainer &triggers =
+ comp.getTriggerSegments();
+
+ Composition::triggersegmentcontainerconstiterator it;
+
+ kapp->config()->setGroup(TriggerManagerConfigGroup);
+ int timeMode = kapp->config()->readNumEntry("timemode", 0);
+
+ int i = 0;
+
+ for (it = triggers.begin(); it != triggers.end(); ++it) {
+
+ // duration is as of first usage, or 0
+
+ int uses = 0;
+ timeT first = 0;
+ std::set
+ <int> tracks;
+
+ CompositionTimeSliceAdapter tsa(&m_doc->getComposition());
+ for (CompositionTimeSliceAdapter::iterator ci = tsa.begin();
+ ci != tsa.end(); ++ci) {
+ if ((*ci)->has(BaseProperties::TRIGGER_SEGMENT_ID) &&
+ (*ci)->get
+ <Int>(BaseProperties::TRIGGER_SEGMENT_ID) == (long)(*it)->getId()) {
+ ++uses;
+ if (tracks.empty()) {
+ first = (*ci)->getAbsoluteTime();
+ }
+ tracks.insert(ci.getTrack());
+ }
+ }
+
+ timeT duration =
+ (*it)->getSegment()->getEndMarkerTime() -
+ (*it)->getSegment()->getStartTime();
+
+ QString timeString = makeDurationString
+ (first, duration, timeMode);
+
+ QString label = strtoqstr((*it)->getSegment()->getLabel());
+ if (label == "")
+ label = i18n("<no label>");
+
+ QString used = i18n("%1 on 1 track",
+ "%1 on %n tracks",
+ tracks.size()).arg(uses);
+
+ QString pitch = QString("%1 (%2)")
+ .arg(MidiPitchLabel((*it)->getBasePitch()).getQString())
+ .arg((*it)->getBasePitch());
+
+ QString velocity = QString("%1").arg((*it)->getBaseVelocity());
+
+ item = new TriggerManagerItem
+ (m_listView, QString("%1").arg(i + 1), QString("%1").arg((*it)->getId()),
+ label, timeString, pitch, velocity, used);
+
+ item->setRawDuration(duration);
+ item->setId((*it)->getId());
+ item->setUsage(uses);
+ item->setPitch((*it)->getBasePitch());
+
+ m_listView->insertItem(item);
+ ++i;
+ }
+
+ if (m_listView->childCount() == 0) {
+ QListViewItem *item =
+ new TriggerManagerItem(m_listView, i18n("<none>"));
+ m_listView->insertItem(item);
+
+ m_listView->setSelectionMode(QListView::NoSelection);
+ } else {
+ m_listView->setSelectionMode(QListView::Extended);
+ }
+}
+
+void
+TriggerSegmentManager::slotDeleteAll()
+{
+ if (KMessageBox::warningContinueCancel(this, i18n("This will remove all triggered segments from the whole composition. Are you sure?")) != KMessageBox::Continue)
+ return ;
+
+ RG_DEBUG << "TriggerSegmentManager::slotDeleteAll" << endl;
+ KMacroCommand *command = new KMacroCommand(i18n("Remove all triggered segments"));
+
+ QListViewItem *it = m_listView->firstChild();
+
+ do {
+
+ TriggerManagerItem *item =
+ dynamic_cast<TriggerManagerItem*>(it);
+
+ if (!item)
+ continue;
+
+ DeleteTriggerSegmentCommand *c =
+ new DeleteTriggerSegmentCommand(m_doc,
+ item->getId());
+ command->addCommand(c);
+
+ } while ((it = it->nextSibling()));
+
+ addCommandToHistory(command);
+}
+
+void
+TriggerSegmentManager::slotAdd()
+{
+ TimeDialog dialog(this, i18n("Trigger Segment Duration"),
+ &m_doc->getComposition(),
+ 0, 3840, false);
+
+ if (dialog.exec() == QDialog::Accepted) {
+ addCommandToHistory(new AddTriggerSegmentCommand
+ (m_doc, dialog.getTime(), 64));
+ }
+}
+
+void
+TriggerSegmentManager::slotDelete()
+{
+ RG_DEBUG << "TriggerSegmentManager::slotDelete" << endl;
+
+ TriggerManagerItem *item =
+ dynamic_cast<TriggerManagerItem*>(m_listView->currentItem());
+
+ if (!item)
+ return ;
+
+ if (item->getUsage() > 0) {
+ if (KMessageBox::warningContinueCancel(this, i18n("This triggered segment is used 1 time in the current composition. Are you sure you want to remove it?",
+ "This triggered segment is used %n times in the current composition. Are you sure you want to remove it?", item->getUsage())) != KMessageBox::Continue)
+ return ;
+ }
+
+ DeleteTriggerSegmentCommand *command =
+ new DeleteTriggerSegmentCommand(m_doc, item->getId());
+
+ addCommandToHistory(command);
+}
+
+void
+TriggerSegmentManager::slotPasteAsNew()
+{
+ Clipboard *clipboard = m_doc->getClipboard();
+
+ if (clipboard->isEmpty()) {
+ KMessageBox::information(this, i18n("Clipboard is empty"));
+ return ;
+ }
+
+ addCommandToHistory(new PasteToTriggerSegmentCommand
+ (&m_doc->getComposition(),
+ clipboard,
+ "",
+ -1));
+}
+
+void
+TriggerSegmentManager::slotClose()
+{
+ RG_DEBUG << "TriggerSegmentManager::slotClose" << endl;
+
+ if (m_doc)
+ m_doc->getCommandHistory()->detachView(actionCollection());
+ m_doc = 0;
+
+ close();
+}
+
+void
+TriggerSegmentManager::setupActions()
+{
+ KAction* close = KStdAction::close(this,
+ SLOT(slotClose()),
+ actionCollection());
+
+ m_closeButton->setText(close->text());
+ connect(m_closeButton, SIGNAL(released()), this, SLOT(slotClose()));
+
+ QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/");
+
+ // some adjustments
+ new KToolBarPopupAction(i18n("Und&o"),
+ "undo",
+ KStdAccel::key(KStdAccel::Undo),
+ actionCollection(),
+ KStdAction::stdName(KStdAction::Undo));
+
+ new KToolBarPopupAction(i18n("Re&do"),
+ "redo",
+ KStdAccel::key(KStdAccel::Redo),
+ actionCollection(),
+ KStdAction::stdName(KStdAction::Redo));
+
+ new KAction(i18n("Pa&ste as New Triggered Segment"), CTRL + SHIFT + Key_V, this,
+ SLOT(slotPasteAsNew()), actionCollection(),
+ "paste_to_trigger_segment");
+
+ kapp->config()->setGroup(TriggerManagerConfigGroup);
+ int timeMode = kapp->config()->readNumEntry("timemode", 0);
+
+ KRadioAction *action;
+
+ QCanvasPixmap pixmap(pixmapDir + "/toolbar/time-musical.png");
+ QIconSet icon(pixmap);
+
+ action = new KRadioAction(i18n("&Musical Times"), icon, 0, this,
+ SLOT(slotMusicalTime()),
+ actionCollection(), "time_musical");
+ action->setExclusiveGroup("timeMode");
+ if (timeMode == 0)
+ action->setChecked(true);
+
+ pixmap.load(pixmapDir + "/toolbar/time-real.png");
+ icon = QIconSet(pixmap);
+
+ action = new KRadioAction(i18n("&Real Times"), icon, 0, this,
+ SLOT(slotRealTime()),
+ actionCollection(), "time_real");
+ action->setExclusiveGroup("timeMode");
+ if (timeMode == 1)
+ action->setChecked(true);
+
+ pixmap.load(pixmapDir + "/toolbar/time-raw.png");
+ icon = QIconSet(pixmap);
+
+ action = new KRadioAction(i18n("Ra&w Times"), icon, 0, this,
+ SLOT(slotRawTime()),
+ actionCollection(), "time_raw");
+ action->setExclusiveGroup("timeMode");
+ if (timeMode == 2)
+ action->setChecked(true);
+
+ createGUI("triggermanager.rc");
+}
+
+void
+TriggerSegmentManager::addCommandToHistory(KCommand *command)
+{
+ getCommandHistory()->addCommand(command);
+ setModified(false);
+}
+
+MultiViewCommandHistory*
+TriggerSegmentManager::getCommandHistory()
+{
+ return m_doc->getCommandHistory();
+}
+
+void
+TriggerSegmentManager::setModified(bool modified)
+{
+ RG_DEBUG << "TriggerSegmentManager::setModified(" << modified << ")" << endl;
+
+ m_modified = modified;
+}
+
+void
+TriggerSegmentManager::checkModified()
+{
+ RG_DEBUG << "TriggerSegmentManager::checkModified(" << m_modified << ")"
+ << endl;
+
+}
+
+void
+TriggerSegmentManager::slotEdit(QListViewItem *i)
+{
+ RG_DEBUG << "TriggerSegmentManager::slotEdit" << endl;
+
+ TriggerManagerItem *item =
+ dynamic_cast<TriggerManagerItem*>(i);
+
+ if (!item)
+ return ;
+
+ TriggerSegmentId id = item->getId();
+
+ RG_DEBUG << "id is " << id << endl;
+
+ emit editTriggerSegment(id);
+}
+
+void
+TriggerSegmentManager::closeEvent(QCloseEvent *e)
+{
+ emit closing();
+ KMainWindow::closeEvent(e);
+}
+
+void
+TriggerSegmentManager::setDocument(RosegardenGUIDoc *doc)
+{
+ // reset our pointers
+ m_doc = doc;
+ m_modified = false;
+
+ slotUpdate();
+}
+
+void
+TriggerSegmentManager::slotItemClicked(QListViewItem *item)
+{
+ RG_DEBUG << "TriggerSegmentManager::slotItemClicked" << endl;
+}
+
+QString
+TriggerSegmentManager::makeDurationString(timeT time,
+ timeT duration, int timeMode)
+{
+ //!!! duplication with EventView::makeDurationString -- merge somewhere?
+
+ switch (timeMode) {
+
+ case 0: // musical time
+ {
+ int bar, beat, fraction, remainder;
+ m_doc->getComposition().getMusicalTimeForDuration
+ (time, duration, bar, beat, fraction, remainder);
+ return QString("%1%2%3-%4%5-%6%7-%8%9 ")
+ .arg(bar / 100)
+ .arg((bar % 100) / 10)
+ .arg(bar % 10)
+ .arg(beat / 10)
+ .arg(beat % 10)
+ .arg(fraction / 10)
+ .arg(fraction % 10)
+ .arg(remainder / 10)
+ .arg(remainder % 10);
+ }
+
+ case 1: // real time
+ {
+ RealTime rt =
+ m_doc->getComposition().getRealTimeDifference
+ (time, time + duration);
+ // return QString("%1 ").arg(rt.toString().c_str());
+ return QString("%1 ").arg(rt.toText().c_str());
+ }
+
+ default:
+ return QString("%1 ").arg(duration);
+ }
+}
+
+void
+TriggerSegmentManager::slotMusicalTime()
+{
+ kapp->config()->setGroup(TriggerManagerConfigGroup);
+ kapp->config()->writeEntry("timemode", 0);
+ slotUpdate();
+}
+
+void
+TriggerSegmentManager::slotRealTime()
+{
+ kapp->config()->setGroup(TriggerManagerConfigGroup);
+ kapp->config()->writeEntry("timemode", 1);
+ slotUpdate();
+}
+
+void
+TriggerSegmentManager::slotRawTime()
+{
+ kapp->config()->setGroup(TriggerManagerConfigGroup);
+ kapp->config()->writeEntry("timemode", 2);
+ slotUpdate();
+}
+
+}
+#include "TriggerSegmentManager.moc"