You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
595 lines
16 KiB
595 lines
16 KiB
/* -*- 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 <glaurent@telegraph-road.org>,
|
|
Chris Cannam <cannam@all-day-breakfast.com>,
|
|
Richard Bown <richard.bown@ferventsoftware.com>
|
|
|
|
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 "MarkerEditor.h"
|
|
#include "MarkerEditorViewItem.h"
|
|
#include <tqlayout.h>
|
|
#include <kapplication.h>
|
|
|
|
#include <klocale.h>
|
|
#include <kstddirs.h>
|
|
#include <kstdaccel.h>
|
|
#include <kconfig.h>
|
|
#include "misc/Debug.h"
|
|
#include "misc/Strings.h"
|
|
#include "base/Composition.h"
|
|
#include "base/Marker.h"
|
|
#include "base/RealTime.h"
|
|
#include "commands/edit/AddMarkerCommand.h"
|
|
#include "commands/edit/ModifyMarkerCommand.h"
|
|
#include "commands/edit/RemoveMarkerCommand.h"
|
|
#include "document/MultiViewCommandHistory.h"
|
|
#include "document/RosegardenGUIDoc.h"
|
|
#include "document/ConfigGroups.h"
|
|
#include "gui/dialogs/MarkerModifyDialog.h"
|
|
#include <kaction.h>
|
|
#include <kcommand.h>
|
|
#include <kglobal.h>
|
|
#include <klistview.h>
|
|
#include <kmainwindow.h>
|
|
#include <kstdaccel.h>
|
|
#include <kstdaction.h>
|
|
#include <tqaccel.h>
|
|
#include <tqdialog.h>
|
|
#include <tqframe.h>
|
|
#include <tqgroupbox.h>
|
|
#include <tqiconset.h>
|
|
#include <tqlabel.h>
|
|
#include <tqlistview.h>
|
|
#include <tqptrlist.h>
|
|
#include <tqpushbutton.h>
|
|
#include <tqsizepolicy.h>
|
|
#include <tqstring.h>
|
|
#include <tqtooltip.h>
|
|
#include <tqvbox.h>
|
|
#include <tqwidget.h>
|
|
#include <tqcanvas.h>
|
|
|
|
|
|
namespace Rosegarden
|
|
{
|
|
|
|
MarkerEditor::MarkerEditor(TQWidget *parent,
|
|
RosegardenGUIDoc *doc):
|
|
KMainWindow(parent, "markereditordialog"),
|
|
m_doc(doc),
|
|
m_modified(false)
|
|
{
|
|
TQVBox* mainFrame = new TQVBox(this);
|
|
setCentralWidget(mainFrame);
|
|
|
|
setCaption(i18n("Manage Markers"));
|
|
|
|
m_listView = new KListView(mainFrame);
|
|
m_listView->addColumn(i18n("Marker time "));
|
|
m_listView->addColumn(i18n("Marker text "));
|
|
m_listView->addColumn(i18n("Marker description "));
|
|
|
|
// Align centrally
|
|
for (int i = 0; i < 3; ++i)
|
|
m_listView->setColumnAlignment(i, TQt::AlignHCenter);
|
|
|
|
TQGroupBox *posGroup = new TQGroupBox(2, Qt::Horizontal,
|
|
i18n("Pointer position"), mainFrame);
|
|
|
|
new TQLabel(i18n("Absolute time:"), posGroup);
|
|
m_absoluteTime = new TQLabel(posGroup);
|
|
|
|
new TQLabel(i18n("Real time:"), posGroup);
|
|
m_realTime = new TQLabel(posGroup);
|
|
|
|
new TQLabel(i18n("In measure:"), posGroup);
|
|
m_barTime = new TQLabel(posGroup);
|
|
|
|
TQFrame* btnBox = new TQFrame(mainFrame);
|
|
|
|
btnBox->tqsetSizePolicy(
|
|
TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed));
|
|
|
|
TQHBoxLayout* tqlayout = new TQHBoxLayout(btnBox, 4, 10);
|
|
|
|
m_addButton = new TQPushButton(i18n("Add"), btnBox);
|
|
m_deleteButton = new TQPushButton(i18n("Delete"), btnBox);
|
|
m_deleteAllButton = new TQPushButton(i18n("Delete All"), btnBox);
|
|
|
|
m_closeButton = new TQPushButton(i18n("Close"), btnBox);
|
|
|
|
TQToolTip::add
|
|
(m_addButton,
|
|
i18n("Add a Marker"));
|
|
|
|
TQToolTip::add
|
|
(m_deleteButton,
|
|
i18n("Delete a Marker"));
|
|
|
|
TQToolTip::add
|
|
(m_deleteAllButton,
|
|
i18n("Delete All Markers"));
|
|
|
|
TQToolTip::add
|
|
(m_closeButton,
|
|
i18n("Close the Marker Editor"));
|
|
|
|
tqlayout->addStretch(10);
|
|
tqlayout->addWidget(m_addButton);
|
|
tqlayout->addWidget(m_deleteButton);
|
|
tqlayout->addWidget(m_deleteAllButton);
|
|
tqlayout->addSpacing(30);
|
|
|
|
tqlayout->addWidget(m_closeButton);
|
|
tqlayout->addSpacing(5);
|
|
|
|
connect(m_addButton, TQT_SIGNAL(released()),
|
|
TQT_SLOT(slotAdd()));
|
|
|
|
connect(m_deleteButton, TQT_SIGNAL(released()),
|
|
TQT_SLOT(slotDelete()));
|
|
|
|
connect(m_closeButton, TQT_SIGNAL(released()),
|
|
TQT_SLOT(slotClose()));
|
|
|
|
connect(m_deleteAllButton, TQT_SIGNAL(released()),
|
|
TQT_SLOT(slotDeleteAll()));
|
|
|
|
setupActions();
|
|
|
|
m_doc->getCommandHistory()->attachView(actionCollection());
|
|
connect(m_doc->getCommandHistory(), TQT_SIGNAL(commandExecuted()),
|
|
this, TQT_SLOT(slotUpdate()));
|
|
|
|
connect(m_listView, TQT_SIGNAL(doubleClicked(TQListViewItem *)),
|
|
TQT_SLOT(slotEdit(TQListViewItem *)));
|
|
|
|
connect(m_listView, TQT_SIGNAL(pressed(TQListViewItem *)),
|
|
this, TQT_SLOT(slotItemClicked(TQListViewItem *)));
|
|
|
|
// Highlight all columns - enable extended selection mode
|
|
//
|
|
m_listView->setAllColumnsShowFocus(true);
|
|
m_listView->setSelectionMode(TQListView::Extended);
|
|
m_listView->setItemsRenameable(true);
|
|
|
|
initDialog();
|
|
|
|
setAutoSaveSettings(MarkerEditorConfigGroup, true);
|
|
|
|
m_accelerators = new TQAccel(this);
|
|
}
|
|
|
|
void
|
|
MarkerEditor::updatePosition()
|
|
{
|
|
timeT pos = m_doc->getComposition().getPosition();
|
|
m_absoluteTime->setText(TQString("%1").tqarg(pos));
|
|
|
|
RealTime rT = m_doc->getComposition().getElapsedRealTime(pos);
|
|
long hours = rT.sec / (60 * 60);
|
|
long mins = rT.sec / 60;
|
|
long secs = rT.sec;
|
|
long msecs = rT.msec();
|
|
|
|
TQString realTime, secsStr;
|
|
if (hours)
|
|
realTime += TQString("%1h ").tqarg(hours);
|
|
if (mins)
|
|
realTime += TQString("%1m ").tqarg(mins);
|
|
secsStr.sprintf("%ld.%03lds", secs, msecs);
|
|
realTime += secsStr;
|
|
|
|
// only update if we need to to try and avoid flickering
|
|
if (m_realTime->text() != realTime)
|
|
m_realTime->setText(realTime);
|
|
|
|
TQString barTime =
|
|
TQString("%1").tqarg(m_doc->getComposition().getBarNumber(pos) + 1);
|
|
|
|
// again only update if needed
|
|
if (m_barTime->text() != barTime)
|
|
m_barTime->setText(barTime);
|
|
|
|
/*
|
|
// Don't allow us to add another marker if there's already one
|
|
// at the current position.
|
|
//
|
|
if (m_doc->getComposition().
|
|
isMarkerAtPosition(m_doc->getComposition().getPosition()))
|
|
m_addButton->setEnabled(false);
|
|
else
|
|
m_addButton->setEnabled(true);
|
|
*/
|
|
}
|
|
|
|
MarkerEditor::~MarkerEditor()
|
|
{
|
|
RG_DEBUG << "MarkerEditor::~MarkerEditor" << endl;
|
|
|
|
m_listView->saveLayout(kapp->config(), MarkerEditorConfigGroup);
|
|
|
|
if (m_doc)
|
|
m_doc->getCommandHistory()->detachView(actionCollection());
|
|
}
|
|
|
|
void
|
|
MarkerEditor::initDialog()
|
|
{
|
|
RG_DEBUG << "MarkerEditor::initDialog" << endl;
|
|
slotUpdate();
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotUpdate()
|
|
{
|
|
RG_DEBUG << "MarkerEditor::slotUpdate" << endl;
|
|
|
|
//TQPtrList<TQListViewItem> selection = m_listView->selectedItems();
|
|
|
|
MarkerEditorViewItem *item;
|
|
|
|
m_listView->clear();
|
|
|
|
Composition::markercontainer markers =
|
|
m_doc->getComposition().getMarkers();
|
|
|
|
Composition::markerconstiterator it;
|
|
|
|
kapp->config()->setGroup(MarkerEditorConfigGroup);
|
|
int timeMode = kapp->config()->readNumEntry("timemode", 0);
|
|
|
|
for (it = markers.begin(); it != markers.end(); ++it) {
|
|
TQString timeString = makeTimeString((*it)->getTime(), timeMode);
|
|
|
|
item = new
|
|
MarkerEditorViewItem(m_listView,
|
|
(*it)->getID(),
|
|
timeString,
|
|
strtoqstr((*it)->getName()),
|
|
strtoqstr((*it)->getDescription()));
|
|
|
|
// Set this for the MarkerEditor
|
|
//
|
|
item->setRawTime((*it)->getTime());
|
|
|
|
m_listView->insertItem(item);
|
|
}
|
|
|
|
if (m_listView->childCount() == 0) {
|
|
TQListViewItem *item =
|
|
new MarkerEditorViewItem(m_listView, 0, i18n("<none>"));
|
|
((MarkerEditorViewItem *)item)->setFake(true);
|
|
m_listView->insertItem(item);
|
|
|
|
m_listView->setSelectionMode(TQListView::NoSelection);
|
|
} else {
|
|
m_listView->setSelectionMode(TQListView::Extended);
|
|
}
|
|
|
|
updatePosition();
|
|
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotDeleteAll()
|
|
{
|
|
RG_DEBUG << "MarkerEditor::slotDeleteAll" << endl;
|
|
KMacroCommand *command = new KMacroCommand(i18n("Remove all markers"));
|
|
|
|
TQListViewItem *item = m_listView->firstChild();
|
|
|
|
do {
|
|
MarkerEditorViewItem *ei =
|
|
dynamic_cast<MarkerEditorViewItem *>(item);
|
|
if (!ei || ei->isFake())
|
|
continue;
|
|
|
|
RemoveMarkerCommand *rc =
|
|
new RemoveMarkerCommand(&m_doc->getComposition(),
|
|
ei->getID(),
|
|
ei->getRawTime(),
|
|
qstrtostr(item->text(1)),
|
|
qstrtostr(item->text(2)));
|
|
command->addCommand(rc);
|
|
} while ((item = item->nextSibling()));
|
|
|
|
addCommandToHistory(command);
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotAdd()
|
|
{
|
|
RG_DEBUG << "MarkerEditor::slotAdd" << endl;
|
|
|
|
AddMarkerCommand *command =
|
|
new AddMarkerCommand(&m_doc->getComposition(),
|
|
m_doc->getComposition().getPosition(),
|
|
std::string("new marker"),
|
|
std::string("no description"));
|
|
|
|
addCommandToHistory(command);
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotDelete()
|
|
{
|
|
RG_DEBUG << "MarkerEditor::slotDelete" << endl;
|
|
TQListViewItem *item = m_listView->currentItem();
|
|
|
|
MarkerEditorViewItem *ei =
|
|
dynamic_cast<MarkerEditorViewItem *>(item);
|
|
|
|
if (!ei || ei->isFake())
|
|
return ;
|
|
|
|
RemoveMarkerCommand *command =
|
|
new RemoveMarkerCommand(&m_doc->getComposition(),
|
|
ei->getID(),
|
|
ei->getRawTime(),
|
|
qstrtostr(item->text(1)),
|
|
qstrtostr(item->text(2)));
|
|
|
|
addCommandToHistory(command);
|
|
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotClose()
|
|
{
|
|
RG_DEBUG << "MarkerEditor::slotClose" << endl;
|
|
|
|
if (m_doc)
|
|
m_doc->getCommandHistory()->detachView(actionCollection());
|
|
m_doc = 0;
|
|
|
|
close();
|
|
}
|
|
|
|
void
|
|
MarkerEditor::setupActions()
|
|
{
|
|
KAction* close = KStdAction::close(TQT_TQOBJECT(this),
|
|
TQT_SLOT(slotClose()),
|
|
actionCollection());
|
|
|
|
m_closeButton->setText(close->text());
|
|
connect(m_closeButton, TQT_SIGNAL(released()), this, TQT_SLOT(slotClose()));
|
|
|
|
// 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));
|
|
|
|
TQString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/");
|
|
kapp->config()->setGroup(MarkerEditorConfigGroup);
|
|
int timeMode = kapp->config()->readNumEntry("timemode", 0);
|
|
|
|
KRadioAction *action;
|
|
|
|
TQCanvasPixmap pixmap(pixmapDir + "/toolbar/time-musical.png");
|
|
TQIconSet icon(pixmap);
|
|
|
|
action = new KRadioAction(i18n("&Musical Times"), icon, 0, TQT_TQOBJECT(this),
|
|
TQT_SLOT(slotMusicalTime()),
|
|
actionCollection(), "time_musical");
|
|
action->setExclusiveGroup("timeMode");
|
|
if (timeMode == 0)
|
|
action->setChecked(true);
|
|
|
|
pixmap.load(pixmapDir + "/toolbar/time-real.png");
|
|
icon = TQIconSet(pixmap);
|
|
|
|
action = new KRadioAction(i18n("&Real Times"), icon, 0, TQT_TQOBJECT(this),
|
|
TQT_SLOT(slotRealTime()),
|
|
actionCollection(), "time_real");
|
|
action->setExclusiveGroup("timeMode");
|
|
if (timeMode == 1)
|
|
action->setChecked(true);
|
|
|
|
pixmap.load(pixmapDir + "/toolbar/time-raw.png");
|
|
icon = TQIconSet(pixmap);
|
|
|
|
action = new KRadioAction(i18n("Ra&w Times"), icon, 0, TQT_TQOBJECT(this),
|
|
TQT_SLOT(slotRawTime()),
|
|
actionCollection(), "time_raw");
|
|
action->setExclusiveGroup("timeMode");
|
|
if (timeMode == 2)
|
|
action->setChecked(true);
|
|
|
|
createGUI("markereditor.rc");
|
|
}
|
|
|
|
void
|
|
MarkerEditor::addCommandToHistory(KCommand *command)
|
|
{
|
|
getCommandHistory()->addCommand(command);
|
|
setModified(false);
|
|
}
|
|
|
|
MultiViewCommandHistory*
|
|
MarkerEditor::getCommandHistory()
|
|
{
|
|
return m_doc->getCommandHistory();
|
|
}
|
|
|
|
void
|
|
MarkerEditor::setModified(bool modified)
|
|
{
|
|
RG_DEBUG << "MarkerEditor::setModified(" << modified << ")" << endl;
|
|
|
|
if (modified) {}
|
|
else {}
|
|
|
|
m_modified = modified;
|
|
}
|
|
|
|
void
|
|
MarkerEditor::checkModified()
|
|
{
|
|
RG_DEBUG << "MarkerEditor::checkModified(" << m_modified << ")"
|
|
<< endl;
|
|
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotEdit(TQListViewItem *i)
|
|
{
|
|
RG_DEBUG << "MarkerEditor::slotEdit" << endl;
|
|
|
|
if (m_listView->selectionMode() == TQListView::NoSelection) {
|
|
// The marker list is empty, so we shouldn't allow editing the
|
|
// <none> placeholder
|
|
return ;
|
|
}
|
|
|
|
// Need to get the raw time from the ListViewItem
|
|
//
|
|
MarkerEditorViewItem *item =
|
|
dynamic_cast<MarkerEditorViewItem*>(i);
|
|
|
|
if (!item || item->isFake())
|
|
return ;
|
|
|
|
MarkerModifyDialog dialog(this,
|
|
&m_doc->getComposition(),
|
|
item->getRawTime(),
|
|
item->text(1),
|
|
item->text(2));
|
|
|
|
if (dialog.exec() == TQDialog::Accepted) {
|
|
ModifyMarkerCommand *command =
|
|
new ModifyMarkerCommand(&m_doc->getComposition(),
|
|
item->getID(),
|
|
dialog.getOriginalTime(),
|
|
dialog.getTime(),
|
|
qstrtostr(dialog.getName()),
|
|
qstrtostr(dialog.getDescription()));
|
|
|
|
addCommandToHistory(command);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void
|
|
MarkerEditor::closeEvent(TQCloseEvent *e)
|
|
{
|
|
emit closing();
|
|
KMainWindow::closeEvent(e);
|
|
}
|
|
|
|
void
|
|
MarkerEditor::setDocument(RosegardenGUIDoc *doc)
|
|
{
|
|
// reset our pointers
|
|
m_doc = doc;
|
|
m_modified = false;
|
|
|
|
slotUpdate();
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotItemClicked(TQListViewItem *item)
|
|
{
|
|
RG_DEBUG << "MarkerEditor::slotItemClicked" << endl;
|
|
MarkerEditorViewItem *ei =
|
|
dynamic_cast<MarkerEditorViewItem *>(item);
|
|
|
|
if (ei && !ei->isFake()) {
|
|
RG_DEBUG << "MarkerEditor::slotItemClicked - "
|
|
<< "jump to marker at " << ei->getRawTime() << endl;
|
|
|
|
emit jumpToMarker(timeT(ei->getRawTime()));
|
|
}
|
|
}
|
|
|
|
TQString
|
|
MarkerEditor::makeTimeString(timeT time, int timeMode)
|
|
{
|
|
switch (timeMode) {
|
|
|
|
case 0: // musical time
|
|
{
|
|
int bar, beat, fraction, remainder;
|
|
m_doc->getComposition().getMusicalTimeForAbsoluteTime
|
|
(time, bar, beat, fraction, remainder);
|
|
++bar;
|
|
return TQString("%1%2%3-%4%5-%6%7-%8%9 ")
|
|
.tqarg(bar / 100)
|
|
.tqarg((bar % 100) / 10)
|
|
.tqarg(bar % 10)
|
|
.tqarg(beat / 10)
|
|
.tqarg(beat % 10)
|
|
.tqarg(fraction / 10)
|
|
.tqarg(fraction % 10)
|
|
.tqarg(remainder / 10)
|
|
.tqarg(remainder % 10);
|
|
}
|
|
|
|
case 1: // real time
|
|
{
|
|
RealTime rt =
|
|
m_doc->getComposition().getElapsedRealTime(time);
|
|
// return TQString("%1 ").tqarg(rt.toString().c_str());
|
|
return TQString("%1 ").tqarg(rt.toText().c_str());
|
|
}
|
|
|
|
default:
|
|
return TQString("%1 ").tqarg(time);
|
|
}
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotMusicalTime()
|
|
{
|
|
kapp->config()->setGroup(MarkerEditorConfigGroup);
|
|
kapp->config()->writeEntry("timemode", 0);
|
|
slotUpdate();
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotRealTime()
|
|
{
|
|
kapp->config()->setGroup(MarkerEditorConfigGroup);
|
|
kapp->config()->writeEntry("timemode", 1);
|
|
slotUpdate();
|
|
}
|
|
|
|
void
|
|
MarkerEditor::slotRawTime()
|
|
{
|
|
kapp->config()->setGroup(MarkerEditorConfigGroup);
|
|
kapp->config()->writeEntry("timemode", 2);
|
|
slotUpdate();
|
|
}
|
|
|
|
}
|
|
#include "MarkerEditor.moc"
|