mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
WPD: Implement deleting objects
This commit is contained in:
parent
b63dd79142
commit
41f8e96740
@ -20,12 +20,13 @@ class FileOrFolder(object):
|
||||
self.object_id = entry['id']
|
||||
self.is_folder = entry['is_folder']
|
||||
self.name = force_unicode(entry.get('name', '___'), 'utf-8')
|
||||
self.storage_id = entry.get('storage_id', None)
|
||||
self.persistent_id = entry.get('persistent_id', self.object_id)
|
||||
self.size = entry.get('size', 0)
|
||||
# self.parent_id is None for storage objects
|
||||
self.parent_id = entry.get('parent_id', None)
|
||||
if self.parent_id == 0:
|
||||
sid = entry['storage_id']
|
||||
sid = self.storage_id
|
||||
if sid not in all_storage_ids:
|
||||
sid = all_storage_ids[0]
|
||||
self.parent_id = sid
|
||||
@ -79,7 +80,17 @@ class FilesystemCache(object):
|
||||
FileOrFolder(entry, self, all_storage_ids)
|
||||
|
||||
for item in self.id_map.itervalues():
|
||||
try:
|
||||
p = item.parent
|
||||
except KeyError:
|
||||
# Parent does not exist, set the parent to be the storage
|
||||
# object
|
||||
sid = p.storage_id
|
||||
if sid not in all_storage_ids:
|
||||
sid = all_storage_ids[0]
|
||||
item.parent_id = sid
|
||||
p = item.parent
|
||||
|
||||
if p is not None:
|
||||
t = p.folders if item.is_folder else p.files
|
||||
t.append(item)
|
||||
|
@ -572,4 +572,44 @@ end:
|
||||
|
||||
} // }}}
|
||||
|
||||
PyObject* wpd::delete_object(IPortableDevice *device, const wchar_t *object_id) { // {{{
|
||||
IPortableDeviceContent *content = NULL;
|
||||
HRESULT hr;
|
||||
BOOL ok = FALSE;
|
||||
PROPVARIANT pv;
|
||||
IPortableDevicePropVariantCollection *object_ids = NULL;
|
||||
|
||||
PropVariantInit(&pv);
|
||||
pv.vt = VT_LPWSTR;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL,
|
||||
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&object_ids));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (FAILED(hr)) { hresult_set_exc("Failed to create propvariantcollection", hr); goto end; }
|
||||
pv.pwszVal = (wchar_t*)object_id;
|
||||
hr = object_ids->Add(&pv);
|
||||
pv.pwszVal = NULL;
|
||||
if (FAILED(hr)) { hresult_set_exc("Failed to add device id to propvariantcollection", hr); goto end; }
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
hr = device->Content(&content);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); goto end; }
|
||||
|
||||
hr = content->Delete(PORTABLE_DEVICE_DELETE_NO_RECURSION, object_ids, NULL);
|
||||
if (hr == E_ACCESSDENIED) PyErr_SetString(WPDError, "Do not have permission to delete this object");
|
||||
else if (hr == HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) || hr == HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION)) PyErr_SetString(WPDError, "Cannot delete object as it has children");
|
||||
else if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND) || SUCCEEDED(hr)) ok = TRUE;
|
||||
else hresult_set_exc("Cannot delete object", hr);
|
||||
|
||||
end:
|
||||
PropVariantClear(&pv);
|
||||
if (content != NULL) content->Release();
|
||||
if (object_ids != NULL) object_ids->Release();
|
||||
if (!ok) return NULL;
|
||||
Py_RETURN_NONE;
|
||||
|
||||
} // }}}
|
||||
|
||||
} // namespace wpd
|
||||
|
@ -78,20 +78,22 @@ update_data(Device *self, PyObject *args, PyObject *kwargs) {
|
||||
// get_filesystem() {{{
|
||||
static PyObject*
|
||||
py_get_filesystem(Device *self, PyObject *args, PyObject *kwargs) {
|
||||
PyObject *storage_id;
|
||||
PyObject *storage_id, *ret;
|
||||
wchar_t *storage;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &storage_id)) return NULL;
|
||||
storage = unicode_to_wchar(storage_id);
|
||||
if (storage == NULL) return NULL;
|
||||
|
||||
return wpd::get_filesystem(self->device, storage, self->bulk_properties);
|
||||
ret = wpd::get_filesystem(self->device, storage, self->bulk_properties);
|
||||
free(storage);
|
||||
return ret;
|
||||
} // }}}
|
||||
|
||||
// get_file() {{{
|
||||
static PyObject*
|
||||
py_get_file(Device *self, PyObject *args, PyObject *kwargs) {
|
||||
PyObject *object_id, *stream, *callback = NULL;
|
||||
PyObject *object_id, *stream, *callback = NULL, *ret;
|
||||
wchar_t *object;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OO|O", &object_id, &stream, &callback)) return NULL;
|
||||
@ -100,13 +102,15 @@ py_get_file(Device *self, PyObject *args, PyObject *kwargs) {
|
||||
|
||||
if (callback == NULL || !PyCallable_Check(callback)) callback = NULL;
|
||||
|
||||
return wpd::get_file(self->device, object, stream, callback);
|
||||
ret = wpd::get_file(self->device, object, stream, callback);
|
||||
free(object);
|
||||
return ret;
|
||||
} // }}}
|
||||
|
||||
// create_folder() {{{
|
||||
static PyObject*
|
||||
py_create_folder(Device *self, PyObject *args, PyObject *kwargs) {
|
||||
PyObject *pparent_id, *pname;
|
||||
PyObject *pparent_id, *pname, *ret;
|
||||
wchar_t *parent_id, *name;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OO", &pparent_id, &pname)) return NULL;
|
||||
@ -114,7 +118,24 @@ py_create_folder(Device *self, PyObject *args, PyObject *kwargs) {
|
||||
name = unicode_to_wchar(pname);
|
||||
if (parent_id == NULL || name == NULL) return NULL;
|
||||
|
||||
return wpd::create_folder(self->device, parent_id, name);
|
||||
ret = wpd::create_folder(self->device, parent_id, name);
|
||||
free(parent_id); free(name);
|
||||
return ret;
|
||||
} // }}}
|
||||
|
||||
// delete_object() {{{
|
||||
static PyObject*
|
||||
py_delete_object(Device *self, PyObject *args, PyObject *kwargs) {
|
||||
PyObject *pobject_id, *ret;
|
||||
wchar_t *object_id;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &pobject_id)) return NULL;
|
||||
object_id = unicode_to_wchar(pobject_id);
|
||||
if (object_id == NULL) return NULL;
|
||||
|
||||
ret = wpd::delete_object(self->device, object_id);
|
||||
free(object_id);
|
||||
return ret;
|
||||
} // }}}
|
||||
|
||||
static PyMethodDef Device_methods[] = {
|
||||
@ -134,6 +155,10 @@ static PyMethodDef Device_methods[] = {
|
||||
"create_folder(parent_id, name) -> Create a folder. Returns the folder metadata."
|
||||
},
|
||||
|
||||
{"delete_object", (PyCFunction)py_delete_object, METH_VARARGS,
|
||||
"delete_object(object_id) -> Delete the object identified by object_id. Note that trying to delete a non-empty folder will raise an error."
|
||||
},
|
||||
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
@ -156,6 +156,7 @@ class MTP_DEVICE(MTPDeviceBase):
|
||||
storage = {'id':storage_id, 'size':capacity, 'name':name,
|
||||
'is_folder':True}
|
||||
id_map = self.dev.get_filesystem(storage_id)
|
||||
for x in id_map.itervalues(): x['storage_id'] = storage_id
|
||||
all_storage.append(storage)
|
||||
items.append(id_map.itervalues())
|
||||
self._filesystem_cache = FilesystemCache(all_storage, chain(*items))
|
||||
|
@ -59,6 +59,7 @@ extern PyObject* get_device_information(IPortableDevice *device, IPortableDevice
|
||||
extern PyObject* get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties);
|
||||
extern PyObject* get_file(IPortableDevice *device, const wchar_t *object_id, PyObject *dest, PyObject *callback);
|
||||
extern PyObject* create_folder(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name);
|
||||
extern PyObject* delete_object(IPortableDevice *device, const wchar_t *object_id);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user