From: Vadim Zeitlin Date: Mon, 18 Dec 2000 04:48:37 +0000 (+0000) Subject: wxMimeTypesManager now supports creating associations as well as querying X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/c7ce8392e0fa752d121000b7732c8f4ac3e3088d?ds=sidebyside wxMimeTypesManager now supports creating associations as well as querying them (MSW only, thanks to Chris Elliott) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8936 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/mimetype.h b/include/wx/mimetype.h index dcd26cafa4..28a529ddda 100644 --- a/include/wx/mimetype.h +++ b/include/wx/mimetype.h @@ -3,6 +3,7 @@ // Purpose: classes and functions to manage MIME types // Author: Vadim Zeitlin // Modified by: +// Chris Elliott (biol75@york.ac.uk) 5 Dec 00: write support for Win32 // Created: 23.09.98 // RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin @@ -81,8 +82,12 @@ public: // fill passed in array with all extensions associated with this file // type bool GetExtensions(wxArrayString& extensions); - // get the icon corresponding to this file type - bool GetIcon(wxIcon *icon) const; + // get the icon corresponding to this file type, the name of the file + // where the icon resides is return in iconfile if !NULL and its index + // in this file (Win-only) is in iconIndex + bool GetIcon(wxIcon *icon, + wxString *iconFile = NULL, + int *iconIndex = NULL) const; // get a brief file type description ("*.txt" => "text document") bool GetDescription(wxString *desc) const; @@ -94,6 +99,39 @@ public: bool GetPrintCommand(wxString *printCmd, const MessageParameters& params) const; + + // return the number of commands defined for this file type, 0 if none + size_t GetAllCommands(wxArrayString *verbs, wxArrayString *commands, + const wxFileType::MessageParameters& params) const; + + // the methods which modify the system database are only implemented under + // Win32 so far (on other platforms they will just return FALSE) + // + // also, they should only be used with the objects created using + // wxMimeTypesManager::Associate() + + // set the command to be used for opening the file + bool SetOpenCommand(const wxString& cmd, bool overwriteprompt = TRUE); + + // set an arbitrary command, ask confirmation if it already exists and + // overwriteprompt is TRUE + bool SetCommand(const wxString& cmd, const wxString& verb, + bool overwriteprompt = TRUE); + + // set the MIME type for this filetype + bool SetMimeType(const wxString& mimeType); + // set the default icon for this filetype + bool SetDefaultIcon(const wxString& cmd = wxEmptyString, int index = 0); + + // remove the association from the system database + bool Unassociate(); + + // delete registration info + bool RemoveOpenCommand(); + bool RemoveCommand(const wxString& verb); + bool RemoveMimeType(); + bool RemoveDefaultIcon(); + // operations // expand a string in the format of GetOpenCommand (which may contain // '%s' and '%t' format specificators for the file name and mime type @@ -186,6 +224,7 @@ public: // deleting it. // get file type from file extension wxFileType *GetFileTypeFromExtension(const wxString& ext); + wxFileType *GetOrAllocateFileTypeFromExtension(const wxString& ext); // get file type from MIME type (in format /) wxFileType *GetFileTypeFromMimeType(const wxString& mimeType); @@ -218,6 +257,14 @@ public: // The filetypes array should be terminated by a NULL entry void AddFallbacks(const wxFileTypeInfo *filetypes); + // create a new association between the given extension and MIME type and + // return the wxFileType object corresponding (which should be deleted by + // caller) or NULL if something went wrong + wxFileType *Associate(const wxString& ext, + const wxString& mimeType, + const wxString& filetype = wxEmptyString, + const wxString& desc = wxEmptyString); + // dtor (not virtual, shouldn't be derived from) ~wxMimeTypesManager(); @@ -227,10 +274,10 @@ private: wxMimeTypesManager& operator=(const wxMimeTypesManager&); wxMimeTypesManagerImpl *m_impl; - + // if m_impl is NULL, create one void EnsureImpl(); - + friend class wxMimeTypeCmnModule; }; diff --git a/include/wx/msw/mimetype.h b/include/wx/msw/mimetype.h index 605c00fe01..4a15a2b72f 100644 --- a/include/wx/msw/mimetype.h +++ b/include/wx/msw/mimetype.h @@ -32,8 +32,7 @@ public: // initialize us with our file type name and extension - in this case // we will read all other data from the registry - void Init(const wxString& strFileType, const wxString& ext) - { m_strFileType = strFileType; m_ext = ext; } + void Init(const wxString& strFileType, const wxString& ext); // initialize us with a wxFileTypeInfo object - it contains all the // data @@ -44,26 +43,43 @@ public: bool GetExtensions(wxArrayString& extensions); bool GetMimeType(wxString *mimeType) const; bool GetMimeTypes(wxArrayString& mimeTypes) const; - bool GetIcon(wxIcon *icon) const; + bool GetIcon(wxIcon *icon, wxString *sCommand = NULL, int *iIndex = NULL) const; bool GetDescription(wxString *desc) const; bool GetOpenCommand(wxString *openCmd, const wxFileType::MessageParameters& params) const; bool GetPrintCommand(wxString *printCmd, const wxFileType::MessageParameters& params) const; + size_t GetAllCommands(wxArrayString * verbs, wxArrayString * commands, + const wxFileType::MessageParameters& params) const; + + bool SetCommand(const wxString& cmd, const wxString& verb, + bool overwriteprompt = true); + bool SetMimeType(const wxString& mimeType); + bool SetDefaultIcon(const wxString& cmd = wxEmptyString, int index = 0); + + bool RemoveCommand(const wxString& verb); + bool RemoveMimeType(); + bool RemoveDefaultIcon(); + private: // helper function: reads the command corresponding to the specified verb // from the registry (returns an empty string if not found) wxString GetCommand(const wxChar *verb) const; + // get the registry path for the given verb + wxString GetVerbPath(const wxString& verb) const; + + // check that the registry key for our extension exists, create it if it + // doesn't, return FALSE if this failed + bool EnsureExtKeyExists(); + // we use either m_info or read the data from the registry if m_info == NULL const wxFileTypeInfo *m_info; wxString m_strFileType, // may be empty m_ext; }; - - class WXDLLEXPORT wxMimeTypesManagerImpl { public: @@ -73,6 +89,7 @@ public: // implement containing class functions wxFileType *GetFileTypeFromExtension(const wxString& ext); + wxFileType *GetOrAllocateFileTypeFromExtension(const wxString& ext) ; wxFileType *GetFileTypeFromMimeType(const wxString& mimeType); size_t EnumAllFileTypes(wxArrayString& mimetypes); @@ -85,6 +102,9 @@ public: void AddFallback(const wxFileTypeInfo& ft) { m_fallbacks.Add(ft); } + // create a new filetype with the given name and extension + wxFileType *CreateFileType(const wxString& filetype, const wxString& ext); + private: wxArrayFileTypeInfo m_fallbacks; }; diff --git a/samples/console/console.cpp b/samples/console/console.cpp index bf78c7d957..984046b47a 100644 --- a/samples/console/console.cpp +++ b/samples/console/console.cpp @@ -40,7 +40,7 @@ //#define TEST_DATETIME //#define TEST_DIR //#define TEST_DLLLOADER -#define TEST_ENVIRON +//#define TEST_ENVIRON //#define TEST_EXECUTE //#define TEST_FILE //#define TEST_FILECONF @@ -48,7 +48,7 @@ //#define TEST_LIST //#define TEST_LOG //#define TEST_LONGLONG -//#define TEST_MIME +#define TEST_MIME //#define TEST_INFO_FUNCTIONS //#define TEST_REGISTRY //#define TEST_SOCKETS @@ -763,6 +763,32 @@ static void TestMimeFilename() } } +static void TestMimeAssociate() +{ + wxPuts(_T("*** Testing creation of filetype association ***\n")); + + wxFileType *ft = g_mimeManager.Associate + ( + _T(".xyz"), + _T("application/x-xyz"), + _T("XYZFile"), // filetype (MSW only) + _T("XYZ File") // description (Unix only) + ); + if ( !ft ) + { + wxPuts(_T("ERROR: failed to create association!")); + } + else + { + if ( !ft->SetOpenCommand(_T("myprogram")) ) + { + wxPuts(_T("ERROR: failed to set open command!")); + } + + delete ft; + } +} + #endif // TEST_MIME // ---------------------------------------------------------------------------- @@ -3809,9 +3835,12 @@ int main(int argc, char **argv) #ifdef TEST_MIME wxLog::AddTraceMask(_T("mime")); if ( 0 ) + { TestMimeEnum(); - TestMimeOverride(); - TestMimeFilename(); + TestMimeOverride(); + TestMimeFilename(); + } + TestMimeAssociate(); #endif // TEST_MIME #ifdef TEST_INFO_FUNCTIONS diff --git a/src/common/mimecmn.cpp b/src/common/mimecmn.cpp index 7a773543f0..8bf7953030 100644 --- a/src/common/mimecmn.cpp +++ b/src/common/mimecmn.cpp @@ -3,6 +3,7 @@ // Purpose: classes and functions to manage MIME types // Author: Vadim Zeitlin // Modified by: +// Chris Elliott (biol75@york.ac.uk) 5 Dec 00: write support for Win32 // Created: 23.09.98 // RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin @@ -66,13 +67,13 @@ class WXDLLEXPORT wxIcon; // implementation classes: #if defined(__WXMSW__) -#include "wx/msw/mimetype.h" + #include "wx/msw/mimetype.h" #elif defined (__WXMAC__) -#include "wx/mac/mimetype.h" + #include "wx/mac/mimetype.h" #elif defined (__WXPM__) -#include "wx/os2/mimetype.h" -#else -#include "wx/unix/mimetype.h" + #include "wx/os2/mimetype.h" +#else // Unix + #include "wx/unix/mimetype.h" #endif // ============================================================================ @@ -230,9 +231,15 @@ bool wxFileType::GetMimeTypes(wxArrayString& mimeTypes) const return m_impl->GetMimeTypes(mimeTypes); } -bool wxFileType::GetIcon(wxIcon *icon) const +bool wxFileType::GetIcon(wxIcon *icon, + wxString *iconFile, + int *iconIndex) const { +#ifdef __WXMSW__ + return m_impl->GetIcon(icon, iconFile, iconIndex); +#else return m_impl->GetIcon(icon); +#endif } bool wxFileType::GetDescription(wxString *desc) const @@ -254,13 +261,156 @@ wxFileType::GetPrintCommand(wxString *printCmd, return m_impl->GetPrintCommand(printCmd, params); } + +size_t wxFileType::GetAllCommands(wxArrayString *verbs, + wxArrayString *commands, + const wxFileType::MessageParameters& params) const +{ + if ( verbs ) + verbs->Clear(); + if ( commands ) + commands->Clear(); + +#ifdef __WXMSW__ + return m_impl->GetAllCommands(verbs, commands, params); +#else // !__WXMSW__ + // we don't know how to retrieve all commands, so just try the 2 we know + // about + size_t count = 0; + wxString cmd; + if ( m_impl->GetOpenCommand(&cmd, params) ) + { + if ( verbs ) + verbs->Add(_T("Open")); + if ( commands ) + commands->Add(cmd); + count++; + } + + if ( GetPrintCommand(&cmd, params) ) + { + if ( verbs ) + verbs->Add(_T("Print")); + if ( commands ) + commands->Add(cmd); + + count++; + } + + return count; +#endif // __WXMSW__/!__WXMSW__ +} + +bool wxFileType::SetOpenCommand(const wxString& cmd, bool overwriteprompt) +{ + return SetCommand(cmd, _T("open"), overwriteprompt); +} + +bool wxFileType::SetCommand(const wxString& cmd, const wxString& verb, + bool overwriteprompt) +{ +#ifdef __WXMSW__ + return m_impl->SetCommand(cmd, verb, overwriteprompt); +#else + wxFAIL_MSG(_T("not implemented")); + + return FALSE; +#endif +} + +bool wxFileType::SetMimeType(const wxString& mimeType) +{ + // empty MIME type is meaningless here + wxCHECK_MSG( !mimeType.empty(), FALSE, _T("use RemoveMimeType()") ); + +#ifdef __WXMSW__ + return m_impl->SetMimeType(mimeType); +#else + wxFAIL_MSG(_T("not implemented")); + + return FALSE; +#endif +} + +bool wxFileType::SetDefaultIcon(const wxString& cmd, int index) +{ + wxString sTmp = cmd; + // VZ: should we do this? + if ( sTmp.empty() ) + GetOpenCommand(&sTmp, wxFileType::MessageParameters("", "")); + + wxCHECK_MSG( !sTmp.empty(), false, _T("need the icon file") ); + + +#ifdef __WXMSW__ + return m_impl->SetDefaultIcon (cmd, index); +#else + wxFAIL_MSG(_T("not implemented")); + + return FALSE; +#endif +} + +// now do remove functions +bool wxFileType::RemoveOpenCommand() +{ + return RemoveCommand(_T("open")); +} + +bool wxFileType::RemoveCommand(const wxString& verb) +{ +#ifdef __WXMSW__ + return m_impl->RemoveCommand(verb); +#else + wxFAIL_MSG(_T("not implemented")); + + return FALSE; +#endif +} + +bool wxFileType::RemoveMimeType() +{ +#ifdef __WXMSW__ + return m_impl->RemoveMimeType (); +#else + wxFAIL_MSG(_T("not implemented")); + + return FALSE; +#endif +} + +bool wxFileType::RemoveDefaultIcon() +{ +#ifdef __WXMSW__ + return m_impl->RemoveDefaultIcon(); +#else + wxFAIL_MSG(_T("not implemented")); + + return FALSE; +#endif +} + +bool wxFileType::Unassociate() +{ + bool result = TRUE; + if ( !RemoveOpenCommand() ) + result = FALSE; + if ( !RemoveDefaultIcon() ) + result = FALSE; + if ( !RemoveMimeType() ) + result = FALSE; + + // in MSW this leaves a HKCR.xzy key + return result; +} + // ---------------------------------------------------------------------------- // wxMimeTypesManager // ---------------------------------------------------------------------------- void wxMimeTypesManager::EnsureImpl() { - if (m_impl == NULL) + if ( !m_impl ) m_impl = new wxMimeTypesManagerImpl; } @@ -293,8 +443,7 @@ wxMimeTypesManager::wxMimeTypesManager() wxMimeTypesManager::~wxMimeTypesManager() { - if (m_impl != NULL) - delete m_impl; + delete m_impl; } wxFileType * @@ -304,6 +453,34 @@ wxMimeTypesManager::GetFileTypeFromExtension(const wxString& ext) return m_impl->GetFileTypeFromExtension(ext); } +wxFileType * +wxMimeTypesManager::GetOrAllocateFileTypeFromExtension(const wxString& ext) +{ + EnsureImpl(); + +#ifdef __WXMSW__ + // this writes a root entry to the registry in HKCR.ext + return m_impl->GetOrAllocateFileTypeFromExtension(ext); +#else // !__WXMSW__ + // VZ: "static const"??? (FIXME) + // just make a dummy entry with no writing to file + static const wxFileTypeInfo fallback[] = + { + wxFileTypeInfo("application/x-" + ext, + "", + "", + ext + " format file", + ext, NULL), + // must terminate the table with this! + wxFileTypeInfo() + }; + + AddFallbacks (fallback); + return m_impl->GetFileTypeFromExtension(ext); +#endif // __WXMSW__/!__WXMSW__ +} + + wxFileType * wxMimeTypesManager::GetFileTypeFromMimeType(const wxString& mimeType) { @@ -348,30 +525,26 @@ static wxMimeTypesManager gs_mimeTypesManager; // and public pointer wxMimeTypesManager * wxTheMimeTypesManager = &gs_mimeTypesManager; - - - - class wxMimeTypeCmnModule: public wxModule { -DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule) public: - wxMimeTypeCmnModule() : wxModule() {} - bool OnInit() { return TRUE; } - void OnExit() - { // this avoids false memory leak allerts: - if (gs_mimeTypesManager.m_impl != NULL) - { - delete gs_mimeTypesManager.m_impl; - gs_mimeTypesManager.m_impl = NULL; - } + wxMimeTypeCmnModule() : wxModule() { } + virtual bool OnInit() { return TRUE; } + virtual void OnExit() + { + // this avoids false memory leak allerts: + if ( gs_mimeTypesManager.m_impl != NULL ) + { + delete gs_mimeTypesManager.m_impl; + gs_mimeTypesManager.m_impl = NULL; + } } + + DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule) }; IMPLEMENT_DYNAMIC_CLASS(wxMimeTypeCmnModule, wxModule) - - #endif // wxUSE_FILE && wxUSE_TEXTFILE diff --git a/src/msw/mimetype.cpp b/src/msw/mimetype.cpp index 4ca0315ec2..699c76c856 100644 --- a/src/msw/mimetype.cpp +++ b/src/msw/mimetype.cpp @@ -52,7 +52,7 @@ class WXDLLEXPORT wxIcon; // These classes use Windows registry to retrieve the required information. // // Keys used (not all of them are documented, so it might actually stop working -// in futur versions of Windows...): +// in future versions of Windows...): // 1. "HKCR\MIME\Database\Content Type" contains subkeys for all known MIME // types, each key has a string value "Extension" which gives (dot preceded) // extension for the files of this MIME type. @@ -73,6 +73,218 @@ class WXDLLEXPORT wxIcon; // location, uses it, so it isn't likely to change static const wxChar *MIME_DATABASE_KEY = wxT("MIME\\Database\\Content Type\\"); +void wxFileTypeImpl::Init(const wxString& strFileType, const wxString& ext) +{ + // VZ: does it? (FIXME) + wxCHECK_RET( !ext.IsEmpty(), _T("needs an extension") ); + + if ( ext[0u] != wxT('.') ) { + m_ext = wxT('.'); + } + m_ext << ext; + + m_strFileType = strFileType; + if ( !strFileType ) { + m_strFileType = m_ext.AfterFirst('.') + "_auto_file"; + } +} + +wxString wxFileTypeImpl::GetVerbPath(const wxString& verb) const +{ + wxString path; + path << m_strFileType << _T("\\shell\\") << verb << _T("\\command"); + return path; +} + +size_t wxFileTypeImpl::GetAllCommands(wxArrayString *verbs, + wxArrayString *commands, + const wxFileType::MessageParameters& params) const +{ + wxCHECK_MSG( !m_ext.IsEmpty(), 0, _T("GetAllCommands() needs an extension") ); + + if ( m_strFileType.IsEmpty() ) + { + // get it from the registry + wxFileTypeImpl *self = wxConstCast(this, wxFileTypeImpl); + wxRegKey rkey(wxRegKey::HKCR, m_ext); + if ( !rkey.Exists() || !rkey.QueryValue(_T(""), self->m_strFileType) ) + { + wxLogDebug(_T("Can't get the filetype for extension '%s'."), + m_ext.c_str()); + + return 0; + } + } + + // enum all subkeys of HKCR\filetype\shell + size_t count = 0; + wxRegKey rkey(wxRegKey::HKCR, m_strFileType + _T("\\shell")); + long dummy; + wxString verb; + bool ok = rkey.GetFirstKey(verb, dummy); + while ( ok ) + { + wxString command = wxFileType::ExpandCommand(GetCommand(verb), params); + + // we want the open bverb to eb always the first + + if ( verb.CmpNoCase(_T("open")) == 0 ) + { + if ( verbs ) + verbs->Insert(verb, 0); + if ( commands ) + commands->Insert(command, 0); + } + else // anything else than "open" + { + if ( verbs ) + verbs->Add(verb); + if ( commands ) + commands->Add(command); + } + + ok = rkey.GetNextKey(verb, dummy); + } + + return count; +} + +// ---------------------------------------------------------------------------- +// modify the registry database +// ---------------------------------------------------------------------------- + +bool wxFileTypeImpl::EnsureExtKeyExists() +{ + wxRegKey rkey(wxRegKey::HKCR, m_ext); + if ( !rkey.Exists() ) + { + if ( !rkey.Create() || !rkey.SetValue(_T(""), m_strFileType) ) + { + wxLogError(_("Failed to create registry entry for '%s' files."), + m_ext.c_str()); + return FALSE; + } + } + + return TRUE; +} + +bool wxFileTypeImpl::SetCommand(const wxString& cmd, + const wxString& verb, + bool overwriteprompt) +{ + wxCHECK_MSG( !m_ext.IsEmpty() && !verb.IsEmpty(), FALSE, + _T("SetCommand() needs an extension and a verb") ); + + if ( !EnsureExtKeyExists() ) + return FALSE; + + wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb)); + + if ( rkey.Exists() && overwriteprompt ) + { +#if wxUSE_GUI + wxString old; + rkey.QueryValue(wxT(""), old); + if ( wxMessageBox + ( + wxString::Format( + _("Do you want to overwrite the command used to %s " + "files with extension \"%s\" (current value is '%s', " + "new value is '%s')?"), + verb.c_str(), + m_ext.c_str(), + old.c_str(), + cmd.c_str()), + _("Confirm registry update"), + wxYES_NO | wxICON_QUESTION + ) != wxYES ) +#endif // wxUSE_GUI + { + // cancelled by user + return FALSE; + } + } + + // TODO: + // 1. translate '%s' to '%1' instead of always adding it + // 2. create DDEExec value if needed (undo GetCommand) + return rkey.Create() && rkey.SetValue(_T(""), cmd + _T(" \"%1\"") ); +} + +bool wxFileTypeImpl::SetMimeType(const wxString& mimeTypeOrig) +{ + wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("SetMimeType() needs extension") ); + + if ( !EnsureExtKeyExists() ) + return FALSE; + + // VZ: is this really useful? (FIXME) + wxString mimeType; + if ( !mimeTypeOrig ) + { + // make up a default value for it + wxString cmd; + wxSplitPath(GetCommand(_T("open")), NULL, &cmd, NULL); + mimeType << _T("application/x-") << cmd; + } + else + { + mimeType = mimeTypeOrig; + } + + wxRegKey rkey(wxRegKey::HKCR, m_ext); + return rkey.Create() && rkey.SetValue(_T("Content Type"), mimeType); +} + +bool wxFileTypeImpl::SetDefaultIcon(const wxString& cmd, int index) +{ + wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("SetMimeType() needs extension") ); + wxCHECK_MSG( wxFileExists(cmd), FALSE, _T("Icon file not found.") ); + + if ( !EnsureExtKeyExists() ) + return FALSE; + + wxRegKey rkey(wxRegKey::HKCR, m_strFileType + _T("\\DefaultIcon")); + + return rkey.Create() && + rkey.SetValue(_T(""), + wxString::Format(_T("%s,%d"), cmd.c_str(), index)); +} + +// ---------------------------------------------------------------------------- +// remove file association +// ---------------------------------------------------------------------------- + +bool wxFileTypeImpl::RemoveCommand(const wxString& verb) +{ + wxCHECK_MSG( !m_ext.IsEmpty() && !verb.IsEmpty(), FALSE, + _T("RemoveCommand() needs an extension and a verb") ); + + wxString sKey = m_strFileType; + wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb)); + + // if the key already doesn't exist, it's a success + return !rkey.Exists() || rkey.DeleteSelf(); +} + +bool wxFileTypeImpl::RemoveMimeType() +{ + wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("RemoveMimeType() needs extension") ); + + wxRegKey rkey(wxRegKey::HKCR, m_ext); + return !rkey.Exists() || rkey.DeleteSelf(); +} + +bool wxFileTypeImpl::RemoveDefaultIcon() +{ + wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, + _T("RemoveDefaultIcon() needs extension") ); + + wxRegKey rkey (wxRegKey::HKCR, m_strFileType + _T("\\DefaultIcon")); + return !rkey.Exists() || rkey.DeleteSelf(); +} + wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const { // suppress possible error messages @@ -226,12 +438,11 @@ bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const // suppress possible error messages wxLogNull nolog; - wxRegKey key(wxRegKey::HKCR, wxT(".") + m_ext); + wxRegKey key(wxRegKey::HKCR, m_ext); return key.Open() && key.QueryValue(wxT("Content Type"), *mimeType); } - bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const { wxString s; @@ -247,7 +458,9 @@ bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const } -bool wxFileTypeImpl::GetIcon(wxIcon *icon) const +bool wxFileTypeImpl::GetIcon(wxIcon *icon, + wxString *iconFile, + int *iconIndex) const { #if wxUSE_GUI if ( m_info ) { @@ -280,7 +493,7 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon) const } wxString strExpPath = wxExpandEnvVars(strFullPath); - int nIndex = wxAtoi(strIndex); + int nIndex = wxAtoi(strIndex) - 1 ; //bug here we need C based counting!! HICON hIcon = ExtractIcon(GetModuleHandle(NULL), strExpPath, nIndex); switch ( (int)hIcon ) { @@ -292,6 +505,10 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon) const default: icon->SetHICON((WXHICON)hIcon); + if ( iconIndex ) + *iconIndex = nIndex; + if ( iconFile ) + *iconFile = strFullPath; return TRUE; } } @@ -326,6 +543,15 @@ bool wxFileTypeImpl::GetDescription(wxString *desc) const return FALSE; } +// helper function +wxFileType * +wxMimeTypesManagerImpl::CreateFileType(const wxString& filetype, const wxString& ext) +{ + wxFileType *fileType = new wxFileType; + fileType->m_impl->Init(filetype, ext); + return fileType; +} + // extension -> file type wxFileType * wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext) @@ -348,10 +574,7 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext) // it's the default value of the key if ( key.QueryValue(wxT(""), strFileType) ) { // create the new wxFileType object - wxFileType *fileType = new wxFileType; - fileType->m_impl->Init(strFileType, ext); - - return fileType; + return CreateFileType(strFileType, ext); } else { // this extension doesn't have a filetype, but it's known to the @@ -380,12 +603,22 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext) return NULL; } - wxFileType *fileType = new wxFileType; - fileType->m_impl->Init(wxEmptyString, ext); + return CreateFileType(wxEmptyString, ext); +} + +wxFileType * +wxMimeTypesManagerImpl::GetOrAllocateFileTypeFromExtension(const wxString& ext) +{ + wxFileType *fileType = GetFileTypeFromExtension(ext); + if ( !fileType ) + { + fileType = CreateFileType(wxEmptyString, ext); + } return fileType; } + // MIME type -> extension -> file type wxFileType * wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType) @@ -440,6 +673,93 @@ size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes) return mimetypes.GetCount(); } +// ---------------------------------------------------------------------------- +// create a new association +// ---------------------------------------------------------------------------- + +wxFileType *wxMimeTypesManager::Associate(const wxString& ext, + const wxString& mimetype, + const wxString& filetypeOrig, + const wxString& WXUNUSED(desc)) +{ + wxCHECK_MSG( !ext.empty(), NULL, _T("Associate() needs extension") ); + + wxString extWithDot; + if ( ext[0u] != _T('.') ) + extWithDot = _T('.'); + extWithDot += ext; + + wxRegKey key(wxRegKey::HKCR, extWithDot); + wxFileType *ft = NULL; + if ( !key.Exists() ) + { + wxString filetype; + + // create the mapping from the extension to the filetype + bool ok = key.Create(); + if ( ok ) + { + if ( filetypeOrig.empty() ) + { + // make it up from the extension + filetype << extWithDot.c_str() + 1 << _T("_auto_file"); + } + else + { + // just use the provided one + filetype = filetypeOrig; + } + + ok = key.SetValue(_T(""), filetype); + } + + if ( ok && !mimetype.empty() ) + { + // set the MIME type + ok = key.SetValue(_T("Content Type"), mimetype); + + if ( ok ) + { + // create the MIME key + wxString strKey = MIME_DATABASE_KEY; + strKey << mimetype; + wxRegKey keyMIME(wxRegKey::HKCR, strKey); + ok = keyMIME.Create(); + + if ( ok ) + { + // and provide a back link to the extension + ok = keyMIME.SetValue(_T("Extension"), extWithDot); + } + } + } + + if ( ok ) + { + // create the filetype key itself (it will be empty for now, but + // SetCommand(), SetDefaultIcon() &c will use it later) + wxRegKey keyFT(wxRegKey::HKCR, filetype); + ok = keyFT.Create(); + } + + if ( ok ) + { + // ok, we've created everything correctly + ft = m_impl->CreateFileType(filetype, extWithDot); + } + else + { + // one of the registry operations failed + wxLogError(_("Failed to register extension '%s'."), ext.c_str()); + } + } + else // key already exists + { + // FIXME we probably should return an existing file type then? + } + + return ft; +} #endif // __WIN16__