mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-06 23:47:45 +02:00
Duplicate Project in ProjectWindows
Patch imported by Audacity and adapted for Tenacity. Original commit: 6477c9e0a6cb93b781c6c83153f1d036a7cc4c13 Signed-off-by: Panagiotis Vasilopoulos <hello@alwayslivid.com>
This commit is contained in:
parent
bc13febb29
commit
0843918fa0
172
src/ProjectWindows.cpp
Normal file
172
src/ProjectWindows.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
|
||||||
|
Audacity: A Digital Audio Editor
|
||||||
|
|
||||||
|
Project.cpp
|
||||||
|
|
||||||
|
Dominic Mazzoni
|
||||||
|
Vaughan Johnson
|
||||||
|
|
||||||
|
*//*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Project.h"
|
||||||
|
|
||||||
|
#include "widgets/wxWidgetsBasicUI.h"
|
||||||
|
|
||||||
|
#include <wx/display.h>
|
||||||
|
#include <wx/filename.h>
|
||||||
|
#include <wx/frame.h>
|
||||||
|
|
||||||
|
wxDEFINE_EVENT(EVT_TRACK_PANEL_TIMER, wxCommandEvent);
|
||||||
|
|
||||||
|
size_t AllProjects::size() const
|
||||||
|
{
|
||||||
|
return gAudacityProjects.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto AllProjects::begin() const -> const_iterator
|
||||||
|
{
|
||||||
|
return gAudacityProjects.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto AllProjects::end() const -> const_iterator
|
||||||
|
{
|
||||||
|
return gAudacityProjects.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto AllProjects::rbegin() const -> const_reverse_iterator
|
||||||
|
{
|
||||||
|
return gAudacityProjects.rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto AllProjects::rend() const -> const_reverse_iterator
|
||||||
|
{
|
||||||
|
return gAudacityProjects.rend();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto AllProjects::Remove( AudacityProject &project ) -> value_type
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard{ Mutex() };
|
||||||
|
auto start = begin(), finish = end(), iter = std::find_if(
|
||||||
|
start, finish,
|
||||||
|
[&]( const value_type &ptr ){ return ptr.get() == &project; }
|
||||||
|
);
|
||||||
|
if (iter == finish)
|
||||||
|
return nullptr;
|
||||||
|
auto result = *iter;
|
||||||
|
gAudacityProjects.erase( iter );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllProjects::Add( const value_type &pProject )
|
||||||
|
{
|
||||||
|
if (!pProject) {
|
||||||
|
wxASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> guard{ Mutex() };
|
||||||
|
gAudacityProjects.push_back( pProject );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::mutex &AllProjects::Mutex()
|
||||||
|
{
|
||||||
|
static std::mutex theMutex;
|
||||||
|
return theMutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AudacityProject::mProjectCounter=0;// global counter.
|
||||||
|
|
||||||
|
/* Define Global Variables */
|
||||||
|
//This array holds onto all of the projects currently open
|
||||||
|
AllProjects::Container AllProjects::gAudacityProjects;
|
||||||
|
|
||||||
|
AudacityProject::AudacityProject()
|
||||||
|
{
|
||||||
|
mProjectNo = mProjectCounter++; // Bug 322
|
||||||
|
AttachedObjects::BuildAll();
|
||||||
|
// But not for the attached windows. They get built only on demand, such as
|
||||||
|
// from menu items.
|
||||||
|
}
|
||||||
|
|
||||||
|
AudacityProject::~AudacityProject()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::SetFrame( wxFrame *pFrame )
|
||||||
|
{
|
||||||
|
mFrame = pFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::SetPanel( wxWindow *pPanel )
|
||||||
|
{
|
||||||
|
mPanel = pPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wxString &AudacityProject::GetProjectName() const
|
||||||
|
{
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::SetProjectName(const wxString &name)
|
||||||
|
{
|
||||||
|
mName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath AudacityProject::GetInitialImportPath() const
|
||||||
|
{
|
||||||
|
return mInitialImportPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudacityProject::SetInitialImportPath(const FilePath &path)
|
||||||
|
{
|
||||||
|
if (mInitialImportPath.empty())
|
||||||
|
{
|
||||||
|
mInitialImportPath = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TENACITY_DLL_API wxFrame &GetProjectFrame( AudacityProject &project )
|
||||||
|
{
|
||||||
|
auto ptr = project.GetFrame();
|
||||||
|
if ( !ptr )
|
||||||
|
THROW_INCONSISTENCY_EXCEPTION;
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TENACITY_DLL_API const wxFrame &GetProjectFrame( const AudacityProject &project )
|
||||||
|
{
|
||||||
|
auto ptr = project.GetFrame();
|
||||||
|
if ( !ptr )
|
||||||
|
THROW_INCONSISTENCY_EXCEPTION;
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<const BasicUI::WindowPlacement>
|
||||||
|
ProjectFramePlacement( AudacityProject *project )
|
||||||
|
{
|
||||||
|
if (!project)
|
||||||
|
return std::make_unique<BasicUI::WindowPlacement>();
|
||||||
|
return std::make_unique<wxWidgetsWindowPlacement>(
|
||||||
|
&GetProjectFrame(*project));
|
||||||
|
}
|
||||||
|
|
||||||
|
TENACITY_DLL_API wxWindow &GetProjectPanel( AudacityProject &project )
|
||||||
|
{
|
||||||
|
auto ptr = project.GetPanel();
|
||||||
|
if ( !ptr )
|
||||||
|
THROW_INCONSISTENCY_EXCEPTION;
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TENACITY_DLL_API const wxWindow &GetProjectPanel(
|
||||||
|
const AudacityProject &project )
|
||||||
|
{
|
||||||
|
auto ptr = project.GetPanel();
|
||||||
|
if ( !ptr )
|
||||||
|
THROW_INCONSISTENCY_EXCEPTION;
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the needed, linkable registry functions
|
||||||
|
DEFINE_XML_METHOD_REGISTRY( ProjectFileIORegistry );
|
187
src/ProjectWindows.h
Normal file
187
src/ProjectWindows.h
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
|
||||||
|
Audacity: A Digital Audio Editor
|
||||||
|
|
||||||
|
Project.h
|
||||||
|
|
||||||
|
Dominic Mazzoni
|
||||||
|
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#ifndef __AUDACITY_PROJECT__
|
||||||
|
#define __AUDACITY_PROJECT__
|
||||||
|
|
||||||
|
#include "Identifier.h"
|
||||||
|
|
||||||
|
#include "ClientData.h" // to inherit
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <wx/weakref.h> // member variable
|
||||||
|
#include <wx/window.h> // MSVC wants this
|
||||||
|
|
||||||
|
class wxFrame;
|
||||||
|
class wxWindow;
|
||||||
|
namespace BasicUI { class WindowPlacement; }
|
||||||
|
|
||||||
|
class AudacityProject;
|
||||||
|
|
||||||
|
//! Like a standard library container of all open projects.
|
||||||
|
//! @invariant pointers accessible through the iterators are not null
|
||||||
|
/*!
|
||||||
|
So you can iterate easily over shared pointers to them with range-for :
|
||||||
|
for (auto pProject : AllProjects{}) { ... }
|
||||||
|
The pointers are never null.
|
||||||
|
|
||||||
|
However iterators will be invalid if addition or deletion of projects occur
|
||||||
|
during traversal.
|
||||||
|
*/
|
||||||
|
class TENACITY_DLL_API AllProjects
|
||||||
|
{
|
||||||
|
|
||||||
|
// Use shared_ptr to projects, because elsewhere we need weak_ptr
|
||||||
|
using AProjectHolder = std::shared_ptr< AudacityProject >;
|
||||||
|
using Container = std::vector< AProjectHolder >;
|
||||||
|
static Container gAudacityProjects;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AllProjects() = default;
|
||||||
|
|
||||||
|
size_t size() const;
|
||||||
|
bool empty() const { return size() == 0; }
|
||||||
|
|
||||||
|
using const_iterator = Container::const_iterator;
|
||||||
|
const_iterator begin() const;
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
using const_reverse_iterator = Container::const_reverse_iterator;
|
||||||
|
const_reverse_iterator rbegin() const;
|
||||||
|
const_reverse_iterator rend() const;
|
||||||
|
|
||||||
|
using value_type = Container::value_type;
|
||||||
|
|
||||||
|
// If the project is present, remove it from the global array and return
|
||||||
|
// a shared pointer, else return null. This invalidates any iterators.
|
||||||
|
value_type Remove( AudacityProject &project );
|
||||||
|
|
||||||
|
//! This invalidates iterators
|
||||||
|
/*!
|
||||||
|
@pre pProject is not null
|
||||||
|
*/
|
||||||
|
void Add( const value_type &pProject );
|
||||||
|
|
||||||
|
/// In case you must iterate in a non-main thread, use this to prevent
|
||||||
|
/// changes in the set of open projects
|
||||||
|
static std::mutex &Mutex();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Container of various objects associated with the project, which is
|
||||||
|
// responsible for destroying them
|
||||||
|
using AttachedProjectObjects = ClientData::Site<
|
||||||
|
AudacityProject, ClientData::Base, ClientData::SkipCopying, std::shared_ptr
|
||||||
|
>;
|
||||||
|
// Container of pointers to various windows associated with the project, which
|
||||||
|
// is not responsible for destroying them -- wxWidgets handles that instead
|
||||||
|
using AttachedProjectWindows = ClientData::Site<
|
||||||
|
AudacityProject, wxWindow, ClientData::SkipCopying, ClientData::BarePtr
|
||||||
|
>;
|
||||||
|
|
||||||
|
wxDECLARE_EXPORTED_EVENT(TENACITY_DLL_API,
|
||||||
|
EVT_TRACK_PANEL_TIMER, wxCommandEvent);
|
||||||
|
|
||||||
|
///\brief The top-level handle to an Audacity project. It serves as a source
|
||||||
|
/// of events that other objects can bind to, and a container of associated
|
||||||
|
/// sub-objects that it treats opaquely. It stores a filename and a status
|
||||||
|
/// message and a few other things.
|
||||||
|
/// There is very little in this class, most of the intelligence residing in
|
||||||
|
/// the cooperating attached objects.
|
||||||
|
class TENACITY_DLL_API AudacityProject final
|
||||||
|
: public wxEvtHandler
|
||||||
|
, public AttachedProjectObjects
|
||||||
|
, public AttachedProjectWindows
|
||||||
|
, public std::enable_shared_from_this<AudacityProject>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using AttachedObjects = ::AttachedProjectObjects;
|
||||||
|
using AttachedWindows = ::AttachedProjectWindows;
|
||||||
|
|
||||||
|
AudacityProject();
|
||||||
|
virtual ~AudacityProject();
|
||||||
|
|
||||||
|
wxFrame *GetFrame() { return mFrame; }
|
||||||
|
const wxFrame *GetFrame() const { return mFrame; }
|
||||||
|
void SetFrame( wxFrame *pFrame );
|
||||||
|
|
||||||
|
wxWindow *GetPanel() { return mPanel; }
|
||||||
|
const wxWindow *GetPanel() const { return mPanel; }
|
||||||
|
void SetPanel( wxWindow *pPanel );
|
||||||
|
|
||||||
|
int GetProjectNumber(){ return mProjectNo;}
|
||||||
|
|
||||||
|
// Project name can be either empty or have the name of the project.
|
||||||
|
//
|
||||||
|
// If empty, it signifies that the project is empty/unmodified or
|
||||||
|
// that the project hasn't yet been saved to a permanent project
|
||||||
|
// file.
|
||||||
|
//
|
||||||
|
// If a name has been assigned, it is merely used to identify
|
||||||
|
// the project and should not be used for any other purposes.
|
||||||
|
const wxString &GetProjectName() const;
|
||||||
|
void SetProjectName(const wxString &name);
|
||||||
|
|
||||||
|
// Used exclusively in batch mode, this allows commands to remember
|
||||||
|
// and use the initial import path
|
||||||
|
FilePath GetInitialImportPath() const;
|
||||||
|
void SetInitialImportPath(const FilePath &path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// The project's name
|
||||||
|
wxString mName;
|
||||||
|
|
||||||
|
static int mProjectCounter;// global counter.
|
||||||
|
int mProjectNo; // count when this project was created.
|
||||||
|
|
||||||
|
FilePath mInitialImportPath;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool mbBusyImporting{ false }; // used to fix bug 584
|
||||||
|
int mBatchMode{ 0 };// 0 means not, >0 means in batch mode.
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxWeakRef< wxFrame > mFrame{};
|
||||||
|
wxWeakRef< wxWindow > mPanel{};
|
||||||
|
};
|
||||||
|
|
||||||
|
///\brief Get the top-level window associated with the project (as a wxFrame
|
||||||
|
/// only, when you do not need to use the subclass ProjectWindow)
|
||||||
|
TENACITY_DLL_API wxFrame &GetProjectFrame( AudacityProject &project );
|
||||||
|
TENACITY_DLL_API const wxFrame &GetProjectFrame( const AudacityProject &project );
|
||||||
|
|
||||||
|
///\brief Get a pointer to the window associated with a project, or null if
|
||||||
|
/// the given pointer is null.
|
||||||
|
inline wxFrame *FindProjectFrame( AudacityProject *project ) {
|
||||||
|
return project ? &GetProjectFrame( *project ) : nullptr;
|
||||||
|
}
|
||||||
|
inline const wxFrame *FindProjectFrame( const AudacityProject *project ) {
|
||||||
|
return project ? &GetProjectFrame( *project ) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Make a WindowPlacement object suitable for `project` (which may be null)
|
||||||
|
/*! @post return value is not null */
|
||||||
|
TENACITY_DLL_API std::unique_ptr<const BasicUI::WindowPlacement>
|
||||||
|
ProjectFramePlacement( AudacityProject *project );
|
||||||
|
|
||||||
|
///\brief Get the main sub-window of the project frame that displays track data
|
||||||
|
// (as a wxWindow only, when you do not need to use the subclass TrackPanel)
|
||||||
|
TENACITY_DLL_API wxWindow &GetProjectPanel( AudacityProject &project );
|
||||||
|
TENACITY_DLL_API const wxWindow &GetProjectPanel(
|
||||||
|
const AudacityProject &project );
|
||||||
|
|
||||||
|
// Generate a registry for serialized data attached to the project
|
||||||
|
#include "XMLMethodRegistry.h"
|
||||||
|
class AudacityProject;
|
||||||
|
using ProjectFileIORegistry = XMLMethodRegistry<AudacityProject>;
|
||||||
|
DECLARE_XML_METHOD_REGISTRY( TENACITY_DLL_API, ProjectFileIORegistry );
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user