mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Get icons for programs that dont specify an icon resource in the registry
This commit is contained in:
parent
d829a221db
commit
250fbf8c3f
@ -67,7 +67,7 @@ def entry_to_icon_text(entry, only_text=False):
|
|||||||
if iswindows:
|
if iswindows:
|
||||||
# Windows {{{
|
# Windows {{{
|
||||||
from calibre.utils.winreg.default_programs import find_programs, friendly_app_name
|
from calibre.utils.winreg.default_programs import find_programs, friendly_app_name
|
||||||
from calibre.utils.open_with.windows import load_icon_resource
|
from calibre.utils.open_with.windows import load_icon_resource, load_icon_for_cmdline
|
||||||
from win32process import CreateProcess, STARTUPINFO
|
from win32process import CreateProcess, STARTUPINFO
|
||||||
from win32event import WaitForInputIdle
|
from win32event import WaitForInputIdle
|
||||||
import win32con
|
import win32con
|
||||||
@ -76,9 +76,20 @@ if iswindows:
|
|||||||
def entry_sort_key(entry):
|
def entry_sort_key(entry):
|
||||||
return sort_key(entry.get('name') or '')
|
return sort_key(entry.get('name') or '')
|
||||||
|
|
||||||
|
def icon_for_entry(entry, delete_icon_resource=False, as_data=False):
|
||||||
|
res = entry.pop('icon_resource', None) if delete_icon_resource else entry.get('icon_resource')
|
||||||
|
if res is None:
|
||||||
|
return load_icon_for_cmdline(entry['cmdline'], as_data=as_data)
|
||||||
|
try:
|
||||||
|
return load_icon_resource(res, as_data=as_data)
|
||||||
|
except Exception:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return load_icon_for_cmdline(entry['cmdline'], as_data=as_data)
|
||||||
|
|
||||||
def finalize_entry(entry):
|
def finalize_entry(entry):
|
||||||
try:
|
try:
|
||||||
data = load_icon_resource(entry.pop('icon_resource', None), as_data=True)
|
data = icon_for_entry(entry, delete_icon_resource=True, as_data=True)
|
||||||
except Exception:
|
except Exception:
|
||||||
data = None
|
data = None
|
||||||
import traceback
|
import traceback
|
||||||
@ -89,7 +100,7 @@ if iswindows:
|
|||||||
|
|
||||||
def entry_to_item(entry, parent):
|
def entry_to_item(entry, parent):
|
||||||
try:
|
try:
|
||||||
icon = load_icon_resource(entry.get('icon_resource'))
|
icon = icon_for_entry(entry)
|
||||||
except Exception:
|
except Exception:
|
||||||
icon = None
|
icon = None
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -6,6 +6,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
from PyQt5.Qt import QBuffer, QByteArray, QPixmap, Qt, QtWin
|
from PyQt5.Qt import QBuffer, QByteArray, QPixmap, Qt, QtWin
|
||||||
|
|
||||||
from calibre.constants import plugins
|
from calibre.constants import plugins
|
||||||
@ -75,8 +76,24 @@ def load_icon_resource(icon_resource, as_data=False, size=ICON_SIZE):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def load_icon_for_file(path: str, as_data=False, size=ICON_SIZE):
|
||||||
|
try:
|
||||||
|
hicon = winutil.get_icon_for_file(path)
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
must_use_qt()
|
||||||
|
pmap = hicon_to_pixmap(hicon)
|
||||||
|
if not pmap.isNull():
|
||||||
|
if pmap.width() != size:
|
||||||
|
pmap = pmap.scaled(size, size, aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation)
|
||||||
|
return pixmap_to_data(pmap) if as_data else pmap
|
||||||
|
|
||||||
|
|
||||||
|
def load_icon_for_cmdline(cmdline: str):
|
||||||
|
return load_icon_for_cmdline(split_commandline(cmdline)[0])
|
||||||
|
|
||||||
|
|
||||||
def display_image(png_data):
|
def display_image(png_data):
|
||||||
import sys
|
|
||||||
from base64 import standard_b64encode
|
from base64 import standard_b64encode
|
||||||
|
|
||||||
def serialize_gr_command(cmd, payload=None):
|
def serialize_gr_command(cmd, payload=None):
|
||||||
@ -105,6 +122,10 @@ def display_image(png_data):
|
|||||||
|
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
import sys
|
|
||||||
png_data = load_icon_resource(sys.argv[-1], as_data=True)
|
png_data = load_icon_resource(sys.argv[-1], as_data=True)
|
||||||
display_image(png_data)
|
display_image(png_data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_shell():
|
||||||
|
png_data = load_icon_for_file(sys.argv[-1], as_data=True)
|
||||||
|
display_image(png_data)
|
||||||
|
@ -14,7 +14,12 @@
|
|||||||
#include <combaseapi.h>
|
#include <combaseapi.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
#include <shlguid.h>
|
||||||
|
#include <shellapi.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
#include <commoncontrols.h>
|
||||||
|
#include <comip.h>
|
||||||
|
#include <comdef.h>
|
||||||
#include <atlbase.h> // for CComPtr
|
#include <atlbase.h> // for CComPtr
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <versionhelpers.h>
|
#include <versionhelpers.h>
|
||||||
@ -781,6 +786,7 @@ load_library(PyObject *self, PyObject *args) {
|
|||||||
return (PyObject*)Handle_create(h, ModuleHandle, PyTuple_GET_ITEM(args, 0));
|
return (PyObject*)Handle_create(h, ModuleHandle, PyTuple_GET_ITEM(args, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Icon loading {{{
|
||||||
#pragma pack( push )
|
#pragma pack( push )
|
||||||
#pragma pack( 2 )
|
#pragma pack( 2 )
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -873,6 +879,41 @@ load_icons(PyObject *self, PyObject *args) {
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_COM_SMARTPTR_TYPEDEF(IImageList, __uuidof(IImageList));
|
||||||
|
|
||||||
|
static HICON
|
||||||
|
get_icon_at_index(int shilsize, int index) {
|
||||||
|
IImageListPtr spiml;
|
||||||
|
HRESULT hr = SHGetImageList(shilsize, IID_PPV_ARGS(&spiml));
|
||||||
|
HICON hico = NULL;
|
||||||
|
if (SUCCEEDED(hr)) spiml->GetIcon(index, ILD_TRANSPARENT, &hico);
|
||||||
|
return hico;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
get_icon_for_file(PyObject *self, PyObject *args) {
|
||||||
|
wchar_raii path;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL;
|
||||||
|
scoped_com_initializer com;
|
||||||
|
if (!com.succeded()) { PyErr_SetString(PyExc_OSError, "Failed to initialize COM"); return NULL; }
|
||||||
|
SHFILEINFO fi = {0};
|
||||||
|
DWORD_PTR res;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
res = SHGetFileInfoW(path.ptr(), 0, &fi, sizeof(fi), SHGFI_SYSICONINDEX);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
if (!res) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, ERROR_RESOURCE_TYPE_NOT_FOUND, PyTuple_GET_ITEM(args, 0));
|
||||||
|
HICON icon;
|
||||||
|
#define R(shil) { \
|
||||||
|
Py_BEGIN_ALLOW_THREADS \
|
||||||
|
icon = get_icon_at_index(SHIL_JUMBO, fi.iIcon); \
|
||||||
|
Py_END_ALLOW_THREADS \
|
||||||
|
if (icon) return (PyObject*)Handle_create(icon, IconHandle); \
|
||||||
|
}
|
||||||
|
R(SHIL_JUMBO); R(SHIL_EXTRALARGE); R(SHIL_LARGE); R(SHIL_SYSSMALL); R(SHIL_SMALL);
|
||||||
|
#undef R
|
||||||
|
return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, ERROR_RESOURCE_TYPE_NOT_FOUND, PyTuple_GET_ITEM(args, 0));
|
||||||
|
} // }}}
|
||||||
|
|
||||||
// Boilerplate {{{
|
// Boilerplate {{{
|
||||||
static const char winutil_doc[] = "Defines utility methods to interface with windows.";
|
static const char winutil_doc[] = "Defines utility methods to interface with windows.";
|
||||||
|
|
||||||
@ -888,6 +929,7 @@ static PyMethodDef winutil_methods[] = {
|
|||||||
M(get_last_error, METH_NOARGS),
|
M(get_last_error, METH_NOARGS),
|
||||||
M(load_library, METH_VARARGS),
|
M(load_library, METH_VARARGS),
|
||||||
M(load_icons, METH_VARARGS),
|
M(load_icons, METH_VARARGS),
|
||||||
|
M(get_icon_for_file, METH_VARARGS),
|
||||||
|
|
||||||
{"special_folder_path", winutil_folder_path, METH_VARARGS,
|
{"special_folder_path", winutil_folder_path, METH_VARARGS,
|
||||||
"special_folder_path(csidl_id) -> path\n\n"
|
"special_folder_path(csidl_id) -> path\n\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user