File indexing completed on 2024-05-05 04:51:42

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "k3baudiotracksplitdialog.h"
0007 #include "k3baudiotrack.h"
0008 #include "k3baudioeditorwidget.h"
0009 
0010 #include "k3bmsf.h"
0011 #include "k3bmsfedit.h"
0012 
0013 #include <KLocalizedString>
0014 #include <KActionCollection>
0015 
0016 #include <QEvent>
0017 #include <QContextMenuEvent>
0018 #include <QMouseEvent>
0019 #include <QAction>
0020 #include <QDialogButtonBox>
0021 #include <QGridLayout>
0022 #include <QLabel>
0023 #include <QLayout>
0024 #include <QMenu>
0025 
0026 
0027 K3b::AudioTrackSplitDialog::AudioTrackSplitDialog( K3b::AudioTrack* track, QWidget* parent )
0028     : QDialog( parent),
0029       m_track(track)
0030 {
0031     setWindowTitle(i18n("Split Audio Track"));
0032 
0033     m_editorWidget = new K3b::AudioEditorWidget( this );
0034     m_msfEditStart = new K3b::MsfEdit( this );
0035     m_msfEditEnd = new K3b::MsfEdit( this );
0036 
0037     QVBoxLayout* layout = new QVBoxLayout( this );
0038 
0039     // FIXME: After the string freeze replace the text with a better one explaining how to use this dialog
0040     layout->addWidget( new QLabel( i18n("Please select the position where the track should be split."),
0041                                    this ) );
0042     layout->addWidget( m_editorWidget );
0043 
0044     QHBoxLayout* rangeLayout = new QHBoxLayout;
0045     rangeLayout->addWidget( new QLabel( i18n("Split track at:"), this ), 1 );
0046     rangeLayout->addWidget( m_msfEditStart, 0 );
0047     rangeLayout->addWidget( new QLabel( " - ", this ), 0, Qt::AlignCenter );
0048     rangeLayout->addWidget( m_msfEditEnd, 0 );
0049     layout->addLayout( rangeLayout );
0050 
0051     m_editorWidget->setAllowOverlappingRanges( false );
0052     m_editorWidget->enableRangeSelection( true );
0053     m_editorWidget->installEventFilter( this );
0054 
0055     connect( m_editorWidget, SIGNAL(rangeChanged(int,K3b::Msf,K3b::Msf)),
0056              this, SLOT(slotRangeModified(int,K3b::Msf,K3b::Msf)) );
0057     connect( m_editorWidget, SIGNAL(selectedRangeChanged(int)),
0058              this, SLOT(slotRangeSelectionChanged(int)) );
0059     connect( m_msfEditStart, SIGNAL(valueChanged(K3b::Msf)),
0060              this, SLOT(slotMsfEditChanged(K3b::Msf)) );
0061     connect( m_msfEditEnd, SIGNAL(valueChanged(K3b::Msf)),
0062              this, SLOT(slotMsfEditChanged(K3b::Msf)) );
0063 
0064     setupActions();
0065 
0066     // load the track
0067     m_editorWidget->setLength( m_track->length() );
0068 
0069     // default split
0070     K3b::Msf mid = m_track->length().lba() / 2;
0071     m_editorWidget->addRange( 0, mid-1 );
0072     m_editorWidget->addRange( mid, m_track->length()-1 );
0073 
0074     QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this );
0075     connect( buttonBox, SIGNAL(accepted()), SLOT(accept()) );
0076     connect( buttonBox, SIGNAL(rejected()), SLOT(reject()) );
0077     layout->addWidget( buttonBox );
0078 
0079     slotRangeSelectionChanged( 0 );
0080 }
0081 
0082 
0083 K3b::AudioTrackSplitDialog::~AudioTrackSplitDialog()
0084 {
0085 }
0086 
0087 
0088 void K3b::AudioTrackSplitDialog::setupActions()
0089 {
0090     m_popupMenu = new QMenu( this );
0091 
0092     QAction* actionSplitHere = new QAction( this );
0093     actionSplitHere->setText( i18n("Split Here") );
0094     connect( actionSplitHere, SIGNAL(triggered()), this, SLOT(slotSplitHere()) );
0095 
0096     QAction* actionRemoveRange = new QAction( this );
0097     actionRemoveRange->setText( i18n("Remove part") );
0098     connect( actionRemoveRange, SIGNAL(triggered()), this, SLOT(slotRemoveRange()) );
0099 
0100     m_popupMenu->addAction( actionSplitHere );
0101     m_popupMenu->addAction( actionRemoveRange );
0102 }
0103 
0104 
0105 void K3b::AudioTrackSplitDialog::slotRangeModified( int id, const K3b::Msf& start, const K3b::Msf& end )
0106 {
0107     if( id == m_editorWidget->selectedRange() ) {
0108         m_msfEditStart->blockSignals( true );
0109         m_msfEditEnd->blockSignals( true );
0110 
0111         m_msfEditStart->setValue( start );
0112         m_msfEditEnd->setValue( end );
0113 
0114         m_msfEditStart->blockSignals( false );
0115         m_msfEditEnd->blockSignals( false );
0116     }
0117 }
0118 
0119 
0120 void K3b::AudioTrackSplitDialog::slotMsfEditChanged( const K3b::Msf& )
0121 {
0122     m_editorWidget->modifyRange( m_editorWidget->selectedRange(), m_msfEditStart->value(), m_msfEditEnd->value() );
0123 }
0124 
0125 
0126 void K3b::AudioTrackSplitDialog::slotRangeSelectionChanged( int id )
0127 {
0128     if( id > 0 ) {
0129         m_msfEditStart->blockSignals( true );
0130         m_msfEditEnd->blockSignals( true );
0131 
0132         m_msfEditStart->setValue( m_editorWidget->rangeStart( id ) );
0133         m_msfEditEnd->setValue( m_editorWidget->rangeEnd( id ) );
0134         m_msfEditStart->setEnabled( true );
0135         m_msfEditEnd->setEnabled( true );
0136 
0137         m_msfEditStart->blockSignals( false );
0138         m_msfEditEnd->blockSignals( false );
0139     }
0140     else {
0141         m_msfEditStart->setEnabled( false );
0142         m_msfEditEnd->setEnabled( false );
0143     }
0144 }
0145 
0146 
0147 void K3b::AudioTrackSplitDialog::splitAt( const QPoint& p )
0148 {
0149     int id = m_editorWidget->findRange( p.x() );
0150     if( id ) {
0151         K3b::Msf msf = m_editorWidget->posToMsf( p.x() );
0152         m_editorWidget->addRange( msf+1, m_editorWidget->rangeEnd( id ) );
0153         m_editorWidget->modifyRange( id, m_editorWidget->rangeStart( id ), msf );
0154         slotRangeSelectionChanged( m_editorWidget->selectedRange() );
0155     }
0156 }
0157 
0158 
0159 bool K3b::AudioTrackSplitDialog::eventFilter( QObject* o, QEvent* e )
0160 {
0161     if( o == m_editorWidget ) {
0162         if( e->type() == QEvent::MouseButtonDblClick ) {
0163             QMouseEvent* me = static_cast<QMouseEvent*>( e );
0164             splitAt( me->pos() );
0165         }
0166         else if( e->type() == QEvent::ContextMenu ) {
0167             QContextMenuEvent* ce = static_cast<QContextMenuEvent*>( e );
0168             ce->accept();
0169             m_lastClickPosition = ce->pos();
0170             if( m_editorWidget->findRange( ce->pos().x() ) > 0 )
0171                 m_popupMenu->popup( ce->globalPos() );
0172         }
0173     }
0174 
0175     return QDialog::eventFilter( o, e );
0176 }
0177 
0178 
0179 void K3b::AudioTrackSplitDialog::slotSplitHere()
0180 {
0181     splitAt( m_lastClickPosition );
0182 }
0183 
0184 
0185 void K3b::AudioTrackSplitDialog::slotRemoveRange()
0186 {
0187     m_editorWidget->removeRange( m_editorWidget->findRange( m_lastClickPosition.x() ) );
0188 }
0189 
0190 
0191 void K3b::AudioTrackSplitDialog::splitTrack( K3b::AudioTrack* track,
0192                        QWidget* parent )
0193 {
0194     if ( !track ) {
0195         return;
0196     }
0197 
0198     K3b::AudioTrackSplitDialog d( track, parent );
0199     if( d.exec() == QDialog::Accepted ) {
0200         QList<int> ranges = d.m_editorWidget->allRanges();
0201         // we split the track at all range ends and just delete those that relate to the gaps in between
0202         K3b::Msf pos = 0;
0203         for( QList<int>::const_iterator it = ranges.constBegin();
0204              it != ranges.constEnd(); ++it ) {
0205 
0206             // delete the unwanted part
0207             if( d.m_editorWidget->rangeStart( *it ) > pos ) {
0208                 // split so the range's start is the first frame of the new track
0209                 K3b::AudioTrack* nextTrack = track->split( d.m_editorWidget->rangeStart( *it ) - pos );
0210                 delete track;
0211                 track = nextTrack;
0212             }
0213 
0214             // create a new track part for the range itself
0215             pos = d.m_editorWidget->rangeStart( *it );
0216             if( d.m_editorWidget->rangeEnd( *it ) < d.m_editorWidget->length()-1 ) {
0217                 // split so the range's end is the last frame in the old track
0218                 // and thus, the range's end + 1 the first frame in the new track
0219                 track = track->split( d.m_editorWidget->rangeEnd( *it ) - pos + 1 );
0220             }
0221             pos = d.m_editorWidget->rangeEnd( *it )+1;
0222         }
0223 
0224         // remove the last unwanted part
0225         if( pos < d.m_editorWidget->length() ) {
0226             delete track;
0227         }
0228     }
0229 }
0230 
0231 #include "moc_k3baudiotracksplitdialog.cpp"