Knife Tool for Sample Clips (Again) (#5524)

* Rebase BaraMGB's Knife
Co-authored-by: Steffen Baranowsky <BaraMGB@freenet.de>

* Draw marker

* Refactoring and shift mode

* Allow resizing

* Add Icon

* Fix stuck marker on RMB, remove unnecessary cast

* Remove redundant line, more const

* Fix

* Review fixes

* Only perform split logic for SampleTCO

* Add unquantizedModHeld function

* missed one

* Don't use copy/paste

* Don't use copy/paste

* More git troubles

* Fix undo

* git dammit

* Cleaner solution?

* Set cursor, add copy assignment to SampleBuffer

* Add TODO comment

* Make it build

* Fixes from review

* Make splitTCO virtual

* Make splitTCO more generic

Co-authored-by: IanCaio <iancaio_dev@hotmail.com>

* Prevent resizing of MIDI clips in knife mode

* Fix move/resize and rework box select via ctrl

* Apply suggestions from code review.

Co-authored-by: IanCaio <iancaio_dev@hotmail.com>

* Don't show inaccurate/useless/empty text float in knife mode

* Addresses Github review

	- Fixes a typo where QWidget::mousePressEvent was being called
inside mouseReleaseEvent.
	- Avoids unnecessarily disabling journalling on the Split
action, since it doesn't require it.

* Revert format changes in Track

* Revert format changes in Track.h

* Revert formatting changes in Track.cpp

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: IanCaio <iancaio_dev@hotmail.com>
This commit is contained in:
Spekular
2021-03-12 22:49:54 +01:00
committed by GitHub
parent 266ad8d45e
commit 8acb9222fd
14 changed files with 276 additions and 98 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

View File

@@ -598,10 +598,10 @@ FxLine {
color: #e0e0e0;
qproperty-backgroundActive: qlineargradient(spread:reflect, x1:0, y1:0, x2:1, y2:0,
stop:0 #7b838d, stop:1 #6b7581 );
qproperty-strokeOuterActive: rgb( 0, 0, 0 );
qproperty-strokeOuterInactive: rgba( 0, 0, 0, 50 );
qproperty-strokeInnerActive: rgba( 255, 255, 255, 100 );
qproperty-strokeInnerInactive: rgba( 255, 255, 255, 50 );
qproperty-strokeOuterActive: rgb( 0, 0, 0 );
qproperty-strokeOuterInactive: rgba( 0, 0, 0, 50 );
qproperty-strokeInnerActive: rgba( 255, 255, 255, 100 );
qproperty-strokeInnerInactive: rgba( 255, 255, 255, 50 );
}
/* persistent peak markers for fx peak meters */
@@ -658,7 +658,8 @@ TrackContentObjectView {
qproperty-gradient: true; /* boolean property, set true to have a gradient */
/* finger tip offset of cursor */
qproperty-mouseHotspotHand: 3px 3px;
qproperty-mouseHotspotKnife: 0px 0px;
font-size: 11px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

View File

@@ -704,7 +704,8 @@ TrackContentObjectView {
qproperty-gradient: false; /* boolean property, set true to have a gradient */
/* finger tip offset of cursor */
qproperty-mouseHotspotHand: 7px 2px;
qproperty-mouseHotspotKnife: 0px 0px;
font-size: 11px;
}

View File

@@ -93,7 +93,6 @@ private:
BoolModel m_recordModel;
bool m_isPlaying;
friend class SampleTCOView;
@@ -132,6 +131,7 @@ protected:
private:
SampleTCO * m_tco;
QPixmap m_paintPixmap;
bool splitTCO( const TimePos pos ) override;
} ;

View File

@@ -55,6 +55,7 @@ public:
enum EditMode
{
DrawMode,
KnifeMode,
SelectMode
};
@@ -77,6 +78,7 @@ public slots:
void setEditMode( EditMode mode );
void setEditModeDraw();
void setEditModeKnife();
void setEditModeSelect();
void toggleProportionalSnap();
@@ -112,6 +114,7 @@ private:
void wheelEvent( QWheelEvent * we ) override;
bool allowRubberband() const override;
bool knifeMode() const override;
int trackIndexFromSelectionPoint(int yPos);
int indexOfTrackView(const TrackView* tv);
@@ -173,6 +176,7 @@ public:
QSize sizeHint() const override;
SongEditor* m_editor;
void syncEditMode();
protected:
void resizeEvent( QResizeEvent * event ) override;
@@ -194,9 +198,6 @@ signals:
void resized();
private:
void keyPressEvent( QKeyEvent * ke ) override;
void keyReleaseEvent( QKeyEvent * ke ) override;
QAction* m_addBBTrackAction;
QAction* m_addSampleTrackAction;
QAction* m_addAutomationTrackAction;
@@ -204,6 +205,7 @@ private:
ActionGroup * m_editModeGroup;
QAction* m_drawModeAction;
QAction* m_knifeModeAction;
QAction* m_selectModeAction;
QAction* m_crtlAction;

View File

@@ -80,6 +80,7 @@ public:
const TrackView * trackViewAt( const int _y ) const;
virtual bool allowRubberband() const;
virtual bool knifeMode() const;
inline bool rubberBandActive() const
{

View File

@@ -58,6 +58,7 @@ class TrackContentObjectView : public selectableObject, public ModelView
// We have to use a QSize here because using QPoint isn't supported.
// width -> x, height -> y
Q_PROPERTY( QSize mouseHotspotHand WRITE setMouseHotspotHand )
Q_PROPERTY( QSize mouseHotspotKnife WRITE setMouseHotspotKnife )
public:
TrackContentObjectView( TrackContentObject * tco, TrackView * tv );
@@ -93,6 +94,7 @@ public:
void setBBPatternBackground( const QColor & c );
void setGradient( const bool & b );
void setMouseHotspotHand(const QSize & s);
void setMouseHotspotKnife(const QSize & s);
// access needsUpdate member variable
bool needsUpdate();
@@ -118,6 +120,9 @@ public:
QColor getColorForDisplay( QColor );
void inline setMarkerPos(int x) { m_markerPos = x; }
void inline setMarkerEnabled(bool e) { m_marker = e; }
public slots:
virtual bool close();
void remove();
@@ -137,6 +142,13 @@ protected:
Merge
};
TrackView * m_trackView;
TimePos m_initialTCOPos;
TimePos m_initialTCOEnd;
bool m_marker = false;
int m_markerPos = 0;
virtual void constructContextMenu( QMenu * )
{
}
@@ -145,7 +157,6 @@ protected:
void contextMenuAction( ContextMenuAction action );
void dragEnterEvent( QDragEnterEvent * dee ) override;
void dropEvent( QDropEvent * de ) override;
void leaveEvent( QEvent * e ) override;
void mousePressEvent( QMouseEvent * me ) override;
void mouseMoveEvent( QMouseEvent * me ) override;
void mouseReleaseEvent( QMouseEvent * me ) override;
@@ -155,6 +166,9 @@ protected:
selectableObject::resizeEvent( re );
}
bool unquantizedModHeld( QMouseEvent * me );
TimePos quantizeSplitPos( TimePos, bool shiftMode );
float pixelsPerBar();
@@ -176,6 +190,7 @@ private:
MoveSelection,
Resize,
ResizeLeft,
Split,
CopySelection,
ToggleSelected
} ;
@@ -183,12 +198,9 @@ private:
static TextFloat * s_textFloat;
TrackContentObject * m_tco;
TrackView * m_trackView;
Actions m_action;
QPoint m_initialMousePos;
QPoint m_initialMouseGlobalPos;
TimePos m_initialTCOPos;
TimePos m_initialTCOEnd;
QVector<TimePos> m_initialOffsets;
TextFloat * m_hint;
@@ -202,7 +214,10 @@ private:
QColor m_textShadowColor;
QColor m_BBPatternBackground;
bool m_gradient;
QSize m_mouseHotspotHand; // QSize must be used because QPoint isn't supported by property system
QSize m_mouseHotspotHand; // QSize must be used because QPoint
QSize m_mouseHotspotKnife; // isn't supported by property system
QCursor m_cursorHand;
QCursor m_cursorKnife;
bool m_cursorSetYet;
bool m_needsUpdate;
@@ -217,6 +232,10 @@ private:
bool mouseMovedDistance( QMouseEvent * me, int distance );
TimePos draggedTCOPos( QMouseEvent * me );
int knifeMarkerPos( QMouseEvent * me );
//! Return true iff TCO could be split. Currently only implemented for samples
virtual bool splitTCO( const TimePos pos ){ return false; };
void updateCursor(QMouseEvent * me);
} ;

View File

@@ -99,6 +99,7 @@ protected:
void dragEnterEvent( QDragEnterEvent * dee ) override;
void dropEvent( QDropEvent * de ) override;
void mousePressEvent( QMouseEvent * me ) override;
void mouseReleaseEvent( QMouseEvent * me ) override;
void paintEvent( QPaintEvent * pe ) override;
void resizeEvent( QResizeEvent * re ) override;

View File

@@ -308,6 +308,14 @@ bool TrackContainerView::allowRubberband() const
bool TrackContainerView::knifeMode() const
{
return false;
}
void TrackContainerView::setPixelsPerBar( int ppb )
{
m_ppb = ppb;
@@ -374,7 +382,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de )
//it->toggledInstrumentTrackButton( true );
_de->accept();
}
else if( type == "samplefile" || type == "pluginpresetfile"
else if( type == "samplefile" || type == "pluginpresetfile"
|| type == "soundfontfile" || type == "vstpluginfile"
|| type == "patchfile" )
{

View File

@@ -77,13 +77,13 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco,
TrackView * tv ) :
selectableObject( tv->getTrackContentWidget() ),
ModelView( NULL, this ),
m_tco( tco ),
m_trackView( tv ),
m_initialTCOPos( TimePos(0) ),
m_initialTCOEnd( TimePos(0) ),
m_tco( tco ),
m_action( NoAction ),
m_initialMousePos( QPoint( 0, 0 ) ),
m_initialMouseGlobalPos( QPoint( 0, 0 ) ),
m_initialTCOPos( TimePos(0) ),
m_initialTCOEnd( TimePos(0) ),
m_initialOffsets( QVector<TimePos>() ),
m_hint( NULL ),
m_mutedColor( 0, 0, 0 ),
@@ -94,6 +94,9 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco,
m_BBPatternBackground( 0, 0, 0 ),
m_gradient( true ),
m_mouseHotspotHand( 0, 0 ),
m_mouseHotspotKnife( 0, 0 ),
m_cursorHand( QCursor( embed::getIconPixmap( "hand" ) ) ),
m_cursorKnife( QCursor( embed::getIconPixmap( "cursor_knife" ) ) ),
m_cursorSetYet( false ),
m_needsUpdate( true )
{
@@ -106,7 +109,7 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco,
setAttribute( Qt::WA_OpaquePaintEvent, true );
setAttribute( Qt::WA_DeleteOnClose, true );
setFocusPolicy( Qt::StrongFocus );
setCursor( QCursor( embed::getIconPixmap( "hand" ), m_mouseHotspotHand.width(), m_mouseHotspotHand.height() ) );
setCursor( m_cursorHand );
move( 0, 0 );
show();
@@ -159,7 +162,9 @@ void TrackContentObjectView::update()
{
if( !m_cursorSetYet )
{
setCursor( QCursor( embed::getIconPixmap( "hand" ), m_mouseHotspotHand.width(), m_mouseHotspotHand.height() ) );
m_cursorHand = QCursor( embed::getIconPixmap( "hand" ), m_mouseHotspotHand.width(), m_mouseHotspotHand.height() );
m_cursorKnife = QCursor( embed::getIconPixmap( "cursor_knife" ), m_mouseHotspotKnife.width(), m_mouseHotspotKnife.height() );
setCursor( m_cursorHand );
m_cursorSetYet = true;
}
@@ -248,6 +253,11 @@ void TrackContentObjectView::setMouseHotspotHand(const QSize & s)
m_mouseHotspotHand = s;
}
void TrackContentObjectView::setMouseHotspotKnife(const QSize & s)
{
m_mouseHotspotKnife = s;
}
// access needsUpdate member variable
bool TrackContentObjectView::needsUpdate()
{ return m_needsUpdate; }
@@ -439,22 +449,32 @@ void TrackContentObjectView::dropEvent( QDropEvent * de )
/*! \brief Handle a dragged selection leaving our 'airspace'.
/* @brief Chooses the correct cursor to be displayed on the widget
*
* \param e The QEvent to watch.
* @param me The QMouseEvent that is triggering the cursor change
*/
void TrackContentObjectView::leaveEvent( QEvent * e )
void TrackContentObjectView::updateCursor(QMouseEvent * me)
{
if( cursor().shape() != Qt::BitmapCursor )
SampleTCO * sTco = dynamic_cast<SampleTCO*>(m_tco);
// If we are at the edges, use the resize cursor
if ((me->x() > width() - RESIZE_GRIP_WIDTH && !me->buttons() && !m_tco->getAutoResize())
|| (me->x() < RESIZE_GRIP_WIDTH && !me->buttons() && sTco && !m_tco->getAutoResize()))
{
setCursor( QCursor( embed::getIconPixmap( "hand" ), m_mouseHotspotHand.width(), m_mouseHotspotHand.height() ) );
setCursor(Qt::SizeHorCursor);
}
if( e != NULL )
// If we are in the middle on knife mode, use the knife cursor
else if (sTco && m_trackView->trackContainerView()->knifeMode())
{
QWidget::leaveEvent( e );
setCursor(m_cursorKnife);
}
// If we are in the middle in any other mode, use the hand cursor
else { setCursor(m_cursorHand); }
}
/*! \brief Create a DataFile suitable for copying multiple trackContentObjects.
*
* trackContentObjects in the vector are written to the "tcos" node in the
@@ -568,7 +588,10 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me )
setInitialOffsets();
if( !fixedTCOs() && me->button() == Qt::LeftButton )
{
if( me->modifiers() & Qt::ControlModifier )
SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco );
const bool knifeMode = m_trackView->trackContainerView()->knifeMode();
if ( me->modifiers() & Qt::ControlModifier && !(sTco && knifeMode) )
{
if( isSelected() )
{
@@ -579,9 +602,7 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me )
m_action = ToggleSelected;
}
}
else if( !me->modifiers()
|| (me->modifiers() & Qt::AltModifier)
|| (me->modifiers() & Qt::ShiftModifier) )
else
{
if( isSelected() )
{
@@ -592,28 +613,43 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me )
gui->songEditor()->m_editor->selectAllTcos( false );
m_tco->addJournalCheckPoint();
// move or resize
m_tco->setJournalling( false );
// Move, Resize and ResizeLeft
// Split action doesn't disable TCO journalling
if (m_action == Move || m_action == Resize || m_action == ResizeLeft)
{
m_tco->setJournalling(false);
}
setInitialPos( me->pos() );
setInitialOffsets();
SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco );
if( me->x() < RESIZE_GRIP_WIDTH && sTco
&& !m_tco->getAutoResize() )
if( m_tco->getAutoResize() )
{ // Always move clips that can't be manually resized
m_action = Move;
setCursor( Qt::SizeAllCursor );
}
else if( me->x() >= width() - RESIZE_GRIP_WIDTH )
{
m_action = Resize;
setCursor( Qt::SizeHorCursor );
}
else if( me->x() < RESIZE_GRIP_WIDTH && sTco )
{
m_action = ResizeLeft;
setCursor( Qt::SizeHorCursor );
}
else if( m_tco->getAutoResize() || me->x() < width() - RESIZE_GRIP_WIDTH )
else if( sTco && knifeMode )
{
m_action = Move;
setCursor( Qt::SizeAllCursor );
m_action = Split;
setCursor( m_cursorKnife );
setMarkerPos( knifeMarkerPos( me ) );
setMarkerEnabled( true );
update();
}
else
{
m_action = Resize;
setCursor( Qt::SizeHorCursor );
m_action = Move;
setCursor( Qt::SizeAllCursor );
}
if( m_action == Move )
@@ -641,7 +677,7 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me )
// s_textFloat->reparent( this );
// setup text-float as if TCO was already moved/resized
s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2) );
s_textFloat->show();
if ( m_action != Split) { s_textFloat->show(); }
}
delete m_hint;
@@ -662,6 +698,16 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me )
{
remove( active );
}
if (m_action == Split)
{
m_action = NoAction;
SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco );
if (sTco)
{
setMarkerEnabled( false );
update();
}
}
}
else if( me->button() == Qt::MidButton )
{
@@ -790,8 +836,6 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me )
}
else if( m_action == Resize || m_action == ResizeLeft )
{
// If the user is holding alt, or pressed ctrl after beginning the drag, don't quantize
const bool unquantized = (me->modifiers() & Qt::ControlModifier) || (me->modifiers() & Qt::AltModifier);
const float snapSize = gui->songEditor()->m_editor->getSnapSize();
// Length in ticks of one snap increment
const TimePos snapLength = TimePos( (int)(snapSize * TimePos::ticksPerBar()) );
@@ -801,7 +845,8 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me )
// The clip's new length
TimePos l = static_cast<int>( me->x() * TimePos::ticksPerBar() / ppb );
if ( unquantized )
// If the user is holding alt, or pressed ctrl after beginning the drag, don't quantize
if ( unquantizedModHeld(me) )
{ // We want to preserve this adjusted offset,
// even if the user switches to snapping later
setInitialPos( m_initialMousePos );
@@ -837,7 +882,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me )
m_trackView->trackContainerView()->currentPosition() +
static_cast<int>( x * TimePos::ticksPerBar() / ppb ) );
if( unquantized )
if( unquantizedModHeld(me) )
{ // We want to preserve this adjusted offset,
// even if the user switches to snapping later
setInitialPos( m_initialMousePos );
@@ -882,19 +927,17 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me )
TimePos::ticksPerBar() ) );
s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2) );
}
else
else if( m_action == Split )
{
SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco );
if( ( me->x() > width() - RESIZE_GRIP_WIDTH && !me->buttons() && !m_tco->getAutoResize() )
|| ( me->x() < RESIZE_GRIP_WIDTH && !me->buttons() && sTco && !m_tco->getAutoResize() ) )
{
setCursor( Qt::SizeHorCursor );
}
else
{
leaveEvent( NULL );
if (sTco) {
setCursor( m_cursorKnife );
setMarkerPos( knifeMarkerPos( me ) );
}
update();
}
// None of the actions above, we will just handle the cursor
else { updateCursor(me); }
}
@@ -918,17 +961,26 @@ void TrackContentObjectView::mouseReleaseEvent( QMouseEvent * me )
{
setSelected( !isSelected() );
}
if( m_action == Move || m_action == Resize || m_action == ResizeLeft )
else if( m_action == Move || m_action == Resize || m_action == ResizeLeft )
{
// TODO: Fix m_tco->setJournalling() consistency
m_tco->setJournalling( true );
}
else if( m_action == Split )
{
const float ppb = m_trackView->trackContainerView()->pixelsPerBar();
const TimePos relPos = me->pos().x() * TimePos::ticksPerBar() / ppb;
splitTCO(unquantizedModHeld(me) ?
relPos :
quantizeSplitPos(relPos, me->modifiers() & Qt::ShiftModifier)
);
}
m_action = NoAction;
delete m_hint;
m_hint = NULL;
s_textFloat->hide();
leaveEvent( NULL );
updateCursor(me);
selectableObject::mouseReleaseEvent( me );
}
@@ -1271,6 +1323,15 @@ bool TrackContentObjectView::mouseMovedDistance( QMouseEvent * me, int distance
bool TrackContentObjectView::unquantizedModHeld( QMouseEvent * me )
{
return me->modifiers() & Qt::ControlModifier || me->modifiers() & Qt::AltModifier;
}
/*! \brief Calculate the new position of a dragged TCO from a mouse event
*
*
@@ -1285,12 +1346,8 @@ TimePos TrackContentObjectView::draggedTCOPos( QMouseEvent * me )
TimePos newPos = m_initialTCOPos + mouseOff * TimePos::ticksPerBar() / ppb;
TimePos offset = newPos - m_initialTCOPos;
// If the user is holding alt, or pressed ctrl after beginning the drag, don't quantize
if ( me->button() != Qt::NoButton
|| (me->modifiers() & Qt::ControlModifier)
|| (me->modifiers() & Qt::AltModifier) )
{
// We want to preserve this adjusted offset,
// even if the user switches to snapping
if ( me->button() != Qt::NoButton || unquantizedModHeld(me) )
{ // We want to preserve this adjusted offset, even if the user switches to snapping
setInitialPos( m_initialMousePos );
}
else if ( me->modifiers() & Qt::ShiftModifier )
@@ -1313,6 +1370,50 @@ TimePos TrackContentObjectView::draggedTCOPos( QMouseEvent * me )
}
int TrackContentObjectView::knifeMarkerPos( QMouseEvent * me )
{
//Position relative to start of clip
const int markerPos = me->pos().x();
//In unquantized mode, we don't have to mess with the position at all
if ( unquantizedModHeld(me) ) { return markerPos; }
else
{ //Otherwise we...
//1: Convert the position to a TimePos
const float ppb = m_trackView->trackContainerView()->pixelsPerBar();
TimePos midiPos = markerPos * TimePos::ticksPerBar() / ppb;
//2: Snap to the correct position, based on modifier keys
midiPos = quantizeSplitPos( midiPos, me->modifiers() & Qt::ShiftModifier );
//3: Convert back to a pixel position
return midiPos * ppb / TimePos::ticksPerBar();
}
}
TimePos TrackContentObjectView::quantizeSplitPos( TimePos midiPos, bool shiftMode )
{
const float snapSize = gui->songEditor()->m_editor->getSnapSize();
if ( shiftMode )
{ //If shift is held we quantize the length of the new left clip...
const TimePos leftPos = midiPos.quantize( snapSize );
//...or right clip...
const TimePos rightOff = m_tco->length() - midiPos;
const TimePos rightPos = m_tco->length() - rightOff.quantize( snapSize );
//...whichever gives a position closer to the cursor
if ( abs(leftPos - midiPos) < abs(rightPos - midiPos) ) { return leftPos; }
else { return rightPos; }
}
else
{
return TimePos(midiPos + m_initialTCOPos).quantize( snapSize ) - m_initialTCOPos;
}
}
// Return the color that the TCO's background should be
QColor TrackContentObjectView::getColorForDisplay( QColor defaultColor )
{
@@ -1355,4 +1456,3 @@ QColor TrackContentObjectView::getColorForDisplay( QColor defaultColor )
// Return color to caller
return c;
}

View File

@@ -449,6 +449,11 @@ void SongEditor::setEditModeDraw()
setEditMode(DrawMode);
}
void SongEditor::setEditModeKnife()
{
setEditMode(KnifeMode);
}
void SongEditor::setEditModeSelect()
{
setEditMode(SelectMode);
@@ -860,6 +865,14 @@ bool SongEditor::allowRubberband() const
bool SongEditor::knifeMode() const
{
return m_mode == KnifeMode;
}
int SongEditor::trackIndexFromSelectionPoint(int yPos)
{
const TrackView * tv = trackViewAt(yPos - m_timeLine->height());
@@ -944,13 +957,16 @@ SongEditorWindow::SongEditorWindow(Song* song) :
m_editModeGroup = new ActionGroup(this);
m_drawModeAction = m_editModeGroup->addAction(embed::getIconPixmap("edit_draw"), tr("Draw mode"));
m_knifeModeAction = m_editModeGroup->addAction(embed::getIconPixmap("edit_knife"), tr("Knife mode (split sample clips)"));
m_selectModeAction = m_editModeGroup->addAction(embed::getIconPixmap("edit_select"), tr("Edit mode (select and move)"));
m_drawModeAction->setChecked(true);
connect(m_drawModeAction, SIGNAL(triggered()), m_editor, SLOT(setEditModeDraw()));
connect(m_knifeModeAction, SIGNAL(triggered()), m_editor, SLOT(setEditModeKnife()));
connect(m_selectModeAction, SIGNAL(triggered()), m_editor, SLOT(setEditModeSelect()));
editActionsToolBar->addAction( m_drawModeAction );
editActionsToolBar->addAction( m_knifeModeAction );
editActionsToolBar->addAction( m_selectModeAction );
DropToolBar *timeLineToolBar = addDropToolBarToTop(tr("Timeline controls"));
@@ -1031,6 +1047,13 @@ void SongEditorWindow::updateSnapLabel(){
void SongEditorWindow::syncEditMode(){
m_editModeGroup->checkedAction()->trigger();
}
void SongEditorWindow::resizeEvent(QResizeEvent *event)
{
emit resized();
@@ -1108,31 +1131,3 @@ void SongEditorWindow::adjustUiAfterProjectLoad()
connect( qobject_cast<SubWindow *>( parentWidget() ), SIGNAL( focusLost() ), this, SLOT( lostFocus() ) );
m_editor->scrolled(0);
}
void SongEditorWindow::keyPressEvent( QKeyEvent *ke )
{
if( ke->key() == Qt::Key_Control )
{
m_crtlAction = m_editModeGroup->checkedAction();
m_selectModeAction->setChecked( true );
m_selectModeAction->trigger();
}
}
void SongEditorWindow::keyReleaseEvent( QKeyEvent *ke )
{
if( ke->key() == Qt::Key_Control )
{
if( m_crtlAction )
{
m_crtlAction->setChecked( true );
m_crtlAction->trigger();
}
}
}

View File

@@ -547,14 +547,22 @@ void TrackContentWidget::dropEvent( QDropEvent * de )
*/
void TrackContentWidget::mousePressEvent( QMouseEvent * me )
{
// Enable box select if control is held when clicking an empty space
// (If we had clicked a TCO it would have intercepted the mouse event)
if( me->modifiers() & Qt::ControlModifier ){
gui->songEditor()->m_editor->setEditMode(SongEditor::EditMode::SelectMode);
}
// Forward event to allow box select if the editor supports it and is in that mode
if( m_trackView->trackContainerView()->allowRubberband() == true )
{
QWidget::mousePressEvent( me );
}
// Forward shift clicks so tracks can be resized
else if( me->modifiers() & Qt::ShiftModifier )
{
QWidget::mousePressEvent( me );
}
// For an unmodified click, create a new TCO
else if( me->button() == Qt::LeftButton &&
!m_trackView->trackContainerView()->fixedTCOs() )
{
@@ -573,6 +581,15 @@ void TrackContentWidget::mousePressEvent( QMouseEvent * me )
void TrackContentWidget::mouseReleaseEvent( QMouseEvent * me )
{
gui->songEditor()->syncEditMode();
QWidget::mouseReleaseEvent(me);
}
/*! \brief Repaint the trackContentWidget on command
*
* \param pe the Paint Event to respond to
@@ -707,4 +724,3 @@ void TrackContentWidget::setGridColor( const QBrush & c )
//! \brief CSS theming qproperty access method
void TrackContentWidget::setEmbossColor( const QBrush & c )
{ m_embossColor = c; }

View File

@@ -106,9 +106,6 @@ SampleTCO::SampleTCO( Track * _track ) :
updateTrackTcos();
}
SampleTCO::SampleTCO(const SampleTCO& orig) :
SampleTCO(orig.getTrack())
{
@@ -634,6 +631,10 @@ void SampleTCOView::paintEvent( QPaintEvent * pe )
embed::getIconPixmap( "muted", size, size ) );
}
if ( m_marker )
{
p.drawLine(m_markerPos, rect().bottom(), m_markerPos, rect().top());
}
// recording sample tracks is not possible at the moment
/* if( m_tco->isRecord() )
@@ -667,6 +668,39 @@ void SampleTCOView::reverseSample()
//! Split this TCO.
/*! \param pos the position of the split, relative to the start of the clip */
bool SampleTCOView::splitTCO( const TimePos pos )
{
setMarkerEnabled( false );
const TimePos splitPos = m_initialTCOPos + pos;
//Don't split if we slid off the TCO or if we're on the clip's start/end
//Cutting at exactly the start/end position would create a zero length
//clip (bad), and a clip the same length as the original one (pointless).
if ( splitPos > m_initialTCOPos && splitPos < m_initialTCOEnd )
{
m_tco->getTrack()->addJournalCheckPoint();
m_tco->getTrack()->saveJournallingState( false );
SampleTCO * rightTCO = new SampleTCO ( *m_tco );
m_tco->changeLength( splitPos - m_initialTCOPos );
rightTCO->movePosition( splitPos );
rightTCO->changeLength( m_initialTCOEnd - splitPos );
rightTCO->setStartTimeOffset( m_tco->startTimeOffset() - m_tco->length() );
m_tco->getTrack()->restoreJournallingState();
return true;
}
else { return false; }
}
SampleTrack::SampleTrack(TrackContainer* tc) :