ApplyMacro returns true on success, false otherwise. Any error reporting to the user in setting up the macro has already been done.
| 641 | // Any error reporting to the user in setting up the macro |
| 642 | // has already been done. |
| 643 | bool MacroCommands::ApplyMacro( |
| 644 | const MacroCommandsCatalog &catalog, const wxString & filename) |
| 645 | { |
| 646 | // Check for reentrant ApplyMacro commands. |
| 647 | // We'll allow 1 level of reentry, but not more. |
| 648 | // And we treat ignoring deeper levels as a success. |
| 649 | if (MacroReentryCount > 1) { |
| 650 | return true; |
| 651 | } |
| 652 | |
| 653 | // Restore the reentry counter (to zero) when we exit. |
| 654 | auto cleanup1 = valueRestorer(MacroReentryCount); |
| 655 | MacroReentryCount++; |
| 656 | |
| 657 | AudacityProject *proj = &mProject; |
| 658 | bool res = false; |
| 659 | |
| 660 | // Only perform this group on initial entry. They should not be done |
| 661 | // while recursing. |
| 662 | if (MacroReentryCount == 1) { |
| 663 | mFileName = filename; |
| 664 | |
| 665 | TranslatableString longDesc, shortDesc; |
| 666 | wxString name = gPrefs->Read(wxT("/Batch/ActiveMacro"), wxEmptyString); |
| 667 | if (name.empty()) { |
| 668 | /* i18n-hint: active verb in past tense */ |
| 669 | longDesc = XO("Applied Macro"); |
| 670 | shortDesc = XO("Apply Macro"); |
| 671 | } |
| 672 | else { |
| 673 | /* i18n-hint: active verb in past tense */ |
| 674 | longDesc = XO("Applied Macro '%s'").Format(name); |
| 675 | shortDesc = XO("Apply '%s'").Format(name); |
| 676 | } |
| 677 | |
| 678 | // Save the project state before making any changes. It will be rolled |
| 679 | // back if an error occurs. |
| 680 | // It also causes any calls to ModifyState (such as by simple |
| 681 | // view-changing commands) to append changes to this state, not to the |
| 682 | // previous state in history. See Bug 2076 |
| 683 | if (proj) { |
| 684 | ProjectHistory::Get(*proj).PushState(longDesc, shortDesc); |
| 685 | } |
| 686 | } |
| 687 | |
| 688 | // Upon exit of the top level apply, roll back the state if an error occurs. |
| 689 | auto cleanup2 = finally([&, macroReentryCount = MacroReentryCount] { |
| 690 | if (macroReentryCount == 1 && !res && proj) { |
| 691 | // Be sure that exceptions do not escape this destructor |
| 692 | GuardedCall([&]{ |
| 693 | // Macro failed or was cancelled; revert to the previous state |
| 694 | auto &history = ProjectHistory::Get(*proj); |
| 695 | history.RollbackState(); |
| 696 | // The added undo state is now vacuous. Remove it (Bug 2759) |
| 697 | auto &undoManager = UndoManager::Get(*proj); |
| 698 | undoManager.Undo( |
| 699 | [&]( const UndoStackElem &elem ){ |
| 700 | history.PopState( elem.state ); } ); |
no test coverage detected