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!
pull/16/head
Timothy Pearson 12 years ago
parent 8b807c6872
commit 40a38a2f9b

@ -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

@ -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

@ -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}
)

@ -24,6 +24,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/kio
${CMAKE_SOURCE_DIR}/kio/kssl
${CMAKE_SOURCE_DIR}/interfaces
${LIBR_INCLUDEDIR}
)

@ -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;
}

Loading…
Cancel
Save