mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 16:10:06 +02:00
Define FileNames::FileType and related utility functions
This commit is contained in:
parent
1c7fd66b6e
commit
fc668f09b0
@ -49,6 +49,102 @@ used throughout Audacity into this one place.
|
|||||||
|
|
||||||
static wxString gDataDir;
|
static wxString gDataDir;
|
||||||
|
|
||||||
|
const FileNames::FileType
|
||||||
|
FileNames::AllFiles{ XO("All files"), { wxT("") } }
|
||||||
|
/* i18n-hint an Audacity project is the state of the program, stored as
|
||||||
|
files that can be reopened to resume the session later */
|
||||||
|
, FileNames::AudacityProjects{ XO("Audacity projects"), { wxT("aup") }, true }
|
||||||
|
, FileNames::DynamicLibraries{
|
||||||
|
#if defined(__WXMSW__)
|
||||||
|
XO("Dynamically Linked Libraries"), { wxT("dll") }, true
|
||||||
|
#elif defined(__WXMAC__)
|
||||||
|
XO("Dynamic Libraries"), { wxT("dylib") }, true
|
||||||
|
#else
|
||||||
|
XO("Dynamically Linked Libraries"), { wxT("so*") }, true
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
, FileNames::TextFiles{ XO("Text files"), { wxT("txt") }, true }
|
||||||
|
, FileNames::XMLFiles{ XO("XML files"), { wxT("xml"), wxT("XML") }, true }
|
||||||
|
;
|
||||||
|
|
||||||
|
wxString FileNames::FormatWildcard( const FileTypes &fileTypes )
|
||||||
|
{
|
||||||
|
// |-separated list of:
|
||||||
|
// [ Description,
|
||||||
|
// ( if appendExtensions, then ' (', globs, ')' ),
|
||||||
|
// '|',
|
||||||
|
// globs ]
|
||||||
|
// where globs is a ;-separated list of filename patterns, which are
|
||||||
|
// '*' for an empty extension, else '*.' then the extension
|
||||||
|
// Only the part before | is displayed in the choice drop-down of file
|
||||||
|
// dialogs
|
||||||
|
//
|
||||||
|
// Exceptional case: if there is only one type and its description is empty,
|
||||||
|
// then just give the globs with no |
|
||||||
|
// Another exception: an empty description, when there is more than one
|
||||||
|
// type, is replaced with a default
|
||||||
|
// Another exception: if an extension contains a dot, it is interpreted as
|
||||||
|
// not really an extension, but a literal filename
|
||||||
|
|
||||||
|
const wxString dot{ '.' };
|
||||||
|
const auto makeGlobs = [&dot]( const FileExtensions &extensions ){
|
||||||
|
wxString globs;
|
||||||
|
for ( const auto &extension: extensions ) {
|
||||||
|
if ( !globs.empty() )
|
||||||
|
globs += ';';
|
||||||
|
if ( extension.Contains( dot ) )
|
||||||
|
globs += extension;
|
||||||
|
else {
|
||||||
|
globs += '*';
|
||||||
|
if ( !extension.empty() ) {
|
||||||
|
globs += '.';
|
||||||
|
globs += extension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return globs;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto defaultDescription = []( const FileExtensions &extensions ){
|
||||||
|
// Assume extensions is not empty
|
||||||
|
wxString exts = extensions[0];
|
||||||
|
for (size_t ii = 1, size = extensions.size(); ii < size; ++ii ) {
|
||||||
|
exts += XO(", ").Translation();
|
||||||
|
exts += extensions[ii];
|
||||||
|
}
|
||||||
|
/* i18n-hint a type or types such as "txt" or "txt, xml" will be
|
||||||
|
substituted for %s */
|
||||||
|
return XO("%s files").Format( exts );
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( fileTypes.size() == 1 && fileTypes[0].description.empty() ) {
|
||||||
|
return makeGlobs( fileTypes[0].extensions );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wxString result;
|
||||||
|
for ( const auto &fileType : fileTypes ) {
|
||||||
|
const auto &extensions = fileType.extensions;
|
||||||
|
if (extensions.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!result.empty())
|
||||||
|
result += '|';
|
||||||
|
|
||||||
|
const auto globs = makeGlobs( extensions );
|
||||||
|
|
||||||
|
auto mask = fileType.description;
|
||||||
|
if ( mask.empty() )
|
||||||
|
mask = defaultDescription( extensions );
|
||||||
|
if ( fileType.appendExtensions )
|
||||||
|
mask.Join( XO("(%s)").Format( globs ), " " );
|
||||||
|
result += mask.Translation();
|
||||||
|
result += '|';
|
||||||
|
result += globs;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool FileNames::CopyFile(
|
bool FileNames::CopyFile(
|
||||||
const FilePath& file1, const FilePath& file2, bool overwrite)
|
const FilePath& file1, const FilePath& file2, bool overwrite)
|
||||||
{
|
{
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <wx/dir.h> // for wxDIR_FILES
|
#include <wx/dir.h> // for wxDIR_FILES
|
||||||
#include <wx/string.h> // function return value
|
#include <wx/string.h> // function return value
|
||||||
#include "audacity/Types.h"
|
#include "audacity/Types.h"
|
||||||
|
#include "MemoryX.h"
|
||||||
|
|
||||||
class wxFileName;
|
class wxFileName;
|
||||||
class wxFileNameWrapper;
|
class wxFileNameWrapper;
|
||||||
@ -25,6 +26,37 @@ class wxFileNameWrapper;
|
|||||||
class AUDACITY_DLL_API FileNames
|
class AUDACITY_DLL_API FileNames
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// A description of a type of file
|
||||||
|
struct FileType {
|
||||||
|
FileType() = default;
|
||||||
|
|
||||||
|
FileType( TranslatableString d, FileExtensions e, bool a = false )
|
||||||
|
: description{ std::move( d ) }
|
||||||
|
, extensions( std::move( e ) )
|
||||||
|
, appendExtensions{ a }
|
||||||
|
{}
|
||||||
|
|
||||||
|
TranslatableString description;
|
||||||
|
FileExtensions extensions;
|
||||||
|
// Whether to extend the displayed description with mention of the
|
||||||
|
// extensions:
|
||||||
|
bool appendExtensions = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frequently used types
|
||||||
|
static const FileType
|
||||||
|
AllFiles // *
|
||||||
|
, AudacityProjects // *.aup
|
||||||
|
, DynamicLibraries // depends on the operating system
|
||||||
|
, TextFiles // *.txt
|
||||||
|
, XMLFiles; // *.xml, *.XML
|
||||||
|
|
||||||
|
using FileTypes = std::vector< FileType >;
|
||||||
|
|
||||||
|
// Convert fileTypes into a single string as expected by wxWidgets file
|
||||||
|
// selection dialog
|
||||||
|
static wxString FormatWildcard( const FileTypes &fileTypes );
|
||||||
|
|
||||||
// This exists to compensate for bugs in wxCopyFile:
|
// This exists to compensate for bugs in wxCopyFile:
|
||||||
static bool CopyFile(
|
static bool CopyFile(
|
||||||
const FilePath& file1, const FilePath& file2, bool overwrite = true);
|
const FilePath& file1, const FilePath& file2, bool overwrite = true);
|
||||||
|
@ -41,6 +41,7 @@ and ImportLOF.cpp.
|
|||||||
#include "ImportPlugin.h"
|
#include "ImportPlugin.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
@ -145,6 +146,78 @@ void Importer::GetSupportedImportFormats(FormatList *formatList)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileNames::FileTypes
|
||||||
|
Importer::GetFileTypes( const FileNames::FileType &extraType )
|
||||||
|
{
|
||||||
|
// Construct the filter
|
||||||
|
FileNames::FileTypes fileTypes{
|
||||||
|
FileNames::AllFiles,
|
||||||
|
// Will fill in the list of extensions later:
|
||||||
|
{ XO("All supported files"), {} }
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( !extraType.extensions.empty() )
|
||||||
|
fileTypes.push_back( extraType );
|
||||||
|
|
||||||
|
FormatList l;
|
||||||
|
GetSupportedImportFormats(&l);
|
||||||
|
|
||||||
|
using ExtensionSet = std::unordered_set< FileExtension >;
|
||||||
|
FileExtensions allList = extraType.extensions, newList;
|
||||||
|
ExtensionSet allSet{ allList.begin(), allList.end() }, newSet;
|
||||||
|
for ( const auto &format : l ) {
|
||||||
|
newList.clear();
|
||||||
|
newSet.clear();
|
||||||
|
for ( const auto &extension : format.formatExtensions ) {
|
||||||
|
if ( newSet.insert( extension ).second )
|
||||||
|
newList.push_back( extension );
|
||||||
|
if ( allSet.insert( extension ).second )
|
||||||
|
allList.push_back( extension );
|
||||||
|
}
|
||||||
|
fileTypes.push_back( { format.formatName, newList } );
|
||||||
|
}
|
||||||
|
|
||||||
|
fileTypes[1].extensions = allList;
|
||||||
|
return fileTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Importer::SetLastOpenType( const FileNames::FileType &type )
|
||||||
|
{
|
||||||
|
// PRL: Preference key /LastOpenType, unusually, stores a localized
|
||||||
|
// string!
|
||||||
|
// The bad consequences of a change of locale are not severe -- only that
|
||||||
|
// a default choice of file type for an open dialog is not remembered
|
||||||
|
gPrefs->Write(wxT("/LastOpenType"), type.description.Translation());
|
||||||
|
gPrefs->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Importer::SetDefaultOpenType( const FileNames::FileType &type )
|
||||||
|
{
|
||||||
|
// PRL: Preference key /DefaultOpenType, unusually, stores a localized
|
||||||
|
// string!
|
||||||
|
// The bad consequences of a change of locale are not severe -- only that
|
||||||
|
// a default choice of file type for an open dialog is not remembered
|
||||||
|
gPrefs->Write(wxT("/DefaultOpenType"), type.description.Translation());
|
||||||
|
gPrefs->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Importer::SelectDefaultOpenType( const FileNames::FileTypes &fileTypes )
|
||||||
|
{
|
||||||
|
wxString defaultValue;
|
||||||
|
if ( !fileTypes.empty() )
|
||||||
|
defaultValue = fileTypes[0].description.Translation();
|
||||||
|
|
||||||
|
wxString type = gPrefs->Read(wxT("/DefaultOpenType"), defaultValue);
|
||||||
|
// Convert the type to the filter index
|
||||||
|
auto begin = fileTypes.begin();
|
||||||
|
auto index = std::distance(
|
||||||
|
begin,
|
||||||
|
std::find_if( begin, fileTypes.end(),
|
||||||
|
[&type](const FileNames::FileType &fileType){
|
||||||
|
return fileType.description.Translation() == type; } ) );
|
||||||
|
return (index == fileTypes.size()) ? 0 : index;
|
||||||
|
}
|
||||||
|
|
||||||
void Importer::StringToList(wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod)
|
void Importer::StringToList(wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod)
|
||||||
{
|
{
|
||||||
wxStringTokenizer toker;
|
wxStringTokenizer toker;
|
||||||
@ -389,10 +462,6 @@ bool Importer::Import(const FilePath &fName,
|
|||||||
|
|
||||||
for (const auto &plugin : sImportPluginList())
|
for (const auto &plugin : sImportPluginList())
|
||||||
{
|
{
|
||||||
// PRL: Preference keys /DefaultOpenType and /LastOpenType, unusually,
|
|
||||||
// store localized strings!
|
|
||||||
// The bad consequences of a change of locale are not severe -- only that
|
|
||||||
// a default choice of file type for an open dialog is not remembered
|
|
||||||
if (plugin->GetPluginFormatDescription().Translation() == type )
|
if (plugin->GetPluginFormatDescription().Translation() == type )
|
||||||
{
|
{
|
||||||
// This plugin corresponds to user-selected filter, try it first.
|
// This plugin corresponds to user-selected filter, try it first.
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <wx/tokenzr.h> // for enum wxStringTokenizerMode
|
#include <wx/tokenzr.h> // for enum wxStringTokenizerMode
|
||||||
|
|
||||||
#include "../widgets/wxPanelWrapper.h" // to inherit
|
#include "../widgets/wxPanelWrapper.h" // to inherit
|
||||||
|
#include "../FileNames.h" // for FileType
|
||||||
|
|
||||||
class wxArrayString;
|
class wxArrayString;
|
||||||
class wxListBox;
|
class wxListBox;
|
||||||
@ -120,6 +121,31 @@ public:
|
|||||||
*/
|
*/
|
||||||
void GetSupportedImportFormats(FormatList *formatList);
|
void GetSupportedImportFormats(FormatList *formatList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a list of types, for use by file opening dialogs, that includes
|
||||||
|
* all supported file types
|
||||||
|
*/
|
||||||
|
FileNames::FileTypes
|
||||||
|
GetFileTypes( const FileNames::FileType &extraType = {} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remember a file type in preferences
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
SetLastOpenType( const FileNames::FileType &type );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remember a file type in preferences
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
SetDefaultOpenType( const FileNames::FileType &type );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Choose index of preferred type
|
||||||
|
*/
|
||||||
|
static size_t
|
||||||
|
SelectDefaultOpenType( const FileNames::FileTypes &fileTypes );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads extended import filters from gPrefs into internal
|
* Reads extended import filters from gPrefs into internal
|
||||||
* list mExtImportItems
|
* list mExtImportItems
|
||||||
|
Loading…
x
Reference in New Issue
Block a user