added support for loading and importing data via dnd

This commit is contained in:
DYefremov
2020-09-19 12:32:08 +03:00
parent 1edbd7d771
commit 08c1dca06d
3 changed files with 69 additions and 17 deletions

View File

@@ -1,7 +1,7 @@
from contextlib import suppress
from pathlib import Path
from app.commons import run_idle
from app.commons import run_idle, log
from app.eparser import get_bouquets, get_services
from app.eparser.ecommons import BqType, BqServiceType, Bouquet
from app.eparser.enigma.bouquets import get_bouquet
@@ -123,6 +123,7 @@ class ImportDialog:
self._services_model.clear()
try:
if not self._bouquets:
log("Import [init data]: getting bouquets...")
self._bouquets = get_bouquets(path, self._profile)
for bqs in self._bouquets:
for bq in bqs.bouquets:
@@ -133,6 +134,7 @@ class ImportDialog:
for srv in services:
self._services[srv.fav_id] = srv
except FileNotFoundError as e:
log("Import error [init data]: {}".format(e))
self.show_info_message(str(e), Gtk.MessageType.ERROR)
def on_import(self, item):
@@ -143,9 +145,17 @@ class ImportDialog:
if not self._bouquets or show_dialog(DialogType.QUESTION, self._dialog_window) == Gtk.ResponseType.CANCEL:
return
self.import_data()
@run_idle
def import_data(self):
""" Importing data into models. """
if not self._bouquets:
return
log("Importing data...")
services = set()
to_delete = set()
for row in self._main_model:
bq = (row[0], row[1])
if row[-1]:
@@ -155,19 +165,16 @@ class ImportDialog:
services.add(srv)
else:
to_delete.add(bq)
bqs_to_delete = []
for bqs in self._bouquets:
for bq in bqs.bouquets:
if (bq.name, bq.type) in to_delete:
bqs_to_delete.append(bq)
for bqs in self._bouquets:
bq = bqs.bouquets
for b in bqs_to_delete:
with suppress(ValueError):
bq.remove(b)
self._append(self._bouquets, list(filter(lambda s: s.fav_id not in self._service_ids, services)))
self._dialog_window.destroy()

View File

@@ -4,6 +4,7 @@ from contextlib import suppress
from datetime import datetime
from functools import lru_cache
from itertools import chain
from urllib.parse import urlparse, unquote
from gi.repository import GLib, Gio
@@ -476,7 +477,7 @@ class Application(Gtk.Application):
self.set_profile(profile)
def init_drag_and_drop(self):
""" Enable drag-and-drop """
""" Enable drag-and-drop. """
target = []
bq_target = []
@@ -496,6 +497,7 @@ class Application(Gtk.Application):
self._services_view.drag_source_set_target_list(None)
self._services_view.drag_source_add_text_targets()
self._services_view.drag_dest_add_text_targets()
self._services_view.drag_dest_add_uri_targets()
self._bouquets_view.drag_dest_set_target_list(None)
@@ -504,6 +506,9 @@ class Application(Gtk.Application):
self._bouquets_view.drag_source_add_text_targets()
self._bouquets_view.drag_dest_add_uri_targets()
self._app_info_box.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
self._app_info_box.drag_dest_add_text_targets()
def init_colors(self, update=False):
""" Initialisation of background colors for the services.
@@ -1035,11 +1040,12 @@ class Application(Gtk.Application):
txt = data.get_text()
uris = data.get_uris()
if txt:
self.receive_selection(view=view, drop_info=view.get_dest_row_at_pos(x, y), data=txt)
if txt.startswith("file://"):
self.on_import_data(urlparse(unquote(txt)).path.strip())
else:
self.receive_selection(view=view, drop_info=view.get_dest_row_at_pos(x, y), data=txt)
if uris:
from urllib.parse import unquote, urlparse
src, sep, dest = uris[0].partition("::::")
picon_path = urlparse(unquote(src)).path
dest_path = urlparse(unquote(dest)).path + "/"
@@ -1060,6 +1066,10 @@ class Application(Gtk.Application):
if not data:
return
if data.startswith("file://"):
self.on_import_bouquet(None, file_path=urlparse(unquote(data)).path.strip())
return
itr_str, sep, source = data.partition("::::")
if source != self.BQ_MODEL_NAME:
return
@@ -1269,17 +1279,24 @@ class Application(Gtk.Application):
def open_compressed_data(self, data_path):
""" Opening archived data. """
arch_path = self.get_archive_path(data_path)
if arch_path:
gen = self.update_data("{}{}".format(arch_path.name, os.sep), callback=arch_path.cleanup)
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
def get_archive_path(self, data_path):
""" Returns the temp dir path for the extracted data, or None if the archive format is not supported. """
import zipfile
import tarfile
import tempfile
tmp_path = tempfile.TemporaryDirectory()
tmp_path_name = str(tmp_path.name)
tmp_path_name = tmp_path.name
if zipfile.is_zipfile(data_path):
with zipfile.ZipFile(data_path) as zip_file:
for zip_info in zip_file.infolist():
if not zip_info.is_dir():
if not zip_info.filename.endswith(os.sep):
zip_info.filename = os.path.basename(zip_info.filename)
zip_file.extract(zip_info, path=tmp_path_name)
elif tarfile.is_tarfile(data_path):
@@ -1289,12 +1306,12 @@ class Application(Gtk.Application):
mb.name = os.path.basename(mb.name)
tar.extract(mb, path=tmp_path_name)
else:
self.show_error_dialog("Unsupported format!")
tmp_path.cleanup()
log("Error getting the path for the archive. Unsupported file format: {}".format(data_path))
self.show_error_dialog("Unsupported format!")
return
gen = self.update_data("{}{}".format(tmp_path_name, os.sep), callback=tmp_path.cleanup)
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
return tmp_path
def update_data(self, data_path, callback=None):
self._profile_combo_box.set_sensitive(False)
@@ -2034,6 +2051,16 @@ class Application(Gtk.Application):
else:
show_dialog(DialogType.INFO, self._main_window, "Done!")
def on_import_data(self, path):
msg = "Combine with the current data?"
if len(self._services_model) > 0 and show_dialog(DialogType.QUESTION, self._main_window,
msg) == Gtk.ResponseType.OK:
self.import_data(path, force=True)
else:
if os.path.isdir(path) and not path.endswith(os.sep):
path += os.sep
self.open_data(path)
def on_import_bouquet(self, action, value=None, file_path=None):
model, paths = self._bouquets_view.get_selection().get_selected_rows()
if not paths:
@@ -2048,17 +2075,34 @@ class Application(Gtk.Application):
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
return
self.import_data(response)
def import_data(self, path, force=None, callback=None):
if os.path.isdir(path) and not path.endswith(os.sep):
path += os.sep
elif os.path.isfile(path):
arch_path = self.get_archive_path(path)
if not arch_path:
return
path = arch_path.name + os.sep
callback = arch_path.cleanup
def append(b, s):
gen = self.append_imported_data(b, s)
gen = self.append_imported_data(b, s, callback)
GLib.idle_add(lambda: next(gen, False))
ImportDialog(self._main_window, response, self._settings, self._services.keys(), append).show()
dialog = ImportDialog(self._main_window, path, self._settings, self._services.keys(), append)
dialog.import_data() if force else dialog.show()
def append_imported_data(self, bouquets, services):
def append_imported_data(self, bouquets, services, callback=None):
try:
self._wait_dialog.show()
yield from self.append_data(bouquets, services)
finally:
log("Importing data done!")
if callback:
callback()
self._wait_dialog.hide()
# ***************** Backup ********************#

View File

@@ -2778,6 +2778,7 @@ Author: Dmitriy Yefremov
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="orientation">vertical</property>
<signal name="drag-data-received" handler="on_view_drag_data_received" object="services_tree_view" swapped="no"/>
<signal name="key-press-event" handler="on_tree_view_key_press" object="services_tree_view" swapped="no"/>
<signal name="key-release-event" handler="on_tree_view_key_release" object="services_tree_view" swapped="no"/>
<child>