diff --git a/kio/CMakeLists.txt b/kio/CMakeLists.txt index 73c2c9dba..2c1d8ff0d 100644 --- a/kio/CMakeLists.txt +++ b/kio/CMakeLists.txt @@ -51,6 +51,11 @@ install( FILES kpasswdserver.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded ) install( FILES data.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) +if( HAVE_ELFICON ) + set( ELFICON_STATIC_LIB tdelficon-static ) +endif( HAVE_ELFICON ) + + ##### libkio #################################### set( target kio ) @@ -60,7 +65,7 @@ configure_file( ${CMAKE_SOURCE_DIR}/cmake/modules/template_dummy_cpp.cmake dummy 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 + EMBED kssl-static kiocore-static ksycoca-static kbookmarks-static kfile-static ${ELFICON_STATIC_LIB} 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 479814f15..9d8790f46 100644 --- a/kio/kio/CMakeLists.txt +++ b/kio/kio/CMakeLists.txt @@ -114,3 +114,20 @@ set( ${target}_SRCS tde_add_library( ${target} STATIC_PIC AUTOMOC SOURCES ${${target}_SRCS} ) + + +##### tdelficon ################################### + +if( HAVE_ELFICON ) + + set( target tdelficon ) + + set( ${target}_SRCS + tdelficon.cpp + ) + + tde_add_library( ${target} STATIC_PIC AUTOMOC + SOURCES ${${target}_SRCS} + ) + +endif( HAVE_ELFICON ) \ No newline at end of file diff --git a/kio/kio/kfileitem.cpp b/kio/kio/kfileitem.cpp index 839c38a68..e74b407be 100644 --- a/kio/kio/kfileitem.cpp +++ b/kio/kio/kfileitem.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -49,112 +50,7 @@ #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); -} - +#include "tdelficon.h" #endif // HAVE_ELFICON class KFileItem::KFileItemPrivate { @@ -780,7 +676,7 @@ TQPixmap KFileItem::pixmap( int _size, int _state ) const } while((entry = get_nexticon(&icons, entry)) != NULL) { - if (KGlobal::iconLoader()->iconPath(entry->name, _size, true) != "") { + if (KGlobal::iconLoader()->iconPath(entry->name, 0, true) != "") { iconresnamefound = 1; p = DesktopIcon( entry->name, _size, _state ); break; @@ -792,6 +688,11 @@ TQPixmap KFileItem::pixmap( int _size, int _state ) const 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 + if (icon_size != 0) { + TQImage ip = p.convertToImage(); + ip = ip.smoothScale(icon_size, icon_size); + p.convertFromImage(ip); + } free(icondata); libr_icon_close(icon); } diff --git a/kio/kio/kurifilter.cpp b/kio/kio/kurifilter.cpp index 2c4c5b12e..f6910e6a1 100644 --- a/kio/kio/kurifilter.cpp +++ b/kio/kio/kurifilter.cpp @@ -28,6 +28,11 @@ #include #include +#ifdef HAVE_ELFICON +#include +#include "tdelficon.h" +#endif // HAVE_ELFICON + #include "kurifilter.h" template class TQPtrList; @@ -159,6 +164,7 @@ TQString KURIFilterData::iconName() { if( m_bChanged ) { + m_customIconPixmap = TQPixmap(); switch ( m_iType ) { case KURIFilterData::LOCAL_FILE: @@ -175,12 +181,78 @@ TQString KURIFilterData::iconName() KService::Ptr service = KService::serviceByDesktopName( exeName ); if (service && service->icon() != TQString::fromLatin1( "unknown" )) m_strIconName = service->icon(); - // Try to find an icon with the same name as the binary (useful for non-kde apps) + // Try to find an icon with the same name as the binary (useful for non-tde apps) + // FIXME: We should only do this if the binary is in the system path somewhere, + // otherwise TDE could end up showing system icons for user binaries else if ( !KGlobal::iconLoader()->loadIcon( exeName, KIcon::NoGroup, 16, KIcon::DefaultState, 0, true ).isNull() ) m_strIconName = exeName; - else + else { + // not found, try to load from elf file (if supported) +#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; + char libr_can_continue = 1; + + if((handle = libr_open(const_cast(m_pURI.path().ascii()), access)) == NULL) + { + kdWarning() << "failed to open file" << m_pURI.path() << endl; + libr_can_continue = 0; + } + + if (libr_can_continue == 1) { + icon_size = 32; // FIXME: Is this a reasonable size request for all possible usages of kurifilter? + icon = libr_icon_geticon_bysize(handle, icon_size); + if(icon == NULL) + { + kdWarning() << "failed to obtain ELF icon: " << libr_errmsg() << endl; + libr_close(handle); + libr_can_continue = 0; + } + + if (libr_can_continue == 1) { + // 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, 0, true) != "") { + iconresnamefound = 1; + m_strIconName = entry->name; + break; + } + } + + if (iconresnamefound == 0) { + // Extract the embedded icon + size_t icon_data_length; + char* icondata = libr_icon_malloc(icon, &icon_data_length); + m_customIconPixmap.loadFromData(static_cast(static_cast(icondata)), icon_data_length); // EVIL CAST + if (icon_size != 0) { + TQImage ip = m_customIconPixmap.convertToImage(); + ip = ip.smoothScale(icon_size, icon_size); + m_customIconPixmap.convertFromImage(ip); + } + free(icondata); + libr_icon_close(icon); + } + + libr_close(handle); + } + } +#endif // HAVE_ELFICON + // not found, use default m_strIconName = TQString::fromLatin1("exec"); + } break; } case KURIFilterData::HELP: @@ -208,6 +280,11 @@ TQString KURIFilterData::iconName() return m_strIconName; } +TQPixmap KURIFilterData::customIconPixmap() +{ + return m_customIconPixmap; +} + //******************************************** KURIFilterPlugin ********************************************** void KURIFilterPlugin::setArguments( KURIFilterData& data, const TQString& args ) const { diff --git a/kio/kio/kurifilter.h b/kio/kio/kurifilter.h index 2cd999582..0887d8e4b 100644 --- a/kio/kio/kurifilter.h +++ b/kio/kio/kurifilter.h @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -256,6 +257,16 @@ public: */ TQString iconName(); + /** + * Returns the current custom icon + * The results are valid iff iconName() has + * returned TQString::null + * + * @return a pixmap with the current custom icon, + * or a null pixmap if no icon is available + */ + TQPixmap customIconPixmap(); + /** * Check whether the provided uri is executable or not. * @@ -332,6 +343,8 @@ private: KURL m_pURI; URITypes m_iType; KURIFilterDataPrivate *d; + + TQPixmap m_customIconPixmap; };