mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Use the more modern API for getting icons
Qt's fromHBITMAP is totally broken so convert the bitmap to an HICON ourselves first.
This commit is contained in:
parent
8059813337
commit
42c283bdee
@ -4,13 +4,14 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from qt.core import QBuffer, QByteArray, QIODevice, QPixmap, Qt
|
from qt.core import QBuffer, QByteArray, QIODevice, QPixmap, Qt
|
||||||
|
|
||||||
from calibre.gui2 import must_use_qt
|
from calibre.gui2 import must_use_qt
|
||||||
from calibre.utils.winreg.default_programs import split_commandline
|
from calibre.utils.winreg.default_programs import split_commandline
|
||||||
from calibre_extensions import winutil, progress_indicator
|
from calibre_extensions import progress_indicator, winutil
|
||||||
|
|
||||||
ICON_SIZE = 256
|
ICON_SIZE = 256
|
||||||
|
|
||||||
@ -76,6 +77,7 @@ def load_icon_resource(icon_resource, as_data=False, size=ICON_SIZE):
|
|||||||
|
|
||||||
|
|
||||||
def load_icon_for_file(path: str, as_data=False, size=ICON_SIZE):
|
def load_icon_for_file(path: str, as_data=False, size=ICON_SIZE):
|
||||||
|
path = os.path.abspath(path)
|
||||||
try:
|
try:
|
||||||
hicon = winutil.get_icon_for_file(path)
|
hicon = winutil.get_icon_for_file(path)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -1104,46 +1104,9 @@ 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 | ILD_IMAGE, &hico);
|
|
||||||
spiml->Release();
|
|
||||||
return hico;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
get_icon_for_file(PyObject *self, PyObject *args) {
|
get_icon_for_file(PyObject *self, PyObject *args) {
|
||||||
wchar_raii path;
|
wchar_raii path;
|
||||||
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL;
|
|
||||||
scoped_com_initializer com;
|
|
||||||
if (!com.succeeded()) { 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, 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
get_bitmap_for_file(PyObject *self, PyObject *args) {
|
|
||||||
wchar_raii path;
|
|
||||||
long width = 256, height = 256;
|
long width = 256, height = 256;
|
||||||
if (!PyArg_ParseTuple(args, "O&|ll", py_to_wchar_no_none, &path, &width, &height)) return NULL;
|
if (!PyArg_ParseTuple(args, "O&|ll", py_to_wchar_no_none, &path, &width, &height)) return NULL;
|
||||||
scoped_com_initializer com;
|
scoped_com_initializer com;
|
||||||
@ -1159,13 +1122,30 @@ get_bitmap_for_file(PyObject *self, PyObject *args) {
|
|||||||
SIZE size = { width, height };
|
SIZE size = { width, height };
|
||||||
HBITMAP hbmp;
|
HBITMAP hbmp;
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hr = pImageFactory->GetImage(size, SIIGBF_BIGGERSIZEOK, &hbmp);
|
hr = pImageFactory->GetImage(size, SIIGBF_BIGGERSIZEOK | SIIGBF_SCALEUP, &hbmp);
|
||||||
pImageFactory->Release();
|
pImageFactory->Release();
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
if (!SUCCEEDED(hr)) {
|
if (!SUCCEEDED(hr)) {
|
||||||
return error_from_hresult(hr, "Failed to get image from shell item");
|
return error_from_hresult(hr, "Failed to get image from shell item");
|
||||||
}
|
}
|
||||||
return (PyObject*)Handle_create(hbmp, BitmapHandle);
|
BITMAP bmp;
|
||||||
|
if (GetObject(hbmp, sizeof( BITMAP ), &bmp) == 0) {
|
||||||
|
DeleteObject(hbmp);
|
||||||
|
PyErr_SetString(PyExc_OSError, "Failed to load bitmap data from HBITMAP");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
HBITMAP hbmMask = CreateCompatibleBitmap(GetDC(NULL), bmp.bmWidth, bmp.bmHeight);
|
||||||
|
ICONINFO ii = {0};
|
||||||
|
ii.fIcon = TRUE;
|
||||||
|
ii.hbmColor = hbmp;
|
||||||
|
ii.hbmMask = hbmMask;
|
||||||
|
HICON hIcon = CreateIconIndirect(&ii);
|
||||||
|
DeleteObject(hbmp); DeleteObject(hbmMask);
|
||||||
|
if (hIcon == NULL) {
|
||||||
|
PyErr_SetFromWindowsErr(GetLastError());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (PyObject*)Handle_create(hIcon, IconHandle);
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
// Boilerplate {{{
|
// Boilerplate {{{
|
||||||
@ -1190,7 +1170,6 @@ static PyMethodDef winutil_methods[] = {
|
|||||||
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),
|
M(get_icon_for_file, METH_VARARGS),
|
||||||
M(get_bitmap_for_file, METH_VARARGS),
|
|
||||||
M(parse_cmdline, METH_VARARGS),
|
M(parse_cmdline, METH_VARARGS),
|
||||||
M(write_file, METH_VARARGS),
|
M(write_file, METH_VARARGS),
|
||||||
M(wait_named_pipe, METH_VARARGS),
|
M(wait_named_pipe, METH_VARARGS),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user