2#include "../AdornedRulerPanel.h"
3#include "../Clipboard.h"
4#include "../CommonCommandFlags.h"
5#include "../LabelTrack.h"
7#include "../NoteTrack.h"
11#include "../ProjectSettings.h"
12#include "../ProjectWindow.h"
13#include "../ProjectWindows.h"
14#include "../SelectUtilities.h"
15#include "../SyncLock.h"
16#include "../TrackPanel.h"
17#include "../TrackPanelAx.h"
20#include "../WaveTrack.h"
21#include "../commands/CommandContext.h"
22#include "../commands/CommandManager.h"
24#include "../prefs/PrefsDialog.h"
25#include "../tracks/labeltrack/ui/LabelTrackView.h"
26#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
27#include "../widgets/AudacityMessageBox.h"
28#include "../widgets/VetoDialogHook.h"
48 for (
auto pLabelTrack : tracks.Any<
LabelTrack>())
55 if (view.PasteSelectedText( project, selectedRegion.t0(),
56 selectedRegion.t1() ))
59 .
PushState(
XO(
"Pasted text from the clipboard"),
XO(
"Paste"));
63 if (view.CalcCursorX( project, &x )) {
64 window.ScrollIntoView(x);
85 if (tracks.Selected())
90 auto clipTrackRange = clipboard.GetTracks().Any<
const Track >();
91 if (clipTrackRange.empty())
94 Track* pFirstNewTrack = NULL;
95 for (
auto pClip : clipTrackRange) {
96 auto pNewTrack = pClip->
PasteInto( project );
97 bool newTrack = (pNewTrack.use_count() == 1);
101 pFirstNewTrack = pNewTrack.get();
116 selectedRegion.setTimes(
124 if (pFirstNewTrack) {
141 auto &project = context.
project;
153 if (trackPanel.IsMouseCaptured()) {
161 auto t = *tracks.Selected().begin();
163 t = *tracks.Any().begin();
172 auto &project = context.
project;
183 if (trackPanel.IsMouseCaptured()) {
191 auto t = *tracks.Selected().begin();
193 t = *tracks.Any().begin();
202 auto &project = context.
project;
213 for (
auto lt : tracks.Selected<
LabelTrack >()) {
215 if (view.CutSelectedText( context.
project )) {
216 trackPanel.Refresh(
false);
223 for (
auto wt : tracks.Any<
WaveTrack>()) {
225 if (view.CutSelectedText(context.
project)) {
226 trackPanel.Refresh(
false);
235 auto &newClipboard = *pNewClipboard;
237 tracks.Selected().Visit(
241 auto dest = n->
Cut(selectedRegion.t0(),
242 selectedRegion.t1());
248 auto dest = n->
Copy(selectedRegion.t0(),
249 selectedRegion.t1());
257 std::move( newClipboard ),
260 project.shared_from_this()
275 if (
gPrefs->Read(
wxT(
"/GUI/EnableCutLines"), (long)0)) {
278 selectedRegion.t1());
285 n->
Clear(selectedRegion.t0(), selectedRegion.t1());
289 selectedRegion.collapseToT0();
296 ruler.DrawOverlays(
true );
301 auto &project = context.
project;
306 for (
auto n : tracks.Any()) {
307 if (!n->SupportsBasicEditing())
310 n->Clear(selectedRegion.t0(), selectedRegion.t1());
314 double seconds = selectedRegion.duration();
316 selectedRegion.collapseToT0();
319 XO(
"Deleted %.2f seconds at t=%.2f")
320 .
Format( seconds, selectedRegion.t0()),
327 auto &project = context.
project;
332 for (
auto lt : tracks.Selected<
LabelTrack >()) {
334 if (view.CopySelectedText( context.
project )) {
341 for (
auto wt : tracks.Any<
WaveTrack>()) {
343 if (view.CopySelectedText(context.
project)) {
352 auto &newClipboard = *pNewClipboard;
354 for (
auto n : tracks.Selected()) {
355 if (n->SupportsBasicEditing()) {
356 auto dest = n->Copy(selectedRegion.t0(),
357 selectedRegion.t1());
363 clipboard.Assign( std::move( newClipboard ),
364 selectedRegion.t0(), selectedRegion.t1(), project.shared_from_this() );
367 trackPanel.Refresh(
false);
372 double sel0 = 0.0, sel1 = 0.0;
377 auto &selectedRegion = *pRegion;
378 sel0 = selectedRegion.t0();
379 sel1 = selectedRegion.t1();
385 sel0 = selectedRegion.
t0();
386 sel1 = selectedRegion.t1();
389 return { sel0, sel1 };
394 auto &project = context.
project;
398 auto &pSampleBlockFactory = trackFactory.GetSampleBlockFactory();
402 auto isSyncLocked =
settings.IsSyncLocked();
410 for (
auto wt : tracks.Any<
WaveTrack>()) {
412 if (view.PasteText(context.
project)) {
413 trackPanel.Refresh(
false);
423 auto clipTrackRange = clipboard.GetTracks().Any<
const Track >();
424 if (clipTrackRange.empty())
431 auto pN = tracks.Any().begin();
434 const Track *lastClipBeforeMismatch = NULL;
435 const Track *mismatchedClip = NULL;
436 const Track *prevClip = NULL;
438 bool bAdvanceClipboard =
true;
439 bool bPastedSomething =
false;
442 bPastedSomething =
true;
448 auto pC = clipTrackRange.begin();
449 size_t nnChannels=0, ncChannels=0;
453 if (n->GetSelected()) {
454 bAdvanceClipboard =
true;
457 if (!c->SameKindAs(*n)) {
458 if (!mismatchedClip) {
459 lastClipBeforeMismatch = prevClip;
462 bAdvanceClipboard =
false;
463 c = lastClipBeforeMismatch;
467 while (c && !c->SameKindAs(*n)) {
477 while (n && (!c->SameKindAs(*n) || !n->GetSelected()))
481 auto newT1 = t0 + clipboard.Duration();
482 if (t1 != newT1 && t1 <= n->GetEndTime()) {
484 bPastedSomething =
true;
501 XO(
"Pasting one type of track into another is not allowed."),
503 "Error:_Copying_or_Pasting"
508 if ( n->IsLeader() ) {
509 wxASSERT( c->IsLeader() );
512 ncChannels = cChannels.size();
514 nnChannels = nChannels.size();
520 if (ncChannels > nnChannels)
522 if (ncChannels > 2) {
532 XO(
"Copying stereo audio into a mono track is not allowed."),
534 "Error:_Copying_or_Pasting"
542 wxASSERT( n && c && n->SameKindAs(*c) );
545 pasteWaveTrack(wn,
static_cast<const WaveTrack *
>(c));
552 ln->ShiftLabelsOnInsert( clipboard.Duration(), t0 );
554 bPastedSomething |= ln->PasteOver(t0, c);
557 bPastedSomething =
true;
570 while (nnChannels > 0 && ncChannels == 0)
577 pasteWaveTrack(wn, c);
581 bPastedSomething =
true;
587 if (bAdvanceClipboard) {
594 auto newT1 = t0 + clipboard.Duration();
595 if (t1 != newT1 && t1 <= n->GetEndTime()) {
597 bPastedSomething =
true;
610 *clipboard.GetTracks().Any<
const WaveTrack >().rbegin();
612 tracks.Any().StartingWith(*pN).Visit(
614 if (!wt->GetSelected())
615 return fallthrough();
618 pasteWaveTrack(wt, wc);
621 auto tmp = wt->EmptyCopy( pSampleBlockFactory );
622 tmp->InsertSilence( 0.0,
624 clipboard.Duration() );
627 pasteWaveTrack(wt, tmp.get());
632 return fallthrough();
639 clipboard.Duration(), t0);
643 n->SyncLockAdjust(t1, t0 + clipboard.Duration() );
650 if (bPastedSomething)
653 .
setTimes( t0, t0 + clipboard.Duration() );
661 ff->LinkConsistencyFix();
668 auto &project = context.
project;
674 auto range = tracks.Selected();
675 auto last = *range.rbegin();
676 for (
auto n : range) {
677 if (!n->SupportsBasicEditing())
681 auto dest = n->Copy(selectedRegion.t0(),
682 selectedRegion.t1(),
false);
684 dest->SetOffset(wxMax(selectedRegion.t0(), n->GetOffset()));
698 auto &project = context.
project;
707 auto &newClipboard = *pNewClipboard;
711 tracks.Selected().Visit(
715 selectedRegion.t1());
721 dest = n->
Copy(selectedRegion.t0(),
722 selectedRegion.t1());
723 n->
Silence(selectedRegion.t0(),
724 selectedRegion.t1());
732 clipboard.Assign( std::move( newClipboard ),
733 selectedRegion.t0(), selectedRegion.t1(), project.shared_from_this() );
736 .
PushState(
XO(
"Split-cut to the clipboard"),
XO(
"Split Cut"));
741 auto &project = context.
project;
746 tracks.Selected().Visit(
749 selectedRegion.t1());
752 if (n->SupportsBasicEditing())
753 n->Silence(selectedRegion.t0(),
754 selectedRegion.t1());
759 XO(
"Split-deleted %.2f seconds at t=%.2f")
760 .
Format( selectedRegion.duration(), selectedRegion.t0() ),
766 auto &project = context.
project;
770 for (
auto n : tracks.Selected<
WaveTrack >() )
771 n->Silence(selectedRegion.t0(), selectedRegion.t1());
774 XO(
"Silenced selected tracks for %.2f seconds at %.2f")
775 .
Format( selectedRegion.duration(), selectedRegion.t0() ),
777 XC(
"Silence",
"command"));
782 auto &project = context.
project;
787 if (selectedRegion.isPoint())
790 tracks.Selected().Visit(
793 wt->
Trim(selectedRegion.t0(),
794 selectedRegion.t1());
799 XO(
"Trim selected audio tracks from %.2f seconds to %.2f seconds")
800 .
Format( selectedRegion.t0(), selectedRegion.t1() ),
806 auto &project = context.
project;
812 if (
auto pWaveTrack =
dynamic_cast<WaveTrack*
>(pTrack))
814 pChannel->Split( sel0, sel1 );
820 for (
auto wt : tracks.Selected<
WaveTrack >())
821 wt->Split( sel0, sel1 );
875 auto &project = context.
project;
883 auto range = tracks.Selected();
884 auto last = *range.rbegin();
885 for (
auto track : range) {
893 selectedRegion.t0()));
895 selectedRegion.t1()));
898 dest->SetOffset(wxMax(newt0, offset));
907 dest = n->Cut(viewInfo.selectedRegion.t0(),
908 viewInfo.selectedRegion.t1());
910 dest->SetOffset(wxMax(0, n->GetOffset()));
926 auto &project = context.
project;
931 for (
auto wt : tracks.Selected<
WaveTrack >())
932 wt->Join(selectedRegion.t0(),
933 selectedRegion.t1());
936 XO(
"Joined %.2f seconds at t=%.2f")
937 .
Format( selectedRegion.duration(), selectedRegion.t0() ),
943 auto &project = context.
project;
948 for (
auto wt : tracks.Selected<
WaveTrack >())
949 wt->Disjoin(selectedRegion.t0(),
950 selectedRegion.t1());
953 XO(
"Detached %.2f seconds at t=%.2f")
954 .
Format( selectedRegion.duration(), selectedRegion.t0() ),
960 auto &project = context.
project;
978#if defined(__WXGTK__)
986 wxRect r = window.GetRect();
987 window.SetSize(wxSize(1,1));
988 window.SetSize(r.GetSize());
998 auto &project = context.
project;
999 auto &selectedRegion = project.GetViewInfo().selectedRegion;
1001 if((AudacityProject::msClipT1 - AudacityProject::msClipT0) > 0.0)
1003 selectedRegion.setT1(
1004 selectedRegion.t0() +
1005 (AudacityProject::msClipT1 - AudacityProject::msClipT0));
1026 if ( !range.empty() )
1046 static const auto NotBusyTimeAndTracksFlags =
1050 static constexpr auto redoKey =
1060 static constexpr auto prefKey =
1101 NotBusyTimeAndTracksFlags,
wxT(
"Ctrl+D") ),
1104 Menu(
wxT(
"RemoveSpecial"),
XXO(
"R&emove Special"),
1108 NotBusyTimeAndTracksFlags,
1112 NotBusyTimeAndTracksFlags,
1148 NotBusyTimeAndTracksFlags,
wxT(
"Ctrl+J") ),
1150 NotBusyTimeAndTracksFlags,
wxT(
"Ctrl+Alt+J") )
1177 static const auto flags =
1230 wxT(
"Optional/Extra/Part1"),
@ BadUserAction
Indicates that the user performed an action that is not allowed.
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
AttachedItem sAttachment1
AttachedItem sAttachment2
std::bitset< NCommandFlags > CommandFlag
const ReservedCommandFlag & NoAutoSelect()
const ReservedCommandFlag & NoiseReductionTimeSelectedFlag()
bool EditableTracksSelectedPred(const AudacityProject &project)
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & UndoAvailableFlag()
const ReservedCommandFlag & RedoAvailableFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & EditableTracksSelectedFlag()
const ReservedCommandFlag & AnyTracksSelectedFlag()
const CommandFlagOptions & cutCopyOptions()
const ReservedCommandFlag & TracksExistFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
bool TimeSelectedPred(const AudacityProject &project)
XXO("&Cut/Copy/Paste Toolbar")
auto Visit(Visitor &&vis, Variant &&var)
Mimic some of std::visit, for the case of one visitor only.
#define QUANTIZED_TIME(time, rate)
an object holding per-project preferred sample rate
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
static Settings & settings()
static AdornedRulerPanel & Get(AudacityProject &project)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
TemporarySelection temporarySelection
AudacityProject & project
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
A LabelTrack is a Track that holds labels (LabelStruct).
void ShiftLabelsOnInsert(double length, double pt)
void Clear(double t0, double t1) override
static LabelTrackView & Get(LabelTrack &)
bool IsTextSelected(AudacityProject &project) const
int GetTextEditIndex(AudacityProject &project) const
A Track that is used for Midi notes. (Somewhat old code).
Track::Holder Cut(double t0, double t1) override
void Clear(double t0, double t1) override
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
bool setTimes(double t0, double t1)
Unit slope but with either a jump (pasting more) or a flat interval (pasting less)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
void PopState(const UndoState &state, bool doAutosave=true)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
static ProjectSettings & Get(AudacityProject &project)
static ProjectWindow & Get(AudacityProject &project)
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
A MessageBoxException that shows a given, unvarying string.
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
static bool IsSyncLockSelected(const Track *pTrack)
Abstract base class for an object holding data associated with points on a time axis.
void EnsureVisible(bool modifyState=false)
virtual void SetSelected(bool s)
virtual Holder PasteInto(AudacityProject &) const =0
Find or create the destination track for a paste, maybe in a different project.
static void FinishCopy(const Track *n, Track *dest)
virtual bool SupportsBasicEditing() const
Whether this track type implements cut-copy-paste; by default, true.
virtual void SyncLockAdjust(double oldT1, double newT1)
std::shared_ptr< Track > Holder
Continuation<> Fallthrough
Type of arguments passed as optional second parameter to TypeSwitch<void>() cases.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
static std::shared_ptr< TrackList > Create(AudacityProject *pOwner)
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
auto Any() -> TrackIterRange< TrackType >
static TrackList & Get(AudacityProject &project)
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
static TrackPanel & Get(AudacityProject &project)
static UndoManager & Get(AudacityProject &project)
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
static WaveTrackFactory & Get(AudacityProject &project)
A Track that contains audio waveform data.
void SplitDelete(double t0, double t1)
void Silence(double t0, double t1) override
void ClearAndAddCutLine(double t0, double t1)
double GetOffset() const override
void Trim(double t0, double t1)
void ClearAndPaste(double t0, double t1, const Track *src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=NULL)
Track::Holder SplitCut(double t0, double t1)
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
static WaveTrackView & Get(WaveTrack &track)
std::shared_ptr< BaseItem > BaseItemSharedPtr
void DoSelectAllAudio(AudacityProject &project)
CommandManager::Options Options
SelectedRegion * pSelectedRegion
Holds one item with description and time range for the UndoManager.