• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

desktop.h

Go to the documentation of this file.
00001 
00002 
00003 #include <wibble/string.h>
00004 
00005 #include <ept/token.h>
00006 #include <ept/core/desktopfile.h>
00007 #include <ept/core/source.h>
00008 
00009 #include <set>
00010 #include <vector>
00011 #include <fstream>
00012 #include <sstream>
00013 #include <iterator>
00014 #include <functional>
00015 
00016 #include <dirent.h>
00017 
00018 #ifndef EPT_CORE_DESKTOP_H
00019 #define EPT_CORE_DESKTOP_H
00020 
00021 namespace ept {
00022 namespace core {
00023 namespace desktop {
00024 
00025 typedef enum { Name, Group, ShortDescription, Package, Icon } PropertyId;
00026 
00027 template< PropertyId > struct PropertyType {};
00028 template<> struct PropertyType< Name > { typedef std::string T; };
00029 template<> struct PropertyType< Group > { typedef std::string T; };
00030 template<> struct PropertyType< ShortDescription > { typedef std::string T; };
00031 template<> struct PropertyType< Package > { typedef ept::Token T; };
00032 template<> struct PropertyType< Icon > { typedef std::string T; };
00033 
00034 typedef std::set< std::string > Categories;
00035 
00036 struct Category {
00037     std::string name;
00038     operator std::string() const { return name; }
00039 };
00040 
00041 inline std::istream &operator >>( std::istream &i, Category &cat ) {
00042     char c;
00043     cat.name = "";
00044     while ( i.peek() != EOF ) {
00045         c = i.get();
00046         if ( c == ';' ) return i;
00047         cat.name += c;
00048     }
00049     return i;
00050 }
00051 
00052 struct Entry : wibble::mixin::Comparable< Entry > {
00053     Entry() {}
00054     Entry( std::string n, std::string g,
00055            std::string p, std::string d , std::string i )
00056         : m_name( n ),
00057           m_package( p ),
00058           m_description( d ),
00059           m_icon( i )
00060     { setCategories( g ); }
00061 
00062     void load( std::string file ) {
00063         m_id = file;
00064         std::ifstream i( file.c_str() );
00065         if ( !i.is_open() )
00066             return; // throw?
00067         desktop::File e;
00068         i >> e;
00069         i.close();
00070         desktop::File::Group &g = e.group( "Desktop Entry" );
00071         m_name = g.entry( "Name" ).value;
00072         m_description = g.entry( "Comment" ).value;
00073         if ( m_description == "" )
00074             m_description = g.entry( "GenericName" ).value;
00075         m_package = g.entry( "X-AppInstall-Package" ).value;
00076         // m_group = g.entry( "Categories" ).value;
00077         m_icon = g.entry( "Icon" ).value;
00078         setCategories( g.entry( "Categories" ).value );
00079     }
00080 
00081     void setCategories( std::string s ) {
00082         std::istringstream i( s );
00083         m_categories.clear();
00084         std::remove_copy_if(
00085             std::istream_iterator< Category >( i ),
00086             std::istream_iterator< Category >(),
00087             std::inserter( m_categories, m_categories.begin() ),
00088             std::bind1st( std::equal_to< std::string >(), "" ) );
00089     }
00090 
00091     Categories categories() const { return m_categories; }
00092     bool inCategory( std::string c ) const {
00093         return m_categories.find( c ) != m_categories.end();
00094     }
00095     std::string id() const { return m_id; }
00096     std::string name() const { return m_name; }
00097     std::string package() const { return m_package; }
00098     std::string description() const { return m_description; }
00099     std::string icon() const { return m_icon; }
00100     bool operator< ( const Entry &o ) const {
00101         if ( m_name < o.m_name ) return true;
00102         if ( m_name == o.m_name )
00103             if ( m_package < o.m_package ) return true;
00104         return false;
00105     }
00106 protected:
00107     std::string m_name, m_package, m_description, m_icon, m_id;
00108     bool m_supported, m_free;
00109     Categories m_categories;
00110 };
00111 
00112 struct InternalList {
00113     std::string dir;
00114     std::string current;
00115     mutable Entry entry;
00116     off_t offset;
00117     mutable bool loaded;
00118 
00119     InternalList() : dir( "" ), offset( -2 ), loaded( false ) {}
00120     InternalList( std::string d ) : dir( d ), offset( -1 ), loaded( false )
00121     {
00122         firstFile();
00123     }
00124 
00125     Entry head() const {
00126         if (!loaded)
00127             entry.load( current );
00128         loaded = true;
00129         return entry;
00130     }
00131 
00132     bool empty() const {
00133         return (offset == -2);
00134     }
00135 
00136     void firstFile() {
00137         offset = -1;
00138         nextFile();
00139     }
00140 
00141     InternalList tail() const {
00142         InternalList r = *this;
00143         r.nextFile();
00144         return r;
00145     }
00146 
00147     void nextFile() {
00148         loaded = false;
00149         DIR *d = opendir( dir.c_str() );
00150         if ( !d ) {
00151             offset = -2;
00152             closedir( d );
00153             return;
00154         }
00155 
00156         if ( offset != -1 )
00157             seekdir( d, offset );
00158 
00159         dirent *ent = 0;
00160         while ( ( ent = readdir( d ) ) != 0 ) {
00161             std::string name( ent->d_name );
00162             if ( name == "." || name == ".." )
00163                 continue;
00164             if ( !wibble::str::endsWith( name, ".desktop" ) )
00165                 continue;
00166             current = dir + "/" + name;
00167             offset = telldir( d );
00168             closedir( d );
00169             return;
00170         }
00171         closedir( d );
00172         offset = -2;
00173     }
00174 };
00175 
00176 struct Setup {
00177     typedef ept::Token Token;
00178     typedef Entry Internal;
00179     typedef desktop::PropertyId PropertyId;
00180     typedef desktop::InternalList InternalList;
00181 };
00182 
00183 struct GroupPolicy {
00184     virtual std::string group( const Entry &e )
00185     {
00186         return wibble::str::fmt( e.categories() );
00187     }
00188     virtual ~GroupPolicy() {}
00189 };
00190 
00191 struct Source : core::Source< Source, Setup, PropertyType >
00192 {
00193     std::string m_dir;
00194 
00195     GroupPolicy m_defaultPolicy;
00196     GroupPolicy *m_policy;
00197 
00198     Source( std::string dir ) : m_dir( dir ),
00199                                 m_policy( &m_defaultPolicy ) {}
00200 
00201     InternalList listInternal() {
00202         return InternalList( m_dir );
00203     }
00204 
00205     Token getToken( Entry i ) {
00206         Token t;
00207         t._id = std::string( "desktop:" ) + i.id();
00208         return t;
00209     }
00210 
00211     Entry lookupToken( Token t ) {
00212         Entry e;
00213         e.load( t.desktop() );
00214         return e;
00215     }
00216 
00217     void setGroupPolicy( GroupPolicy *p ) {
00218         m_policy = p;
00219     }
00220 
00221     template< PropertyId p >
00222     typename PropertyType< p >::T getInternal( Entry );
00223 
00224     struct IsInGroup {
00225         std::string g;
00226         IsInGroup( std::string _g = "" ) : g( _g ) {}
00227         bool operator()( Token, std::string gr ) const {
00228             return gr == g;
00229         }
00230     };
00231 
00232     PropertyFilter< Group, IsInGroup >::T group( std::string id )
00233     {
00234         return propertyFilter< Group >( IsInGroup( id ) );
00235     }
00236 
00237 };
00238 
00239 template<> inline std::string Source::getInternal< Name >( Entry e ) {
00240     return e.name();
00241 }
00242 
00243 template<> inline std::string Source::getInternal< Icon >( Entry e ) {
00244     return e.icon();
00245 }
00246 
00247 template<> inline ept::Token Source::getInternal< Package >( Entry e ) {
00248     ept::Token t;
00249     t._id = e.package();
00250     return t;
00251 }
00252 
00253 template<> inline std::string Source::getInternal< Group >( Entry e ) {
00254     return m_policy->group( e );
00255 }
00256 
00257 template<> inline std::string Source::getInternal< ShortDescription >( Entry e ) {
00258     return e.description();
00259 }
00260 
00261 }
00262 }
00263 }
00264 
00265 #endif

Generated on Thu Aug 18 2016 17:48:34 for libept by  doxygen 1.7.1