diff --git a/CMakeLists.txt b/CMakeLists.txt index 6962394a0..86c2fcdda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ OPTION( WITH_JASPER "Enable jasper (jpeg2k) support" OFF ) OPTION( WITH_OPENEXR "Enable openexr support" OFF ) OPTION( WITH_UTEMPTER "Use utempter for utmp management" OFF ) OPTION( WITH_AVAHI "Enable AVAHI support" OFF ) +OPTION( WITH_ELFICON "Enable ELF embedded icon support" OFF ) OPTION( WITH_ASPELL "Enable aspell support" OFF ) OPTION( WITH_HSPELL "Enable hspell support" OFF ) @@ -715,6 +716,26 @@ if( WITH_AVAHI ) endif( WITH_QT3 ) endif( ) + +##### check for libr ########################### +# WARNING +# before altering the LIBR_VERSION check, +# please ensure that nothing changed in the +# duplicated data definitions present in +# kio/kio/kfileitem.cpp + +if( WITH_ELFICON ) + pkg_search_module( LIBR libr ) + if( NOT LIBR_FOUND ) + message(FATAL_ERROR "\nelficon support was requested, but libr was not found on your system" ) + endif( NOT LIBR_FOUND ) + if( LIBR_VERSION != 0.6.0 ) + message(FATAL_ERROR "\nelficon support was requested, but the libr version on your system may not be compatible with TDE" ) + endif( LIBR_VERSION != 0.6.0 ) + set( HAVE_ELFICON 1 ) +endif( ) + + ##### check for aspell ########################## # we need ASPELL_DATADIR too diff --git a/config.h.cmake b/config.h.cmake index c52da286f..80b8d071c 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -110,6 +110,9 @@ /* Define if you have OpenEXR */ #cmakedefine HAVE_EXR 1 +/* Defined if you have elficon support. */ +#cmakedefine HAVE_ELFICON 1 + /* Define is posix_fadvise is supported */ #undef HAVE_FADVISE diff --git a/kio/CMakeLists.txt b/kio/CMakeLists.txt index b18bfef33..73c2c9dba 100644 --- a/kio/CMakeLists.txt +++ b/kio/CMakeLists.txt @@ -30,6 +30,7 @@ include_directories( link_directories( ${TQT_LIBRARY_DIRS} + ${LIBR_LIBDIR} ) @@ -60,6 +61,6 @@ tde_add_library( ${target} SHARED SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp VERSION 4.2.0 EMBED kssl-static kiocore-static ksycoca-static kbookmarks-static kfile-static - LINK tdeui-shared tdesu-shared kwalletclient-shared + LINK tdeui-shared tdesu-shared kwalletclient-shared ${LIBR_LIBRARIES} DESTINATION ${LIB_INSTALL_DIR} ) diff --git a/kio/kio/CMakeLists.txt b/kio/kio/CMakeLists.txt index f9976a6d2..479814f15 100644 --- a/kio/kio/CMakeLists.txt +++ b/kio/kio/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/kio ${CMAKE_SOURCE_DIR}/kio/kssl ${CMAKE_SOURCE_DIR}/interfaces + ${LIBR_INCLUDEDIR} ) diff --git a/kio/kio/kfileitem.cpp b/kio/kio/kfileitem.cpp index 010832573..eaedf0a2d 100644 --- a/kio/kio/kfileitem.cpp +++ b/kio/kio/kfileitem.cpp @@ -19,6 +19,8 @@ */ // $Id$ +#include + #include #include #include @@ -46,6 +48,115 @@ #include #include +#ifdef HAVE_ELFICON +#include +#include +#include + +extern "C" { + #include + + // BEGIN HACK + // libr does not export these structures and defines, + // but we need access to them to make the UI behave sanely + // Keep them in sync with libr and all should be OK + + // Valid for libr version 0.6.0 + // See libr detection code in ConfigureChecks.cmake + + typedef uint32_t ID8; + typedef uint16_t ID4; + typedef struct {uint64_t p:48;} __attribute__((__packed__)) ID12; + + typedef struct { + ID8 g1; + ID4 g2; + ID4 g3; + ID4 g4; + ID12 g5; + } __attribute__((__packed__)) UUID; + + typedef struct { + char *name; + size_t offset; + size_t entry_size; + libr_icontype_t type; + unsigned int icon_size; + } iconentry; + + typedef struct{ + size_t size; + char *buffer; + iconentry entry; + } iconlist; + + #define ICON_SECTION ".icon" + // END HACK + +// int get_iconlist(libr_file *file_handle, iconlist *icons); +// iconentry *get_nexticon(iconlist *icons, iconentry *last_entry); +} + +/* + * Obtain an existing icon resource list + */ +int get_iconlist(libr_file *file_handle, iconlist *icons) +{ + if(icons == NULL) + { + /* Need to be able to return SOMETHING */ + return false; + } + /* Obtain the icon resource list */ + icons->buffer = libr_malloc(file_handle, ICON_SECTION, &(icons->size)); + if(icons->buffer == NULL) + return false; + return true; +} + +/* + * Get the next entry in an icon resource list + */ +iconentry *get_nexticon(iconlist *icons, iconentry *last_entry) +{ + size_t i; + + /* The icon list is needed both for the data buffer and for a call-specific iconentry instance */ + if(icons == NULL) + return NULL; + /* If this is the first call (last_entry == NULL) then return the first entry */ + if(last_entry == NULL) + icons->entry.offset = sizeof(uint32_t)+sizeof(UUID); + else + icons->entry.offset += icons->entry.entry_size; + /* Check to see if we've run out of entries */ + if(icons->entry.offset >= icons->size) + return NULL; + i = icons->entry.offset; + memcpy(&(icons->entry.entry_size), &(icons->buffer[i]), sizeof(uint32_t)); + i += sizeof(uint32_t); + icons->entry.type = (libr_icontype_t)icons->buffer[i]; + i += sizeof(unsigned char); + switch(icons->entry.type) + { + case LIBR_SVG: + icons->entry.icon_size = 0; + icons->entry.name = &(icons->buffer[i]); + break; + case LIBR_PNG: + memcpy(&(icons->entry.icon_size), &(icons->buffer[i]), sizeof(uint32_t)); + i += sizeof(uint32_t); + icons->entry.name = &(icons->buffer[i]); + break; + default: + /* Invalid entry type */ + return NULL; + } + return &(icons->entry); +} + +#endif // HAVE_ELFICON + class KFileItem::KFileItemPrivate { public: TQString iconName; @@ -630,6 +741,64 @@ TQPixmap KFileItem::pixmap( int _size, int _state ) const if (p.isNull()) kdWarning() << "Pixmap not found for mimetype " << m_pMimeType->name() << endl; + if ( mime->name() == "application/x-executable" ) { + // FIXME + // Look for .desktop files for this executable + // before resorting to the embedded icon + // (look at how the minicli does it) +#ifdef HAVE_ELFICON + // Check for an embedded icon + unsigned int icon_size; + libr_icon *icon = NULL; + libr_file *handle = NULL; + libr_access_t access = LIBR_READ; + + if((handle = libr_open(const_cast(url.path().ascii()), access)) == NULL) + { + kdWarning() << "failed to open file" << url.path() << endl; + return p; + } + + icon_size = _size; + icon = libr_icon_geticon_bysize(handle, icon_size); + if(icon == NULL) + { + kdWarning() << "failed to obtain ELF icon: " << libr_errmsg() << endl; + libr_close(handle); + return p; + } + + // See if the embedded icon name matches any icon file names already on the system + // If it does, use the system icon instead of the embedded one + int iconresnamefound = 0; + iconentry *entry = NULL; + iconlist icons; + if(!get_iconlist(handle, &icons)) + { + // Failed to obtain a list of ELF icons + } + while((entry = get_nexticon(&icons, entry)) != NULL) + { + if (KGlobal::iconLoader()->iconPath(entry->name, _size, true) != "") { + iconresnamefound = 1; + p = DesktopIcon( entry->name, _size, _state ); + break; + } + } + + if (iconresnamefound == 0) { + // Extract the embedded icon + size_t icon_data_length; + char* icondata = libr_icon_malloc(icon, &icon_data_length); + p.loadFromData(static_cast(static_cast(icondata)), icon_data_length); // EVIL CAST + free(icondata); + libr_icon_close(icon); + } + + libr_close(handle); +#endif // HAVE_ELFICON + } + return p; }