option 'replace existing' for import dialog (#127)

This commit is contained in:
DYefremov
2023-01-24 23:02:28 +03:00
parent 2dc8611294
commit adbc9ad322
3 changed files with 78 additions and 17 deletions

View File

@@ -3,7 +3,7 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2018-2022 Dmitriy Yefremov Copyright (c) 2018-2023 Dmitriy Yefremov
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -27,11 +27,12 @@ Author: Dmitriy Yefremov
--> -->
<interface domain="demon-editor"> <interface domain="demon-editor">
<requires lib="gtk+" version="3.20"/> <requires lib="gtk+" version="3.22"/>
<!-- interface-css-provider-path style.css -->
<!-- interface-license-type mit --> <!-- interface-license-type mit -->
<!-- interface-name DemonEditor --> <!-- interface-name DemonEditor -->
<!-- interface-description Enigma2 channel and satellite list editor. --> <!-- interface-description Enigma2 channel and satellite list editor. -->
<!-- interface-copyright 2018-2022 Dmitriy Yefremov --> <!-- interface-copyright 2018-2023 Dmitriy Yefremov -->
<!-- interface-authors Dmitriy Yefremov --> <!-- interface-authors Dmitriy Yefremov -->
<object class="GtkListStore" id="bq_list_store"> <object class="GtkListStore" id="bq_list_store">
<columns> <columns>
@@ -217,7 +218,6 @@ Author: Dmitriy Yefremov
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<property name="tooltip-text" translatable="yes">Bouquets and services</property> <property name="tooltip-text" translatable="yes">Bouquets and services</property>
<property name="valign">center</property>
<property name="image">import_image</property> <property name="image">import_image</property>
<property name="always-show-image">True</property> <property name="always-show-image">True</property>
<signal name="clicked" handler="on_import" swapped="no"/> <signal name="clicked" handler="on_import" swapped="no"/>
@@ -228,13 +228,43 @@ Author: Dmitriy Yefremov
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkBox" id="extra_header_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="spacing">5</property>
<child>
<object class="GtkLabel" id="replace_existing_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Replace existing</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="replace_existing_switch">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="valign">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child> <child>
<object class="GtkToggleButton" id="details_button"> <object class="GtkToggleButton" id="details_button">
<property name="label" translatable="yes">Details</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="focus-on-click">False</property> <property name="focus-on-click">False</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<property name="tooltip-text" translatable="yes">Details</property>
<property name="margin-start">5</property>
<property name="image">details_image</property> <property name="image">details_image</property>
<property name="always-show-image">True</property> <property name="always-show-image">True</property>
</object> </object>
@@ -242,7 +272,15 @@ Author: Dmitriy Yefremov
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="pack-type">end</property> <property name="pack-type">end</property>
<property name="position">1</property> <property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack-type">end</property>
<property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>

View File

@@ -144,6 +144,7 @@ class ImportDialog:
self._dialog_window.set_transient_for(app.app_window) self._dialog_window.set_transient_for(app.app_window)
self._info_bar = builder.get_object("info_bar") self._info_bar = builder.get_object("info_bar")
self._message_label = builder.get_object("message_label") self._message_label = builder.get_object("message_label")
self._replace_existing_switch = builder.get_object("replace_existing_switch")
# Bouquets page. # Bouquets page.
self._bq_model = builder.get_object("bq_list_store") self._bq_model = builder.get_object("bq_list_store")
self._bq_view = builder.get_object("bq_view") self._bq_view = builder.get_object("bq_view")
@@ -168,9 +169,9 @@ class ImportDialog:
button = builder.get_object("import_button") button = builder.get_object("import_button")
actions_box.remove(button) actions_box.remove(button)
header_bar.pack_start(button) header_bar.pack_start(button)
button = builder.get_object("details_button") extra_box = builder.get_object("extra_header_box")
actions_box.remove(button) actions_box.remove(extra_box)
header_bar.pack_end(button) header_bar.pack_end(extra_box)
self._dialog_window.set_titlebar(header_bar) self._dialog_window.set_titlebar(header_bar)
window_size = self._settings.get("import_dialog_window_size") window_size = self._settings.get("import_dialog_window_size")
@@ -266,9 +267,10 @@ class ImportDialog:
if show_dialog(DialogType.QUESTION, self._dialog_window) != Gtk.ResponseType.OK: if show_dialog(DialogType.QUESTION, self._dialog_window) != Gtk.ResponseType.OK:
return return
replace_existing = False replace_existing = self._replace_existing_switch.get_active()
services = [] services = []
current_services = self._app.current_services current_services = self._app.current_services
to_replace = {}
for row in self._sat_model: for row in self._sat_model:
if row[-1]: if row[-1]:
@@ -277,10 +279,14 @@ class ImportDialog:
for s in filter(lambda srv: srv.fav_id not in skip, self._sat_services.get(sat[0], ())): for s in filter(lambda srv: srv.fav_id not in skip, self._sat_services.get(sat[0], ())):
if replace_existing and s.fav_id in self._ids: if replace_existing and s.fav_id in self._ids:
current_services[s.fav_id] = s current_services[s.fav_id] = s
to_replace[s.fav_id] = s
elif s.fav_id not in self._ids: elif s.fav_id not in self._ids:
services.append(s) services.append(s)
self._append((), services) self._append((), services)
if to_replace:
self._app.emit("services_update", to_replace)
self._dialog_window.destroy() self._dialog_window.destroy()
@run_idle @run_idle

View File

@@ -308,6 +308,8 @@ class Application(Gtk.Application):
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
GObject.signal_new("epg-dat-downloaded", self, GObject.SIGNAL_RUN_LAST, GObject.signal_new("epg-dat-downloaded", self, GObject.SIGNAL_RUN_LAST,
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
GObject.signal_new("services-update", self, GObject.SIGNAL_RUN_LAST,
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
GObject.signal_new("iptv-service-edited", self, GObject.SIGNAL_RUN_LAST, GObject.signal_new("iptv-service-edited", self, GObject.SIGNAL_RUN_LAST,
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
GObject.signal_new("iptv-service-added", self, GObject.SIGNAL_RUN_LAST, GObject.signal_new("iptv-service-added", self, GObject.SIGNAL_RUN_LAST,
@@ -488,6 +490,7 @@ class Application(Gtk.Application):
self._logs_box = builder.get_object("logs_box") self._logs_box = builder.get_object("logs_box")
self._logs_box.pack_start(LogsClient(self), True, True, 0) self._logs_box.pack_start(LogsClient(self), True, True, 0)
self._bottom_paned = builder.get_object("bottom_paned") self._bottom_paned = builder.get_object("bottom_paned")
self.connect("services-update", self.on_services_update)
# Send/Receive. # Send/Receive.
self.connect("data-receive", self.on_download) self.connect("data-receive", self.on_download)
self.connect("data-send", self.on_upload) self.connect("data-send", self.on_upload)
@@ -1268,6 +1271,20 @@ class Application(Gtk.Application):
self._bouquets_buffer.clear() self._bouquets_buffer.clear()
self.update_bouquets_type() self.update_bouquets_type()
def on_services_update(self, app, services):
""" Updates services in the main model. """
for r in self._fav_model:
fav_id = r[Column.FAV_ID]
if fav_id in services:
service = services[fav_id]
r[Column.FAV_SERVICE] = service.service
for r in self._services_model:
fav_id = r[Column.SRV_FAV_ID]
if fav_id in services:
service = services[fav_id]
r[Column.SRV_SERVICE] = service.service
# ***************** Deletion ********************* # # ***************** Deletion ********************* #
def on_delete(self, view): def on_delete(self, view):
@@ -4270,7 +4287,7 @@ class Application(Gtk.Application):
row = model[path][:] row = model[path][:]
srv = self._services.get(row[Column.ALT_FAV_ID], None) srv = self._services.get(row[Column.ALT_FAV_ID], None)
if srv and srv.transponder or row[Column.ALT_TYPE] == BqServiceType.IPTV.name: if srv and srv.transponder or row[Column.ALT_TYPE] == BqServiceType.IPTV.name:
self._control_tool.on_service_changed(srv.picon_id.rstrip(".png").replace("_", ":")) self._control_tool.on_services_update(srv.picon_id.rstrip(".png").replace("_", ":"))
# ***************** Profile label ********************* # # ***************** Profile label ********************* #