1#include "../AdornedRulerPanel.h" 
    2#include "../Clipboard.h" 
    3#include "../CommonCommandFlags.h" 
    5#include "../MenuCreator.h" 
   12#include "../ProjectWindows.h" 
   13#include "../ProjectWindows.h" 
   14#include "../SelectUtilities.h" 
   17#include "../TrackPanel.h" 
   28#include "../prefs/PrefsDialog.h" 
   29#include "../prefs/TracksBehaviorsPrefs.h" 
   30#include "../tracks/labeltrack/ui/LabelTrackView.h" 
   31#include "../tracks/playabletrack/wavetrack/ui/WaveChannelView.h" 
   33#include "../AudioPasteDialog.h" 
   39#include <wx/clipbrd.h> 
   60         if (view.PasteSelectedText( 
project, selectedRegion.t0(),
 
   61                                            selectedRegion.t1() ))
 
   64               .
PushState(
XO(
"Pasted text from the clipboard"), 
XO(
"Paste"));
 
   68            if (view.CalcCursorX( 
project, &x )) {
 
   69               viewport.ScrollIntoView(x);
 
   83         trackPanel.Refresh(
false);
 
   95      const auto samplesCount =
 
   97      result += samplesCount.as_long_long() *
 
  105   BlockArray::size_type result{};
 
  113   for (
auto track : src) {
 
  115         track->Copy(track->GetStartTime(), track->GetEndTime(), 
false);
 
  116      pTrack->MoveTo(track->GetStartTime());
 
  117      if (
const auto waveTrack = 
dynamic_cast<WaveTrack*
>(pTrack.get()))
 
  134   assert(
tracks.Selected().empty());
 
  136   Track* pFirstNewTrack = NULL;
 
  137   for (
auto pClip : src) {
 
  140         pFirstNewTrack = pNewTrack.get();
 
  149   const double srcTempo =
 
  150      pFirstNewTrack ? 
GetProjectTempo(*pFirstNewTrack).value_or(projTempo) :
 
  155   const double quantT0 = 
QUANTIZED_TIME(t0 * srcTempo / projTempo, projRate);
 
  156   const double quantT1 = 
QUANTIZED_TIME(t1 * srcTempo / projTempo, projRate);
 
  157   selectedRegion.setTimes(
 
  165   if (pFirstNewTrack) {
 
  174   return std::any_of(range.begin(), range.end(),
 
  176         return WaveTrackUtilities::HasHiddenData(*pTrack);
 
  195   if (trackPanel.IsMouseCaptured()) {
 
  203   auto t = *
tracks.Selected().begin();
 
  223   if (trackPanel.IsMouseCaptured()) {
 
  231   auto t = *
tracks.Selected().begin();
 
  241   if (wxTheClipboard->Open())
 
  246      const auto success = wxTheClipboard->SetData(
safenew wxTextDataObject);
 
  248      wxTheClipboard->Clear();
 
  249      wxTheClipboard->Close();
 
  269      if (view.CutSelectedText( context.
project )) {
 
  270         trackPanel.Refresh(
false);
 
  279      if (view.CutSelectedText(context.
project)) {
 
  280         trackPanel.Refresh(
false);
 
  289   auto &newClipboard = *pNewClipboard;
 
  295         auto dest = n.
Cut(selectedRegion.t0(), selectedRegion.t1());
 
  296         newClipboard.Add(dest);
 
  301            auto dest = n.
Copy(selectedRegion.t0(), selectedRegion.t1());
 
  302            newClipboard.Add(dest);
 
  309       std::move( newClipboard ),
 
  326      [&](
auto &&fallthrough){ 
return [&](
WaveTrack &wt) {
 
  328            wt.ClearAndAddCutLine(selectedRegion.t0(), selectedRegion.t1());
 
  334            n.
Clear(selectedRegion.t0(), selectedRegion.t1());
 
  338   selectedRegion.collapseToT0();
 
  345   ruler.DrawOverlays( 
true );
 
  355      if (!n->SupportsBasicEditing())
 
  358         n->Clear(selectedRegion.t0(), selectedRegion.t1());
 
  362   double seconds = selectedRegion.
duration();
 
  364   selectedRegion.collapseToT0();
 
  367      XO(
"Deleted %.2f seconds at t=%.2f")
 
  368         .
Format( seconds, selectedRegion.t0()),
 
  384      if (view.CopySelectedText( context.
project )) {
 
  393      if (view.CopySelectedText(context.
project)) {
 
  402   auto &newClipboard = *pNewClipboard;
 
  404   for (
auto n : 
tracks.Selected()) {
 
  405      if (n->SupportsBasicEditing()) {
 
  406         auto dest = n->Copy(selectedRegion.t0(), selectedRegion.t1());
 
  407         newClipboard.Add(dest);
 
  412   clipboard.Assign( std::move( newClipboard ),
 
  413      selectedRegion.t0(), selectedRegion.t1(), 
project.shared_from_this() );
 
  416   trackPanel.Refresh(
false);
 
  421   double sel0 = 0.0, sel1 = 0.0;
 
  426      auto &selectedRegion = *pRegion;
 
  427      sel0 = selectedRegion.t0();
 
  428      sel1 = selectedRegion.t1();
 
  434      sel0 = selectedRegion.
t0();
 
  435      sel1 = selectedRegion.t1();
 
  438   return { sel0, sel1 };
 
  447   auto discardTrimmed = 
false;
 
  448   if (&context.
project != &*clipboard.Project().lock()) {
 
  450      if (waveClipCopyPolicy == 
wxT(
"Ask") &&
 
  457         const auto result = audioPasteDialog.ShowModal();
 
  458         if(result == wxID_CANCEL)
 
  463      else if(waveClipCopyPolicy == 
wxT(
"Discard"))
 
  464         discardTrimmed = 
true;
 
  467   std::shared_ptr<const TrackList> srcTracks;
 
  471      srcTracks = clipboard.GetTracks().shared_from_this();
 
  482   auto &pSampleBlockFactory = trackFactory.GetSampleBlockFactory();
 
  483   return pSampleBlockFactory->Subscribe([
 
  486      copyStartTime = std::chrono::system_clock::now(),
 
  487      progressDialog = std::shared_ptr<BasicUI::ProgressDialog>()]
 
  489         using namespace std::chrono;
 
  490         constexpr auto ProgressDialogShowDelay = milliseconds { 100 };
 
  492         if(!progressDialog) {
 
  493            if(duration_cast<milliseconds>(system_clock::now() - copyStartTime) >= ProgressDialogShowDelay)
 
  497            progressDialog->Poll(nCopied, toCopy);
 
  520   auto dstRange = dstTracks.
Selected();
 
  521   if (dstRange.size() == 1)
 
  524      dstRange = dstTracks.
Any().StartingWith(*dstRange.begin());
 
  525   auto srcRange = srcTracks.
Any();
 
  526   while (!(dstRange.empty() || srcRange.empty())) {
 
  527      auto &dst = **dstRange.begin();
 
  528      auto &src = **srcRange.begin();
 
  534      result.emplace_back(&dst, &src);
 
  539   if (!srcRange.empty())
 
  548   if (wxTheClipboard->IsSupported(wxDF_FILENAME) && wxTheClipboard->Open())
 
  550      wxFileDataObject data;
 
  551      const auto hadData = wxTheClipboard->GetData(data);
 
  552      wxTheClipboard->Close();
 
  567   if (clipboard.GetTracks().empty())
 
  581         project, *srcTracks, clipboard.T0(), clipboard.T1());
 
  588   auto newT1 = t0 + clipboard.Duration();
 
  592   bool bPastedSomething = 
false;
 
  596   if (correspondence.empty()) {
 
  597      if (
tracks.Selected().size() == 1)
 
  599"The content you are trying to paste will span across more tracks than you " 
  600"currently have available. Add more tracks and try again.")
 
  604"There are not enough tracks selected to accommodate your copied content. " 
  605"Select additional tracks and try again.")
 
  609   auto iPair = correspondence.begin();
 
  610   const auto endPair = correspondence.cend();
 
  613   auto next = 
tracks.begin();
 
  614   for (
auto range = 
tracks.Any(); !range.empty();
 
  618      if (iPair == endPair)
 
  622      next = 
tracks.Find(*group.rbegin());
 
  625      if (!group.contains(iPair->first))
 
  630      for (
auto member : group) {
 
  631         if (iPair == endPair || member != iPair->first) {
 
  634               if (t1 != newT1 && t1 <= member->GetEndTime()) {
 
  635                  member->SyncLockAdjust(t1, newT1);
 
  636                  bPastedSomething = 
true;
 
  645            const auto src = (iPair++)->second;
 
  648                  bPastedSomething = 
true;
 
  651                  const auto newClipOnPaste =
 
  659                  const auto merge = newClipOnPaste ? false : 
true;
 
  660                  const auto preserveExistingBoundaries = newClipOnPaste ? false : 
true;
 
  661                  auto clearByTrimming = newClipOnPaste ? true : 
false;
 
  662                  if(src->NChannels() == 1 && wn.
NChannels() == 2)
 
  666                     const auto pastedTrack = std::static_pointer_cast<WaveTrack>(src->Duplicate());
 
  667                     pastedTrack->MonoToStereo();
 
  669                        t0, t1, *pastedTrack,
 
  670                        preserveExistingBoundaries, merge, &warper,
 
  676                        t0, t1, *
static_cast<const WaveTrack*
>(src),
 
  677                        preserveExistingBoundaries, merge, &warper,
 
  686                  ln.ShiftLabelsOnInsert( clipboard.Duration(), t0 );
 
  688                  bPastedSomething |= ln.PasteOver(t0, *src);
 
  691                  bPastedSomething = 
true;
 
  702   if (bPastedSomething) {
 
  710         const auto offset = srcTracks->GetEndTime() - (t1 - t0);
 
  713            const auto it = std::find_if(correspondence.begin(), correspondence.end(),
 
  714                                   [=](
auto& p) { return p.first == track; });
 
  715            if(it != correspondence.end())
 
  718            track->ShiftBy(t0, offset);
 
  723         .
setTimes( t0, t0 + clipboard.Duration() );
 
  742   auto range = 
tracks.Selected();
 
  743   auto last = *range.rbegin();
 
  744   for (
auto n : range) {
 
  745      if (!n->SupportsBasicEditing())
 
  749      auto dest = n->Copy(selectedRegion.t0(), selectedRegion.t1(), 
false);
 
  750      dest->MoveTo(std::max(selectedRegion.t0(), n->GetStartTime()));
 
  772   auto &newClipboard = *pNewClipboard;
 
  776         auto track = n.
SplitCut(selectedRegion.t0(), selectedRegion.t1());
 
  777         newClipboard.Add(track);
 
  781            auto dest = n.
Copy(selectedRegion.t0(), selectedRegion.t1());
 
  782            n.
Silence(selectedRegion.t0(), selectedRegion.t1());
 
  783            newClipboard.Add(dest);
 
  789   clipboard.Assign(std::move(newClipboard),
 
  790      selectedRegion.t0(), selectedRegion.t1(), 
project.shared_from_this());
 
  793      .
PushState(
XO(
"Cut to clipboard and leave gap"), 
XO(
"Cut and leave gap"));
 
  804         wt.
SplitDelete(selectedRegion.t0(), selectedRegion.t1());
 
  807         if (n.SupportsBasicEditing())
 
  808            n.Silence(selectedRegion.t0(), selectedRegion.t1());
 
  813      XO(
"Split-deleted %.2f seconds at t=%.2f")
 
  814         .
Format(selectedRegion.duration(), selectedRegion.t0()),
 
  828            selectedWaveTracks.begin(), selectedWaveTracks.end(),
 
  830               n->Silence(selectedRegion.t0(), selectedRegion.t1(), child);
 
  836      XO(
"Silenced selected tracks for %.2f seconds at %.2f")
 
  837         .
Format(selectedRegion.duration(), selectedRegion.t0()),
 
  839      XC(
"Silence", 
"command"));
 
  848   if (selectedRegion.isPoint())
 
  853      wt.
Trim(selectedRegion.t0(), selectedRegion.t1());
 
  857      XO(
"Trim selected audio tracks from %.2f seconds to %.2f seconds")
 
  858         .
Format( selectedRegion.t0(), selectedRegion.t1() ),
 
  868      if (
auto pWaveTrack = 
dynamic_cast<WaveTrack*
>(pTrack))
 
  869         pWaveTrack->Split(sel0, sel1);
 
  876         wt->Split(sel0, sel1);
 
  934   auto range = 
tracks.Selected();
 
  935   auto last = *range.rbegin();
 
  936   for (
auto track : range) {
 
  941            const double newt0 = wt.
SnapToSample(selectedRegion.t0());
 
  942            const double newt1 = wt.
SnapToSample(selectedRegion.t1());
 
  945            const auto dest = wt.
Copy(newt0, newt1, 
false);
 
  959            dest = n.Cut(viewInfo.selectedRegion.t0(),
 
  960                   viewInfo.selectedRegion.t1());
 
  962               dest->MoveTo(std::max(0, n.GetOffset()));
 
  986            selectedTracks.begin(), selectedTracks.end(),
 
  989                  selectedRegion.t0(), selectedRegion.t1(), childProgress);
 
  995      XO(
"Joined %.2f seconds at t=%.2f")
 
  996         .
Format(selectedRegion.duration(), selectedRegion.t0()),
 
 1007      wt->Disjoin(selectedRegion.t0(), selectedRegion.t1());
 
 1010      XO(
"Detached %.2f seconds at t=%.2f")
 
 1011         .
Format(selectedRegion.duration(), selectedRegion.t0()),
 
 1032#if defined(__WXGTK__) 
 1040      wxRect r = window.GetRect();
 
 1041      window.SetSize(wxSize(1,1));
 
 1042      window.SetSize(r.GetSize());
 
 1053   auto &selectedRegion = 
project.GetViewInfo().selectedRegion;
 
 1055   if((AudacityProject::msClipT1 - AudacityProject::msClipT0) > 0.0)
 
 1057      selectedRegion.setT1(
 
 1058         selectedRegion.t0() +
 
 1059         (AudacityProject::msClipT1 - AudacityProject::msClipT0));
 
 1080      if ( !range.empty() )
 
 1103      if(viewInfo.selectedRegion.isPoint())
 
 1107      for (
const auto track : selectedTracks)
 
 1109         const auto selectedClips =
 
 1111               viewInfo.selectedRegion.t0(), viewInfo.selectedRegion.t1());
 
 1112         if(selectedClips.size() > 1)
 
 1123   static const auto NotBusyTimeAndTracksFlags =
 
 1127   static constexpr auto redoKey =
 
 1137   static constexpr auto prefKey =
 
 1145   static auto menu = std::shared_ptr{
 
 1178            NotBusyTimeAndTracksFlags, 
wxT(
"Ctrl+D") ),
 
 1181            Menu( 
wxT(
"RemoveSpecial"), 
XXO(
"R&emove Special"),
 
 1185                     NotBusyTimeAndTracksFlags,
 
 1189                     NotBusyTimeAndTracksFlags,
 
 1227                  NotBusyTimeAndTracksFlags, 
wxT(
"Ctrl+Alt+J") )
 
 1250   static const auto flags =
 
 1252   static auto menu = std::shared_ptr{
 
 1303   wxT(
"Optional/Extra/Part1")
 
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Toolkit-neutral facade for basic user interface services.
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()
bool AudioIOBusyPred(const AudacityProject &project)
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & EditableTracksSelectedFlag()
const ReservedCommandFlag & AnyTracksSelectedFlag()
const ReservedCommandFlag & TracksExistFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
bool TimeSelectedPred(const AudacityProject &project)
XXO("&Cut/Copy/Paste Toolbar")
#define QUANTIZED_TIME(time, rate)
audacity::BasicSettings * gPrefs
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 ...
const std::optional< double > & GetProjectTempo(const ChannelGroup &group)
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
std::function< void(double)> ProgressReporter
ChoiceSetting TracksBehaviorsAudioTrackPastePolicy
An AudacityException with no visible message.
bool GetEditClipsCanMove()
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...
virtual size_t NChannels() const =0
Report the number of channels.
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
TemporarySelection temporarySelection
AudacityProject & project
static CommandManager & Get(AudacityProject &project)
void ModifyUndoMenuItems()
A LabelTrack is a Track that holds labels (LabelStruct).
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
Create tracks and modify this track.
void Clear(double t0, double t1) override
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
bool setTimes(double t0, double t1)
Unit slope but with either a jump (pasting more) or a flat interval (pasting less)
bool Import(const FilePath &fileName, bool addToHistory=true)
static ProjectFileManager & Get(AudacityProject &project)
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 ProjectTimeSignature & Get(AudacityProject &project)
Generates classes whose instances register items at construction.
static TrackIterRange< Track > Group(Track &track)
static bool IsSelectedOrSyncLockSelectedP(const Track *pTrack)
static bool IsSelectedOrSyncLockSelected(const Track &track)
bool IsSyncLocked() const
static SyncLockState & Get(AudacityProject &project)
Abstract base class for an object holding data associated with points on a time axis.
virtual void SetSelected(bool s)
virtual Holder PasteInto(AudacityProject &project, TrackList &list) const =0
bool SameKindAs(const Track &track) const
virtual bool SupportsBasicEditing() const
Whether this track type implements cut-copy-paste; by default, true.
R TypeSwitch(const Functions &...functions)
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
static TrackListHolder Create(AudacityProject *pOwner)
auto Any() -> TrackIterRange< TrackType >
static TrackList & Get(AudacityProject &project)
auto Selected() -> TrackIterRange< TrackType >
static TrackPanel & Get(AudacityProject &project)
static UndoManager & Get(AudacityProject &project)
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
void ShowTrack(const Track &track)
static Viewport & Get(AudacityProject &project)
static WaveChannelView & GetFirst(WaveTrack &wt)
Get the view of the first channel.
static WaveTrackFactory & Get(AudacityProject &project)
A Track that contains audio waveform data.
void SplitDelete(double t0, double t1)
void Silence(double t0, double t1, ProgressReporter reportProgress) override
void Trim(double t0, double t1)
Holder SplitCut(double t0, double t1)
size_t NChannels() const override
A constant property.
void ClearAndPaste(double t0, double t1, const WaveTrack &src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=nullptr, bool clearByTrimming=false)
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
double SnapToSample(double t) const
bool ReadBool(const wxString &key, bool defaultValue) const
virtual bool Read(const wxString &key, bool *value) const =0
std::function< void(double)> ProgressReporter
void SplitProgress(ItType first, ItType last, FnType action, ProgressReporter parent)
Helper for the update of a task's progress bar when this task is made of a range's subtasks.
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
void DoSelectAllAudio(AudacityProject &project)
WAVE_TRACK_API void WithClipRenderingProgress(std::function< void(const ProgressReporter &)> action, TranslatableString title=defaultStretchRenderingTitle)
WAVE_TRACK_API size_t CountBlocks(const WaveTrack &track)
WAVE_TRACK_API sampleCount GetSequenceSamplesCount(const WaveTrack &track)
WAVE_TRACK_API void DiscardTrimmed(WaveTrack &track)
Remove hidden audio from all clips.
WAVE_TRACK_API WaveTrack::IntervalConstHolders GetClipsIntersecting(const WaveTrack &track, double t0, double t1)
CommandFlagOptions && DisableDefaultMessage() &&
SelectedRegion * pSelectedRegion
Holds one item with description and time range for the UndoManager.