summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-12-30 23:32:35 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-12-30 23:32:35 -0600
commit40a38a2f9b45bb73460145148bd4e4560e0d9672 (patch)
tree9710186e887145946ab032505d1c5f75cb457ade
parent8b807c6872f860832ff7974339dc879aa7fa5a63 (diff)
downloadtdelibs-40a38a2f.tar.gz
tdelibs-40a38a2f.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!
-rw-r--r--CMakeLists.txt21
-rw-r--r--config.h.cmake3
-rw-r--r--kio/CMakeLists.txt3
-rw-r--r--kio/kio/CMakeLists.txt1
-rw-r--r--kio/kio/kfileitem.cpp169
5 files changed, 196 insertions, 1 deletions
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 <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;
}