Audacity  2.2.2
Dependencies.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4  Audacity(R) is copyright (c) 1999-2008 Audacity Team.
5  License: GPL v2. See License.txt.
6 
7  Dependencies.cpp
8 
9  Dominic Mazzoni
10  Leland Lucius
11  Markus Meyer
12  LRN
13  Michael Chinen
14  Vaughan Johnson
15 
16  The primary function provided in this source file is
17  ShowDependencyDialogIfNeeded. It checks a project to see if
18  any of its WaveTracks contain AliasBlockFiles; if so it
19  presents a dialog to the user and lets them copy those block
20  files into the project, making it self-contained.
21 
22 ********************************************************************//*****************************************************************//********************************************************************/
36 
37 #include "Audacity.h"
38 #include "Dependencies.h"
39 
40 #include <wx/button.h>
41 #include <wx/defs.h>
42 #include <wx/dialog.h>
43 #include <wx/filename.h>
44 #include <wx/hashmap.h>
45 #include <wx/progdlg.h>
46 #include <wx/choice.h>
47 #include <wx/clipbrd.h>
48 #include <wx/dataobj.h>
49 
50 #include "BlockFile.h"
51 #include "DirManager.h"
52 #include "Internat.h"
53 #include "Prefs.h"
54 #include "Project.h"
55 #include "Sequence.h"
56 #include "ShuttleGui.h"
57 #include "WaveTrack.h"
58 #include "WaveClip.h"
59 #include "widgets/ErrorDialog.h"
60 
61 #include <unordered_map>
62 
63 using AliasedFileHash = std::unordered_map<wxString, AliasedFile*>;
64 
65 // These two hash types are used only inside short scopes
66 // so it is safe to key them by plain pointers.
67 using ReplacedBlockFileHash = std::unordered_map<BlockFile *, BlockFilePtr>;
68 using BoolBlockFileHash = std::unordered_map<BlockFile *, bool>;
69 
70 // Given a project, returns a single array of all SeqBlocks
71 // in the current set of tracks. Enumerating that array allows
72 // you to process all block files in the current set.
73 static void GetAllSeqBlocks(AudacityProject *project,
74  BlockPtrArray *outBlocks)
75 {
76  TrackList *tracks = project->GetTracks();
77  TrackListIterator iter(tracks);
78  Track *t = iter.First();
79  while (t) {
80  if (t->GetKind() == Track::Wave) {
81  WaveTrack *waveTrack = static_cast<WaveTrack*>(t);
82  for(const auto &clip : waveTrack->GetAllClips()) {
83  Sequence *sequence = clip->GetSequence();
84  BlockArray &blocks = sequence->GetBlockArray();
85  int i;
86  for (i = 0; i < (int)blocks.size(); i++)
87  outBlocks->push_back(&blocks[i]);
88  }
89  }
90  t = iter.Next();
91  }
92 }
93 
94 // Given an Audacity project and a hash mapping aliased block
95 // files to un-aliased block files, walk through all of the
96 // tracks and replace each aliased block file with its replacement.
97 // Note that this code respects reference-counting and thus the
98 // process of making a project self-contained is actually undoable.
99 static void ReplaceBlockFiles(BlockPtrArray &blocks,
100  ReplacedBlockFileHash &hash)
101 // NOFAIL-GUARANTEE
102 {
103  for (const auto &pBlock : blocks) {
104  auto &f = pBlock->f;
105  const auto src = &*f;
106  if (hash.count( src ) > 0) {
107  const auto &dst = hash[src];
108  f = dst;
109  }
110  }
111 }
112 
114  AliasedFileArray &outAliasedFiles)
115 {
116  sampleFormat format = project->GetDefaultFormat();
117 
118  BlockPtrArray blocks;
119  GetAllSeqBlocks(project, &blocks);
120 
121  AliasedFileHash aliasedFileHash;
122  BoolBlockFileHash blockFileHash;
123 
124  for (const auto &blockFile : blocks) {
125  const auto &f = blockFile->f;
126  if (f->IsAlias() && (blockFileHash.count( &*f ) == 0))
127  {
128  // f is an alias block we have not yet counted.
129  blockFileHash[ &*f ] = true; // Don't count the same blockfile twice.
130  auto aliasBlockFile = static_cast<AliasBlockFile*>( &*f );
131  const wxFileName &fileName = aliasBlockFile->GetAliasedFileName();
132 
133  // In DirManager::ProjectFSCK(), if the user has chosen to
134  // "Replace missing audio with silence", the code there puts in an empty wxFileName.
135  // Don't count those in dependencies.
136  if (!fileName.IsOk())
137  continue;
138 
139  const wxString &fileNameStr = fileName.GetFullPath();
140  auto blockBytes = (SAMPLE_SIZE(format) *
141  aliasBlockFile->GetLength());
142  if (aliasedFileHash.count(fileNameStr) > 0)
143  // Already put this AliasBlockFile in aliasedFileHash.
144  // Update block count.
145  aliasedFileHash[fileNameStr]->mByteCount += blockBytes;
146  else
147  {
148  // Haven't counted this AliasBlockFile yet.
149  // Add to return array and internal hash.
150 
151  // PRL: do this in two steps so that we move instead of copying.
152  // We don't have a moving push_back in all compilers.
153  outAliasedFiles.push_back(AliasedFile{});
154  outAliasedFiles.back() =
155  AliasedFile {
156  wxFileNameWrapper { fileName },
157  wxLongLong(blockBytes), fileName.FileExists()
158  };
159  aliasedFileHash[fileNameStr] = &outAliasedFiles.back();
160  }
161  }
162  }
163 }
164 
165 // Given a project and a list of aliased files that should no
166 // longer be external dependencies (selected by the user), replace
167 // all of those alias block files with disk block files.
168 static void RemoveDependencies(AudacityProject *project,
169  AliasedFileArray &aliasedFiles)
170 // STRONG-GUARANTEE
171 {
172  const auto &dirManager = project->GetDirManager();
173 
174  ProgressDialog progress
175  (_("Removing Dependencies"),
176  _("Copying audio data into project..."));
177  auto updateResult = ProgressResult::Success;
178 
179  // Hash aliasedFiles based on their full paths and
180  // count total number of bytes to process.
181  AliasedFileHash aliasedFileHash;
182  wxLongLong totalBytesToProcess = 0;
183  for (auto &aliasedFile : aliasedFiles) {
184  totalBytesToProcess += aliasedFile.mByteCount;
185  const wxString &fileNameStr = aliasedFile.mFileName.GetFullPath();
186  aliasedFileHash[fileNameStr] = &aliasedFile;
187  }
188 
189  BlockPtrArray blocks;
190  GetAllSeqBlocks(project, &blocks);
191 
192  const sampleFormat format = project->GetDefaultFormat();
193  ReplacedBlockFileHash blockFileHash;
194  wxLongLong completedBytes = 0;
195  for (const auto blockFile : blocks) {
196  const auto &f = blockFile->f;
197  if (f->IsAlias() && (blockFileHash.count( &*f ) == 0))
198  {
199  // f is an alias block we have not yet processed.
200  auto aliasBlockFile = static_cast<AliasBlockFile*>( &*f );
201  const wxFileName &fileName = aliasBlockFile->GetAliasedFileName();
202  const wxString &fileNameStr = fileName.GetFullPath();
203 
204  if (aliasedFileHash.count(fileNameStr) == 0)
205  // This aliased file was not selected to be replaced. Skip it.
206  continue;
207 
208  // Convert it from an aliased file to an actual file in the project.
209  auto len = aliasBlockFile->GetLength();
210  BlockFilePtr newBlockFile;
211  {
212  SampleBuffer buffer(len, format);
213  // We tolerate exceptions from NewSimpleBlockFile and so we
214  // can allow exceptions from ReadData too
215  f->ReadData(buffer.ptr(), format, 0, len);
216  newBlockFile =
217  dirManager->NewSimpleBlockFile(buffer.ptr(), len, format);
218  }
219 
220  // Update our hash so we know what block files we've done
221  blockFileHash[ &*f ] = newBlockFile;
222 
223  // Update the progress bar
224  completedBytes += SAMPLE_SIZE(format) * len;
225  updateResult = progress.Update(completedBytes, totalBytesToProcess);
226  if (updateResult != ProgressResult::Success)
227  // leave the project unchanged
228  return;
229  }
230  }
231 
232  // COMMIT OPERATIONS needing NOFAIL-GUARANTEE:
233 
234  // Above, we created a SimpleBlockFile contained in our project
235  // to go with each AliasBlockFile that we wanted to migrate.
236  // However, that didn't actually change any references to these
237  // blockfiles in the Sequences, so we do that next...
238  ReplaceBlockFiles(blocks, blockFileHash);
239 }
240 
241 //
242 // DependencyDialog
243 //
244 
245 class DependencyDialog final : public wxDialogWrapper
246 {
247 public:
248  DependencyDialog(wxWindow *parent,
249  wxWindowID id,
250  AudacityProject *project,
251  AliasedFileArray &aliasedFiles,
252  bool isSaving);
253 
254 private:
255  void PopulateList();
256  void PopulateOrExchange(ShuttleGui & S);
257 
258  // event handlers
259  void OnCancel(wxCommandEvent& evt);
260  void OnCopySelectedFiles(wxCommandEvent &evt);
261  void OnList(wxListEvent &evt);
262  void OnSize(wxSizeEvent &evt);
263  void OnNo(wxCommandEvent &evt);
264  void OnYes(wxCommandEvent &evt);
265  void OnRightClick(wxListEvent& evt);
266  void OnCopyToClipboard( wxCommandEvent& evt );
267 
268 
269  void SaveFutureActionChoice();
270 
271 
274  bool mIsSaving;
277 
278  wxStaticText *mMessageStaticText;
279  wxListCtrl *mFileListCtrl;
283 
284 public:
285  DECLARE_EVENT_TABLE()
286 };
287 
288 enum {
289  FileListID = 6000,
293 };
294 
295 BEGIN_EVENT_TABLE(DependencyDialog, wxDialogWrapper)
297  EVT_LIST_ITEM_DESELECTED(FileListID, DependencyDialog::OnList)
298  EVT_LIST_ITEM_RIGHT_CLICK(FileListID, DependencyDialog::OnRightClick )
300  EVT_SIZE(DependencyDialog::OnSize)
301  EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) // mIsSaving ? "Cancel Save" : "Save Without Copying"
302  EVT_BUTTON(wxID_YES, DependencyDialog::OnYes) // "Copy All Files (Safer)"
303  EVT_BUTTON(wxID_CANCEL, DependencyDialog::OnCancel) // "Cancel Save"
304  EVT_MENU(CopyNamesToClipboardID,DependencyDialog::OnCopyToClipboard)
306 
307 DependencyDialog::DependencyDialog(wxWindow *parent,
308  wxWindowID id,
309  AudacityProject *project,
310  AliasedFileArray &aliasedFiles,
311  bool isSaving)
312 : wxDialogWrapper(parent, id, _("Project Depends on Other Audio Files"),
313  wxDefaultPosition, wxDefaultSize,
314  (isSaving ?
315  (wxDEFAULT_DIALOG_STYLE & ~wxCLOSE_BOX) : // no close box when saving
316  wxDEFAULT_DIALOG_STYLE) |
317  wxRESIZE_BORDER),
318  mProject(project),
319  mAliasedFiles(aliasedFiles),
320  mIsSaving(isSaving),
321  mHasMissingFiles(false),
322  mHasNonMissingFiles(false),
323  mMessageStaticText(NULL),
324  mFileListCtrl(NULL),
325  mCopySelectedFilesButton(NULL),
326  mCopyAllFilesButton(NULL),
327  mFutureActionChoice(NULL)
328 {
329  SetName(GetTitle());
330  ShuttleGui S(this, eIsCreating);
331  PopulateOrExchange(S);
332 }
333 
334 static const wxString kStdMsg()
335 {
336  return
337 _("Copying these files into your project will remove this dependency.\
338 \nThis is safer, but needs more disk space.");
339 }
340 
341 static const wxString kExtraMsgForMissingFiles()
342 {
343  return
344 _("\n\nFiles shown as MISSING have been moved or deleted and cannot be copied.\
345 \nRestore them to their original location to be able to copy into project.");
346 }
347 
349 {
350  S.SetBorder(5);
351  S.StartVerticalLay();
352  {
354 
355  S.StartStatic(_("Project Dependencies"),1);
356  {
358  mFileListCtrl->InsertColumn(0, _("Audio File"));
359  mFileListCtrl->SetColumnWidth(0, 220);
360  mFileListCtrl->InsertColumn(1, _("Disk Space"));
361  mFileListCtrl->SetColumnWidth(1, 120);
362  PopulateList();
363 
366  _("Copy Selected Files"),
367  wxALIGN_LEFT);
368  mCopySelectedFilesButton->Enable(
369  mFileListCtrl->GetSelectedItemCount() > 0);
370  mCopySelectedFilesButton->SetDefault();
371  mCopySelectedFilesButton->SetFocus();
372  }
373  S.EndStatic();
374 
375  S.StartHorizontalLay(wxALIGN_CENTRE,0);
376  {
377  if (mIsSaving) {
378  S.Id(wxID_CANCEL).AddButton(_("Cancel Save"));
379  S.Id(wxID_NO).AddButton(_("Save Without Copying"));
380  }
381  else
382  S.Id(wxID_NO).AddButton(_("Do Not Copy"));
383 
385  S.Id(wxID_YES).AddButton(_("Copy All Files (Safer)"));
386 
387  // Enabling mCopyAllFilesButton is also done in PopulateList,
388  // but at its call above, mCopyAllFilesButton does not yet exist.
390  }
391  S.EndHorizontalLay();
392 
393  if (mIsSaving)
394  {
395  S.StartHorizontalLay(wxALIGN_LEFT,0);
396  {
397  wxArrayString choices;
398  /*i18n-hint: One of the choices of what you want Audacity to do when
399  * Audacity finds a project depends on another file.*/
400  choices.Add(_("Ask me"));
401  choices.Add(_("Always copy all files (safest)"));
402  choices.Add(_("Never copy any files"));
405  _("Whenever a project depends on other files:"),
406  _("Ask me"), &choices);
407  }
408  S.EndHorizontalLay();
409  } else
410  {
411  mFutureActionChoice = NULL;
412  }
413  }
414  S.EndVerticalLay();
415  Layout();
416  Fit();
417  SetMinSize(GetSize());
418  Center();
419 }
420 
422 {
423  mFileListCtrl->DeleteAllItems();
424 
425  mHasMissingFiles = false;
426  mHasNonMissingFiles = false;
427  long i = 0;
428  for (const auto &aliasedFile : mAliasedFiles) {
429  const wxFileName &fileName = aliasedFile.mFileName;
430  wxLongLong byteCount = (aliasedFile.mByteCount * 124) / 100;
431  bool bOriginalExists = aliasedFile.mbOriginalExists;
432 
433  if (bOriginalExists)
434  {
435  mFileListCtrl->InsertItem(i, fileName.GetFullPath());
436  mHasNonMissingFiles = true;
437  mFileListCtrl->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
438  }
439  else
440  {
441  mFileListCtrl->InsertItem(i,
442  wxString::Format( _("MISSING %s"), fileName.GetFullPath() ) );
443  mHasMissingFiles = true;
444  mFileListCtrl->SetItemState(i, 0, wxLIST_STATE_SELECTED); // Deselect.
445  mFileListCtrl->SetItemTextColour(i, *wxRED);
446  }
447  mFileListCtrl->SetItem(i, 1, Internat::FormatSize(byteCount));
448  mFileListCtrl->SetItemData(i, long(bOriginalExists));
449 
450  ++i;
451  }
452 
453  wxString msg = kStdMsg();
454  if (mHasMissingFiles)
455  msg += kExtraMsgForMissingFiles();
456  mMessageStaticText->SetLabel(msg);
457 
460 }
461 
462 void DependencyDialog::OnList(wxListEvent &evt)
463 {
465  return;
466 
467  wxString itemStr = evt.GetText();
468  if (evt.GetData() == 0)
469  // This list item is one of mAliasedFiles for which
470  // the original is missing, i.e., moved or deleted.
471  // wxListCtrl does not provide for items that are not
472  // allowed to be selected, so always deselect these items.
473  mFileListCtrl->SetItemState(evt.GetIndex(), 0, wxLIST_STATE_SELECTED); // Deselect.
474 
475  mCopySelectedFilesButton->Enable(
476  mFileListCtrl->GetSelectedItemCount() > 0);
477 }
478 
479 void DependencyDialog::OnSize(wxSizeEvent &evt)
480 {
481  int fileListCtrlWidth, fileListCtrlHeight;
482  mFileListCtrl->GetSize(&fileListCtrlWidth, &fileListCtrlHeight);
483 
484  // File path is column 0. File size is column 1.
485  // File size column is always 120 px wide.
486  // Also subtract 8 from file path column width for borders.
487  mFileListCtrl->SetColumnWidth(0, fileListCtrlWidth - 120 - 8);
488  mFileListCtrl->SetColumnWidth(1, 120);
489  wxDialogWrapper::OnSize(evt);
490 }
491 
492 void DependencyDialog::OnNo(wxCommandEvent & WXUNUSED(event))
493 {
495  EndModal(wxID_NO);
496 }
497 
498 void DependencyDialog::OnYes(wxCommandEvent & WXUNUSED(event))
499 {
501  EndModal(wxID_YES);
502 }
503 
504 void DependencyDialog::OnCopySelectedFiles(wxCommandEvent & WXUNUSED(event))
505 {
506  AliasedFileArray aliasedFilesToDelete, remainingAliasedFiles;
507 
508  long i = 0;
509  for( const auto &file : mAliasedFiles ) {
510  if (mFileListCtrl->GetItemState(i, wxLIST_STATE_SELECTED))
511  aliasedFilesToDelete.push_back( file );
512  else
513  remainingAliasedFiles.push_back( file );
514  ++i;
515  }
516 
517  // provides STRONG-GUARANTEE
518  RemoveDependencies(mProject, aliasedFilesToDelete);
519 
520  // COMMIT OPERATIONS needing NOFAIL-GUARANTEE:
521  mAliasedFiles.swap( remainingAliasedFiles );
522  PopulateList();
523 
524  if (mAliasedFiles.empty() || !mHasNonMissingFiles)
525  {
527  EndModal(wxID_NO); // Don't need to remove dependencies
528  }
529 }
530 
531 void DependencyDialog::OnRightClick( wxListEvent& event)
532 {
533  static_cast<void>(event);
534  wxMenu menu;
535  menu.Append(CopyNamesToClipboardID, _("&Copy Names to Clipboard"));
536  PopupMenu(&menu);
537 }
538 
539 void DependencyDialog::OnCopyToClipboard( wxCommandEvent& evt )
540 {
541  static_cast<void>(evt);
542  wxString Files = "";
543  for (const auto &aliasedFile : mAliasedFiles) {
544  const wxFileName & fileName = aliasedFile.mFileName;
545  wxLongLong byteCount = (aliasedFile.mByteCount * 124) / 100;
546  bool bOriginalExists = aliasedFile.mbOriginalExists;
547  // All fields quoted, as e.g. size may contain a comma in the number.
548  Files += wxString::Format( "\"%s\", \"%s\", \"%s\"\n",
549  fileName.GetFullPath(),
550  Internat::FormatSize( byteCount),
551  bOriginalExists ? "OK":"Missing" );
552  }
553 
554  // copy data onto clipboard
555  if (wxTheClipboard->Open()) {
556  // Clipboard owns the data you give it
557  wxTheClipboard->SetData(safenew wxTextDataObject(Files));
558  wxTheClipboard->Close();
559  }
560 }
561 
562 void DependencyDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
563 {
564  if (mIsSaving)
565  {
566  int ret = AudacityMessageBox(
567  _("If you proceed, your project will not be saved to disk. Is this what you want?"),
568  _("Cancel Save"), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT, this);
569  if (ret != wxYES)
570  return;
571  }
572 
573  EndModal(wxID_CANCEL);
574 }
575 
577 {
579  {
580  wxString savePref;
581  int sel = mFutureActionChoice->GetSelection();
582  switch (sel)
583  {
584  case 1: savePref = wxT("copy"); break;
585  case 2: savePref = wxT("never"); break;
586  default: savePref = wxT("ask");
587  }
588  gPrefs->Write(wxT("/FileFormats/SaveProjectWithDependencies"),
589  savePref);
590  gPrefs->Flush();
591  }
592 }
593 
594 // Checks for alias block files, modifies the project if the
595 // user requests it, and returns true if the user continues.
596 // Returns false only if the user clicks Cancel.
598  bool isSaving)
599 {
600  AliasedFileArray aliasedFiles;
601  FindDependencies(project, aliasedFiles);
602 
603  if (aliasedFiles.empty()) {
604  if (!isSaving)
605  {
606  wxString msg =
607 _("Your project is currently self-contained; it does not depend on any external audio files. \
608 \n\nIf you change the project to a state that has external dependencies on imported \
609 files, it will no longer be self-contained. If you then Save without copying those files in, \
610 you may lose data.");
611  AudacityMessageBox(msg,
612  _("Dependency Check"),
613  wxOK | wxICON_INFORMATION,
614  project);
615  }
616  return true; // Nothing to do.
617  }
618 
619  if (isSaving)
620  {
621  wxString action =
622  gPrefs->Read(
623  wxT("/FileFormats/SaveProjectWithDependencies"),
624  wxT("ask"));
625  if (action == wxT("copy"))
626  {
627  // User always wants to remove dependencies
628  RemoveDependencies(project, aliasedFiles);
629  return true;
630  }
631  if (action == wxT("never"))
632  // User never wants to remove dependencies
633  return true;
634  }
635 
636  DependencyDialog dlog(project, -1, project, aliasedFiles, isSaving);
637  int returnCode = dlog.ShowModal();
638  if (returnCode == wxID_CANCEL)
639  return false;
640  else if (returnCode == wxID_YES)
641  RemoveDependencies(project, aliasedFiles);
642 
643  return true;
644 }
645 
void OnYes(wxCommandEvent &evt)
static wxString FormatSize(wxLongLong size)
Convert a number to a string while formatting it in bytes, KB, MB, GB.
Definition: Internat.cpp:191
void OnCancel(wxCommandEvent &evt)
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
A list of TrackListNode items.
Definition: Track.h:618
void FindDependencies(AudacityProject *project, AliasedFileArray &outAliasedFiles)
DependencyDialog(wxWindow *parent, wxWindowID id, AudacityProject *project, AliasedFileArray &aliasedFiles, bool isSaving)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
ProgressDialog Class.
A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interfac...
Definition: Sequence.h:54
bool ShowDependencyDialogIfNeeded(AudacityProject *project, bool isSaving)
BlockArray & GetBlockArray()
Definition: Sequence.h:194
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
void OnNo(wxCommandEvent &evt)
void PopulateOrExchange(ShuttleGui &S)
IteratorRange< AllClipsIterator > GetAllClips()
Definition: WaveTrack.h:435
int AudacityMessageBox(const wxString &message, const wxString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: ErrorDialog.h:92
#define safenew
Definition: Audacity.h:230
static void GetAllSeqBlocks(AudacityProject *project, BlockPtrArray *outBlocks)
virtual int GetKind() const
Definition: Track.h:329
void EndHorizontalLay()
const std::shared_ptr< DirManager > & GetDirManager()
Definition: Project.cpp:1422
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:176
void EndVerticalLay()
std::vector< SeqBlock * > BlockPtrArray
Definition: Sequence.h:52
const wxFileName & GetAliasedFileName() const
Definition: BlockFile.h:278
void OnRightClick(wxListEvent &evt)
int format
Definition: ExportPCM.cpp:56
static void RemoveDependencies(AudacityProject *project, AliasedFileArray &aliasedFiles)
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
wxListCtrl * AddListControlReportMode()
Definition: ShuttleGui.cpp:689
std::unordered_map< wxString, AliasedFile * > AliasedFileHash
wxChoice * AddChoice(const wxString &Prompt, const wxString &Selected, const wxArrayString *pChoices)
Definition: ShuttleGui.cpp:371
void OnCopySelectedFiles(wxCommandEvent &evt)
sampleFormat
Definition: Types.h:188
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
ShuttleGui & Id(int id)
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:101
ProgressResult Update(int value, const wxString &message=wxEmptyString)
std::list< AliasedFile > AliasedFileArray
Definition: Dependencies.h:53
std::unordered_map< BlockFile *, bool > BoolBlockFileHash
void OnList(wxListEvent &evt)
samplePtr ptr() const
Definition: SampleFormat.h:81
virtual Track * First(TrackList *val=nullptr)
Definition: Track.cpp:418
sampleFormat GetDefaultFormat()
Definition: Project.h:197
void OnSize(wxSizeEvent &evt)
void SaveFutureActionChoice()
wxChoice * mFutureActionChoice
DependencyDialog shows dependencies of an AudacityProject on AliasedFile s.
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
wxListCtrl * mFileListCtrl
An iterator for a TrackList.
Definition: Track.h:401
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
std::unordered_map< BlockFile *, BlockFilePtr > ReplacedBlockFileHash
static const wxString kStdMsg()
static const wxString kExtraMsgForMissingFiles()
An audio file that is referenced (pointed into) directly from an Audacity .aup file rather thna Audac...
Definition: Dependencies.h:24
virtual Track * Next(bool skiplinked=false)
Definition: Track.cpp:460
A BlockFile that refers to data in an existing file.
Definition: BlockFile.h:251
wxStaticText * AddVariableText(const wxString &Str, bool bCenter=false, int PositionFlags=0)
Definition: ShuttleGui.cpp:414
wxStaticBox * StartStatic(const wxString &Str, int iProp=0)
Definition: ShuttleGui.cpp:763
AudacityProject * mProject
wxButton * mCopySelectedFilesButton
void OnCopyToClipboard(wxCommandEvent &evt)
wxStaticText * mMessageStaticText
END_EVENT_TABLE()
static void ReplaceBlockFiles(BlockPtrArray &blocks, ReplacedBlockFileHash &hash)
TrackList * GetTracks()
Definition: Project.h:192
wxButton * mCopyAllFilesButton
void SetBorder(int Border)
Definition: ShuttleGui.h:286
AliasedFileArray & mAliasedFiles
wxButton * AddButton(const wxString &Text, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:341
EVT_LIST_ITEM_SELECTED(CurvesListID, EditCurvesDialog::OnListSelectionChange) EVT_LIST_ITEM_DESELECTED(CurvesListID
Constructor.
void StartVerticalLay(int iProp=1)