mirror of
https://github.com/LMMS/lmms.git
synced 2026-01-29 16:53:07 -05:00
* Starts implementing the feature
The idea of this branch is to allow actions triggered through the context menu of a TCO on the song editor to affect all the selected TCOs. With this commit, only the "Mute/unmute" action affects all selected TCOs, while the others retain their old behavior (only affect the TCO that owns the context menu).
For that, a method was created that processes all actions (the triggered action is parsed as a parameter to the method). In the case of the "Mute" action, it checks if the song editor has selected TCOs, and if it does it mutes/unmutes all of them.
* Allows selected TCOs to be removed too
Now the "Remove" action from the context menu will remove all selected TCOs if there are any.
* Starts implementing selected TCO cut and copy
Now, when multiple TCOs are selected, the context menu actions Cut and Copy will write a DataFile to the clipboard containing the TCO information, so it can later be used to paste it.
The Paste action now checks if there's data in the QApplication clipboard. If there is, it will later paste the TCOs (for now it just prints the data with qWarning). If there's not, it uses the regular TCO paste method that uses the internal LMMS clipboard. Because it now have to decide between the QApplication clipboard and the LMMS internal clipboard, the Clipboard::copy() method now clears anything in the QApplication clipboard, making it empty so LMMS can know it should use the internal clipboard instead in that situation.
Adds safety checks for the selected TCO views.
* Overloads TCW paste selection methods
This commit is a step towards implementing the paste feature of the TCO context menu. It overloads the TrackContentWidget::canPasteSelection and TrackContentWidget::pasteSelection methods so they can be called without having a QDropEvent (only the QMimeData with the copied TCOs information). The overloaded canPasteSelection(MidiTime, QMimeData, bool) method required a third argument which says whether pasting over the same bar should be allowed or not, because it shouldn't when the QDropEvent comes from the same application but should when it doesn't. That is defined in the canPasteSelection(MidiTime, QDropEvent) method.
Also, the pasteSelection(MidiTime, QDropEvent) isn't optimal, since it calls canPasteSelection twice (more details in the comments, but it's basically because the two canPasteSelection methods can return different values depending on the origin of QDropEvent). This could later be fixed by calling canPasteSelection before pasteSelection and removing it from inside the method altogether.
Next step is to add the "tco_" key to the mimeData on the Copy/Cut operations and implementing the paste operation using those methods.
* Adds the TCO type to the clipboard
Adds the key with the TCO type ("tco_" + type number + ":" + TCO Data XML) to the clipboard, so it can be later used by the canPasteSelection and pasteSelection methods.
* Apply changes to "src/tracks/SampleTrack.cpp"
Change the SampleTCOView::contextMenuEvent() method so it behaves the same way as the TrackContentObjectView::contextMenuEvent() method. For that, I had to change the ContextMenuAction enum and the contextMenuAction methods to be protected instead of private, so SampleTCOView can access it.
* Implement the paste action
Now that the canPasteSelection and pasteSelection methods were overloaded, it was possible to implement the paste action using the same logic as the Drag&Drop copy/paste.
Other small changes:
- Removes the TCO views AFTER creating the TCO data file, instead of before (which probably resulted in an empty data file).
- Uses the StringPairDrag::mimeType() instead of Clipboard::mimeType() since that's the one the methods from StringPairDrag.cpp recognizes.
* Removes QDebug header
Forgot to remove the QDebug header on the last commit.
* Creates a Context Menu on the TCW for "paste"
Now it's possible to paste a selection of copied TCOs anywhere in the TCW, as long as the rules to paste are met (same rules as Drag&Drop copy/paste). If the rules are not met the "Paste" menu action shows but is disabled.
* Small code refactoring
Saving a few lines of code.
* Avoids double call to canPasteSelection
This commit adds a third parameter to the pasteSelection overloaded method, which will define whether we whould skip the canPasteSelection check. The only situation where we will want to skip it is if we are calling pasteSelection from inside the other pasteSelection method, which will already have checked it. Because of that the default value is false.
Organizes comments as well.
* Separates methods for the actions on selections
Now the remove, copy, cut, paste and toggle mute actions have a separate method for applying them to selections, which are then called from the contextMenuAction method. That made the code more organized and the contextMenuAction method smaller.
Also, the mouse shortcuts for muting and removing (CTRL+middle button, middle button, CTRL+right button) now apply the action on selections as well.
* Fixes small bug and reorganize code
Fixes a small bug where using a mouse shortcut or choosing an action on a TCO that is not selected while other TCOs were selected would result in the selection being affected.
Also reorganizes the code so the conditional for choosing between the selection action and the individual action stays inside the method.
* Move logic to the action methods
Since the methods that called the action+Selection() methods didn't need the list of selectableObjects, I moved it to the inside of the action+Selection() methods and removed the parameter from them.
* Changes logic structure and labels
As suggested by Spekular, the logic structure was changed. Now, the mousePressEvent and contextMenuAction methods determine whether the action should happen to a selection of TCOs or an individual TCO. The list of TCOs to be affected populate a QVector list called "active", which is parsed to the action method that will apply the action to each object in the list.
I changed the method names to removeActive, cutActive, copyActive and toggleMuteActive, since I believe that better describe the behavior. The paste method is still called pasteSelection for now, because the paste behavior isn't related to the active TCOs but to the content of the clipboard.
The contextMenuEvent method on both src/core/Track.cpp and src/tracks/SampleTrack.cpp were changed so they also check if the right-clicked TCO is part of a selection or an individual TCO, and the labels for the actions are changed to better describe the behavior (i.e.: "Delete" for individual TCO and "Delete selection" for multiple TCOs).
* Make removeActive and toggleMuteActive static
removeActive and toggleMuteActive methods are now static so they can be called from anywhere in the code since they don't require a TCO view instance to work. That makes it possible for them to be used in the future if any feature requires this type of action to be called from out of a TCO view instance.
The same couldn't be done for the copyActive and cutActive methods because those require an instance of the TCO view to call them, since when copying to the clipboard some metadata is written using information from the object instance.
* Renamed TCO View paste method
I renamed the TCO View paste method from pasteSelection to just paste, since the TCO view doesn't currently have a paste method (only the TCO class). It's also a name that accurately describes the action: it will paste either a group of TCOVs or a single TCOV on the current TCOV.
I also moved the logic for deciding between the multiple TCOV paste and single TCOV paste inside the paste method.
* Moves repeated code to a new method
This commit adds another method to TrackContentObjectView called getClickedTCOs, which will return a QVector with the TCO views that are supposed to be affected by a context menu action (either the individual right-clicked TCO or the selection of TCOs). Code was updated on the other methods to make use of this new method.
Method names for actions that affect multiple TCOs were changed. Instead of calling them copyActive, cutActive, toggleMuteActive and removeActive, they are just called copy, cut, toggleMute and remove, hence they are overloaded methods for those actions that affect multiple TCOs (their differenciation is the arguments list, which is a QVector list for those).
* Avoid unnecessary calls to getClickedTCOs()
We use a ternary operator inside TrackContentObjectView::mousePressEvent to avoid unnecessary calls to getClickedTCOs when the list is not going to be used.
The contextMenuEvent method on both Track.cpp and SampleTrack.cpp was reformated to use a more appropriate indentation and spacing between method calls.
* Fix indenting in a ternary operator assignment
800 lines
17 KiB
C++
800 lines
17 KiB
C++
/*
|
|
* Track.h - declaration of classes concerning tracks -> necessary for all
|
|
* track-like objects (beat/bassline, sample-track...)
|
|
*
|
|
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
|
*
|
|
* This file is part of LMMS - https://lmms.io
|
|
*
|
|
* 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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this program (see COPYING); if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA.
|
|
*
|
|
*/
|
|
|
|
#ifndef TRACK_H
|
|
#define TRACK_H
|
|
|
|
#include <QtCore/QVector>
|
|
#include <QtCore/QList>
|
|
#include <QWidget>
|
|
#include <QSize>
|
|
#include <QColor>
|
|
#include <QMimeData>
|
|
|
|
#include "lmms_basics.h"
|
|
#include "MidiTime.h"
|
|
#include "Rubberband.h"
|
|
#include "JournallingObject.h"
|
|
#include "AutomatableModel.h"
|
|
#include "ModelView.h"
|
|
#include "DataFile.h"
|
|
#include "FadeButton.h"
|
|
|
|
|
|
class QMenu;
|
|
class QPushButton;
|
|
|
|
class PixmapButton;
|
|
class TextFloat;
|
|
class Track;
|
|
class TrackContentObjectView;
|
|
class TrackContainer;
|
|
class TrackContainerView;
|
|
class TrackContentWidget;
|
|
class TrackView;
|
|
|
|
|
|
const int DEFAULT_SETTINGS_WIDGET_WIDTH = 224;
|
|
const int TRACK_OP_WIDTH = 78;
|
|
// This shaves 150-ish pixels off track buttons,
|
|
// ruled from config: ui.compacttrackbuttons
|
|
const int DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT = 96;
|
|
const int TRACK_OP_WIDTH_COMPACT = 62;
|
|
|
|
/*! The minimum track height in pixels
|
|
*
|
|
* Tracks can be resized by shift-dragging anywhere inside the track
|
|
* display. This sets the minimum size in pixels for a track.
|
|
*/
|
|
const int MINIMAL_TRACK_HEIGHT = 32;
|
|
const int DEFAULT_TRACK_HEIGHT = 32;
|
|
|
|
const int TCO_BORDER_WIDTH = 2;
|
|
|
|
char const *const FILENAME_FILTER = "[\\0000-\x1f\"*/:<>?\\\\|\x7f]";
|
|
|
|
|
|
class LMMS_EXPORT TrackContentObject : public Model, public JournallingObject
|
|
{
|
|
Q_OBJECT
|
|
MM_OPERATORS
|
|
mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel);
|
|
mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel);
|
|
public:
|
|
TrackContentObject( Track * track );
|
|
virtual ~TrackContentObject();
|
|
|
|
inline Track * getTrack() const
|
|
{
|
|
return m_track;
|
|
}
|
|
|
|
inline const QString & name() const
|
|
{
|
|
return m_name;
|
|
}
|
|
|
|
inline void setName( const QString & name )
|
|
{
|
|
m_name = name;
|
|
emit dataChanged();
|
|
}
|
|
|
|
QString displayName() const override
|
|
{
|
|
return name();
|
|
}
|
|
|
|
|
|
inline const MidiTime & startPosition() const
|
|
{
|
|
return m_startPosition;
|
|
}
|
|
|
|
inline MidiTime endPosition() const
|
|
{
|
|
const int sp = m_startPosition;
|
|
return sp + m_length;
|
|
}
|
|
|
|
inline const MidiTime & length() const
|
|
{
|
|
return m_length;
|
|
}
|
|
|
|
inline void setAutoResize( const bool r )
|
|
{
|
|
m_autoResize = r;
|
|
}
|
|
|
|
inline const bool getAutoResize() const
|
|
{
|
|
return m_autoResize;
|
|
}
|
|
|
|
virtual void movePosition( const MidiTime & pos );
|
|
virtual void changeLength( const MidiTime & length );
|
|
|
|
virtual TrackContentObjectView * createView( TrackView * tv ) = 0;
|
|
|
|
inline void selectViewOnCreate( bool select )
|
|
{
|
|
m_selectViewOnCreate = select;
|
|
}
|
|
|
|
inline bool getSelectViewOnCreate()
|
|
{
|
|
return m_selectViewOnCreate;
|
|
}
|
|
|
|
/// Returns true if and only if a->startPosition() < b->startPosition()
|
|
static bool comparePosition(const TrackContentObject* a, const TrackContentObject* b);
|
|
|
|
MidiTime startTimeOffset() const;
|
|
void setStartTimeOffset( const MidiTime &startTimeOffset );
|
|
|
|
public slots:
|
|
void copy();
|
|
void paste();
|
|
void toggleMute();
|
|
|
|
|
|
signals:
|
|
void lengthChanged();
|
|
void positionChanged();
|
|
void destroyedTCO();
|
|
|
|
|
|
private:
|
|
enum Actions
|
|
{
|
|
NoAction,
|
|
Move,
|
|
Resize
|
|
} ;
|
|
|
|
Track * m_track;
|
|
QString m_name;
|
|
|
|
MidiTime m_startPosition;
|
|
MidiTime m_length;
|
|
MidiTime m_startTimeOffset;
|
|
|
|
BoolModel m_mutedModel;
|
|
BoolModel m_soloModel;
|
|
bool m_autoResize;
|
|
|
|
bool m_selectViewOnCreate;
|
|
|
|
friend class TrackContentObjectView;
|
|
|
|
} ;
|
|
|
|
|
|
|
|
class TrackContentObjectView : public selectableObject, public ModelView
|
|
{
|
|
Q_OBJECT
|
|
|
|
// theming qproperties
|
|
Q_PROPERTY( QColor mutedColor READ mutedColor WRITE setMutedColor )
|
|
Q_PROPERTY( QColor mutedBackgroundColor READ mutedBackgroundColor WRITE setMutedBackgroundColor )
|
|
Q_PROPERTY( QColor selectedColor READ selectedColor WRITE setSelectedColor )
|
|
Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor )
|
|
Q_PROPERTY( QColor textBackgroundColor READ textBackgroundColor WRITE setTextBackgroundColor )
|
|
Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor )
|
|
Q_PROPERTY( QColor BBPatternBackground READ BBPatternBackground WRITE setBBPatternBackground )
|
|
Q_PROPERTY( bool gradient READ gradient WRITE setGradient )
|
|
// We have to use a QSize here because using QPoint isn't supported.
|
|
// width -> x, height -> y
|
|
Q_PROPERTY( QSize mouseHotspotHand WRITE setMouseHotspotHand )
|
|
|
|
public:
|
|
TrackContentObjectView( TrackContentObject * tco, TrackView * tv );
|
|
virtual ~TrackContentObjectView();
|
|
|
|
bool fixedTCOs();
|
|
|
|
inline TrackContentObject * getTrackContentObject()
|
|
{
|
|
return m_tco;
|
|
}
|
|
|
|
inline TrackView * getTrackView()
|
|
{
|
|
return m_trackView;
|
|
}
|
|
|
|
// qproperty access func
|
|
QColor mutedColor() const;
|
|
QColor mutedBackgroundColor() const;
|
|
QColor selectedColor() const;
|
|
QColor textColor() const;
|
|
QColor textBackgroundColor() const;
|
|
QColor textShadowColor() const;
|
|
QColor BBPatternBackground() const;
|
|
bool gradient() const;
|
|
void setMutedColor( const QColor & c );
|
|
void setMutedBackgroundColor( const QColor & c );
|
|
void setSelectedColor( const QColor & c );
|
|
void setTextColor( const QColor & c );
|
|
void setTextBackgroundColor( const QColor & c );
|
|
void setTextShadowColor( const QColor & c );
|
|
void setBBPatternBackground( const QColor & c );
|
|
void setGradient( const bool & b );
|
|
void setMouseHotspotHand(const QSize & s);
|
|
|
|
// access needsUpdate member variable
|
|
bool needsUpdate();
|
|
void setNeedsUpdate( bool b );
|
|
|
|
// Method to get a QVector of TCOs to be affected by a context menu action
|
|
QVector<TrackContentObjectView *> getClickedTCOs();
|
|
|
|
// Methods to remove, copy, cut, paste and mute a QVector of TCO views
|
|
void copy( QVector<TrackContentObjectView *> tcovs );
|
|
void cut( QVector<TrackContentObjectView *> tcovs );
|
|
void paste();
|
|
// remove and toggleMute are static because they don't depend
|
|
// being called from a particular TCO view, but can be called anywhere as long
|
|
// as a valid TCO view list is given, while copy/cut require an instance for
|
|
// some metadata to be written to the clipboard.
|
|
static void remove( QVector<TrackContentObjectView *> tcovs );
|
|
static void toggleMute( QVector<TrackContentObjectView *> tcovs );
|
|
|
|
public slots:
|
|
virtual bool close();
|
|
void cut();
|
|
void remove();
|
|
void update() override;
|
|
|
|
protected:
|
|
enum ContextMenuAction
|
|
{
|
|
Remove,
|
|
Cut,
|
|
Copy,
|
|
Paste,
|
|
Mute
|
|
};
|
|
|
|
virtual void constructContextMenu( QMenu * )
|
|
{
|
|
}
|
|
|
|
void contextMenuEvent( QContextMenuEvent * cme ) override;
|
|
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;
|
|
void resizeEvent( QResizeEvent * re ) override
|
|
{
|
|
m_needsUpdate = true;
|
|
selectableObject::resizeEvent( re );
|
|
}
|
|
|
|
float pixelsPerBar();
|
|
|
|
|
|
DataFile createTCODataFiles(const QVector<TrackContentObjectView *> & tcos) const;
|
|
|
|
virtual void paintTextLabel(QString const & text, QPainter & painter);
|
|
|
|
|
|
protected slots:
|
|
void updateLength();
|
|
void updatePosition();
|
|
|
|
|
|
private:
|
|
enum Actions
|
|
{
|
|
NoAction,
|
|
Move,
|
|
MoveSelection,
|
|
Resize,
|
|
ResizeLeft,
|
|
CopySelection,
|
|
ToggleSelected
|
|
} ;
|
|
|
|
static TextFloat * s_textFloat;
|
|
|
|
TrackContentObject * m_tco;
|
|
TrackView * m_trackView;
|
|
Actions m_action;
|
|
QPoint m_initialMousePos;
|
|
QPoint m_initialMouseGlobalPos;
|
|
MidiTime m_initialTCOPos;
|
|
MidiTime m_initialTCOEnd;
|
|
QVector<MidiTime> m_initialOffsets;
|
|
|
|
TextFloat * m_hint;
|
|
|
|
// qproperty fields
|
|
QColor m_mutedColor;
|
|
QColor m_mutedBackgroundColor;
|
|
QColor m_selectedColor;
|
|
QColor m_textColor;
|
|
QColor m_textBackgroundColor;
|
|
QColor m_textShadowColor;
|
|
QColor m_BBPatternBackground;
|
|
bool m_gradient;
|
|
QSize m_mouseHotspotHand; // QSize must be used because QPoint isn't supported by property system
|
|
bool m_cursorSetYet;
|
|
|
|
bool m_needsUpdate;
|
|
inline void setInitialPos( QPoint pos )
|
|
{
|
|
m_initialMousePos = pos;
|
|
m_initialMouseGlobalPos = mapToGlobal( pos );
|
|
m_initialTCOPos = m_tco->startPosition();
|
|
m_initialTCOEnd = m_initialTCOPos + m_tco->length();
|
|
}
|
|
void setInitialOffsets();
|
|
|
|
bool mouseMovedDistance( QMouseEvent * me, int distance );
|
|
MidiTime draggedTCOPos( QMouseEvent * me );
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
class TrackContentWidget : public QWidget, public JournallingObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
// qproperties for track background gradients
|
|
Q_PROPERTY( QBrush darkerColor READ darkerColor WRITE setDarkerColor )
|
|
Q_PROPERTY( QBrush lighterColor READ lighterColor WRITE setLighterColor )
|
|
Q_PROPERTY( QBrush gridColor READ gridColor WRITE setGridColor )
|
|
Q_PROPERTY( QBrush embossColor READ embossColor WRITE setEmbossColor )
|
|
|
|
public:
|
|
TrackContentWidget( TrackView * parent );
|
|
virtual ~TrackContentWidget();
|
|
|
|
/*! \brief Updates the background tile pixmap. */
|
|
void updateBackground();
|
|
|
|
void addTCOView( TrackContentObjectView * tcov );
|
|
void removeTCOView( TrackContentObjectView * tcov );
|
|
void removeTCOView( int tcoNum )
|
|
{
|
|
if( tcoNum >= 0 && tcoNum < m_tcoViews.size() )
|
|
{
|
|
removeTCOView( m_tcoViews[tcoNum] );
|
|
}
|
|
}
|
|
|
|
bool canPasteSelection( MidiTime tcoPos, const QDropEvent *de );
|
|
bool canPasteSelection( MidiTime tcoPos, const QMimeData *md, bool allowSameBar = false );
|
|
bool pasteSelection( MidiTime tcoPos, QDropEvent * de );
|
|
bool pasteSelection( MidiTime tcoPos, const QMimeData * md, bool skipSafetyCheck = false );
|
|
|
|
MidiTime endPosition( const MidiTime & posStart );
|
|
|
|
// qproperty access methods
|
|
|
|
QBrush darkerColor() const;
|
|
QBrush lighterColor() const;
|
|
QBrush gridColor() const;
|
|
QBrush embossColor() const;
|
|
|
|
void setDarkerColor( const QBrush & c );
|
|
void setLighterColor( const QBrush & c );
|
|
void setGridColor( const QBrush & c );
|
|
void setEmbossColor( const QBrush & c);
|
|
|
|
public slots:
|
|
void update();
|
|
void changePosition( const MidiTime & newPos = MidiTime( -1 ) );
|
|
|
|
protected:
|
|
enum ContextMenuAction
|
|
{
|
|
Paste
|
|
};
|
|
|
|
void contextMenuEvent( QContextMenuEvent * cme ) override;
|
|
void contextMenuAction( QContextMenuEvent * cme, ContextMenuAction action );
|
|
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
|
void dropEvent( QDropEvent * de ) override;
|
|
void mousePressEvent( QMouseEvent * me ) override;
|
|
void paintEvent( QPaintEvent * pe ) override;
|
|
void resizeEvent( QResizeEvent * re ) override;
|
|
|
|
QString nodeName() const override
|
|
{
|
|
return "trackcontentwidget";
|
|
}
|
|
|
|
void saveSettings( QDomDocument& doc, QDomElement& element ) override
|
|
{
|
|
Q_UNUSED(doc)
|
|
Q_UNUSED(element)
|
|
}
|
|
|
|
void loadSettings( const QDomElement& element ) override
|
|
{
|
|
Q_UNUSED(element)
|
|
}
|
|
|
|
|
|
private:
|
|
Track * getTrack();
|
|
MidiTime getPosition( int mouseX );
|
|
|
|
TrackView * m_trackView;
|
|
|
|
typedef QVector<TrackContentObjectView *> tcoViewVector;
|
|
tcoViewVector m_tcoViews;
|
|
|
|
QPixmap m_background;
|
|
|
|
// qproperty fields
|
|
QBrush m_darkerColor;
|
|
QBrush m_lighterColor;
|
|
QBrush m_gridColor;
|
|
QBrush m_embossColor;
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
class TrackOperationsWidget : public QWidget
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
TrackOperationsWidget( TrackView * parent );
|
|
~TrackOperationsWidget();
|
|
|
|
|
|
protected:
|
|
void mousePressEvent( QMouseEvent * me ) override;
|
|
void paintEvent( QPaintEvent * pe ) override;
|
|
|
|
|
|
private slots:
|
|
void cloneTrack();
|
|
void removeTrack();
|
|
void updateMenu();
|
|
void toggleRecording(bool on);
|
|
void recordingOn();
|
|
void recordingOff();
|
|
void clearTrack();
|
|
|
|
private:
|
|
TrackView * m_trackView;
|
|
|
|
QPushButton * m_trackOps;
|
|
PixmapButton * m_muteBtn;
|
|
PixmapButton * m_soloBtn;
|
|
|
|
|
|
friend class TrackView;
|
|
|
|
signals:
|
|
void trackRemovalScheduled( TrackView * t );
|
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
// base-class for all tracks
|
|
class LMMS_EXPORT Track : public Model, public JournallingObject
|
|
{
|
|
Q_OBJECT
|
|
MM_OPERATORS
|
|
mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel);
|
|
mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel);
|
|
public:
|
|
typedef QVector<TrackContentObject *> tcoVector;
|
|
|
|
enum TrackTypes
|
|
{
|
|
InstrumentTrack,
|
|
BBTrack,
|
|
SampleTrack,
|
|
EventTrack,
|
|
VideoTrack,
|
|
AutomationTrack,
|
|
HiddenAutomationTrack,
|
|
NumTrackTypes
|
|
} ;
|
|
|
|
Track( TrackTypes type, TrackContainer * tc );
|
|
virtual ~Track();
|
|
|
|
static Track * create( TrackTypes tt, TrackContainer * tc );
|
|
static Track * create( const QDomElement & element,
|
|
TrackContainer * tc );
|
|
Track * clone();
|
|
|
|
|
|
// pure virtual functions
|
|
TrackTypes type() const
|
|
{
|
|
return m_type;
|
|
}
|
|
|
|
virtual bool play( const MidiTime & start, const fpp_t frames,
|
|
const f_cnt_t frameBase, int tcoNum = -1 ) = 0;
|
|
|
|
|
|
virtual TrackView * createView( TrackContainerView * view ) = 0;
|
|
virtual TrackContentObject * createTCO( const MidiTime & pos ) = 0;
|
|
|
|
virtual void saveTrackSpecificSettings( QDomDocument & doc,
|
|
QDomElement & parent ) = 0;
|
|
virtual void loadTrackSpecificSettings( const QDomElement & element ) = 0;
|
|
|
|
|
|
void saveSettings( QDomDocument & doc, QDomElement & element ) override;
|
|
void loadSettings( const QDomElement & element ) override;
|
|
|
|
void setSimpleSerializing()
|
|
{
|
|
m_simpleSerializingMode = true;
|
|
}
|
|
|
|
// -- for usage by TrackContentObject only ---------------
|
|
TrackContentObject * addTCO( TrackContentObject * tco );
|
|
void removeTCO( TrackContentObject * tco );
|
|
// -------------------------------------------------------
|
|
void deleteTCOs();
|
|
|
|
int numOfTCOs();
|
|
TrackContentObject * getTCO( int tcoNum );
|
|
int getTCONum(const TrackContentObject* tco );
|
|
|
|
const tcoVector & getTCOs() const
|
|
{
|
|
return m_trackContentObjects;
|
|
}
|
|
void getTCOsInRange( tcoVector & tcoV, const MidiTime & start,
|
|
const MidiTime & end );
|
|
void swapPositionOfTCOs( int tcoNum1, int tcoNum2 );
|
|
|
|
void createTCOsForBB( int bb );
|
|
|
|
|
|
void insertBar( const MidiTime & pos );
|
|
void removeBar( const MidiTime & pos );
|
|
|
|
bar_t length() const;
|
|
|
|
|
|
inline TrackContainer* trackContainer() const
|
|
{
|
|
return m_trackContainer;
|
|
}
|
|
|
|
// name-stuff
|
|
virtual const QString & name() const
|
|
{
|
|
return m_name;
|
|
}
|
|
|
|
QString displayName() const override
|
|
{
|
|
return name();
|
|
}
|
|
|
|
using Model::dataChanged;
|
|
|
|
inline int getHeight()
|
|
{
|
|
return m_height >= MINIMAL_TRACK_HEIGHT
|
|
? m_height
|
|
: DEFAULT_TRACK_HEIGHT;
|
|
}
|
|
inline void setHeight( int height )
|
|
{
|
|
m_height = height;
|
|
}
|
|
|
|
void lock()
|
|
{
|
|
m_processingLock.lock();
|
|
}
|
|
void unlock()
|
|
{
|
|
m_processingLock.unlock();
|
|
}
|
|
bool tryLock()
|
|
{
|
|
return m_processingLock.tryLock();
|
|
}
|
|
|
|
BoolModel* getMutedModel();
|
|
|
|
public slots:
|
|
virtual void setName( const QString & newName )
|
|
{
|
|
m_name = newName;
|
|
emit nameChanged();
|
|
}
|
|
|
|
void toggleSolo();
|
|
|
|
|
|
private:
|
|
TrackContainer* m_trackContainer;
|
|
TrackTypes m_type;
|
|
QString m_name;
|
|
int m_height;
|
|
|
|
protected:
|
|
BoolModel m_mutedModel;
|
|
private:
|
|
BoolModel m_soloModel;
|
|
bool m_mutedBeforeSolo;
|
|
|
|
bool m_simpleSerializingMode;
|
|
|
|
tcoVector m_trackContentObjects;
|
|
|
|
QMutex m_processingLock;
|
|
|
|
friend class TrackView;
|
|
|
|
|
|
signals:
|
|
void destroyedTrack();
|
|
void nameChanged();
|
|
void trackContentObjectAdded( TrackContentObject * );
|
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
class TrackView : public QWidget, public ModelView, public JournallingObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
TrackView( Track * _track, TrackContainerView* tcv );
|
|
virtual ~TrackView();
|
|
|
|
inline const Track * getTrack() const
|
|
{
|
|
return m_track;
|
|
}
|
|
|
|
inline Track * getTrack()
|
|
{
|
|
return m_track;
|
|
}
|
|
|
|
inline TrackContainerView* trackContainerView()
|
|
{
|
|
return m_trackContainerView;
|
|
}
|
|
|
|
inline TrackOperationsWidget * getTrackOperationsWidget()
|
|
{
|
|
return &m_trackOperationsWidget;
|
|
}
|
|
|
|
inline QWidget * getTrackSettingsWidget()
|
|
{
|
|
return &m_trackSettingsWidget;
|
|
}
|
|
|
|
inline TrackContentWidget * getTrackContentWidget()
|
|
{
|
|
return &m_trackContentWidget;
|
|
}
|
|
|
|
bool isMovingTrack() const
|
|
{
|
|
return m_action == MoveTrack;
|
|
}
|
|
|
|
virtual void update();
|
|
|
|
// Create a menu for assigning/creating channels for this track
|
|
// Currently instrument track and sample track supports it
|
|
virtual QMenu * createFxMenu(QString title, QString newFxLabel);
|
|
|
|
|
|
public slots:
|
|
virtual bool close();
|
|
|
|
|
|
protected:
|
|
void modelChanged() override;
|
|
|
|
void saveSettings( QDomDocument& doc, QDomElement& element ) override
|
|
{
|
|
Q_UNUSED(doc)
|
|
Q_UNUSED(element)
|
|
}
|
|
|
|
void loadSettings( const QDomElement& element ) override
|
|
{
|
|
Q_UNUSED(element)
|
|
}
|
|
|
|
QString nodeName() const override
|
|
{
|
|
return "trackview";
|
|
}
|
|
|
|
|
|
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
|
void dropEvent( QDropEvent * de ) override;
|
|
void mousePressEvent( QMouseEvent * me ) override;
|
|
void mouseMoveEvent( QMouseEvent * me ) override;
|
|
void mouseReleaseEvent( QMouseEvent * me ) override;
|
|
void paintEvent( QPaintEvent * pe ) override;
|
|
void resizeEvent( QResizeEvent * re ) override;
|
|
|
|
|
|
private:
|
|
enum Actions
|
|
{
|
|
NoAction,
|
|
MoveTrack,
|
|
ResizeTrack
|
|
} ;
|
|
|
|
Track * m_track;
|
|
TrackContainerView * m_trackContainerView;
|
|
|
|
TrackOperationsWidget m_trackOperationsWidget;
|
|
QWidget m_trackSettingsWidget;
|
|
TrackContentWidget m_trackContentWidget;
|
|
|
|
Actions m_action;
|
|
|
|
virtual FadeButton * getActivityIndicator()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
void setIndicatorMute(FadeButton* indicator, bool muted);
|
|
|
|
friend class TrackLabelButton;
|
|
|
|
|
|
private slots:
|
|
void createTCOView( TrackContentObject * tco );
|
|
void muteChanged();
|
|
|
|
} ;
|
|
|
|
|
|
|
|
#endif
|