added utility module for computing list of desktop apps handling MIME type
This commit is contained in:
parent
a46925d492
commit
7da8d7b293
4 changed files with 268 additions and 0 deletions
|
@ -58,6 +58,7 @@ ${depth}/rcldb/stemdb.cpp \
|
|||
${depth}/rcldb/stoplist.cpp \
|
||||
${depth}/rcldb/synfamily.cpp \
|
||||
${depth}/unac/unac.cpp \
|
||||
${depth}/utils/appformime.cpp \
|
||||
${depth}/utils/base64.cpp \
|
||||
${depth}/utils/circache.cpp \
|
||||
${depth}/utils/closefrom.cpp \
|
||||
|
|
|
@ -30,6 +30,14 @@ trfstreewalk.o : fstreewalk.cpp fstreewalk.h
|
|||
$(CXX) -o trfstreewalk.o -c $(ALL_CXXFLAGS) \
|
||||
-DTEST_FSTREEWALK fstreewalk.cpp
|
||||
|
||||
APPFORMIME_OBJS= trappformime.o
|
||||
trappformime : $(APPFORMIME_OBJS)
|
||||
$(CXX) -o trappformime $(APPFORMIME_OBJS) \
|
||||
$(LIBRECOLL) $(LIBICONV) $(LIBSYS)
|
||||
trappformime.o : appformime.cpp
|
||||
$(CXX) -o trappformime.o -c $(ALL_CXXFLAGS) \
|
||||
-DTEST_APPFORMIME appformime.cpp
|
||||
|
||||
READFILE_OBJS= trreadfile.o
|
||||
trreadfile : $(READFILE_OBJS)
|
||||
$(CXX) -o trreadfile $(READFILE_OBJS) $(LIBRECOLL) $(LIBICONV) $(LIBSYS)
|
||||
|
|
198
src/utils/appformime.cpp
Normal file
198
src/utils/appformime.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
/* Copyright (C) 2004 J.F.Dockes
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef TEST_APPFORMIME
|
||||
#include <conftree.h>
|
||||
#include <fstreewalk.h>
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include "pathut.h"
|
||||
#include "smallut.h"
|
||||
#include "appformime.h"
|
||||
|
||||
static const string topappsdir("/usr/share/applications");
|
||||
static const string desktopext("desktop");
|
||||
|
||||
static DesktopDb *theDb;
|
||||
|
||||
typedef map<string, vector<DesktopDb::AppDef> > AppMap;
|
||||
static AppMap theAppMap;
|
||||
|
||||
static std::string o_reason;
|
||||
static bool o_ok;
|
||||
|
||||
class FstCb : public FsTreeWalkerCB {
|
||||
public:
|
||||
FstCb(AppMap *appdefs)
|
||||
: m_appdefs(appdefs)
|
||||
{
|
||||
}
|
||||
virtual FsTreeWalker::Status
|
||||
processone(const string &, const struct stat *, FsTreeWalker::CbFlag);
|
||||
AppMap *m_appdefs;
|
||||
};
|
||||
|
||||
FsTreeWalker::Status FstCb::processone(const string& fn, const struct stat *,
|
||||
FsTreeWalker::CbFlag flg)
|
||||
{
|
||||
if (flg != FsTreeWalker::FtwRegular)
|
||||
return FsTreeWalker::FtwOk;
|
||||
|
||||
if (path_suffix(fn).compare(desktopext)) {
|
||||
//cerr << fn << " does not end with .desktop" << endl;
|
||||
return FsTreeWalker::FtwOk;
|
||||
}
|
||||
|
||||
ConfSimple dt(fn.c_str(), true);
|
||||
if (!dt.ok()) {
|
||||
cerr << fn << " cant parse" << endl;
|
||||
return FsTreeWalker::FtwOk;
|
||||
}
|
||||
string tp, nm, cmd, mt;
|
||||
if (!dt.get("Type", tp, "Desktop Entry")) {
|
||||
//cerr << fn << " no Type" << endl;
|
||||
return FsTreeWalker::FtwOk;
|
||||
}
|
||||
if (tp.compare("Application")) {
|
||||
//cerr << fn << " wrong Type " << tp << endl;
|
||||
return FsTreeWalker::FtwOk;
|
||||
}
|
||||
if (!dt.get("Exec", cmd, "Desktop Entry")) {
|
||||
//cerr << fn << " no Exec" << endl;
|
||||
return FsTreeWalker::FtwOk;
|
||||
}
|
||||
if (!dt.get("Name", nm, "Desktop Entry")) {
|
||||
//cerr << fn << " no Name" << endl;
|
||||
nm = path_basename(fn, desktopext);
|
||||
}
|
||||
if (!dt.get("MimeType", mt, "Desktop Entry")) {
|
||||
//cerr << fn << " no MimeType" << endl;
|
||||
return FsTreeWalker::FtwOk;
|
||||
}
|
||||
DesktopDb::AppDef appdef(nm, cmd);
|
||||
// Breakup mime type list, and push app to mime entries
|
||||
vector<string> mimes;
|
||||
stringToTokens(mt, mimes, ";");
|
||||
for (vector<string>::const_iterator it = mimes.begin();
|
||||
it != mimes.end(); it++) {
|
||||
(*m_appdefs)[*it].push_back(appdef);
|
||||
}
|
||||
return FsTreeWalker::FtwOk;
|
||||
}
|
||||
|
||||
DesktopDb* DesktopDb::getDb()
|
||||
{
|
||||
if (theDb == 0) {
|
||||
theDb = new DesktopDb();
|
||||
}
|
||||
if (o_ok)
|
||||
return theDb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DesktopDb::DesktopDb()
|
||||
{
|
||||
FstCb procapp(&theAppMap);
|
||||
FsTreeWalker walker;
|
||||
if (walker.walk(topappsdir, procapp) != FsTreeWalker::FtwOk) {
|
||||
o_ok = false;
|
||||
o_reason = walker.getReason();
|
||||
}
|
||||
o_ok = true;
|
||||
}
|
||||
|
||||
bool DesktopDb::appForMime(const string& mime, vector<AppDef> *apps,
|
||||
string *reason)
|
||||
{
|
||||
AppMap::const_iterator it = theAppMap.find(mime);
|
||||
if (it == theAppMap.end()) {
|
||||
if (reason)
|
||||
*reason = string("No application found for ") + mime;
|
||||
}
|
||||
*apps = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
const string& DesktopDb::getReason()
|
||||
{
|
||||
return o_reason;
|
||||
}
|
||||
|
||||
#else // TEST_APPFORMIME
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
#include "appformime.h"
|
||||
|
||||
static char *thisprog;
|
||||
|
||||
static char usage [] =
|
||||
" appformime <mime type>\n\n"
|
||||
;
|
||||
static void
|
||||
Usage(void)
|
||||
{
|
||||
fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
thisprog = argv[0];
|
||||
argc--; argv++;
|
||||
|
||||
if (argc != 1)
|
||||
Usage();
|
||||
string mime = *argv++;argc--;
|
||||
|
||||
string reason;
|
||||
vector<DesktopDb::AppDef> appdefs;
|
||||
DesktopDb *ddb = DesktopDb::getDb();
|
||||
if (ddb == 0) {
|
||||
cerr << "Could not initialize desktop db: " << DesktopDb::getReason()
|
||||
<< endl;
|
||||
exit(1);
|
||||
}
|
||||
if (!ddb->appForMime(mime, &appdefs, &reason)) {
|
||||
cerr << "appForMime failed: " << reason << endl;
|
||||
exit(1);
|
||||
}
|
||||
if (appdefs.empty()) {
|
||||
cerr << "No application found for [" << mime << "]" << endl;
|
||||
exit(1);
|
||||
}
|
||||
cout << mime << " -> ";
|
||||
for (vector<DesktopDb::AppDef>::const_iterator it = appdefs.begin();
|
||||
it != appdefs.end(); it++) {
|
||||
cout << "[" << it->name << ", " << it->command << "], ";
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#endif //TEST_APPFORMIME
|
61
src/utils/appformime.h
Normal file
61
src/utils/appformime.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* Copyright (C) 2014 J.F.Dockes
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef _APPFORMIME_H_INCLUDED_
|
||||
#define _APPFORMIME_H_INCLUDED_
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Rather strangely, I could not find a reasonably simple piece of
|
||||
* code which would parse /usr/share/applications to return a list of
|
||||
* apps for a given mime type. So here goes. Note that the implementation
|
||||
* is very primitive for now (no use of cache file, no updating once built).
|
||||
*/
|
||||
class DesktopDb {
|
||||
public:
|
||||
class AppDef {
|
||||
public:
|
||||
AppDef(const std::string& nm, const std::string& cmd)
|
||||
: name(nm), command(cmd)
|
||||
{}
|
||||
std::string name;
|
||||
std::string command;
|
||||
};
|
||||
|
||||
static DesktopDb* getDb();
|
||||
static const string& getReason();
|
||||
~DesktopDb();
|
||||
|
||||
/**
|
||||
* Get a list of applications able to process a given MIME type.
|
||||
* @param mime MIME type we want the apps for
|
||||
* @param[output] apps appropriate applications
|
||||
* @param[output] reason if we fail, an explanation ?
|
||||
* @return true for no error (apps may still be empty). false if a serious
|
||||
* problem was detected.
|
||||
*/
|
||||
bool appForMime(const std::string& mime, vector<AppDef> *apps,
|
||||
std::string *reason);
|
||||
|
||||
private:
|
||||
DesktopDb();
|
||||
DesktopDb(const DesktopDb &);
|
||||
DesktopDb& operator=(const DesktopDb &);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _APPFORMIME_H_INCLUDED_ */
|
Loading…
Add table
Add a link
Reference in a new issue