/* -*- 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 "TriggerSegmentManager.h"
# include "TriggerManagerItem.h"
# include <layout.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 <tqaccel.h>
# include <tqdialog.h>
# include <tqframe.h>
# include <tqiconset.h>
# include <tqlistview.h>
# include <tqpushbutton.h>
# include <tqsizepolicy.h>
# include <tqstring.h>
# include <tqtooltip.h>
# include <tqvbox.h>
# include <tqwidget.h>
# include <tqcanvas.h>
namespace Rosegarden
{
TriggerSegmentManager : : TriggerSegmentManager ( TQWidget * parent ,
RosegardenGUIDoc * doc ) :
KMainWindow ( parent , " triggereditordialog " ) ,
m_doc ( doc ) ,
m_modified ( false )
{
TQVBox * mainFrame = new TQVBox ( 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 , TQt : : AlignHCenter ) ;
TQFrame * btnBox = new TQFrame ( mainFrame ) ;
btnBox - > setSizePolicy (
TQSizePolicy ( TQSizePolicy : : Minimum , TQSizePolicy : : Fixed ) ) ;
TQHBoxLayout * layout = 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 Triggered Segment " ) ) ;
TQToolTip : : add
( m_deleteButton ,
i18n ( " Delete a Triggered Segment " ) ) ;
TQToolTip : : add
( m_deleteAllButton ,
i18n ( " Delete All Triggered Segments " ) ) ;
TQToolTip : : 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 , 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 ( TriggerManagerConfigGroup , true ) ;
m_accelerators = new TQAccel ( 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 ( ) ;
TQString timeString = makeDurationString
( first , duration , timeMode ) ;
TQString label = strtoqstr ( ( * it ) - > getSegment ( ) - > getLabel ( ) ) ;
if ( label = = " " )
label = i18n ( " <no label> " ) ;
TQString used = i18n ( " %1 on 1 track " ,
" %1 on %n tracks " ,
tracks . size ( ) ) . arg ( uses ) ;
TQString pitch = TQString ( " %1 (%2) " )
. arg ( MidiPitchLabel ( ( * it ) - > getBasePitch ( ) ) . getTQString ( ) )
. arg ( ( * it ) - > getBasePitch ( ) ) ;
TQString velocity = TQString ( " %1 " ) . arg ( ( * it ) - > getBaseVelocity ( ) ) ;
item = new TriggerManagerItem
( m_listView , TQString ( " %1 " ) . arg ( i + 1 ) , TQString ( " %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 ) {
TQListViewItem * item =
new TriggerManagerItem ( m_listView , i18n ( " <none> " ) ) ;
m_listView - > insertItem ( item ) ;
m_listView - > setSelectionMode ( TQListView : : NoSelection ) ;
} else {
m_listView - > setSelectionMode ( TQListView : : 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 " ) ) ;
TQListViewItem * 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 ( ) = = TQDialog : : 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 ( TQT_TQOBJECT ( this ) ,
TQT_SLOT ( slotClose ( ) ) ,
actionCollection ( ) ) ;
m_closeButton - > setText ( close - > text ( ) ) ;
connect ( m_closeButton , TQT_SIGNAL ( released ( ) ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( slotClose ( ) ) ) ;
TQString 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 , TQT_TQOBJECT ( this ) ,
TQT_SLOT ( slotPasteAsNew ( ) ) , actionCollection ( ) ,
" paste_to_trigger_segment " ) ;
kapp - > config ( ) - > setGroup ( TriggerManagerConfigGroup ) ;
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 ( " 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 ( TQListViewItem * 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 ( TQCloseEvent * e )
{
emit closing ( ) ;
KMainWindow : : closeEvent ( e ) ;
}
void
TriggerSegmentManager : : setDocument ( RosegardenGUIDoc * doc )
{
// reset our pointers
m_doc = doc ;
m_modified = false ;
slotUpdate ( ) ;
}
void
TriggerSegmentManager : : slotItemClicked ( TQListViewItem * item )
{
RG_DEBUG < < " TriggerSegmentManager::slotItemClicked " < < endl ;
}
TQString
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 TQString ( " %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 TQString("%1 ").arg(rt.toString().c_str());
return TQString ( " %1 " ) . arg ( rt . toText ( ) . c_str ( ) ) ;
}
default :
return TQString ( " %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"