diff --git a/app/ui/iptv.py b/app/ui/iptv.py
index 192fa716..be744cf1 100644
--- a/app/ui/iptv.py
+++ b/app/ui/iptv.py
@@ -30,6 +30,8 @@ import concurrent.futures
import os
import re
import urllib
+from datetime import date
+from itertools import groupby
from urllib.error import HTTPError
from urllib.parse import urlparse, unquote, quote
from urllib.request import Request, urlopen
@@ -44,7 +46,7 @@ from app.eparser.iptv import (NEUTRINO_FAV_ID_FORMAT, StreamType, ENIGMA2_FAV_ID
from app.settings import SettingsType
from app.tools.yt import YouTubeException, YouTube
from app.ui.dialogs import Action, show_dialog, DialogType, translate, get_builder, BaseDialog
-from app.ui.main_helper import get_iptv_url, on_popup_menu, get_picon_pixbuf, show_info_bar_message
+from app.ui.main_helper import get_iptv_url, on_popup_menu, get_picon_pixbuf, show_info_bar_message, gen_bouquet_name
from app.ui.uicommons import (Gtk, Gdk, UI_RESOURCES_PATH, IPTV_ICON, Column, KeyboardKey, get_yt_icon, HeaderBar)
_DIGIT_ENTRY_NAME = "digit-entry"
@@ -725,10 +727,13 @@ class M3uImportDialog(IptvListDialog):
self._data_box.add(m3u_box)
else:
self._data_box.set_visible(False)
+ self._group_bq_button.set_sensitive(False)
self._sub_bq_button.set_sensitive(False)
m3u_box.set_margin_start(5)
m3u_box.set_margin_end(5)
- self._dialog.get_content_area().pack_start(m3u_box, True, True, 0)
+ area = self._dialog.get_content_area()
+ area.pack_start(m3u_box, True, True, 0)
+ area.reorder_child(m3u_box, 0)
self.get_m3u(m3_path, s_type)
@@ -756,7 +761,7 @@ class M3uImportDialog(IptvListDialog):
self._epg_links_button.set_active(0)
def on_apply(self, item):
- if not self._app.current_bouquet:
+ if self._current_bq_button.get_active() and not self._app.current_bouquet:
self.show_info_message("Error. No bouquet is selected!", Gtk.MessageType.ERROR)
return
@@ -804,7 +809,51 @@ class M3uImportDialog(IptvListDialog):
else:
self.on_apply_done()
- self._app.append_imported_services(services)
+ self.import_services(services)
+
+ def import_services(self, services):
+ if self._current_bq_button.get_active():
+ self._app.append_imported_services(services)
+ return
+
+ s_type = self._app.app_settings.setting_type
+ model = self._app.bouquets_view.get_model()
+
+ if s_type is SettingsType.ENIGMA_2:
+ itr = model.get_iter_first()
+ else:
+ # We will use the 'FAV' section for Neutrino!
+ itr = model.get_iter(Gtk.TreePath.new_from_indices([1]))
+
+ bqs = self._app.current_bouquets
+ bq_type = model.get_value(itr, Column.BQ_TYPE)
+ def_bq_name = gen_bouquet_name(bqs, f"IPTV {date.today()} ", bq_type)
+
+ if self._single_bq_button.get_active():
+ self.append_bouquet(def_bq_name, bq_type, bqs, model, itr, services)
+ else:
+ # Sub-bouquets.
+ if self._sub_bq_button.get_active():
+ itr = self.append_bouquet(gen_bouquet_name(bqs, def_bq_name, bq_type), bq_type, bqs, model, itr, ())
+ # Generating groups with skipping markers.
+ m_name = BqServiceType.MARKER.value
+ def_bq_name = f"{def_bq_name} [No group]"
+ gr = self.get_services_groups(filter(lambda s: s.service_type != m_name, services), def_bq_name)
+ [self.append_bouquet(gen_bouquet_name(bqs, g, bq_type), bq_type, bqs, model, itr, s) for g, s in gr.items()]
+
+ def append_bouquet(self, bq_name, bq_type, bqs, model, itr, services):
+ """ Adds new bouquet and returns iter of appended row. """
+ cur_services = self._app.current_services
+ bqs[f"{bq_name}:{bq_type}"] = [s.fav_id for s in services]
+ cur_services.update({s.fav_id: s for s in services})
+ bq = (bq_name, None, None, bq_type)
+ return model.append(itr, bq)
+
+ def get_services_groups(self, services, def_gr_name="No group"):
+ def grouper(s):
+ return s.package or def_gr_name
+
+ return {k: list(v) for k, v in groupby(sorted(services, key=grouper), key=grouper)}
def on_add_epg_source(self):
active_src = self._epg_links_button.get_active_id()
diff --git a/app/ui/m3u.glade b/app/ui/m3u.glade
index 8e77f029..ed58481a 100644
--- a/app/ui/m3u.glade
+++ b/app/ui/m3u.glade
@@ -485,7 +485,6 @@ Author: Dmitriy Yefremov
Single bouquet
header-button
True
- False
True
False
True
@@ -503,7 +502,6 @@ Author: Dmitriy Yefremov
Split by groups
header-button
True
- False
True
False
True
@@ -521,7 +519,6 @@ Author: Dmitriy Yefremov
Create sub-bouquets
header-button
True
- False
True
False
True