diff --git a/app/ui/imports.py b/app/ui/imports.py
index 4509f325..d4041b1b 100644
--- a/app/ui/imports.py
+++ b/app/ui/imports.py
@@ -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()
diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py
index 1578fa38..e3e8db36 100644
--- a/app/ui/main_app_window.py
+++ b/app/ui/main_app_window.py
@@ -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 ********************#
diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade
index 24e08ff5..e4e013cd 100644
--- a/app/ui/main_window.glade
+++ b/app/ui/main_window.glade
@@ -2778,6 +2778,7 @@ Author: Dmitriy Yefremov
True
True
vertical
+