diff options
author | Vilem Duha <vilem.duha@gmail.com> | 2019-05-21 00:01:41 +0300 |
---|---|---|
committer | Vilem Duha <vilem.duha@gmail.com> | 2019-05-21 00:03:01 +0300 |
commit | 3778680f22bef286234434e22ca03481c7ef0495 (patch) | |
tree | 6b0f777600a2e403972b9012cdb00283779ee125 /blenderkit | |
parent | 01500c966186519c9a0dc1287022c58e92e0a07e (diff) |
BlenderKit: Downloads can now be cancelled
- converted main download thread into object with stop-ability.
Diffstat (limited to 'blenderkit')
-rw-r--r-- | blenderkit/download.py | 121 | ||||
-rw-r--r-- | blenderkit/search.py | 1 | ||||
-rw-r--r-- | blenderkit/ui_panels.py | 4 |
3 files changed, 85 insertions, 41 deletions
diff --git a/blenderkit/download.py b/blenderkit/download.py index c8695f5e..7bc04481 100644 --- a/blenderkit/download.py +++ b/blenderkit/download.py @@ -290,7 +290,7 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None, user_preferences = bpy.context.preferences.addons['blenderkit'].preferences if user_preferences.api_key == '': - user_preferences.asset_counter+=1 + user_preferences.asset_counter += 1 if asset_data['asset_type'] == 'scene': scene = append_link.append_scene(file_names[0], link=False, fake_user=False) @@ -507,41 +507,69 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff, not return .2 -def main_thread(asset_data, tcom, scene_id, api_key): - '''try to download file from blenderkit''' - - # TODO get real link here... - get_download_url(asset_data, scene_id, api_key, tcom=tcom) - if tcom.error: - return - # only now we can check if the file allready exists. This should have 2 levels, for materials and for brushes - # different than for the non free content. delete is here when called after failed append tries. - if check_existing(asset_data) and not tcom.passargs.get('delete'): - # this sends the thread for processing, where another check should occur, since the file might be corrupted. - tcom.downloaded = 100 - print('not downloading, trying to append again') - return; - file_name = paths.get_download_filenames(asset_data)[0] # prefer global dir if possible. - # for k in asset_data: - # print(asset_data[k]) - - with open(file_name, "wb") as f: - print("Downloading %s" % file_name) - headers = utils.get_headers(api_key) - - response = requests.get(asset_data['url'], stream=True) - total_length = response.headers.get('Content-Length') - - if total_length is None: # no content length header - f.write(response.content) - else: - tcom.file_size = int(total_length) - dl = 0 - for data in response.iter_content(chunk_size=4096): - dl += len(data) - tcom.downloaded = dl - tcom.progress = int(100 * tcom.downloaded / tcom.file_size) - f.write(data) +class Downloader(threading.Thread): + def __init__(self, asset_data, tcom, scene_id, api_key): + super(Downloader, self).__init__() + self.asset_data = asset_data + self.tcom = tcom + self.scene_id = scene_id + self.api_key = api_key + self._stop_event = threading.Event() + + def stop(self): + self._stop_event.set() + + def stopped(self): + return self._stop_event.is_set() + + # def main_download_thread(asset_data, tcom, scene_id, api_key): + def run(self): + '''try to download file from blenderkit''' + asset_data = self.asset_data + tcom = self.tcom + scene_id = self.scene_id + api_key = self.api_key + + # TODO get real link here... + get_download_url(asset_data, scene_id, api_key, tcom=tcom) + if tcom.error: + return + # only now we can check if the file allready exists. This should have 2 levels, for materials and for brushes + # different than for the non free content. delete is here when called after failed append tries. + if check_existing(asset_data) and not tcom.passargs.get('delete'): + # this sends the thread for processing, where another check should occur, since the file might be corrupted. + tcom.downloaded = 100 + print('not downloading, trying to append again') + return; + file_name = paths.get_download_filenames(asset_data)[0] # prefer global dir if possible. + # for k in asset_data: + # print(asset_data[k]) + if self.stopped(): + utils.p('stopping download: ' + asset_data['name']) + return; + + with open(file_name, "wb") as f: + print("Downloading %s" % file_name) + headers = utils.get_headers(api_key) + + response = requests.get(asset_data['url'], stream=True) + total_length = response.headers.get('Content-Length') + + if total_length is None: # no content length header + f.write(response.content) + else: + tcom.file_size = int(total_length) + dl = 0 + for data in response.iter_content(chunk_size=4096): + dl += len(data) + tcom.downloaded = dl + tcom.progress = int(100 * tcom.downloaded / tcom.file_size) + f.write(data) + if self.stopped(): + utils.p('stopping download: ' + asset_data['name']) + f.close() + os.remove(file_name) + return; class ThreadCom: # object passed to threads to read background process stdout info @@ -572,8 +600,7 @@ def download(asset_data, **kwargs): else: asset_data = asset_data.to_dict() - # main_thread(asset_data, tcom, scene_id, api_key) - readthread = threading.Thread(target=main_thread, args=([asset_data, tcom, scene_id, api_key]), daemon=True) + readthread = Downloader(asset_data, tcom, scene_id, api_key) readthread.start() global download_threads @@ -761,6 +788,22 @@ asset_types = ( ) +class BlenderkitKillDownloadOperator(bpy.types.Operator): + """Kill a download.""" + bl_idname = "scene.blenderkit_download_kill" + bl_label = "BlenderKit Kill Asset Download" + bl_options = {'REGISTER', 'UNDO'} + + thread_index: IntProperty(name="Thread index", description='index of the thread to kill', default=-1) + + def execute(self, context): + global download_threads + td = download_threads[self.thread_index] + download_threads.remove(td) + td[0].stop() + return {'FINISHED'} + + class BlenderkitDownloadOperator(bpy.types.Operator): """Download and link asset to scene. Only link if asset allready available locally.""" bl_idname = "scene.blenderkit_download" @@ -820,6 +863,7 @@ class BlenderkitDownloadOperator(bpy.types.Operator): def register_download(): bpy.utils.register_class(BlenderkitDownloadOperator) + bpy.utils.register_class(BlenderkitKillDownloadOperator) bpy.app.handlers.load_post.append(scene_load) bpy.app.handlers.save_pre.append(scene_save) # bpy.app.timers.register(timer_update, persistent = True) @@ -827,6 +871,7 @@ def register_download(): def unregister_download(): bpy.utils.unregister_class(BlenderkitDownloadOperator) + bpy.utils.unregister_class(BlenderkitKillDownloadOperator) bpy.app.handlers.load_post.remove(scene_load) bpy.app.handlers.save_pre.remove(scene_save) # bpy.app.timers.unregister(timer_update) diff --git a/blenderkit/search.py b/blenderkit/search.py index 8e40dd17..452ec434 100644 --- a/blenderkit/search.py +++ b/blenderkit/search.py @@ -952,7 +952,6 @@ def add_search_process(query, params): tempdir = paths.get_temp_dir('%s_search' % query['asset_type']) thread = Searcher(query, params) - # thread = threading.Thread(target=Searcher, args=([query]), daemon=True) thread.start() search_threads.append([thread, tempdir, query['asset_type']]) diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py index 664aa0c8..88d14386 100644 --- a/blenderkit/ui_panels.py +++ b/blenderkit/ui_panels.py @@ -288,7 +288,7 @@ def draw_panel_model_search(self, context): # layout.prop(props, 'append_link', expand=True, icon_only=False) # layout.prop(props, 'import_as', expand=True, icon_only=False) - #layout.prop(props, "search_advanced") + # layout.prop(props, "search_advanced") if props.search_advanced: layout.separator() @@ -589,7 +589,6 @@ class VIEW3D_PT_blenderkit_unified(Panel): layout.prop(user_preferences, 'api_key', text='') layout.separator() if bpy.data.filepath == '': - label_multiline(layout, text="It's better to save the file first.", width=w) layout.separator() if wm.get('bkit_update'): @@ -802,6 +801,7 @@ class VIEW3D_PT_blenderkit_downloads(Panel): row = layout.row() row.label(text=asset_data['name']) row.label(text=str(int(tcom.progress)) + ' %') + row.operator('scene.blenderkit_download_kill', text='', icon='CANCEL') classess = ( |