diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-12-30 23:32:35 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-12-30 23:32:35 -0600 |
commit | 40a38a2f9b45bb73460145148bd4e4560e0d9672 (patch) | |
tree | 9710186e887145946ab032505d1c5f75cb457ade /kio | |
parent | 8b807c6872f860832ff7974339dc879aa7fa5a63 (diff) | |
download | tdelibs-40a38a2f9b45bb73460145148bd4e4560e0d9672.tar.gz tdelibs-40a38a2f9b45bb73460145148bd4e4560e0d9672.zip |
Add initial support for ELF embedded icons in Konqueror
This feature still needs quite a bit of work to add embedding support to other
parts of TDE such as the minicli, as well as bringing konqueror behaviour
more in line with the minicli previews, but it is a start at least!
Diffstat (limited to 'kio')
-rw-r--r-- | kio/CMakeLists.txt | 3 | ||||
-rw-r--r-- | kio/kio/CMakeLists.txt | 1 | ||||
-rw-r--r-- | kio/kio/kfileitem.cpp | 169 |
3 files changed, 172 insertions, 1 deletions
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 <config.h> + #include <sys/time.h> #include <pwd.h> #include <grp.h> @@ -46,6 +48,115 @@ #include <kmimetype.h> #include <krun.h> +#ifdef HAVE_ELFICON +#include <alloca.h> +#include <stdint.h> +#include <cstdlib> + +extern "C" { + #include <libr-icons.h> + + // 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<char*>(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<uchar*>(static_cast<void*>(icondata)), icon_data_length); // EVIL CAST + free(icondata); + libr_icon_close(icon); + } + + libr_close(handle); +#endif // HAVE_ELFICON + } + return p; } |