+ wxLogTrace(TRACE_MIME, wxT("loading KDE file %s"), filename.c_str());
+
+ wxMimeTextFile file;
+ if ( !file.Open(filename) )
+ return;
+
+ // Here, only type 'Application' should be considered.
+ int nIndex = file.pIndexOf( wxT("Type=") );
+ if (nIndex != wxNOT_FOUND &&
+ file.GetCmd(nIndex).Lower() != wxT("application"))
+ return;
+
+ // The hidden entry specifies a file to be ignored.
+ nIndex = file.pIndexOf( wxT("Hidden=") );
+ if (nIndex != wxNOT_FOUND && file.GetCmd(nIndex).Lower() == wxT("true"))
+ return;
+
+ // Semicolon separated list of mime types handled by the application.
+ nIndex = file.pIndexOf( wxT("MimeType=") );
+ if (nIndex == wxNOT_FOUND)
+ return;
+ wxString mimetypes = file.GetCmd (nIndex);
+
+ // Name of the application
+ wxString nameapp;
+ nIndex = wxNOT_FOUND;
+#if wxUSE_INTL // try "Name[locale name]" first
+ wxLocale *locale = wxGetLocale();
+ if ( locale )
+ nIndex = file.pIndexOf(_T("Name[")+locale->GetName()+_T("]="));
+#endif // wxUSE_INTL
+ if(nIndex == wxNOT_FOUND)
+ nIndex = file.pIndexOf( wxT("Name=") );
+ if(nIndex != wxNOT_FOUND)
+ nameapp = file.GetCmd(nIndex);
+
+ // Icon of the application.
+ wxString nameicon, namemini;
+ nIndex = wxNOT_FOUND;
+#if wxUSE_INTL // try "Icon[locale name]" first
+ if ( locale )
+ nIndex = file.pIndexOf(_T("Icon[")+locale->GetName()+_T("]="));
+#endif // wxUSE_INTL
+ if(nIndex == wxNOT_FOUND)
+ nIndex = file.pIndexOf( wxT("Icon=") );
+ if(nIndex != wxNOT_FOUND) {
+ nameicon = wxString(wxT("--icon ")) + file.GetCmd(nIndex);
+ namemini = wxString(wxT("--miniicon ")) + file.GetCmd(nIndex);
+ }
+
+ // Replace some of the field code in the 'Exec' entry.
+ // TODO: deal with %d, %D, %n, %N, %k and %v (but last one is deprecated)
+ nIndex = file.pIndexOf( wxT("Exec=") );
+ if (nIndex == wxNOT_FOUND)
+ return;
+ wxString sCmd = file.GetCmd(nIndex);
+ // we expect %f; others including %F and %U and %u are possible
+ sCmd.Replace(wxT("%F"), wxT("%f"));
+ sCmd.Replace(wxT("%U"), wxT("%f"));
+ sCmd.Replace(wxT("%u"), wxT("%f"));
+ if (0 == sCmd.Replace ( wxT("%f"), wxT("%s") ))
+ sCmd = sCmd + wxT(" %s");
+ sCmd.Replace(wxT("%c"), nameapp);
+ sCmd.Replace(wxT("%i"), nameicon);
+ sCmd.Replace(wxT("%m"), namemini);
+
+ wxStringTokenizer tokenizer(mimetypes, _T(";"));
+ while(tokenizer.HasMoreTokens()) {
+ wxString mimetype = tokenizer.GetNextToken().Lower();
+ nIndex = m_aTypes.Index(mimetype);
+ if(nIndex != wxNOT_FOUND) { // is this a known MIME type?
+ wxMimeTypeCommands* entry = m_aEntries[nIndex];
+ entry->AddOrReplaceVerb(wxT("open"), sCmd);
+ }
+ }
+}
+
+void wxMimeTypesManagerImpl::LoadKDEAppsFilesFromDir(const wxString& dirname)
+{
+ // Don't complain if we don't have permissions to read - it confuses users
+ wxLogNull logNull;
+
+ if(! wxDir::Exists(dirname))
+ return;
+ wxDir dir(dirname);
+ if ( !dir.IsOpened() )
+ return;
+
+ wxString filename;
+ // Look into .desktop files
+ bool cont = dir.GetFirst(&filename, _T("*.desktop"), wxDIR_FILES);
+ while(cont) {
+ wxFileName p(dirname, filename);
+ LoadKDEApp( p.GetFullPath() );
+ cont = dir.GetNext(&filename);
+ }
+ // Look recursively into subdirs
+ cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS);
+ while(cont) {
+ wxFileName p(dirname, wxEmptyString);
+ p.AppendDir(filename);
+ LoadKDEAppsFilesFromDir( p.GetPath() );
+ cont = dir.GetNext(&filename);
+ }
+}
+
+// Return base KDE directories.
+// 1) Environment variable $KDEHOME, or "~/.kde" if not set.
+// 2) List of directories in colon separated environment variable $KDEDIRS.
+// 3) Environment variable $KDEDIR in case $KDEDIRS is not set.
+// Notice at least the local kde directory is added to the list. If it is the
+// only one, use later the application 'kde-config' to get additional paths.
+static void GetKDEBaseDirs(wxArrayString& basedirs)
+{
+ wxString env = wxGetenv( wxT("KDEHOME") );
+ if(env.IsEmpty())
+ env = wxGetHomeDir() + wxT("/.kde");
+ basedirs.Add(env);
+
+ env = wxGetenv( wxT("KDEDIRS") );
+ if(env.IsEmpty()) {
+ env = wxGetenv( wxT("KDEDIR") );
+ if(! env.IsEmpty())
+ basedirs.Add(env);
+ } else {
+ wxStringTokenizer tokenizer(env, wxT(":"));
+ while(tokenizer.HasMoreTokens())
+ basedirs.Add( tokenizer.GetNextToken() );
+ }
+}
+
+static wxString ReadPathFromKDEConfig(const wxString& request)
+{
+ wxString str;
+ wxArrayString output;
+ if(wxExecute(wxT("kde-config --path ")+request, output) == 0 &&
+ output.GetCount() > 0)
+ str = output.Item(0);
+ return str;
+}
+
+// Try to find the "Theme" entry in the configuration file, provided it exists.
+static wxString GetKDEThemeInFile(const wxFileName& filename)
+{
+ wxString theme;
+ wxMimeTextFile config;
+ if ( filename.FileExists() && config.Open(filename.GetFullPath()) )
+ {
+ size_t cnt = config.GetLineCount();
+ for ( size_t i = 0; i < cnt; i++ )
+ {
+ if ( config[i].StartsWith(wxT("Theme="), &theme) )
+ break;
+ }
+ }
+
+ return theme;
+}
+
+// Try to find a file "kdeglobals" in one of the directories and read the
+// "Theme" entry there.
+static wxString GetKDETheme(const wxArrayString& basedirs)
+{
+ wxString theme;
+ for(size_t i = 0; i < basedirs.GetCount(); i++) {
+ wxFileName filename(basedirs.Item(i), wxEmptyString);
+ filename.AppendDir( wxT("share") );
+ filename.AppendDir( wxT("config") );
+ filename.SetName( wxT("kdeglobals") );
+ theme = GetKDEThemeInFile(filename);
+ if(! theme.IsEmpty())
+ return theme;
+ }
+ // If $KDEDIRS and $KDEDIR were set, we try nothing more. Otherwise, we
+ // try to get the configuration file with 'kde-config'.
+ if(basedirs.GetCount() > 1)
+ return theme;
+ wxString paths = ReadPathFromKDEConfig(wxT("config"));
+ if(! paths.IsEmpty()) {
+ wxStringTokenizer tokenizer(paths, wxT(":"));
+ while( tokenizer.HasMoreTokens() ) {
+ wxFileName filename(tokenizer.GetNextToken(), wxT("kdeglobals"));
+ theme = GetKDEThemeInFile(filename);
+ if(! theme.IsEmpty())
+ return theme;
+ }
+ }
+ return theme;
+}
+
+// Get list of directories of icons.
+static void GetKDEIconDirs(const wxArrayString& basedirs,
+ wxArrayString& icondirs)
+{
+ wxString theme = GetKDETheme(basedirs);
+ if(theme.IsEmpty())
+ theme = wxT("default.kde");
+
+ for(size_t i = 0; i < basedirs.GetCount(); i++) {
+ wxFileName dirname(basedirs.Item(i), wxEmptyString);
+ dirname.AppendDir( wxT("share") );
+ dirname.AppendDir( wxT("icons") );
+ dirname.AppendDir(theme);
+ dirname.AppendDir( wxT("32x32") );
+ dirname.AppendDir( wxT("mimetypes") );
+ if( wxDir::Exists( dirname.GetPath() ) )
+ icondirs.Add( dirname.GetPath() );
+ }
+
+ // If $KDEDIRS and $KDEDIR were not set, use 'kde-config'
+ if(basedirs.GetCount() > 1)
+ return;
+ wxString paths = ReadPathFromKDEConfig(wxT("icon"));
+ if(! paths.IsEmpty()) {
+ wxStringTokenizer tokenizer(paths, wxT(":"));
+ while( tokenizer.HasMoreTokens() ) {
+ wxFileName dirname(tokenizer.GetNextToken(), wxEmptyString);
+ dirname.AppendDir(theme);
+ dirname.AppendDir( wxT("32x32") );
+ dirname.AppendDir( wxT("mimetypes") );
+ if(icondirs.Index(dirname.GetPath()) == wxNOT_FOUND &&
+ wxDir::Exists( dirname.GetPath() ) )
+ icondirs.Add( dirname.GetPath() );
+ }
+ }
+}
+
+// Get list of directories of mime types.
+static void GetKDEMimeDirs(const wxArrayString& basedirs,
+ wxArrayString& mimedirs)
+{
+ for(size_t i = 0; i < basedirs.GetCount(); i++) {
+ wxFileName dirname(basedirs.Item(i), wxEmptyString);
+ dirname.AppendDir( wxT("share") );
+ dirname.AppendDir( wxT("mimelnk") );
+ if( wxDir::Exists( dirname.GetPath() ) )
+ mimedirs.Add( dirname.GetPath() );
+ }
+
+ // If $KDEDIRS and $KDEDIR were not set, use 'kde-config'
+ if(basedirs.GetCount() > 1)
+ return;
+ wxString paths = ReadPathFromKDEConfig(wxT("mime"));
+ if(! paths.IsEmpty()) {
+ wxStringTokenizer tokenizer(paths, wxT(":"));
+ while( tokenizer.HasMoreTokens() ) {
+ wxFileName p(tokenizer.GetNextToken(), wxEmptyString);
+ wxString dirname = p.GetPath(); // To remove possible trailing '/'
+ if(mimedirs.Index(dirname) == wxNOT_FOUND &&
+ wxDir::Exists(dirname) )
+ mimedirs.Add(dirname);
+ }
+ }
+}
+
+// Get list of directories of application desktop files.
+static void GetKDEAppsDirs(const wxArrayString& basedirs,
+ wxArrayString& appsdirs)
+{
+ for(size_t i = 0; i < basedirs.GetCount(); i++) {
+ wxFileName dirname(basedirs.Item(i), wxEmptyString);
+ dirname.AppendDir( wxT("share") );
+ dirname.AppendDir( wxT("applnk") );
+ if( wxDir::Exists( dirname.GetPath() ) )
+ appsdirs.Add( dirname.GetPath() );
+ }
+
+ // If $KDEDIRS and $KDEDIR were not set, use 'kde-config'
+ if(basedirs.GetCount() > 1)
+ return;
+ wxString paths = ReadPathFromKDEConfig(wxT("apps"));
+ if(! paths.IsEmpty()) {
+ wxStringTokenizer tokenizer(paths, wxT(":"));
+ while( tokenizer.HasMoreTokens() ) {
+ wxFileName p(tokenizer.GetNextToken(), wxEmptyString);
+ wxString dirname = p.GetPath(); // To remove possible trailing '/'
+ if(appsdirs.Index(dirname) == wxNOT_FOUND &&
+ wxDir::Exists(dirname) )
+ appsdirs.Add(dirname);
+ }
+ }
+ paths = ReadPathFromKDEConfig(wxT("xdgdata-apps"));
+ if(! paths.IsEmpty()) {
+ wxStringTokenizer tokenizer(paths, wxT(":"));
+ while( tokenizer.HasMoreTokens() ) {
+ wxFileName p(tokenizer.GetNextToken(), wxEmptyString);
+ wxString dirname = p.GetPath(); // To remove possible trailing '/'
+ if(appsdirs.Index(dirname) == wxNOT_FOUND &&
+ wxDir::Exists(dirname) )
+ appsdirs.Add(dirname);
+ }
+ }
+}
+
+// Fill database with all mime types.
+void wxMimeTypesManagerImpl::GetKDEMimeInfo(const wxString& sExtraDir)
+{
+ wxArrayString basedirs;
+ GetKDEBaseDirs(basedirs);
+