Audacity  3.0.3
Public Member Functions | Private Member Functions | Private Attributes | List of all members
TagsEditorDialog Class Referencefinal

Derived from ExpandingToolBar, this dialog allows editing of Tags. More...

#include <Tags.h>

Inheritance diagram for TagsEditorDialog:
[legend]
Collaboration diagram for TagsEditorDialog:
[legend]

Public Member Functions

 TagsEditorDialog (wxWindow *parent, const TranslatableString &title, Tags *tags, bool editTitle, bool editTrack)
 
virtual ~TagsEditorDialog ()
 
bool IsEscapeKey (const wxKeyEvent &) override
 
void PopulateOrExchange (ShuttleGui &S)
 
void OnDontShow (wxCommandEvent &Evt)
 
void OnHelp (wxCommandEvent &Evt)
 
bool TransferDataToWindow () override
 
bool TransferDataFromWindow () override
 
- Public Member Functions inherited from wxDialogWrapper
 wxDialogWrapper ()
 
 wxDialogWrapper (wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE, const TranslatableString &name=XO("Dialog"))
 
bool Create (wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE, const TranslatableString &name=XO("Dialog"))
 
void SetTitle (const TranslatableString &title)
 
void SetLabel (const TranslatableString &title)
 
void SetName (const TranslatableString &title)
 
void SetName ()
 
- Public Member Functions inherited from wxTabTraversalWrapper< wxDialog >
 wxTabTraversalWrapper (Args &&... args)
 
 wxTabTraversalWrapper (const wxTabTraversalWrapper &)=delete
 
 wxTabTraversalWrapper (wxTabTraversalWrapper &&)=delete
 
wxTabTraversalWrapperoperator= (const wxTabTraversalWrapper &)=delete
 
wxTabTraversalWrapperoperator= (wxTabTraversalWrapper &&)=delete
 

Private Member Functions

void PopulateGenres ()
 
void SetEditors ()
 
void OnChange (wxGridEvent &event)
 
void OnEdit (wxCommandEvent &event)
 
void OnReset (wxCommandEvent &event)
 
void OnClear (wxCommandEvent &event)
 
void OnLoad (wxCommandEvent &event)
 
void OnSave (wxCommandEvent &event)
 
void OnSaveDefaults (wxCommandEvent &event)
 
void OnAdd (wxCommandEvent &event)
 
void OnRemove (wxCommandEvent &event)
 
void OnOk (wxCommandEvent &event)
 
void DoCancel (bool escKey)
 
void OnCancel (wxCommandEvent &event)
 
void OnKeyDown (wxKeyEvent &event)
 
bool IsWindowRectValid (const wxRect *windowRect) const
 

Private Attributes

TagsmTags
 
bool mEditTitle
 
bool mEditTrack
 
Tags mLocal
 
GridmGrid
 
ComboEditormComboEditor
 
wxGridCellStringRenderer * mStringRenderer
 

Detailed Description

Derived from ExpandingToolBar, this dialog allows editing of Tags.

Definition at line 143 of file Tags.h.

Constructor & Destructor Documentation

◆ TagsEditorDialog()

TagsEditorDialog::TagsEditorDialog ( wxWindow *  parent,
const TranslatableString title,
Tags tags,
bool  editTitle,
bool  editTrack 
)

Definition at line 801 of file Tags.cpp.

806 : wxDialogWrapper(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize,
807  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
808  mTags(tags),
809  mEditTitle(editTitle),
810  mEditTrack(editTrack)
811 {
812  SetName();
813 
814  mGrid = NULL;
815 
816  // Make a local copy of the passed in tags
817  mLocal = *mTags;
818 
819  // Build, size, and position the dialog
820  ShuttleGui S(this, eIsCreating);
822 
824 
825  Layout();
826  Fit();
827  Center();
828  SetSizeHints(GetSize());
829 
830  // Restore the original tags because TransferDataToWindow() will be called again
831  mLocal.Clear();
832  mLocal = *mTags;
833 
834  // Override size and position with last saved
835  wxRect r = GetRect();
836  gPrefs->Read(wxT("/TagsEditorDialog/x"), &r.x, r.x);
837  gPrefs->Read(wxT("/TagsEditorDialog/y"), &r.y, r.y);
838  gPrefs->Read(wxT("/TagsEditorDialog/width"), &r.width, r.width);
839  gPrefs->Read(wxT("/TagsEditorDialog/height"), &r.height, r.height);
840  //On multi-monitor systems, there's a chance the last saved window position is
841  //on a monitor that has been removed or is unavailable.
842  if (IsWindowRectValid(&r))
843  Move(r.GetPosition());
844 
845  SetSize(r.GetSize());
846  Layout();
847 
848  // Resize value column width based on width of columns and the vertical scrollbar
849  wxScrollBar sb(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL);
850  r = mGrid->GetClientRect();
851  r.width -= mGrid->GetColSize(0);
852  r.width -= sb.GetSize().GetWidth();
853  r.width -= 10;
854  r.width -= r.x;
855  mGrid->SetColSize(1, r.width);
856  //Bug 2038
857  mGrid->SetFocus();
858 
859  // Load the genres
860  PopulateGenres();
861 }

References eIsCreating, and gPrefs.

◆ ~TagsEditorDialog()

TagsEditorDialog::~TagsEditorDialog ( )
virtual

Definition at line 863 of file Tags.cpp.

864 {
865  // This DELETE is not needed because wxWidgets owns the grid.
866 // DELETE mGrid;
867 
868 // TODO: Need to figure out if these should be deleted. Looks like the wxGrid
869 // code takes ownership and uses reference counting, but there's been
870 // cases where they show up as memory leaks.
871 // PRL: Fixed the leaks, see commit c87eb0804bc5f40659b133cab6e2ade061959645
872 // DELETE mStringRenderer;
873 // DELETE mComboEditor;
874 }

Member Function Documentation

◆ DoCancel()

void TagsEditorDialog::DoCancel ( bool  escKey)
private

Definition at line 1452 of file Tags.cpp.

1453 {
1454  if (mGrid->IsCellEditControlShown()) {
1455  auto editor = mGrid->GetCellEditor(mGrid->GetGridCursorRow(),
1456  mGrid->GetGridCursorCol());
1457  editor->Reset();
1458  // To avoid memory leak, don't forget DecRef()!
1459  editor->DecRef();
1460  mGrid->HideCellEditControl();
1461 #if defined(__WXMSW__)
1462  return;
1463 #endif
1464  }
1465 
1466  auto focus = wxWindow::FindFocus();
1467  if (escKey && focus == mGrid)
1468  return;
1469 
1470  EndModal(wxID_CANCEL);
1471 }

References mGrid.

Referenced by OnCancel(), and OnKeyDown().

Here is the caller graph for this function:

◆ IsEscapeKey()

bool TagsEditorDialog::IsEscapeKey ( const wxKeyEvent &  )
inlineoverride

Definition at line 156 of file Tags.h.

156 { return false; }

◆ IsWindowRectValid()

bool TagsEditorDialog::IsWindowRectValid ( const wxRect *  windowRect) const
private

Definition at line 1520 of file Tags.cpp.

1521 {
1522  wxDisplay display;
1523  wxPoint topLeft(windowRect->GetTopLeft().x, windowRect->GetTopLeft().y);
1524  wxPoint topRight(windowRect->GetTopRight().x, windowRect->GetTopRight().y);
1525  wxPoint bottomLeft(windowRect->GetBottomLeft().x, windowRect->GetBottomLeft().y);
1526  wxPoint bottomRight(windowRect->GetBottomRight().x, windowRect->GetBottomRight().y);
1527  display.GetFromPoint(topLeft);
1528  if (display.GetFromPoint(topLeft) == -1 &&
1529  display.GetFromPoint(topRight) == -1 &&
1530  display.GetFromPoint(bottomLeft) == -1 &&
1531  display.GetFromPoint(bottomRight) == -1) {
1532  return false;
1533  }
1534 
1535  return true;
1536 }

◆ OnAdd()

void TagsEditorDialog::OnAdd ( wxCommandEvent &  event)
private

Definition at line 1392 of file Tags.cpp.

1393 {
1394  mGrid->AppendRows();
1395 }

References mGrid.

◆ OnCancel()

void TagsEditorDialog::OnCancel ( wxCommandEvent &  event)
private

Definition at line 1447 of file Tags.cpp.

1448 {
1449  DoCancel(false);
1450 }

References DoCancel().

Here is the call graph for this function:

◆ OnChange()

void TagsEditorDialog::OnChange ( wxGridEvent &  event)
private

Definition at line 1095 of file Tags.cpp.

1096 {
1097  static bool ischanging = false;
1098 
1099  // Prevent recursion
1100  if (ischanging) {
1101  return;
1102  }
1103 
1104  event.Skip();
1105 
1106  if (event.GetCol() != 0) {
1107  return;
1108  }
1109 
1110  // Do not permit duplication of any of the tags.
1111  // Tags differing only in case are nondistinct.
1112  auto row = event.GetRow();
1113  const wxString key0 = mGrid->GetCellValue(row, 0).Upper();
1114  auto nn = mGrid->GetNumberRows();
1115  for (decltype(nn) ii = 0; ii < nn; ++ii) {
1116  if (ii == row)
1117  continue;
1118  auto key = mGrid->GetCellValue(ii, 0).Upper();
1119  if (key0.CmpNoCase(key) == 0) {
1120  ischanging = true;
1121  wxBell();
1122  mGrid->SetGridCursor(ii, 0);
1123  event.Veto();
1124  ischanging = false;
1125  break;
1126  }
1127  }
1128 
1129  return;
1130 }

References key, anonymous_namespace{TracksPrefs.cpp}::key0, and mGrid.

◆ OnClear()

void TagsEditorDialog::OnClear ( wxCommandEvent &  event)
private

Definition at line 1230 of file Tags.cpp.

1231 {
1232  mLocal.Clear();
1233 
1235 }

References Tags::Clear(), mLocal, and TransferDataToWindow().

Here is the call graph for this function:

◆ OnDontShow()

void TagsEditorDialog::OnDontShow ( wxCommandEvent &  Evt)

Definition at line 967 of file Tags.cpp.

968 {
969  bool bShow = !Evt.IsChecked();
970  gPrefs->Write(wxT("/AudioFiles/ShowId3Dialog"), bShow );
971  gPrefs->Flush();
972 }

References FileConfig::Flush(), and gPrefs.

Here is the call graph for this function:

◆ OnEdit()

void TagsEditorDialog::OnEdit ( wxCommandEvent &  event)
private

Definition at line 1132 of file Tags.cpp.

1133 {
1134  if (mGrid->IsCellEditControlShown()) {
1135  mGrid->SaveEditControlValue();
1136  mGrid->HideCellEditControl();
1137  }
1138 
1139  wxDialogWrapper dlg(this, wxID_ANY, XO("Edit Genres"),
1140  wxDefaultPosition, wxDefaultSize,
1141  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
1142  dlg.SetName();
1143  wxTextCtrl *tc;
1144 
1145  ShuttleGui S(&dlg, eIsCreating);
1146 
1147  S.StartVerticalLay(true);
1148  {
1149  tc = S.AddTextWindow(wxT(""));
1150  }
1151  S.EndVerticalLay();
1152 
1153  S.AddStandardButtons();
1154 
1155  wxArrayString g;
1156  int cnt = mLocal.GetNumUserGenres();
1157  for (int i = 0; i < cnt; i++) {
1158  g.push_back(mLocal.GetUserGenre(i));
1159  }
1160  std::sort( g.begin(), g.end() );
1161 
1162  for (int i = 0; i < cnt; i++) {
1163  tc->AppendText(g[i] + wxT("\n"));
1164  }
1165 
1166  dlg.Center();
1167  if (dlg.ShowModal() == wxID_CANCEL) {
1168  return;
1169  }
1170 
1171  wxFileName fn(FileNames::DataDir(), wxT("genres.txt"));
1172  wxFile f(fn.GetFullPath(), wxFile::write);
1173  if (!f.IsOpened() || !f.Write(tc->GetValue())) {
1175  XO("Unable to save genre file."),
1176  XO("Reset Genres") );
1177  return;
1178  }
1179 
1180  mLocal.LoadGenres();
1181 
1182  PopulateGenres();
1183 }

References ShuttleGui::AddStandardButtons(), ShuttleGuiBase::AddTextWindow(), AudacityMessageBox(), FileNames::DataDir(), eIsCreating, ShuttleGuiBase::EndVerticalLay(), fn, Tags::GetNumUserGenres(), Tags::GetUserGenre(), Tags::LoadGenres(), mGrid, mLocal, PopulateGenres(), wxDialogWrapper::SetName(), ShuttleGuiBase::StartVerticalLay(), and XO.

Here is the call graph for this function:

◆ OnHelp()

void TagsEditorDialog::OnHelp ( wxCommandEvent &  Evt)

Definition at line 974 of file Tags.cpp.

975 {
976  HelpSystem::ShowHelp(this, L"Metadata_Editor", true);
977 }

References HelpSystem::ShowHelp().

Here is the call graph for this function:

◆ OnKeyDown()

void TagsEditorDialog::OnKeyDown ( wxKeyEvent &  event)
private

Definition at line 1473 of file Tags.cpp.

1474 {
1475  if (event.GetKeyCode() == WXK_ESCAPE)
1476  DoCancel(true);
1477  else
1478  event.Skip();
1479 }

References DoCancel().

Here is the call graph for this function:

◆ OnLoad()

void TagsEditorDialog::OnLoad ( wxCommandEvent &  event)
private

Definition at line 1237 of file Tags.cpp.

1238 {
1239  wxString fn;
1240 
1241  // Ask the user for the real name
1242  fn = SelectFile(FileNames::Operation::_None,
1243  XO("Load Metadata As:"),
1245  wxT("Tags.xml"),
1246  wxT("xml"),
1247  { FileNames::XMLFiles },
1248  wxFD_OPEN | wxRESIZE_BORDER,
1249  this);
1250 
1251  // User canceled...
1252  if (fn.empty()) {
1253  return;
1254  }
1255 
1256  // Load the metadata
1257  decltype(mLocal) temp;
1258  XMLFileReader reader;
1259  if (!reader.Parse(&temp, fn)) {
1260  // Inform user of load failure
1262  reader.GetErrorStr(),
1263  XO("Error Loading Metadata"),
1264  wxOK | wxCENTRE,
1265  this);
1266  return;
1267  }
1268 
1269  // Remember title and track in case they're read only
1270  wxString title = mLocal.GetTag(TAG_TITLE);
1271  wxString track = mLocal.GetTag(TAG_TRACK);
1272 
1273  // Replace existing tags with loaded ones
1274  mLocal = temp;
1275 
1276  // Restore title
1277  if (!mEditTitle) {
1279  }
1280 
1281  // Restore track
1282  if (!mEditTrack) {
1283  mLocal.SetTag(TAG_TRACK, track);
1284  }
1285 
1286  // Go fill up the window
1288 
1289  return;
1290 }

References AudacityMessageBox(), FileNames::DataDir(), fn, XMLFileReader::GetErrorStr(), Tags::GetTag(), mEditTitle, mEditTrack, mLocal, XMLFileReader::Parse(), SelectFile(), Tags::SetTag(), TAG_TITLE, TAG_TRACK, title, TransferDataToWindow(), FileNames::XMLFiles, and XO.

Here is the call graph for this function:

◆ OnOk()

void TagsEditorDialog::OnOk ( wxCommandEvent &  event)
private

Definition at line 1418 of file Tags.cpp.

1419 {
1420  if (mGrid->IsCellEditControlShown()) {
1421  mGrid->SaveEditControlValue();
1422  mGrid->HideCellEditControl();
1423 #if defined(__WXMAC__)
1424  // The cell editors do not capture the ENTER key, so it invokes
1425  // the default button ("Ok") when it should just close the
1426  // editor. So, cancel the "Ok" action.
1427  return;
1428 #endif
1429  }
1430 
1431  if (!Validate() || !TransferDataFromWindow()) {
1432  return;
1433  }
1434 
1435  *mTags = mLocal;
1436 
1437  wxRect r = GetRect();
1438  gPrefs->Write(wxT("/TagsEditorDialog/x"), r.x);
1439  gPrefs->Write(wxT("/TagsEditorDialog/y"), r.y);
1440  gPrefs->Write(wxT("/TagsEditorDialog/width"), r.width);
1441  gPrefs->Write(wxT("/TagsEditorDialog/height"), r.height);
1442  gPrefs->Flush();
1443 
1444  EndModal(wxID_OK);
1445 }

References FileConfig::Flush(), gPrefs, mGrid, mLocal, mTags, and TransferDataFromWindow().

Here is the call graph for this function:

◆ OnRemove()

void TagsEditorDialog::OnRemove ( wxCommandEvent &  event)
private

Definition at line 1397 of file Tags.cpp.

1398 {
1399  size_t row = mGrid->GetGridCursorRow();
1400 
1401  if (!mEditTitle &&
1402  mGrid->GetCellValue(row, 0).CmpNoCase(LABEL_TITLE.Translation()) == 0) {
1403  return;
1404  }
1405  else if (!mEditTrack &&
1406  mGrid->GetCellValue(row, 0)
1407  .CmpNoCase(LABEL_TRACK.Translation()) == 0) {
1408  return;
1409  }
1410  else if (row < STATICCNT) {
1411  mGrid->SetCellValue(row, 1, wxEmptyString);
1412  }
1413  else if (row >= STATICCNT) {
1414  mGrid->DeleteRows(row, 1);
1415  }
1416 }

References LABEL_TITLE, LABEL_TRACK, mEditTitle, mEditTrack, mGrid, and STATICCNT.

◆ OnReset()

void TagsEditorDialog::OnReset ( wxCommandEvent &  event)
private

Definition at line 1185 of file Tags.cpp.

1186 {
1187  int id = AudacityMessageBox(
1188  XO("Are you sure you want to reset the genre list to defaults?"),
1189  XO("Reset Genres"),
1190  wxYES_NO);
1191 
1192  if (id == wxNO) {
1193  return;
1194  }
1196 
1197  wxFileName fn(FileNames::DataDir(), wxT("genres.txt"));
1198  wxTextFile tf(fn.GetFullPath());
1199 
1200  bool open = (tf.Exists() && tf.Open()) ||
1201  (!tf.Exists() && tf.Create());
1202 
1203  if (!open) {
1205  XO("Unable to open genre file."),
1206  XO("Reset Genres") );
1207  mLocal.LoadGenres();
1208  return;
1209  }
1210 
1211  tf.Clear();
1212  int cnt = mLocal.GetNumUserGenres();
1213  for (int i = 0; i < cnt; i++) {
1214  tf.AddLine(mLocal.GetUserGenre(i));
1215  }
1216 
1217  if (!tf.Write()) {
1219  XO("Unable to save genre file."),
1220  XO("Reset Genres") );
1221  mLocal.LoadGenres();
1222  return;
1223  }
1224 
1225  mLocal.LoadGenres();
1226 
1227  PopulateGenres();
1228 }

References AudacityMessageBox(), FileNames::DataDir(), fn, Tags::GetNumUserGenres(), Tags::GetUserGenre(), Tags::LoadDefaultGenres(), Tags::LoadGenres(), mLocal, PopulateGenres(), and XO.

Here is the call graph for this function:

◆ OnSave()

void TagsEditorDialog::OnSave ( wxCommandEvent &  event)
private

Definition at line 1292 of file Tags.cpp.

1293 {
1294  wxString fn;
1295 
1296  // Refresh tags
1298 
1299  // Ask the user for the real name
1300  fn = SelectFile(FileNames::Operation::_None,
1301  XO("Save Metadata As:"),
1303  wxT("Tags.xml"),
1304  wxT("xml"),
1305  { FileNames::XMLFiles },
1306  wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
1307  this);
1308 
1309  // User canceled...
1310  if (fn.empty()) {
1311  return;
1312  }
1313 
1314  GuardedCall( [&] {
1315  // Create/Open the file
1316  XMLFileWriter writer{ fn, XO("Error Saving Tags File") };
1317 
1318  // Remember title and track in case they're read only
1319  wxString title = mLocal.GetTag(TAG_TITLE);
1320  wxString track = mLocal.GetTag(TAG_TRACK);
1321 
1322  // Clear title
1323  if (!mEditTitle) {
1324  mLocal.SetTag(TAG_TITLE, wxEmptyString);
1325  }
1326 
1327  // Clear track
1328  if (!mEditTrack) {
1329  mLocal.SetTag(TAG_TRACK, wxEmptyString);
1330  }
1331 
1332  auto cleanup = finally( [&] {
1333  // Restore title
1334  if (!mEditTitle) {
1336  }
1337 
1338  // Restore track
1339  if (!mEditTrack) {
1340  mLocal.SetTag(TAG_TRACK, track);
1341  }
1342  } );
1343 
1344  // Write the metadata
1345  mLocal.WriteXML(writer);
1346 
1347  writer.Commit();
1348  } );
1349 }

References FileNames::DataDir(), fn, Tags::GetTag(), GuardedCall(), mEditTitle, mEditTrack, mLocal, SelectFile(), Tags::SetTag(), TAG_TITLE, TAG_TRACK, title, TransferDataFromWindow(), Tags::WriteXML(), FileNames::XMLFiles, and XO.

Here is the call graph for this function:

◆ OnSaveDefaults()

void TagsEditorDialog::OnSaveDefaults ( wxCommandEvent &  event)
private

Definition at line 1351 of file Tags.cpp.

1352 {
1353  // Refresh tags
1355 
1356  // Remember title and track in case they're read only
1357  wxString title = mLocal.GetTag(TAG_TITLE);
1358  wxString track = mLocal.GetTag(TAG_TRACK);
1359 
1360  // Clear title
1361  if (!mEditTitle) {
1362  mLocal.SetTag(TAG_TITLE, wxEmptyString);
1363  }
1364 
1365  // Clear track
1366  if (!mEditTrack) {
1367  mLocal.SetTag(TAG_TRACK, wxEmptyString);
1368  }
1369 
1370  // Remove any previous defaults
1371  gPrefs->DeleteGroup(wxT("/Tags"));
1372 
1373  // Write out each tag
1374  for (const auto &pair : mLocal.GetRange()) {
1375  const auto &n = pair.first;
1376  const auto &v = pair.second;
1377  gPrefs->Write(wxT("/Tags/") + n, v);
1378  }
1379  gPrefs->Flush();
1380 
1381  // Restore title
1382  if (!mEditTitle) {
1384  }
1385 
1386  // Restore track
1387  if (!mEditTrack) {
1388  mLocal.SetTag(TAG_TRACK, track);
1389  }
1390 }

References FileConfig::DeleteGroup(), FileConfig::Flush(), Tags::GetRange(), Tags::GetTag(), gPrefs, mEditTitle, mEditTrack, mLocal, Tags::SetTag(), TAG_TITLE, TAG_TRACK, title, and TransferDataFromWindow().

Here is the call graph for this function:

◆ PopulateGenres()

void TagsEditorDialog::PopulateGenres ( )
private

Definition at line 1497 of file Tags.cpp.

1498 {
1499  int cnt = mLocal.GetNumUserGenres();
1500  int i;
1501  wxString parm;
1502  wxArrayString g;
1503 
1504  for (i = 0; i < cnt; i++) {
1505  g.push_back(mLocal.GetUserGenre(i));
1506  }
1507  std::sort( g.begin(), g.end() );
1508 
1509  for (i = 0; i < cnt; i++) {
1510  parm = parm + (i == 0 ? wxT("") : wxT(",")) + g[i];
1511  }
1512 
1513  // Here was a memory leak! wxWidgets docs for wxGrid::GetDefaultEditorForType() say:
1514  // "The caller must call DecRef() on the returned pointer."
1515  auto editor = mGrid->GetDefaultEditorForType(wxT("Combo"));
1516  editor->SetParameters(parm);
1517  editor->DecRef();
1518 }

References Tags::GetNumUserGenres(), Tags::GetUserGenre(), mGrid, and mLocal.

Referenced by OnEdit(), and OnReset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ PopulateOrExchange()

void TagsEditorDialog::PopulateOrExchange ( ShuttleGui S)

Definition at line 876 of file Tags.cpp.

877 {
878  bool bShow;
879  gPrefs->Read(wxT("/AudioFiles/ShowId3Dialog"), &bShow, true );
880 
881  S.StartVerticalLay();
882  {
883  S.StartHorizontalLay(wxALIGN_LEFT, 0);
884  {
885  S.AddUnits(XO("Use arrow keys (or ENTER key after editing) to navigate fields."));
886  }
887  S.EndHorizontalLay();
888 
889  if (mGrid == NULL) {
890  mGrid = safenew Grid(S.GetParent(),
891  wxID_ANY,
892  wxDefaultPosition,
893  wxDefaultSize,
894  wxSUNKEN_BORDER);
895 
896  mGrid->RegisterDataType(wxT("Combo"),
897  (mStringRenderer = safenew wxGridCellStringRenderer),
898  (mComboEditor = safenew ComboEditor(wxArrayString(), true)));
899 
900  mGrid->SetColLabelSize(mGrid->GetDefaultRowSize());
901 
902  auto cs = transform_container<wxArrayStringEx>(
903  names, std::mem_fn( &TranslatableString::Translation ) );
904 
905  // Build the initial (empty) grid
906  mGrid->CreateGrid(0, 2, wxGrid::wxGridSelectRows);
907  mGrid->SetRowLabelSize(0);
908  mGrid->SetDefaultCellAlignment(wxALIGN_LEFT, wxALIGN_CENTER);
909  mGrid->SetColLabelValue(0, _("Tag"));
910  mGrid->SetColLabelValue(1, _("Value"));
911 
912  // Resize the name column and set default row height.
913  wxComboBox tc(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, cs);
914  mGrid->SetColSize(0, tc.GetSize().x);
915  mGrid->SetColMinimalWidth(0, tc.GetSize().x);
916  }
917  S.Prop(1)
918  .Position(wxEXPAND | wxALL)
919  .AddWindow(mGrid);
920 
921  S.StartMultiColumn(4, wxALIGN_CENTER);
922  {
923  S.Id(AddID).AddButton(XXO("&Add"));
924  S.Id(RemoveID).AddButton(XXO("&Remove"));
925  S.AddTitle( {} );
926  S.Id(ClearID).AddButton(XXO("Cl&ear"));
927  }
928  S.EndMultiColumn();
929 
930  S.StartHorizontalLay(wxALIGN_CENTRE, 0);
931  {
932  S.StartStatic(XO("Genres"));
933  {
934  S.StartMultiColumn(4, wxALIGN_CENTER);
935  {
936  S.Id(EditID).AddButton(XXO("E&dit..."));
937  S.Id(ResetID).AddButton(XXO("Rese&t..."));
938  }
939  S.EndMultiColumn();
940  }
941  S.EndStatic();
942  S.StartStatic(XO("Template"));
943  {
944  S.StartMultiColumn(4, wxALIGN_CENTER);
945  {
946  S.Id(LoadID).AddButton(XXO("&Load..."));
947  S.Id(SaveID).AddButton(XXO("&Save..."));
948  S.AddTitle( {} );
949  S.Id(SaveDefaultsID).AddButton(XXO("Set De&fault"));
950  }
951  S.EndMultiColumn();
952  }
953  S.EndStatic();
954  }
955  S.EndHorizontalLay();
956  S.StartHorizontalLay(wxALIGN_LEFT, 0);
957  {
958  S.Id( DontShowID ).AddCheckBox( XXO("Don't show this when exporting audio"), !bShow );
959  }
960  S.EndHorizontalLay();
961  }
962  S.EndVerticalLay();
963 
965 }

References _, ShuttleGuiBase::AddButton(), ShuttleGuiBase::AddCheckBox(), AddID, ShuttleGui::AddStandardButtons(), ShuttleGuiBase::AddTitle(), ShuttleGuiBase::AddUnits(), ShuttleGuiBase::AddWindow(), ClearID, DontShowID, eCancelButton, EditID, eHelpButton, ShuttleGuiBase::EndHorizontalLay(), ShuttleGuiBase::EndMultiColumn(), ShuttleGuiBase::EndStatic(), ShuttleGuiBase::EndVerticalLay(), eOkButton, ShuttleGuiBase::GetParent(), gPrefs, ShuttleGui::Id(), LoadID, mComboEditor, mGrid, mStringRenderer, names, ShuttleGui::Position(), ShuttleGui::Prop(), RemoveID, ResetID, safenew, SaveDefaultsID, SaveID, ShuttleGuiBase::StartHorizontalLay(), ShuttleGuiBase::StartMultiColumn(), ShuttleGuiBase::StartStatic(), ShuttleGuiBase::StartVerticalLay(), TranslatableString::Translation(), XO, and XXO.

Here is the call graph for this function:

◆ SetEditors()

void TagsEditorDialog::SetEditors ( )
private

Definition at line 1481 of file Tags.cpp.

1482 {
1483  int cnt = mGrid->GetNumberRows();
1484 
1485  for (int i = 0; i < cnt; i++) {
1486  wxString label = mGrid->GetCellValue(i, 0);
1487  if (label.CmpNoCase(LABEL_GENRE.Translation()) == 0) {
1488  // This use of GetDefaultEditorForType does not require DecRef.
1489  mGrid->SetCellEditor(i, 1, mGrid->GetDefaultEditorForType(wxT("Combo")));
1490  }
1491  else {
1492  mGrid->SetCellEditor(i, 1, NULL); //mGrid->GetDefaultEditor());
1493  }
1494  }
1495 }

References label, LABEL_GENRE, and mGrid.

Referenced by TransferDataToWindow().

Here is the caller graph for this function:

◆ TransferDataFromWindow()

bool TagsEditorDialog::TransferDataFromWindow ( )
override

Definition at line 979 of file Tags.cpp.

980 {
981  int i, cnt = mGrid->GetNumberRows();
982 
983  if (mGrid->IsCellEditControlShown()) {
984  mGrid->SaveEditControlValue();
985  mGrid->HideCellEditControl();
986  }
987 
988  mLocal.Clear();
989  for (i = 0; i < cnt; i++) {
990  // Get tag name from the grid
991 
992  auto n = mGrid->GetCellValue(i, 0);
993  wxString v = mGrid->GetCellValue(i, 1);
994 
995  if (n.empty()) {
996  continue;
997  }
998 
999  bool bSpecialTag = true;
1000 
1001  // Map special tag names back to internal keys
1002  if (n.CmpNoCase(LABEL_ARTIST.Translation()) == 0) {
1003  n = TAG_ARTIST;
1004  }
1005  else if (n.CmpNoCase(LABEL_TITLE.Translation()) == 0) {
1006  n = TAG_TITLE;
1007  }
1008  else if (n.CmpNoCase(LABEL_ALBUM.Translation()) == 0) {
1009  n = TAG_ALBUM;
1010  }
1011  else if (n.CmpNoCase(LABEL_TRACK.Translation()) == 0) {
1012  n = TAG_TRACK;
1013  }
1014  else if (n.CmpNoCase(LABEL_YEAR.Translation()) == 0) {
1015  n = TAG_YEAR;
1016  }
1017  else if (n.CmpNoCase(LABEL_GENRE.Translation()) == 0) {
1018  n = TAG_GENRE;
1019  }
1020  else if (n.CmpNoCase(LABEL_COMMENTS.Translation()) == 0) {
1021  n = TAG_COMMENTS;
1022  }
1023  else {
1024  bSpecialTag = false;
1025  }
1026 
1027  mLocal.SetTag(n, v, bSpecialTag);
1028  }
1029 
1030  return true;
1031 }

References Tags::Clear(), LABEL_ALBUM, LABEL_ARTIST, LABEL_COMMENTS, LABEL_GENRE, LABEL_TITLE, LABEL_TRACK, LABEL_YEAR, mGrid, mLocal, Tags::SetTag(), TAG_ALBUM, TAG_ARTIST, TAG_COMMENTS, TAG_GENRE, TAG_TITLE, TAG_TRACK, and TAG_YEAR.

Referenced by OnOk(), OnSave(), and OnSaveDefaults().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ TransferDataToWindow()

bool TagsEditorDialog::TransferDataToWindow ( )
override

Definition at line 1033 of file Tags.cpp.

1034 {
1035  size_t i;
1036  TagMap popTagMap;
1037 
1038  // Disable redrawing until we're done
1039  mGrid->BeginBatch();
1040 
1041  // Delete all rows
1042  if (mGrid->GetNumberRows()) {
1043  mGrid->DeleteRows(0, mGrid->GetNumberRows());
1044  }
1045 
1046  // Populate the static rows
1047  for (i = 0; i < STATICCNT; i++) {
1048  mGrid->AppendRows();
1049 
1050  mGrid->SetReadOnly(i, 0);
1051  // The special tag name that's displayed and translated may not match
1052  // the key string used for internal lookup.
1053  mGrid->SetCellValue(i, 0, labelmap[i].label.Translation() );
1054  mGrid->SetCellValue(i, 1, mLocal.GetTag(labelmap[i].name));
1055 
1056  if (!mEditTitle &&
1057  mGrid->GetCellValue(i, 0).CmpNoCase(LABEL_TITLE.Translation()) == 0) {
1058  mGrid->SetReadOnly(i, 1);
1059  }
1060 
1061  if (!mEditTrack &&
1062  mGrid->GetCellValue(i, 0).CmpNoCase(LABEL_TRACK.Translation()) == 0) {
1063  mGrid->SetReadOnly(i, 1);
1064  }
1065 
1066  popTagMap[ labelmap[i].name ] = mGrid->GetCellValue(i, 1);
1067  }
1068 
1069  // Populate the rest
1070  for (const auto &pair : mLocal.GetRange()) {
1071  const auto &n = pair.first;
1072  const auto &v = pair.second;
1073  if (popTagMap.find(n) == popTagMap.end()) {
1074  mGrid->AppendRows();
1075  mGrid->SetCellValue(i, 0, n);
1076  mGrid->SetCellValue(i, 1, v);
1077  i++;
1078  }
1079  }
1080 
1081  // Add an extra one to help with initial sizing and to show it can be done
1082  mGrid->AppendRows(1);
1083 
1084  // We're done, so allow the grid to redraw
1085  mGrid->EndBatch();
1086 
1087  // Set the editors
1088  SetEditors();
1089  Layout();
1090  Fit();
1091 
1092  return true;
1093 }

References Tags::GetRange(), Tags::GetTag(), label, LABEL_TITLE, LABEL_TRACK, labelmap, mEditTitle, mEditTrack, mGrid, mLocal, SetEditors(), STATICCNT, and TranslatableString::Translation().

Referenced by OnClear(), and OnLoad().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mComboEditor

ComboEditor* TagsEditorDialog::mComboEditor
private

Definition at line 200 of file Tags.h.

Referenced by PopulateOrExchange().

◆ mEditTitle

bool TagsEditorDialog::mEditTitle
private

Definition at line 194 of file Tags.h.

Referenced by OnLoad(), OnRemove(), OnSave(), OnSaveDefaults(), and TransferDataToWindow().

◆ mEditTrack

bool TagsEditorDialog::mEditTrack
private

Definition at line 195 of file Tags.h.

Referenced by OnLoad(), OnRemove(), OnSave(), OnSaveDefaults(), and TransferDataToWindow().

◆ mGrid

Grid* TagsEditorDialog::mGrid
private

◆ mLocal

Tags TagsEditorDialog::mLocal
private

◆ mStringRenderer

wxGridCellStringRenderer* TagsEditorDialog::mStringRenderer
private

Definition at line 201 of file Tags.h.

Referenced by PopulateOrExchange().

◆ mTags

Tags* TagsEditorDialog::mTags
private

Definition at line 193 of file Tags.h.

Referenced by OnOk().


The documentation for this class was generated from the following files:
key
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: Tags.cpp:233
TagsEditorDialog::DoCancel
void DoCancel(bool escKey)
Definition: Tags.cpp:1452
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
Tags::LoadDefaultGenres
void LoadDefaultGenres()
Definition: Tags.cpp:393
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1184
GuardedCall
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), std::function< void(AudacityException *)> delayedHandler=DefaultDelayedHandlerAction{})
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
Definition: AudacityException.h:202
ShuttleGuiBase::AddCheckBox
wxCheckBox * AddCheckBox(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:309
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Definition: AudacityMessageBox.cpp:17
fn
static const auto fn
Definition: WaveformView.cpp:1108
ShuttleGuiBase::AddTitle
void AddTitle(const TranslatableString &Prompt, int wrapWidth=0)
Centred text string.
Definition: ShuttleGui.cpp:281
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
eHelpButton
@ eHelpButton
Definition: ShuttleGui.h:604
SelectFile
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
Definition: SelectFile.cpp:17
TAG_TRACK
#define TAG_TRACK
Definition: Tags.h:63
Tags::GetRange
Iterators GetRange() const
Definition: Tags.cpp:481
Grid
Supplies an accessible grid based on wxGrid.
Definition: Grid.h:185
TagsEditorDialog::mComboEditor
ComboEditor * mComboEditor
Definition: Tags.h:200
Tags::LoadGenres
void LoadGenres()
Definition: Tags.cpp:401
XO
#define XO(s)
Definition: Internat.h:31
FileNames::XMLFiles
FILES_API const FileType XMLFiles
Definition: FileNames.h:74
Tags::GetUserGenre
wxString GetUserGenre(int value)
Definition: Tags.cpp:419
LABEL_TRACK
#define LABEL_TRACK
Definition: Tags.cpp:739
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1238
RemoveID
@ RemoveID
Definition: Tags.cpp:780
TagsEditorDialog::TransferDataToWindow
bool TransferDataToWindow() override
Definition: Tags.cpp:1033
TagsEditorDialog::mGrid
Grid * mGrid
Definition: Tags.h:199
LABEL_TITLE
#define LABEL_TITLE
Definition: Tags.cpp:737
TagsEditorDialog::mStringRenderer
wxGridCellStringRenderer * mStringRenderer
Definition: Tags.h:201
Tags::GetTag
wxString GetTag(const wxString &name) const
Definition: Tags.cpp:461
HelpSystem::ShowHelp
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:237
ResetID
@ ResetID
Definition: Tags.cpp:775
DontShowID
@ DontShowID
Definition: Tags.cpp:781
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2274
XMLFileReader::Parse
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Definition: XMLFileReader.cpp:42
TagsEditorDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: Tags.cpp:876
FileNames::DataDir
FILES_API FilePath DataDir()
Audacity user data directory.
TagsEditorDialog::SetEditors
void SetEditors()
Definition: Tags.cpp:1481
SaveDefaultsID
@ SaveDefaultsID
Definition: Tags.cpp:778
TagsEditorDialog::mEditTitle
bool mEditTitle
Definition: Tags.h:194
XXO
#define XXO(s)
Definition: Internat.h:44
eCancelButton
@ eCancelButton
Definition: ShuttleGui.h:601
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
XMLFileReader::GetErrorStr
const TranslatableString & GetErrorStr() const
Definition: XMLFileReader.cpp:178
Tags::SetTag
void SetTag(const wxString &name, const wxString &value, const bool bSpecialTag=false)
Definition: Tags.cpp:486
label
TranslatableString label
Definition: Tags.cpp:756
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1229
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1203
LABEL_ALBUM
#define LABEL_ALBUM
Definition: Tags.cpp:738
ShuttleGuiBase::AddUnits
void AddUnits(const TranslatableString &Prompt, int wrapWidth=0)
Left aligned text string.
Definition: ShuttleGui.cpp:263
EditID
@ EditID
Definition: Tags.cpp:774
Tags::Clear
void Clear()
Definition: Tags.cpp:337
TAG_GENRE
#define TAG_GENRE
Definition: Tags.h:65
labelmap
static const struct @0 labelmap[]
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:496
Tags::GetNumUserGenres
int GetNumUserGenres()
Definition: Tags.cpp:388
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:299
TAG_YEAR
#define TAG_YEAR
Definition: Tags.h:64
TagsEditorDialog::TransferDataFromWindow
bool TransferDataFromWindow() override
Definition: Tags.cpp:979
anonymous_namespace{TracksPrefs.cpp}::key0
const auto key0
Definition: TracksPrefs.cpp:78
TagsEditorDialog::PopulateGenres
void PopulateGenres()
Definition: Tags.cpp:1497
ClearID
@ ClearID
Definition: Tags.cpp:773
ShuttleGui::Prop
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:725
ShuttleGuiBase::AddButton
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:360
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:893
SaveID
@ SaveID
Definition: Tags.cpp:777
FileConfig::DeleteGroup
virtual bool DeleteGroup(const wxString &key) wxOVERRIDE
Definition: FileConfig.cpp:219
wxDialogWrapper
Definition: wxPanelWrapper.h:81
LABEL_COMMENTS
#define LABEL_COMMENTS
Definition: Tags.cpp:742
TagMap
std::unordered_map< wxString, wxString > TagMap
Definition: Tags.h:58
title
static const auto title
Definition: NoUpdatesAvailableDialog.cpp:22
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
eOkButton
@ eOkButton
Definition: ShuttleGui.h:600
TagsEditorDialog::mLocal
Tags mLocal
Definition: Tags.h:197
XMLFileReader
Reads a file and passes the results through an XMLTagHandler.
Definition: XMLFileReader.h:18
ShuttleGui::Position
ShuttleGui & Position(int flags)
Definition: ShuttleGui.h:712
TagsEditorDialog::IsWindowRectValid
bool IsWindowRectValid(const wxRect *windowRect) const
Definition: Tags.cpp:1520
names
static TranslatableStrings names
Definition: Tags.cpp:744
_
#define _(s)
Definition: Internat.h:75
Tags::WriteXML
void WriteXML(XMLWriter &xmlFile) const
Definition: Tags.cpp:600
ComboEditor
Definition: Tags.cpp:632
XMLFileWriter
Wrapper to output XML data to files.
Definition: XMLWriter.h:81
TagsEditorDialog::mEditTrack
bool mEditTrack
Definition: Tags.h:195
LABEL_YEAR
#define LABEL_YEAR
Definition: Tags.cpp:740
STATICCNT
#define STATICCNT
Definition: Tags.cpp:770
TAG_COMMENTS
#define TAG_COMMENTS
Definition: Tags.h:66
TagsEditorDialog::mTags
Tags * mTags
Definition: Tags.h:193
TAG_ARTIST
#define TAG_ARTIST
Definition: Tags.h:61
wxDialogWrapper::wxDialogWrapper
wxDialogWrapper()
Definition: wxPanelWrapper.h:84
LABEL_GENRE
#define LABEL_GENRE
Definition: Tags.cpp:741
LoadID
@ LoadID
Definition: Tags.cpp:776
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2444
TranslatableString::Translation
wxString Translation() const
Definition: TranslatableString.h:79
wxDialogWrapper::SetName
void SetName()
Definition: wxPanelWrapper.cpp:81
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:922
safenew
#define safenew
Definition: MemoryX.h:10
TAG_TITLE
#define TAG_TITLE
Definition: Tags.h:60
LABEL_ARTIST
#define LABEL_ARTIST
Definition: Tags.cpp:736
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
TAG_ALBUM
#define TAG_ALBUM
Definition: Tags.h:62
AddID
@ AddID
Definition: Tags.cpp:779