mirror of
https://github.com/DYefremov/DemonEditor.git
synced 2026-05-08 11:56:22 +02:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0daaf6d1e5 | ||
|
|
47f26b0f4c | ||
|
|
e67ce41667 | ||
|
|
0cff24486a | ||
|
|
850ba0d96a | ||
|
|
303c9a0267 | ||
|
|
0f95165088 | ||
|
|
105cf9c90c | ||
|
|
cb40a8d0de | ||
|
|
f19ab37bc8 | ||
|
|
d716bd6a86 | ||
|
|
5b13b22823 | ||
|
|
49076fe477 | ||
|
|
50a517b6f1 | ||
|
|
184c3b18ba | ||
|
|
2f8dcaf47b | ||
|
|
dbe18b345f | ||
|
|
5d68ec8176 | ||
|
|
83e58f9375 | ||
|
|
fe199d78a4 | ||
|
|
d5f7acb019 | ||
|
|
a141c34ee7 | ||
|
|
25c9189e1a | ||
|
|
d9390aa7be | ||
|
|
e12cc86e5f | ||
|
|
f1ef9fe4aa | ||
|
|
728bfd0b20 | ||
|
|
1d6022b6db | ||
|
|
8609d30ac9 | ||
|
|
fde06dca89 | ||
|
|
e41bf5f58f | ||
|
|
b1488df9ce | ||
|
|
c6e4b3624b | ||
|
|
26b843921b | ||
|
|
e73638d006 |
@@ -5,14 +5,17 @@ Experimental support of Neutrino-MP or others on the same basis (BPanther, etc).
|
||||
Focused on the convenience of working in lists from the keyboard. The mouse is also fully supported (Drag and Drop etc)
|
||||
|
||||
Keyboard shortcuts:
|
||||
Ctrl + X, C, V, Up, Down, PageUp, PageDown, S, T, E, L, H, Space; Insert, Delete, F2.
|
||||
Ctrl + X, C, V, Up, Down, PageUp, PageDown, S, T, E, L, H, Space; Insert, Delete, F2.
|
||||
Insert - copies the selected channels from the main list to the bouquet or inserts (creates) a new bouquet.
|
||||
Ctrl + X - only in bouquet list. Ctrl + C - only in services list.
|
||||
Clipboard is "rubber". There is an accumulation before the insertion!
|
||||
Ctrl + E, F2 - edit/rename.
|
||||
Ctrl + S, T, E in Satellites edit tool for create and edit satellite or transponder.
|
||||
Ctrl + L - parental lock.
|
||||
Ctrl + L - parental lock.
|
||||
Ctrl + H - hide/skip.
|
||||
Left/Right - remove selection.
|
||||
|
||||
Multiple selections in lists only with Space key (as in file managers)!
|
||||
|
||||
Extra:
|
||||
Ability to import IPTV into bouquet from m3u files(Enigma2 only)!
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
from collections import namedtuple
|
||||
from enum import Enum
|
||||
|
||||
Service = namedtuple("Service", ["flags_cas", "transponder_type", "coded", "service", "locked", "hide",
|
||||
"package", "service_type", "ssid", "freq", "rate", "pol", "fec",
|
||||
Service = namedtuple("Service", ["flags_cas", "transponder_type", "coded", "service", "locked", "hide", "package",
|
||||
"service_type", "picon", "picon_id", "ssid", "freq", "rate", "pol", "fec",
|
||||
"system", "pos", "data_id", "fav_id", "transponder"])
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ SYSTEM = {"0": "DVB-S", "1": "DVB-S2"}
|
||||
MODULATION = {"0": "Auto", "1": "QPSK", "2": "8PSK", "3": "16APSK", "5": "32APSK"}
|
||||
|
||||
SERVICE_TYPE = {"-2": "Unknown", "1": "TV", "2": "Radio", "3": "Data",
|
||||
"10": "Radio", "12": "Data", "22": "TV", "25": "TV (HD)",
|
||||
"10": "Radio", "12": "Data", "22": "TV", "25": "TV (HD)", "31": "TV (UHD)",
|
||||
"136": "Data", "139": "Data"}
|
||||
|
||||
CAS = {"C:2600": "BISS", "C:0b00": "Conax", "C:0b01": "Conax", "C:0b02": "Conax", "C:0baa": "Conax", "C:0602": "Irdeto",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
""" Module for parsing bouquets """
|
||||
from app.eparser.ecommons import BqServiceType, BouquetService, Bouquets, Bouquet
|
||||
|
||||
_BOUQUETS_PATH = "../data/"
|
||||
_TV_ROOT_FILE_NAME = "bouquets.tv"
|
||||
_RADIO_ROOT_FILE_NAME = "bouquets.radio"
|
||||
|
||||
@@ -19,10 +18,10 @@ def write_bouquets(path, bouquets):
|
||||
line.append("#NAME {}\n".format(bqs.name))
|
||||
|
||||
for bq in bqs.bouquets:
|
||||
line.append(srv_line.format(bq.name, bq.type))
|
||||
line.append(srv_line.format(bq.name.replace(" ", "_"), bq.type))
|
||||
write_bouquet(path, bq.name, bq.type, bq.services)
|
||||
|
||||
with open(path + "bouquets.{}".format(bqs.type), "w") as file:
|
||||
with open(path + "bouquets.{}".format(bqs.type), "w", encoding="utf-8") as file:
|
||||
file.writelines(line)
|
||||
|
||||
|
||||
@@ -38,40 +37,36 @@ def write_bouquet(path, name, bq_type, channels):
|
||||
else:
|
||||
bouquet.append("#SERVICE {}\n".format(to_bouquet_id(ch)))
|
||||
|
||||
with open(path + "userbouquet.{}.{}".format(name, bq_type), "w") as file:
|
||||
with open(path + "userbouquet.{}.{}".format(name.replace(" ", "_"), bq_type), "w", encoding="utf-8") as file:
|
||||
file.writelines(bouquet)
|
||||
|
||||
|
||||
def to_bouquet_id(ch):
|
||||
""" Creates bouquet channel id """
|
||||
data_type = ch.data_id
|
||||
if data_type:
|
||||
data_type = int(ch.data_id.split(":")[-2])
|
||||
if data_type == 22:
|
||||
data_type = 16
|
||||
elif data_type == 25:
|
||||
data_type = 19
|
||||
service = "{}:0:{}:{}:0:0:0:".format(1, data_type, ch.fav_id)
|
||||
if data_type and len(data_type) > 4:
|
||||
data_type = int(ch.data_id.split(":")[4])
|
||||
|
||||
return service
|
||||
return "{}:0:{:X}:{}:0:0:0:".format(1, data_type, ch.fav_id)
|
||||
|
||||
|
||||
def get_bouquet(path, name, bq_type):
|
||||
""" Parsing services ids from bouquet file """
|
||||
with open(path + "userbouquet.{}.{}".format(name, bq_type)) as file:
|
||||
with open(path + "userbouquet.{}.{}".format(name, bq_type), encoding="utf-8") as file:
|
||||
chs_list = file.read()
|
||||
services = []
|
||||
for ch in list(filter(lambda x: len(x) > 1, chs_list.split("#SERVICE")[1:])): # filtering ['']
|
||||
srvs = list(filter(None, chs_list.split("\n#SERVICE"))) # filtering ['']
|
||||
for ch in srvs[1:]:
|
||||
ch_data = ch.strip().split(":")
|
||||
if ch_data[1] == "64":
|
||||
services.append(BouquetService(ch_data[-1].split("\n")[0], BqServiceType.MARKER, ch, ch_data[2]))
|
||||
elif "http" in ch:
|
||||
services.append(BouquetService(ch_data[-1].split("\n")[0], BqServiceType.IPTV, ch, 0))
|
||||
else:
|
||||
services.append(BouquetService(None, BqServiceType.DEFAULT,
|
||||
"{}:{}:{}:{}".format(ch_data[3], ch_data[4], ch_data[5], ch_data[6]), 0))
|
||||
fav_id = "{}:{}:{}:{}".format(ch_data[3], ch_data[4], ch_data[5], ch_data[6])
|
||||
services.append(BouquetService(None, BqServiceType.DEFAULT, fav_id, 0))
|
||||
|
||||
return services
|
||||
return srvs[0].strip("#NAME").strip(), services
|
||||
|
||||
|
||||
def parse_bouquets(path, bq_name, bq_type):
|
||||
@@ -85,10 +80,10 @@ def parse_bouquets(path, bq_name, bq_type):
|
||||
_, _, name = line.partition(nm_sep)
|
||||
bouquets = Bouquets(name.strip(), bq_type, [])
|
||||
if bouquets and "#SERVICE" in line:
|
||||
name = line.split(".")[1]
|
||||
bouquets[2].append(Bouquet(name=name,
|
||||
b_name, services = get_bouquet(path, line.split(".")[1], bq_type)
|
||||
bouquets[2].append(Bouquet(name=b_name,
|
||||
type=bq_type,
|
||||
services=get_bouquet(path, name, bq_type),
|
||||
services=services,
|
||||
locked=None,
|
||||
hidden=None))
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ from .blacklist import get_blacklist
|
||||
from ..ecommons import Service, POLARIZATION, SYSTEM, FEC, SERVICE_TYPE, FLAG
|
||||
|
||||
_HEADER = "eDVB services /4/"
|
||||
_FILE_PATH = "../data/lamedb"
|
||||
_SEP = ":" # separator
|
||||
_FILE_NAME = "lamedb"
|
||||
|
||||
@@ -57,7 +56,7 @@ def parse(path):
|
||||
log(msg)
|
||||
raise SyntaxError(msg)
|
||||
transponders, sep, services = services.partition("services") # 2 step
|
||||
services, sep, _ = services.partition("end") # 3 step
|
||||
services, sep, _ = services.partition("\nend") # 3 step
|
||||
|
||||
return parse_services(services.split("\n"), transponders.split("/"), path)
|
||||
|
||||
@@ -86,9 +85,19 @@ def parse_services(services, transponders, path):
|
||||
for ch in srv:
|
||||
data = str(ch[0]).split(_SEP)
|
||||
sp = "0"
|
||||
tid = data[2]
|
||||
nid = data[3]
|
||||
transponder_id = "{}:{}:{}".format(data[1], tid, nid)
|
||||
transponder = transponders.get(transponder_id, None)
|
||||
|
||||
tid = tid.lstrip(sp).upper()
|
||||
nid = nid.lstrip(sp).upper()
|
||||
ssid = str(data[0]).lstrip(sp).upper()
|
||||
onid = str(data[1]).lstrip(sp).upper()
|
||||
# For comparison in bouquets. Needed in upper case!!!
|
||||
fav_id = "{}:{}:{}:{}".format(str(data[0]).lstrip(sp), str(data[2]).lstrip(sp),
|
||||
str(data[3]).lstrip(sp), str(data[1]).lstrip(sp)).upper()
|
||||
fav_id = "{}:{}:{}:{}".format(ssid, tid, nid, onid)
|
||||
picon_id = "1_0_{}_{}_{}_{}_{}_0_0_0.png".format(1, ssid, tid, nid, onid)
|
||||
|
||||
all_flags = ch[2].split(",")
|
||||
coded = CODED_ICON if list(filter(lambda x: x.startswith("C:"), all_flags)) else None
|
||||
flags = list(filter(lambda x: x.startswith("f:"), all_flags))
|
||||
@@ -98,21 +107,22 @@ def parse_services(services, transponders, path):
|
||||
package = list(filter(lambda x: x.startswith("p:"), all_flags))
|
||||
package = package[0][2:] if package else None
|
||||
|
||||
transponder_id = "{}:{}:{}".format(data[1], data[2], data[3])
|
||||
transponder = transponders.get(transponder_id, None)
|
||||
|
||||
if transponder is not None:
|
||||
tr_type, sp, tr = str(transponder).partition(" ")
|
||||
tr = tr.split(_SEP)
|
||||
service_type = SERVICE_TYPE.get(data[4], SERVICE_TYPE["-2"])
|
||||
# removing all non printable symbols!
|
||||
srv_name = "".join(c for c in ch[1] if c.isprintable())
|
||||
channels.append(Service(flags_cas=ch[2],
|
||||
transponder_type=tr_type,
|
||||
coded=coded,
|
||||
service=ch[1],
|
||||
service=srv_name,
|
||||
locked=locked,
|
||||
hide=hide,
|
||||
package=package,
|
||||
service_type=service_type,
|
||||
picon=None,
|
||||
picon_id=picon_id,
|
||||
ssid=data[0],
|
||||
freq=tr[0],
|
||||
rate=tr[1],
|
||||
|
||||
@@ -3,7 +3,7 @@ from .ecommons import BqServiceType, Service
|
||||
|
||||
def parse_m3u(path):
|
||||
with open(path) as file:
|
||||
aggr = [None] * 8
|
||||
aggr = [None] * 10
|
||||
channels = []
|
||||
count = 0
|
||||
name = None
|
||||
@@ -15,7 +15,8 @@ def parse_m3u(path):
|
||||
count = 0
|
||||
fav_id = " 1:0:1:0:0:0:0:0:0:0:{}:{}\n#DESCRIPTION: {}\n".format(
|
||||
line.strip().replace(":", "%3a"), name, name, None)
|
||||
channels.append(Service(*aggr[0:3], name, *aggr[0:3], BqServiceType.IPTV.name, *aggr, fav_id, None))
|
||||
srv = Service(*aggr[0:3], name, *aggr[0:3], BqServiceType.IPTV.name, *aggr, fav_id, None)
|
||||
channels.append(srv)
|
||||
|
||||
return channels
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ def write_services(path, services):
|
||||
|
||||
for srv in transponers.get(tr):
|
||||
srv_elem = doc.createElement("S")
|
||||
srv_elem.setAttribute("i", srv[8])
|
||||
srv_elem.setAttribute("n", srv[3])
|
||||
srv_elem.setAttribute("i", srv.ssid)
|
||||
srv_elem.setAttribute("n", srv.service)
|
||||
|
||||
srv_attrs = srv.data_id.split(":")
|
||||
api = srv_attrs.pop(0)
|
||||
@@ -116,9 +116,7 @@ def parse_transponder(api, sat, sat_pos, services, tr_elem):
|
||||
sys = sys.value if sys else sys
|
||||
|
||||
tr = "{}:{}:{}:{}:{}:{}:{}:{}:{}".format(tr_id, on, freq, inv, rate, fec, pol, mod, sys)
|
||||
|
||||
tr_id = tr_id.lstrip("0")
|
||||
on = on.lstrip("0")
|
||||
|
||||
for srv_elem in tr_elem.getElementsByTagName("S"):
|
||||
if srv_elem.hasAttributes():
|
||||
@@ -141,7 +139,8 @@ def parse_transponder(api, sat, sat_pos, services, tr_elem):
|
||||
vt = srv_elem.attributes["vt"].value
|
||||
|
||||
data_id = "{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}".format(api, srv_type, sys, num, f, v, a, p, pmt, tx, vt)
|
||||
fav_id = "{}:{}:{}".format(tr_id, on, ssid.lstrip("0"))
|
||||
fav_id = "{}:{}:{}".format(tr_id, on.lstrip("0"), ssid.lstrip("0"))
|
||||
picon_id = "{}{}{}.png".format(tr_id, on, ssid)
|
||||
|
||||
srv = Service(flags_cas=sat,
|
||||
transponder_type=None,
|
||||
@@ -151,6 +150,8 @@ def parse_transponder(api, sat, sat_pos, services, tr_elem):
|
||||
hide=None,
|
||||
package=PROVIDER.get(int(on, 16)),
|
||||
service_type=SERVICE_TYPE.get(str(int(srv_type, 16))),
|
||||
picon=None,
|
||||
picon_id=picon_id,
|
||||
ssid=ssid,
|
||||
freq=freq,
|
||||
rate=rate,
|
||||
|
||||
@@ -22,6 +22,7 @@ class DownloadDataType(Enum):
|
||||
def download_data(*, properties, download_type=DownloadDataType.ALL, callback=None):
|
||||
with FTP(host=properties["host"]) as ftp:
|
||||
ftp.login(user=properties["user"], passwd=properties["password"])
|
||||
ftp.encoding = "utf-8"
|
||||
save_path = properties["data_dir_path"]
|
||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||
files = []
|
||||
@@ -66,6 +67,7 @@ def upload_data(*, properties, download_type=DownloadDataType.ALL, remove_unused
|
||||
|
||||
with FTP(host=host) as ftp:
|
||||
ftp.login(user=properties["user"], passwd=properties["password"])
|
||||
ftp.encoding = "utf-8"
|
||||
|
||||
if download_type is DownloadDataType.ALL or download_type is DownloadDataType.SATELLITES:
|
||||
ftp.cwd(properties["satellites_xml_path"])
|
||||
|
||||
@@ -6,7 +6,10 @@ from html.parser import HTMLParser
|
||||
from app.commons import log
|
||||
from app.properties import Profile
|
||||
|
||||
Provider = namedtuple("Provider", ["logo", "name", "url", "on_id", "selected"])
|
||||
_ENIGMA2_PICON_KEY = "{:X}:{:X}:{:X}0000"
|
||||
_NEUTRINO_PICON_KEY = "{:x}{:04x}{:04x}.png"
|
||||
|
||||
Provider = namedtuple("Provider", ["logo", "name", "pos", "url", "on_id", "selected"])
|
||||
Picon = namedtuple("Picon", ["ref", "ssid", "v_pid"])
|
||||
|
||||
|
||||
@@ -68,7 +71,7 @@ class PiconsParser(HTMLParser):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def parse(open_path, picons_path, tmp_path, on_id, profile=Profile.ENIGMA_2):
|
||||
def parse(open_path, picons_path, tmp_path, on_id, pos, picon_ids, profile=Profile.ENIGMA_2):
|
||||
with open(open_path, encoding="utf-8", errors="replace") as f:
|
||||
parser = PiconsParser()
|
||||
parser.reset()
|
||||
@@ -78,19 +81,20 @@ class PiconsParser(HTMLParser):
|
||||
os.makedirs(picons_path, exist_ok=True)
|
||||
for p in picons:
|
||||
try:
|
||||
picon_file_name = picons_path + PiconsParser.format(p.ssid, on_id, p.v_pid, profile)
|
||||
shutil.copyfile(tmp_path + "www.lyngsat.com/" + p.ref.lstrip("."), picon_file_name)
|
||||
name = PiconsParser.format(p.ssid, on_id, p.v_pid, pos, picon_ids, profile)
|
||||
p_name = picons_path + (name if name else os.path.basename(p.ref))
|
||||
shutil.copyfile(tmp_path + "www.lyngsat.com/" + p.ref.lstrip("."), p_name)
|
||||
except (TypeError, ValueError) as e:
|
||||
log("Picons format parse error: {} {} {}".format(p.ref, p.ssid, p.v_pid) + "\n" + str(e))
|
||||
log("Picons format parse error: {}".format(p) + "\n" + str(e))
|
||||
print(e)
|
||||
|
||||
@staticmethod
|
||||
def format(ssid, on_id, v_pid, profile: Profile):
|
||||
def format(ssid, on_id, v_pid, pos, picon_ids, profile: Profile):
|
||||
tr_id = int(ssid[:-2] if len(ssid) < 4 else ssid[:2])
|
||||
if profile is Profile.ENIGMA_2:
|
||||
return "1_0_{}_{:X}_{:X}_{:X}_1680000_0_0_0.png".format(1 if v_pid else 2, int(ssid), tr_id, int(on_id))
|
||||
return picon_ids.get(_ENIGMA2_PICON_KEY.format(int(ssid), int(on_id), int(pos)), None)
|
||||
elif profile is Profile.NEUTRINO_MP:
|
||||
return "{:x}{:04x}{:04x}.png".format(tr_id, int(on_id), int(ssid))
|
||||
return _NEUTRINO_PICON_KEY.format(tr_id, int(on_id), int(ssid))
|
||||
else:
|
||||
return "{}.png".format(ssid)
|
||||
|
||||
@@ -112,6 +116,8 @@ class ProviderParser(HTMLParser):
|
||||
self._current_cell = []
|
||||
self.rows = []
|
||||
self._ids = set()
|
||||
self._counter = 0
|
||||
self._positon = None
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if tag == 'td':
|
||||
@@ -142,27 +148,40 @@ class ProviderParser(HTMLParser):
|
||||
self._current_cell = []
|
||||
elif tag == 'tr':
|
||||
row = self._current_row
|
||||
# Satellite position
|
||||
self._counter = self._counter + 1
|
||||
if self._counter == 12:
|
||||
pos = str(row)
|
||||
pos = pos[pos.rfind("at") + 2:]
|
||||
self._positon = "".join(c for c in pos if c.isalnum() or c == ".")
|
||||
|
||||
if len(row) == 12:
|
||||
on_id, sep, tid = str(row[-2]).partition("-")
|
||||
if tid and on_id not in self._ON_ID_BLACK_LIST and on_id not in self._ids:
|
||||
row[-2] = on_id
|
||||
self.rows.append(row)
|
||||
self._ids.add(on_id)
|
||||
row[0] = self._positon
|
||||
self._current_row = []
|
||||
|
||||
def error(self, message):
|
||||
pass
|
||||
|
||||
def reset(self):
|
||||
super().reset()
|
||||
self._counter = 0
|
||||
|
||||
|
||||
def parse_providers(open_path):
|
||||
parser = ProviderParser()
|
||||
parser.reset()
|
||||
|
||||
with open(open_path, encoding="utf-8", errors="replace") as f:
|
||||
parser = ProviderParser()
|
||||
parser.reset()
|
||||
parser.feed(f.read())
|
||||
rows = parser.rows
|
||||
|
||||
if rows:
|
||||
return [Provider(logo=r[2], name=r[5], url=r[6], on_id=r[-2], selected=True) for r in rows]
|
||||
return [Provider(logo=r[2], name=r[5], pos=r[0], url=r[6], on_id=r[-2], selected=True) for r in rows]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<property name="icon_name">system-help</property>
|
||||
<property name="type_hint">normal</property>
|
||||
<property name="program_name">DemonEditor</property>
|
||||
<property name="version">0.2.1 Pre-alpha</property>
|
||||
<property name="version">0.2.3 Pre-alpha</property>
|
||||
<property name="copyright" translatable="yes">2018 Dmitriy Yefremov
|
||||
dmitry.v.yefremov@gmail.com
|
||||
</property>
|
||||
@@ -37,9 +37,6 @@ dmitry.v.yefremov@gmail.com
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -563,9 +560,6 @@ dmitry.v.yefremov@gmail.com
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
@@ -611,7 +605,6 @@ dmitry.v.yefremov@gmail.com
|
||||
<property name="value">1</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
<property name="page_size">1</property>
|
||||
</object>
|
||||
<object class="GtkDialog" id="settings_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
|
||||
@@ -58,5 +58,16 @@ def show_dialog(dialog_type: DialogType, transient, text=None, options=None, act
|
||||
return response
|
||||
|
||||
|
||||
def get_chooser_dialog(transient, options, pattern, name):
|
||||
file_filter = Gtk.FileFilter()
|
||||
file_filter.add_pattern(pattern)
|
||||
file_filter.set_name(name)
|
||||
return show_dialog(dialog_type=DialogType.CHOOSER,
|
||||
transient=transient,
|
||||
options=options,
|
||||
action_type=Gtk.FileChooserAction.OPEN,
|
||||
file_filter=file_filter)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
|
||||
@@ -2,18 +2,20 @@ import os
|
||||
from contextlib import suppress
|
||||
from functools import lru_cache
|
||||
|
||||
import shutil
|
||||
|
||||
from app.commons import run_idle, log
|
||||
from app.eparser import get_blacklist, write_blacklist, parse_m3u
|
||||
from app.eparser import get_services, get_bouquets, write_bouquets, write_services, Bouquets, Bouquet, Service
|
||||
from app.eparser.ecommons import CAS, FLAG
|
||||
from app.eparser.enigma.bouquets import BqServiceType
|
||||
from app.properties import get_config, write_config, Profile
|
||||
from .picons_dialog import PiconsDialog
|
||||
from . import Gtk, Gdk, UI_RESOURCES_PATH, LOCKED_ICON, HIDE_ICON
|
||||
from .dialogs import show_dialog, DialogType
|
||||
from .dialogs import show_dialog, DialogType, get_chooser_dialog
|
||||
from .download_dialog import show_download_dialog
|
||||
from .main_helper import edit_marker, insert_marker, move_items, edit, ViewTarget, set_flags, locate_in_services, \
|
||||
scroll_to
|
||||
scroll_to, get_base_model, update_picons, copy_picon_reference, assign_picon, remove_picon, search
|
||||
from .picons_dialog import PiconsDialog
|
||||
from .satellites_dialog import show_satellites_dialog
|
||||
from .settings_dialog import show_settings_dialog
|
||||
|
||||
@@ -24,7 +26,7 @@ class MainAppWindow:
|
||||
_BOUQUETS_LIST_NAME = "bouquets_tree_store"
|
||||
# dynamically active elements depending on the selected view
|
||||
_SERVICE_ELEMENTS = ("copy_tool_button", "to_fav_tool_button", "copy_menu_item", "services_to_fav_move_popup_item",
|
||||
"services_edit_popup_item", "services_copy_popup_item")
|
||||
"services_edit_popup_item", "services_copy_popup_item", "services_picon_popup_item")
|
||||
|
||||
_BOUQUET_ELEMENTS = ("edit_tool_button", "new_tool_button",
|
||||
"bouquets_new_popup_item", "bouquets_edit_popup_item")
|
||||
@@ -35,7 +37,7 @@ class MainAppWindow:
|
||||
_FAV_ELEMENTS = ("cut_tool_button", "paste_tool_button", "cut_menu_item",
|
||||
"paste_menu_item", "fav_cut_popup_item", "fav_paste_popup_item", "import_m3u_tool_button",
|
||||
"fav_import_m3u_popup_item", "fav_insert_marker_popup_item", "fav_edit_popup_item",
|
||||
"fav_locate_popup_item")
|
||||
"fav_locate_popup_item", "fav_picon_popup_item")
|
||||
|
||||
_FAV_ONLY_ELEMENTS = ("import_m3u_tool_button", "fav_import_m3u_popup_item", "fav_insert_marker_popup_item",
|
||||
"fav_edit_marker_popup_item")
|
||||
@@ -51,7 +53,7 @@ class MainAppWindow:
|
||||
"bouquets_remove_popup_item", "fav_remove_popup_item", "hide_tool_button",
|
||||
"import_m3u_tool_button", "fav_import_m3u_popup_item", "fav_insert_marker_popup_item",
|
||||
"fav_edit_marker_popup_item", "fav_edit_popup_item", "fav_locate_popup_item",
|
||||
"services_copy_popup_item")
|
||||
"services_copy_popup_item", "services_picon_popup_item", "fav_picon_popup_item")
|
||||
|
||||
def __init__(self):
|
||||
handlers = {"on_close_main_window": self.on_quit,
|
||||
@@ -90,16 +92,24 @@ class MainAppWindow:
|
||||
"on_edit_marker": self.on_edit_marker,
|
||||
"on_fav_popup": self.on_fav_popup,
|
||||
"on_locate_in_services": self.on_locate_in_services,
|
||||
"on_picons_loader_show": self.on_picons_loader_show}
|
||||
"on_picons_loader_show": self.on_picons_loader_show,
|
||||
"on_filter_changed": self.on_filter_changed,
|
||||
"on_assign_picon": self.on_assign_picon,
|
||||
"on_remove_picon": self.on_remove_picon,
|
||||
"on_reference_picon": self.on_reference_picon,
|
||||
"on_filter_toggled": self.on_filter_toggled,
|
||||
"on_search_toggled": self.on_search_toggled,
|
||||
"on_search": self.on_search}
|
||||
|
||||
self.__options = get_config()
|
||||
self.__profile = self.__options.get("profile")
|
||||
os.makedirs(os.path.dirname(self.__options.get(self.__profile).get("data_dir_path")), exist_ok=True)
|
||||
# Used for copy/paste. When adding the previous data will not be deleted.
|
||||
# Clearing only after the insertion!
|
||||
self.__rows_buffer = []
|
||||
self.__services = {}
|
||||
self.__bouquets = {}
|
||||
self.__bouquets_to_del = []
|
||||
self.__picons = {}
|
||||
self.__blacklist = set()
|
||||
|
||||
builder = Gtk.Builder()
|
||||
@@ -122,6 +132,7 @@ class MainAppWindow:
|
||||
self.__profile_label.set_text("Enigma2 v.4" if Profile(self.__profile) is Profile.ENIGMA_2 else "Neutrino-MP")
|
||||
# dynamically active elements depending on the selected view
|
||||
self.__tool_elements = {k: builder.get_object(k) for k in self.__DYNAMIC_ELEMENTS}
|
||||
self.__picons_download_tool_button = builder.get_object("picons_download_tool_button")
|
||||
self.__cas_label = builder.get_object("cas_label")
|
||||
self.__fav_count_label = builder.get_object("fav_count_label")
|
||||
self.__bouquets_count_label = builder.get_object("bouquets_count_label")
|
||||
@@ -129,7 +140,18 @@ class MainAppWindow:
|
||||
self.__radio_count_label = builder.get_object("radio_count_label")
|
||||
self.__data_count_label = builder.get_object("data_count_label")
|
||||
self.__fav_edit_marker_popup_item = builder.get_object("fav_edit_marker_popup_item")
|
||||
self.__search_info_bar = builder.get_object("search_info_bar")
|
||||
# Filter
|
||||
self.__services_model_filter = builder.get_object("services_model_filter")
|
||||
self.__services_model_filter.set_visible_func(self.services_filter_function)
|
||||
self.__filter_entry = builder.get_object("filter_entry")
|
||||
self.__filter_info_bar = builder.get_object("filter_info_bar")
|
||||
self.init_drag_and_drop() # drag and drop
|
||||
# Force ctrl press event for view. Multiple selections in lists only with Space key(as in file managers)!!!
|
||||
self.__services_view.connect("key-press-event", self.force_ctrl)
|
||||
self.__fav_view.connect("key-press-event", self.force_ctrl)
|
||||
# Clipboard
|
||||
self.__clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||
self.__main_window.show()
|
||||
|
||||
def init_drag_and_drop(self):
|
||||
@@ -146,6 +168,10 @@ class MainAppWindow:
|
||||
self.__services_view.drag_source_set_target_list(None)
|
||||
self.__services_view.drag_source_add_text_targets()
|
||||
|
||||
def force_ctrl(self, view, event):
|
||||
""" Function for force ctrl press event for view """
|
||||
event.state |= Gdk.ModifierType.CONTROL_MASK
|
||||
|
||||
def on_quit(self, *args):
|
||||
""" Called before app quit """
|
||||
write_config(self.__options) # storing current config
|
||||
@@ -180,7 +206,7 @@ class MainAppWindow:
|
||||
def on_copy(self, view):
|
||||
model, paths = view.get_selection().get_selected_rows()
|
||||
itrs = [model.get_iter(path) for path in paths]
|
||||
rows = [(0, *model.get(in_itr, 2, 3, 4, 5, 7, 14, 16)) for in_itr in itrs]
|
||||
rows = [(0, *model.get(in_itr, 2, 3, 4, 5, 7, 16, 18, 8)) for in_itr in itrs]
|
||||
self.__rows_buffer.extend(rows)
|
||||
|
||||
def on_paste(self, view):
|
||||
@@ -210,7 +236,8 @@ class MainAppWindow:
|
||||
self.on_view_focus(view, None)
|
||||
|
||||
def on_edit(self, view):
|
||||
name = view.get_model().get_name()
|
||||
model = get_base_model(view.get_model())
|
||||
name = model.get_name()
|
||||
if name == self._BOUQUETS_LIST_NAME:
|
||||
self.on_bouquets_edit(view)
|
||||
# edit(view, self.__main_window, ViewTarget.BOUQUET)
|
||||
@@ -228,36 +255,41 @@ class MainAppWindow:
|
||||
if view.is_focus():
|
||||
selection = view.get_selection()
|
||||
model, paths = selection.get_selected_rows()
|
||||
model_name = model.get_name()
|
||||
model_name = get_base_model(model).get_name()
|
||||
itrs = [model.get_iter(path) for path in paths]
|
||||
rows = [model.get(in_itr, *[x for x in range(model.get_n_columns())]) for in_itr in itrs]
|
||||
rows = [model[in_itr][:] for in_itr in itrs]
|
||||
bq_selected = self.is_bouquet_selected()
|
||||
fav_bouquet = None
|
||||
|
||||
if bq_selected:
|
||||
fav_bouquet = self.__bouquets.get(bq_selected, None)
|
||||
|
||||
for itr in itrs:
|
||||
if fav_bouquet and model_name == self._FAV_LIST_NAME:
|
||||
del fav_bouquet[int(model.get_path(itr)[0])]
|
||||
if model_name == self._BOUQUETS_LIST_NAME:
|
||||
if len(model.get_path(itr)) < 2:
|
||||
show_dialog(DialogType.ERROR, self.__main_window, "This item is not allowed to be removed!")
|
||||
return
|
||||
else:
|
||||
self.delete_bouquet(bq_selected)
|
||||
model.remove(itr)
|
||||
if model_name == self._FAV_LIST_NAME:
|
||||
self.update_fav_num_column(model)
|
||||
self.remove_favs(fav_bouquet, itrs, model)
|
||||
elif model_name == self._BOUQUETS_LIST_NAME:
|
||||
self.delete_bouquets(itrs, model, bq_selected)
|
||||
elif model_name == self._SERVICE_LIST_NAME:
|
||||
self.delete_services(bq_selected, rows)
|
||||
self.delete_services(bq_selected, itrs, model, rows)
|
||||
|
||||
self.on_view_focus(view, None)
|
||||
|
||||
return rows
|
||||
|
||||
def delete_services(self, bq_selected, rows):
|
||||
def remove_favs(self, fav_bouquet, itrs, model):
|
||||
""" Deleting bouquet services """
|
||||
if fav_bouquet:
|
||||
for itr in itrs:
|
||||
del fav_bouquet[int(model.get_path(itr)[0])]
|
||||
self.__fav_model.remove(itr)
|
||||
self.update_fav_num_column(model)
|
||||
|
||||
def delete_services(self, bq_selected, itrs, model, rows):
|
||||
""" Deleting services """
|
||||
srv_itrs = [self.__services_model_filter.convert_iter_to_child_iter(
|
||||
model.convert_iter_to_child_iter(itr)) for itr in itrs]
|
||||
for s_itr in srv_itrs:
|
||||
self.__services_model.remove(s_itr)
|
||||
|
||||
for row in rows:
|
||||
# There are channels with the same parameters except for the name.
|
||||
# None because it can have duplicates! Need fix
|
||||
@@ -273,13 +305,16 @@ class MainAppWindow:
|
||||
if bq_selected:
|
||||
self.update_bouquet_channels(self.__fav_model, None, bq_selected)
|
||||
|
||||
def delete_bouquet(self, bouquet):
|
||||
""" Deleting bouquet """
|
||||
self.__bouquets.pop(bouquet)
|
||||
self.__fav_model.clear()
|
||||
profile = Profile(self.__profile)
|
||||
if profile is Profile.ENIGMA_2:
|
||||
self.__bouquets_to_del.append(self.get_bouquet_file_name(bouquet))
|
||||
def delete_bouquets(self, itrs, model, bouquet):
|
||||
""" Deleting bouquets """
|
||||
for itr in itrs:
|
||||
if len(model.get_path(itr)) < 2:
|
||||
show_dialog(DialogType.ERROR, self.__main_window, "This item is not allowed to be removed!")
|
||||
return
|
||||
else:
|
||||
self.__bouquets.pop(bouquet)
|
||||
self.__fav_model.clear()
|
||||
self.__bouquets_model.remove(itr)
|
||||
|
||||
def get_bouquet_file_name(self, bouquet):
|
||||
bouquet_file_name = "{}userbouquet.{}.{}".format(self.__options.get(self.__profile).get("data_dir_path"),
|
||||
@@ -292,7 +327,8 @@ class MainAppWindow:
|
||||
|
||||
if paths:
|
||||
itr = model.get_iter(paths[0])
|
||||
bq_type = model.get_value(itr, 1)
|
||||
bq_type = model.get_value(itr, 3)
|
||||
|
||||
bq_name = "bouquet"
|
||||
count = 0
|
||||
key = "{}:{}".format(bq_name, bq_type)
|
||||
@@ -340,14 +376,11 @@ class MainAppWindow:
|
||||
itr = model.get_iter(paths[0])
|
||||
bq_name, bq_type = model.get(itr, 0, 3)
|
||||
response = show_dialog(DialogType.INPUT, self.__main_window, bq_name)
|
||||
|
||||
if response == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
model.set_value(itr, 0, response)
|
||||
self.__bouquets["{}:{}".format(response, bq_type)] = self.__bouquets.pop("{}:{}".format(bq_name, bq_type))
|
||||
if Profile(self.__profile) is Profile.ENIGMA_2:
|
||||
self.__bouquets_to_del.append(self.get_bouquet_file_name(bq_selected))
|
||||
|
||||
def on_to_fav_move(self, view):
|
||||
""" Move items from app to fav list """
|
||||
@@ -359,6 +392,7 @@ class MainAppWindow:
|
||||
def get_selection(self, view):
|
||||
""" Creates a string from the iterators of the selected rows """
|
||||
model, paths = view.get_selection().get_selected_rows()
|
||||
model = get_base_model(model)
|
||||
|
||||
if len(paths) > 0:
|
||||
itrs = [model.get_iter(path) for path in paths]
|
||||
@@ -372,7 +406,7 @@ class MainAppWindow:
|
||||
show_dialog(DialogType.ERROR, self.__main_window, "Error. No bouquet is selected!")
|
||||
return
|
||||
|
||||
model = view.get_model()
|
||||
model = get_base_model(view.get_model())
|
||||
dest_index = 0
|
||||
|
||||
if drop_info:
|
||||
@@ -390,22 +424,21 @@ class MainAppWindow:
|
||||
if source == self._SERVICE_LIST_NAME:
|
||||
ext_model = self.__services_view.get_model()
|
||||
ext_itrs = [ext_model.get_iter_from_string(itr) for itr in itrs]
|
||||
ext_rows = [ext_model.get(ext_itr, *[x for x in range(ext_model.get_n_columns())]) for
|
||||
ext_itr in ext_itrs]
|
||||
ext_rows = [ext_model[ext_itr][:] for ext_itr in ext_itrs]
|
||||
dest_index -= 1
|
||||
for ext_row in ext_rows:
|
||||
dest_index += 1
|
||||
fav_id = ext_row[-2]
|
||||
channel = self.__services[fav_id]
|
||||
model.insert(dest_index, (0, channel.coded, channel.service, channel.locked, channel.hide,
|
||||
channel.service_type, channel.pos, channel.fav_id))
|
||||
fav_bouquet.insert(dest_index, channel.fav_id)
|
||||
fav_id = ext_row[18]
|
||||
ch = self.__services[fav_id]
|
||||
model.insert(dest_index, (0, ch.coded, ch.service, ch.locked, ch.hide,
|
||||
ch.service_type, ch.pos, ch.fav_id, self.__picons.get(ch.picon_id, None)))
|
||||
fav_bouquet.insert(dest_index, ch.fav_id)
|
||||
elif source == self._FAV_LIST_NAME:
|
||||
in_itrs = [model.get_iter_from_string(itr) for itr in itrs]
|
||||
in_rows = [model.get(in_itr, *[x for x in range(model.get_n_columns())]) for in_itr in in_itrs]
|
||||
in_rows = [model[in_itr][:] for in_itr in in_itrs]
|
||||
for row in in_rows:
|
||||
model.insert(dest_index, row)
|
||||
fav_bouquet.insert(dest_index, row[4])
|
||||
fav_bouquet.insert(dest_index, row[7])
|
||||
for in_itr in in_itrs:
|
||||
del fav_bouquet[int(model.get_path(in_itr)[0])]
|
||||
model.remove(in_itr)
|
||||
@@ -465,6 +498,8 @@ class MainAppWindow:
|
||||
self.append_bouquets(data_path)
|
||||
self.append_services(data_path)
|
||||
self.update_services_counts(len(self.__services_model))
|
||||
self.update_picons()
|
||||
self.__picons_download_tool_button.set_sensitive(len(self.__services_model))
|
||||
except FileNotFoundError as e:
|
||||
show_dialog(DialogType.ERROR, self.__main_window, getattr(e, "message", str(e)) +
|
||||
"\n\nPlease, download files from receiver or setup your path for read data!")
|
||||
@@ -483,14 +518,14 @@ class MainAppWindow:
|
||||
name, bt_type, locked, hidden = bt.name, bt.type, bt.locked, bt.hidden
|
||||
self.__bouquets_model.append(parent, [name, locked, hidden, bt_type])
|
||||
services = []
|
||||
agr = [None] * 7
|
||||
agr = [None] * 9
|
||||
for srv in bt.services:
|
||||
fav_id = srv.data
|
||||
# IPTV and MARKER services
|
||||
s_type = srv.type
|
||||
if s_type is BqServiceType.MARKER or s_type is BqServiceType.IPTV:
|
||||
self.__services[fav_id] = Service(*agr[0:3], srv.name, *agr[0:3],
|
||||
s_type.name, *agr, srv.num, fav_id, None)
|
||||
srv = Service(*agr[0:3], srv.name, *agr[0:3], s_type.name, *agr, srv.num, fav_id, None)
|
||||
self.__services[fav_id] = srv
|
||||
services.append(fav_id)
|
||||
self.__bouquets["{}:{}".format(name, bt_type)] = services
|
||||
|
||||
@@ -517,29 +552,34 @@ class MainAppWindow:
|
||||
self.__services.clear()
|
||||
self.__rows_buffer.clear()
|
||||
self.__bouquets.clear()
|
||||
self.__bouquets_to_del.clear()
|
||||
|
||||
def on_data_save(self, *args):
|
||||
if show_dialog(DialogType.QUESTION, self.__main_window) == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
path = self.__options.get(self.__profile).get("data_dir_path")
|
||||
backup_path = path + "backup/"
|
||||
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
|
||||
# backup files in data dir(skipping dirs and satellites.xml)
|
||||
for file in filter(lambda f: f != "satellites.xml" and os.path.isfile(os.path.join(path, f)), os.listdir(path)):
|
||||
shutil.move(os.path.join(path, file), backup_path + file)
|
||||
|
||||
bouquets = []
|
||||
services_model = self.__services_view.get_model()
|
||||
|
||||
def parse_bouquets(model, b_path, itr):
|
||||
bqs = None
|
||||
if model.iter_has_child(itr):
|
||||
num_of_children = model.iter_n_children(itr)
|
||||
bqs = []
|
||||
|
||||
num_of_children = model.iter_n_children(itr)
|
||||
for num in range(num_of_children):
|
||||
bq_itr = model.iter_nth_child(itr, num)
|
||||
bq_name, locked, hidden, bq_type = model.get(bq_itr, 0, 1, 2, 3)
|
||||
favs = self.__bouquets["{}:{}".format(bq_name, bq_type)]
|
||||
bq = Bouquet(bq_name, bq_type, [self.__services.get(f_id, None) for f_id in favs], locked, hidden)
|
||||
bqs.append(bq)
|
||||
bqs = Bouquets(*model.get(itr, 0, 3), bqs)
|
||||
bouquets.append(bqs)
|
||||
if len(b_path) == 1:
|
||||
bouquets.append(Bouquets(*model.get(itr, 0, 3), bqs if bqs else []))
|
||||
|
||||
profile = Profile(self.__profile)
|
||||
# Getting bouquets
|
||||
@@ -549,11 +589,7 @@ class MainAppWindow:
|
||||
services = [Service(*row[:]) for row in services_model]
|
||||
write_services(path, services, profile)
|
||||
# removing bouquet files
|
||||
if profile is profile.ENIGMA_2:
|
||||
for bqf in self.__bouquets_to_del:
|
||||
with suppress(FileNotFoundError):
|
||||
os.remove(bqf)
|
||||
self.__bouquets_to_del.clear()
|
||||
if profile is Profile.ENIGMA_2:
|
||||
# blacklist
|
||||
write_blacklist(path, self.__blacklist)
|
||||
|
||||
@@ -597,7 +633,8 @@ class MainAppWindow:
|
||||
channel = self.__services.get(ch_id, None)
|
||||
if channel:
|
||||
self.__fav_model.append((num + 1, channel.coded, channel.service, channel.locked,
|
||||
channel.hide, channel.service_type, channel.pos, channel.fav_id))
|
||||
channel.hide, channel.service_type, channel.pos, channel.fav_id,
|
||||
self.__picons.get(channel.picon_id, None)))
|
||||
|
||||
def is_bouquet_selected(self):
|
||||
""" Checks whether the bouquet is selected
|
||||
@@ -622,19 +659,21 @@ class MainAppWindow:
|
||||
response = show_settings_dialog(self.__main_window, self.__options)
|
||||
if response != Gtk.ResponseType.CANCEL:
|
||||
profile = self.__options.get("profile")
|
||||
self.__status_bar.push(0, "Current IP: " + self.__options.get(profile).get("host"))
|
||||
if profile != self.__profile:
|
||||
self.__status_bar.push(0, "Current IP: " + self.__options.get(profile).get("host"))
|
||||
self.__profile_label.set_text("Enigma 2 v.4" if Profile(profile) is Profile.ENIGMA_2 else "Neutrino-MP")
|
||||
self.__profile = profile
|
||||
self.clear_current_data()
|
||||
self.update_services_counts()
|
||||
self.__picons_download_tool_button.set_sensitive(len(self.__services_model))
|
||||
|
||||
def on_tree_view_key_release(self, view, event):
|
||||
""" Handling keystrokes """
|
||||
key = event.keyval
|
||||
ctrl = event.state & Gdk.ModifierType.CONTROL_MASK
|
||||
alt = event.state & Gdk.ModifierType.MOD1_MASK
|
||||
model_name = view.get_model().get_name()
|
||||
model = get_base_model(view.get_model())
|
||||
model_name = model.get_name()
|
||||
|
||||
if key == Gdk.KEY_Delete:
|
||||
self.on_delete(view)
|
||||
@@ -643,7 +682,7 @@ class MainAppWindow:
|
||||
elif ctrl and key in (Gdk.KEY_Down, Gdk.KEY_Page_Down, Gdk.KEY_KP_Page_Down):
|
||||
self.move_items(key)
|
||||
elif model_name == self._FAV_LIST_NAME and key == Gdk.KEY_Control_L or key == Gdk.KEY_Control_R:
|
||||
self.update_fav_num_column(view.get_model())
|
||||
self.update_fav_num_column(model)
|
||||
self.update_bouquet_list()
|
||||
elif key == Gdk.KEY_Insert:
|
||||
# Move items from app to fav list
|
||||
@@ -666,8 +705,8 @@ class MainAppWindow:
|
||||
self.on_hide(None)
|
||||
elif ctrl and key == Gdk.KEY_E or key == Gdk.KEY_e or key == Gdk.KEY_F2:
|
||||
self.on_edit(view)
|
||||
elif key == Gdk.KEY_space and model_name == self._FAV_LIST_NAME:
|
||||
pass
|
||||
elif key == Gdk.KEY_Left or key == Gdk.KEY_Right:
|
||||
view.do_unselect_all(view)
|
||||
|
||||
def on_download(self, item):
|
||||
show_download_dialog(transient=self.__main_window,
|
||||
@@ -678,7 +717,7 @@ class MainAppWindow:
|
||||
@run_idle
|
||||
def on_view_focus(self, view, focus_event):
|
||||
profile = Profile(self.__profile)
|
||||
model = view.get_model()
|
||||
model = get_base_model(view.get_model())
|
||||
model_name = model.get_name()
|
||||
not_empty = len(model) > 0 # if > 0 model has items
|
||||
|
||||
@@ -764,14 +803,7 @@ class MainAppWindow:
|
||||
|
||||
def on_import_m3u(self, item):
|
||||
""" Imports iptv from m3u files. """
|
||||
file_filter = Gtk.FileFilter()
|
||||
file_filter.add_pattern("*.m3u")
|
||||
file_filter.set_name("m3u files")
|
||||
response = show_dialog(dialog_type=DialogType.CHOOSER,
|
||||
transient=self.__main_window,
|
||||
options=self.__options.get(self.__profile),
|
||||
action_type=Gtk.FileChooserAction.OPEN,
|
||||
file_filter=file_filter)
|
||||
response = get_chooser_dialog(self.__main_window, self.__options.get(self.__profile), "*.m3u", "m3u files")
|
||||
if response == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
@@ -806,9 +838,69 @@ class MainAppWindow:
|
||||
def on_locate_in_services(self, view):
|
||||
locate_in_services(view, self.__services_view, self.__main_window)
|
||||
|
||||
@run_idle
|
||||
def on_picons_loader_show(self, item):
|
||||
dialog = PiconsDialog(self.__main_window, self.__options.get(self.__profile), Profile(self.__profile))
|
||||
ids = {}
|
||||
if Profile(self.__profile) is Profile.ENIGMA_2:
|
||||
for r in self.__services_model:
|
||||
data = r[9].split("_")
|
||||
ids["{}:{}:{}".format(data[3], data[5], data[6])] = r[9]
|
||||
|
||||
dialog = PiconsDialog(self.__main_window, self.__options.get(self.__profile), ids, Profile(self.__profile))
|
||||
dialog.show()
|
||||
self.update_picons()
|
||||
|
||||
@run_idle
|
||||
def on_filter_toggled(self, toggle_button: Gtk.ToggleToolButton):
|
||||
self.__filter_info_bar.set_visible(toggle_button.get_active())
|
||||
|
||||
@run_idle
|
||||
def on_filter_changed(self, entry):
|
||||
self.__services_model_filter.refilter()
|
||||
|
||||
def services_filter_function(self, model, iter, data):
|
||||
if self.__services_model_filter is None or self.__services_model_filter == "None":
|
||||
return True
|
||||
else:
|
||||
return self.__filter_entry.get_text() in str(model.get(iter, 3, 6, 7, 10, 11, 12, 13, 14, 15, 16))
|
||||
|
||||
def on_search_toggled(self, toggle_button: Gtk.ToggleToolButton):
|
||||
self.__search_info_bar.set_visible(toggle_button.get_active())
|
||||
|
||||
@run_idle
|
||||
def on_search(self, entry, event):
|
||||
search(entry.get_text(),
|
||||
self.__services_view,
|
||||
self.__fav_view,
|
||||
self.__bouquets_view,
|
||||
self.__services,
|
||||
self.__bouquets)
|
||||
|
||||
@run_idle
|
||||
def update_picons(self):
|
||||
update_picons(self.__options.get(self.__profile).get("picons_dir_path"), self.__picons, self.__services_model)
|
||||
|
||||
def on_assign_picon(self, view):
|
||||
assign_picon(self.get_target_view(view),
|
||||
self.__services_view,
|
||||
self.__fav_view,
|
||||
self.__main_window,
|
||||
self.__picons,
|
||||
self.__options.get(self.__profile),
|
||||
self.__services)
|
||||
|
||||
def on_remove_picon(self, view):
|
||||
remove_picon(self.get_target_view(view),
|
||||
self.__services_view,
|
||||
self.__fav_view, self.__picons,
|
||||
self.__options.get(self.__profile))
|
||||
|
||||
def on_reference_picon(self, view):
|
||||
""" Copying picon id to clipboard """
|
||||
copy_picon_reference(self.get_target_view(view), view, self.__services, self.__clipboard, self.__main_window)
|
||||
|
||||
def get_target_view(self, view):
|
||||
return ViewTarget.SERVICES if Gtk.Buildable.get_name(view) == "services_tree_view" else ViewTarget.FAV
|
||||
|
||||
|
||||
def start_app():
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
""" This is helper module for ui """
|
||||
from enum import Enum
|
||||
|
||||
import os
|
||||
|
||||
import shutil
|
||||
from gi.repository import GdkPixbuf
|
||||
|
||||
from app.eparser import Service
|
||||
from app.eparser.ecommons import FLAG
|
||||
from app.eparser.enigma.bouquets import BqServiceType, to_bouquet_id
|
||||
from . import Gtk, Gdk, HIDE_ICON, LOCKED_ICON
|
||||
from .dialogs import show_dialog, DialogType
|
||||
from .dialogs import show_dialog, DialogType, get_chooser_dialog
|
||||
|
||||
|
||||
class ViewTarget(Enum):
|
||||
@@ -28,15 +33,16 @@ def insert_marker(view, bouquets, selected_bouquet, channels, parent_window):
|
||||
return
|
||||
|
||||
# Searching for max num value in all marker services (if empty default = 0)
|
||||
max_num = max(map(lambda num: int(num.data_id, 16),
|
||||
max_num = max(map(lambda num: int(num.data_id, 18),
|
||||
filter(lambda ch: ch.service_type == BqServiceType.MARKER.name, channels.values())), default=0)
|
||||
max_num = '{:x}'.format(max_num + 1)
|
||||
fav_id = "1:64:{}:0:0:0:0:0:0:0::{}\n#DESCRIPTION {}\n".format(max_num, response, response)
|
||||
s_type = BqServiceType.MARKER.name
|
||||
model, paths = view.get_selection().get_selected_rows()
|
||||
itr = model.insert_before(model.get_iter(paths[0]), (None, None, response, None, None, s_type, None, fav_id))
|
||||
channels[fav_id] = Service(None, None, None, response, None, None, None, s_type, *[None] * 7, max_num, fav_id, None)
|
||||
marker = (None, None, response, None, None, s_type, None, fav_id, None)
|
||||
itr = model.insert_before(model.get_iter(paths[0]), marker) if paths else model.insert(0, marker)
|
||||
bouquets[selected_bouquet].insert(model.get_path(itr)[0], fav_id)
|
||||
channels[fav_id] = Service(None, None, None, response, None, None, None, s_type, *[None] * 9, max_num, fav_id, None)
|
||||
|
||||
|
||||
def edit_marker(view, bouquets, selected_bouquet, channels, parent_window):
|
||||
@@ -53,7 +59,7 @@ def edit_marker(view, bouquets, selected_bouquet, channels, parent_window):
|
||||
old_ch = channels.pop(fav_id, None)
|
||||
new_fav_id = "{}::{}\n#DESCRIPTION {}\n".format(fav_id.split("::")[0], response, response)
|
||||
model.set(itr, {2: response, 7: new_fav_id})
|
||||
channels[new_fav_id] = Service(*old_ch[0:3], response, *old_ch[4:15], old_ch.data_id, new_fav_id, None)
|
||||
channels[new_fav_id] = Service(*old_ch[0:3], response, *old_ch[4:17], old_ch.data_id, new_fav_id, None)
|
||||
bq_services.pop(index)
|
||||
bq_services.insert(index, new_fav_id)
|
||||
|
||||
@@ -94,6 +100,7 @@ def move_items(key, view):
|
||||
|
||||
def edit(view, parent_window, target, fav_view=None, service_view=None, channels=None):
|
||||
model, paths = view.get_selection().get_selected_rows()
|
||||
model = get_base_model(model)
|
||||
|
||||
if not paths:
|
||||
return
|
||||
@@ -106,7 +113,7 @@ def edit(view, parent_window, target, fav_view=None, service_view=None, channels
|
||||
channel_name = None
|
||||
|
||||
if target is ViewTarget.SERVICES:
|
||||
name, fav_id = model.get(itr, 3, 16)
|
||||
name, fav_id = model.get(itr, 3, 18)
|
||||
f_id = fav_id
|
||||
response = show_dialog(DialogType.INPUT, parent_window, name)
|
||||
if response == Gtk.ResponseType.CANCEL:
|
||||
@@ -129,8 +136,8 @@ def edit(view, parent_window, target, fav_view=None, service_view=None, channels
|
||||
model.set_value(itr, 2, response)
|
||||
|
||||
if service_view is not None:
|
||||
for row in service_view.get_model():
|
||||
if row[16] == fav_id:
|
||||
for row in get_base_model(service_view.get_model()):
|
||||
if row[18] == fav_id:
|
||||
row[3] = response
|
||||
break
|
||||
|
||||
@@ -157,16 +164,18 @@ def set_flags(flag, services_view, fav_view, channels, blacklist):
|
||||
if not paths:
|
||||
return
|
||||
|
||||
model = get_base_model(model)
|
||||
|
||||
if flag is FLAG.HIDE:
|
||||
if target is ViewTarget.SERVICES:
|
||||
set_hide(channels, model, paths)
|
||||
else:
|
||||
fav_ids = [model.get_value(model.get_iter(path), 7) for path in paths]
|
||||
srv_model = services_view.get_model()
|
||||
srv_paths = [row.path for row in srv_model if row[16] in fav_ids]
|
||||
srv_model = get_base_model(services_view.get_model())
|
||||
srv_paths = [row.path for row in srv_model if row[18] in fav_ids]
|
||||
set_hide(channels, srv_model, srv_paths)
|
||||
elif flag is FLAG.LOCK:
|
||||
set_lock(blacklist, channels, model, paths, target, services_model=services_view.get_model())
|
||||
set_lock(blacklist, channels, model, paths, target, services_model=get_base_model(services_view.get_model()))
|
||||
|
||||
return True
|
||||
|
||||
@@ -179,10 +188,12 @@ def set_lock(blacklist, channels, model, paths, target, services_model):
|
||||
|
||||
for path in paths:
|
||||
itr = model.get_iter(path)
|
||||
fav_id = model.get_value(itr, 16 if target is ViewTarget.SERVICES else 7)
|
||||
fav_id = model.get_value(itr, 18 if target is ViewTarget.SERVICES else 7)
|
||||
channel = channels.get(fav_id, None)
|
||||
if channel:
|
||||
bq_id = to_bouquet_id(channel)
|
||||
if not bq_id:
|
||||
continue
|
||||
blacklist.discard(bq_id) if locked else blacklist.add(bq_id)
|
||||
model.set_value(itr, col_num, None if locked else LOCKED_ICON)
|
||||
channels[fav_id] = Service(*channel[:4], None if locked else LOCKED_ICON, *channel[5:])
|
||||
@@ -190,7 +201,7 @@ def set_lock(blacklist, channels, model, paths, target, services_model):
|
||||
|
||||
if target is ViewTarget.FAV and ids:
|
||||
for ch in services_model:
|
||||
if ch[16] in ids:
|
||||
if ch[18] in ids:
|
||||
ch[4] = None if locked else LOCKED_ICON
|
||||
|
||||
|
||||
@@ -230,7 +241,7 @@ def set_hide(channels, model, paths):
|
||||
flags.append(value)
|
||||
|
||||
model.set_value(itr, 0, (",".join(reversed(sorted(flags)))))
|
||||
fav_id = model.get_value(itr, 16)
|
||||
fav_id = model.get_value(itr, 18)
|
||||
channel = channels.get(fav_id, None)
|
||||
if channel:
|
||||
channels[fav_id] = Service(*channel[:5], None if hide else HIDE_ICON, *channel[6:])
|
||||
@@ -257,7 +268,7 @@ def locate_in_services(fav_view, services_view, parent_window):
|
||||
|
||||
fav_id = model.get_value(model.get_iter(paths[0]), 7)
|
||||
for index, row in enumerate(services_view.get_model()):
|
||||
if row[16] == fav_id:
|
||||
if row[18] == fav_id:
|
||||
scroll_to(index, services_view)
|
||||
break
|
||||
|
||||
@@ -272,8 +283,158 @@ def scroll_to(index, view, paths=None):
|
||||
selection.select_path(index)
|
||||
|
||||
|
||||
# ***************** Picons *********************#
|
||||
|
||||
def update_picons(path, picons, model):
|
||||
if not os.path.exists(path):
|
||||
return
|
||||
|
||||
for file in os.listdir(path):
|
||||
picons[file] = get_picon_pixbuf(path + file)
|
||||
|
||||
for r in model:
|
||||
model.set_value(model.get_iter(r.path), 8, picons.get(r[9], None))
|
||||
|
||||
|
||||
def assign_picon(target, srv_view, fav_view, transient, picons, options, services):
|
||||
view = srv_view if target is ViewTarget.SERVICES else fav_view
|
||||
model, paths = view.get_selection().get_selected_rows()
|
||||
if not is_only_one_item_selected(paths, transient):
|
||||
return
|
||||
|
||||
response = get_chooser_dialog(transient, options, "*.png", "png files")
|
||||
if response == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
if not str(response).endswith(".png"):
|
||||
show_dialog(DialogType.ERROR, transient, text="No png file is selected!")
|
||||
return
|
||||
|
||||
picon_pos = 8
|
||||
model = get_base_model(model)
|
||||
itr = model.get_iter(paths)
|
||||
fav_id = model.get_value(itr, 18 if target is ViewTarget.SERVICES else 7)
|
||||
picon_id = services.get(fav_id)[9]
|
||||
|
||||
if picon_id:
|
||||
picon_file = options.get("picons_dir_path") + picon_id
|
||||
if os.path.isfile(response):
|
||||
shutil.copy(response, picon_file)
|
||||
picon = get_picon_pixbuf(picon_file)
|
||||
picons[picon_id] = picon
|
||||
model.set_value(itr, picon_pos, picon)
|
||||
if target is ViewTarget.SERVICES:
|
||||
set_picon(fav_id, fav_view.get_model(), picon, 7, picon_pos)
|
||||
else:
|
||||
set_picon(fav_id, get_base_model(srv_view.get_model()), picon, 18, picon_pos)
|
||||
|
||||
|
||||
def set_picon(fav_id, model, picon, fav_id_pos, picon_pos):
|
||||
for row in model:
|
||||
if row[fav_id_pos] == fav_id:
|
||||
row[picon_pos] = picon
|
||||
break
|
||||
|
||||
|
||||
def remove_picon(target, srv_view, fav_view, picons, options):
|
||||
view = srv_view if target is ViewTarget.SERVICES else fav_view
|
||||
model, paths = view.get_selection().get_selected_rows()
|
||||
model = get_base_model(model)
|
||||
|
||||
fav_ids = []
|
||||
picon_ids = []
|
||||
picon_pos = 8 # picon position is equal for services and fav
|
||||
|
||||
for path in paths:
|
||||
itr = model.get_iter(path)
|
||||
model.set_value(itr, picon_pos, None)
|
||||
if target is ViewTarget.SERVICES:
|
||||
fav_ids.append(model.get_value(itr, 18))
|
||||
picon_ids.append(model.get_value(itr, 9))
|
||||
else:
|
||||
fav_ids.append(model.get_value(itr, 7))
|
||||
|
||||
def remove(md, path, itr):
|
||||
if md.get_value(itr, 7 if target is ViewTarget.SERVICES else 18) in fav_ids:
|
||||
md.set_value(itr, picon_pos, None)
|
||||
if target is ViewTarget.FAV:
|
||||
picon_ids.append(md.get_value(itr, 9))
|
||||
|
||||
fav_view.get_model().foreach(remove) if target is ViewTarget.SERVICES else get_base_model(
|
||||
srv_view.get_model()).foreach(remove)
|
||||
|
||||
pions_path = options.get("picons_dir_path")
|
||||
backup_path = options.get("data_dir_path") + "backup/picons/"
|
||||
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
|
||||
|
||||
for p_id in picon_ids:
|
||||
picons[p_id] = None
|
||||
src = pions_path + p_id
|
||||
if os.path.isfile(src):
|
||||
shutil.move(src, backup_path + p_id)
|
||||
|
||||
|
||||
def copy_picon_reference(target, view, services, clipboard, transient):
|
||||
""" Copying picon id to clipboard """
|
||||
model, paths = view.get_selection().get_selected_rows()
|
||||
if not is_only_one_item_selected(paths, transient):
|
||||
return
|
||||
|
||||
if target is ViewTarget.SERVICES:
|
||||
picon_id = model.get_value(model.get_iter(paths), 9)
|
||||
if picon_id:
|
||||
clipboard.set_text(picon_id.rstrip(".png"), -1)
|
||||
else:
|
||||
show_dialog(DialogType.ERROR, transient, "No reference is present!")
|
||||
elif target is ViewTarget.FAV:
|
||||
fav_id = model.get_value(model.get_iter(paths), 7)
|
||||
srv = services.get(fav_id, None)
|
||||
if srv and srv.picon_id:
|
||||
clipboard.set_text(srv.picon_id.rstrip(".png"), -1)
|
||||
else:
|
||||
show_dialog(DialogType.ERROR, transient, "No reference is present!")
|
||||
|
||||
|
||||
def is_only_one_item_selected(paths, transient):
|
||||
if len(paths) > 1:
|
||||
show_dialog(DialogType.ERROR, transient, "Please, select only one item!")
|
||||
return False
|
||||
|
||||
if not paths:
|
||||
show_dialog(DialogType.ERROR, transient, "No selected item!")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_picon_pixbuf(path):
|
||||
return GdkPixbuf.Pixbuf.new_from_file_at_scale(filename=path, width=32, height=32, preserve_aspect_ratio=True)
|
||||
|
||||
|
||||
# ***************** Search *********************#
|
||||
|
||||
def search(text, srv_view, fav_view, bqs_view, services, bouquets):
|
||||
for view in srv_view, fav_view:
|
||||
model = get_base_model(view.get_model())
|
||||
selection = view.get_selection()
|
||||
selection.unselect_all()
|
||||
if not text:
|
||||
continue
|
||||
paths = []
|
||||
text = text.upper()
|
||||
for r in model:
|
||||
if text in str(r[:]).upper():
|
||||
path = r.path
|
||||
selection.select_path(r.path)
|
||||
paths.append(path)
|
||||
|
||||
if paths:
|
||||
view.scroll_to_cell(paths[0], None)
|
||||
|
||||
|
||||
# ***************** Others *********************#
|
||||
|
||||
|
||||
def update_entry_data(entry, dialog, options):
|
||||
""" Updates value in text entry from chooser dialog """
|
||||
response = show_dialog(dialog_type=DialogType.CHOOSER, transient=dialog, options=options)
|
||||
@@ -283,5 +444,12 @@ def update_entry_data(entry, dialog, options):
|
||||
return False
|
||||
|
||||
|
||||
def get_base_model(model):
|
||||
""" Returns base tree model if has wrappers ("TreeModelSort" and "TreeModelFilter") """
|
||||
if type(model) is Gtk.TreeModelSort:
|
||||
return model.get_model().get_model()
|
||||
return model
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name fav_id -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name picon -->
|
||||
<column type="GdkPixbuf"/>
|
||||
</columns>
|
||||
<signal name="row-deleted" handler="on_model_changed" swapped="no"/>
|
||||
<signal name="row-inserted" handler="on_model_changed" swapped="no"/>
|
||||
@@ -80,6 +82,41 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">emblem-downloads</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image10">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-copy</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image11">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">insert-link</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image12">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-clear</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image13">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">insert-image</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image14">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">insert-link</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image15">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-clear</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image16">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-copy</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
@@ -207,6 +244,64 @@
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="fav_picon_popup_item">
|
||||
<property name="label" translatable="yes">Picon</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image13</property>
|
||||
<property name="use_stock">False</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu" id="fav_picon_popoup_menu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="fav_assign_picon_popup_item">
|
||||
<property name="label" translatable="yes">Assign</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image14</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_assign_picon" object="fav_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="fav_remove_picon_popup_item">
|
||||
<property name="label" translatable="yes">Remove</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image15</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_remove_picon" object="fav_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="fav_pupup_separator_5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="fav_reference_picon_popup_item">
|
||||
<property name="label" translatable="yes">Copy reference</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image16</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_reference_picon" object="fav_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="fav_pupup_separator_4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="fav_remove_popup_item">
|
||||
<property name="label">gtk-remove</property>
|
||||
@@ -224,10 +319,134 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">insert-image</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image9">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">insert-image</property>
|
||||
</object>
|
||||
<object class="GtkMenu" id="services_popup_menu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_to_fav_move_popup_item">
|
||||
<property name="label">gtk-go-forward</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_to_fav_move" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_copy_popup_item">
|
||||
<property name="label">gtk-copy</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_copy" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_edit_popup_item">
|
||||
<property name="label">gtk-edit</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resize_mode">immediate</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_edit" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_picon_popup_item">
|
||||
<property name="label" translatable="yes">Picon</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image9</property>
|
||||
<property name="use_stock">False</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu" id="services_picon_popoup_menu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_assign_picon_popup_item">
|
||||
<property name="label">Assign</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image11</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_assign_picon" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_remove_picon_popup_item">
|
||||
<property name="label">Remove</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image12</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_remove_picon" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem6">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_reference_picon_popup_item">
|
||||
<property name="label" translatable="yes">Copy reference</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image10</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_reference_picon" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_remove_popup_item">
|
||||
<property name="label">gtk-remove</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_delete" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="send_recive_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">mail-send-receive</property>
|
||||
<property name="icon_name">network-transmit-receive</property>
|
||||
</object>
|
||||
<object class="GtkListStore" id="services_list_store">
|
||||
<columns>
|
||||
@@ -247,6 +466,10 @@
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name service_type -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name picon -->
|
||||
<column type="GdkPixbuf"/>
|
||||
<!-- column-name picon_id -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name ssid -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name freq -->
|
||||
@@ -270,6 +493,12 @@
|
||||
</columns>
|
||||
<signal name="row-deleted" handler="on_model_changed" swapped="no"/>
|
||||
</object>
|
||||
<object class="GtkTreeModelFilter" id="services_model_filter">
|
||||
<property name="child_model">services_list_store</property>
|
||||
</object>
|
||||
<object class="GtkTreeModelSort" id="services_model_tree_model_sort">
|
||||
<property name="model">services_model_filter</property>
|
||||
</object>
|
||||
<object class="GtkApplicationWindow" id="main_window">
|
||||
<property name="width_request">640</property>
|
||||
<property name="can_focus">False</property>
|
||||
@@ -514,7 +743,7 @@
|
||||
<property name="tooltip_text" translatable="yes">FTP-transfer</property>
|
||||
<property name="label" translatable="yes">Download</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">mail-send-receive</property>
|
||||
<property name="icon_name">network-transmit-receive</property>
|
||||
<signal name="clicked" handler="on_download" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -547,6 +776,46 @@
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorToolItem" id="separatortoolitem8">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="filter_tool_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Services filter</property>
|
||||
<property name="label" translatable="yes">Services filter</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="icon_name">tools-check-spelling</property>
|
||||
<signal name="toggled" handler="on_filter_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="search_tool_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Global search</property>
|
||||
<property name="label" translatable="yes">Search</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-find</property>
|
||||
<signal name="toggled" handler="on_search_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorToolItem" id="toolbutton4">
|
||||
<property name="visible">True</property>
|
||||
@@ -821,6 +1090,7 @@
|
||||
<child>
|
||||
<object class="GtkToolButton" id="picons_download_tool_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Picons</property>
|
||||
<property name="label" translatable="yes">Picons loader</property>
|
||||
@@ -884,6 +1154,98 @@
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkInfoBar" id="search_info_bar">
|
||||
<property name="app_paintable">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="search_infobar_action_area">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="content_area">
|
||||
<object class="GtkBox" id="search_infobar_content_area">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">16</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="search_entry">
|
||||
<property name="width_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_name">edit-find-symbolic</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">False</property>
|
||||
<signal name="key-release-event" handler="on_search" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="separator5">
|
||||
<property name="visible">True</property>
|
||||
@@ -893,7 +1255,7 @@
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">2</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -901,8 +1263,8 @@
|
||||
<property name="height_request">250</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_left">2</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="margin_left">1</property>
|
||||
<property name="margin_right">1</property>
|
||||
<property name="wide_handle">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box4">
|
||||
@@ -925,12 +1287,13 @@
|
||||
<object class="GtkScrolledWindow" id="services_scrolled_window">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="services_tree_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="model">services_list_store</property>
|
||||
<property name="model">services_model_tree_model_sort</property>
|
||||
<property name="search_column">3</property>
|
||||
<property name="rubber_banding">True</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
@@ -973,6 +1336,7 @@
|
||||
<object class="GtkTreeViewColumn" id="service_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="spacing">2</property>
|
||||
<property name="min_width">50</property>
|
||||
<property name="title" translatable="yes">Service</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
@@ -1006,7 +1370,7 @@
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="package_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="min_width">50</property>
|
||||
<property name="title" translatable="yes">Package</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
@@ -1022,6 +1386,7 @@
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="service_type_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">Type</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
@@ -1037,33 +1402,25 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="ssid_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title" translatable="yes">Ssid</property>
|
||||
<property name="expand">True</property>
|
||||
<object class="GtkTreeViewColumn" id="picon_column">
|
||||
<property name="title" translatable="yes">Picon</property>
|
||||
<property name="reorderable">True</property>
|
||||
<property name="sort_column_id">8</property>
|
||||
<property name="sort_column_id">9</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="ssid_cellrenderertext">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<object class="GtkCellRendererPixbuf" id="picon_cellrendererpixbuf"/>
|
||||
<attributes>
|
||||
<attribute name="text">8</attribute>
|
||||
<attribute name="pixbuf">8</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="freq_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title" translatable="yes">Freq</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
<property name="sort_column_id">9</property>
|
||||
<object class="GtkTreeViewColumn" id="picon_id_column">
|
||||
<property name="visible">False</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="title" translatable="yes">Picon ID</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="freq_cellrenderertext">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<object class="GtkCellRendererText" id="picon_id_cellrenderertext"/>
|
||||
<attributes>
|
||||
<attribute name="text">9</attribute>
|
||||
</attributes>
|
||||
@@ -1071,14 +1428,15 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="rate_column">
|
||||
<object class="GtkTreeViewColumn" id="ssid_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title" translatable="yes">Rate</property>
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">Ssid</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
<property name="sort_column_id">10</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="rate_cellrenderertext">
|
||||
<object class="GtkCellRendererText" id="ssid_cellrenderertext">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<attributes>
|
||||
@@ -1088,14 +1446,15 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="pol_column">
|
||||
<object class="GtkTreeViewColumn" id="freq_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title" translatable="yes">Pol</property>
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">Freq</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
<property name="sort_column_id">11</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="pol_cellrenderertext">
|
||||
<object class="GtkCellRendererText" id="freq_cellrenderertext">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<attributes>
|
||||
@@ -1105,14 +1464,15 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="fec_column">
|
||||
<object class="GtkTreeViewColumn" id="rate_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title" translatable="yes">FEC</property>
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">Rate</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
<property name="sort_column_id">12</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="fec_cellrenderertext">
|
||||
<object class="GtkCellRendererText" id="rate_cellrenderertext">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<attributes>
|
||||
@@ -1122,14 +1482,15 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="system_column">
|
||||
<object class="GtkTreeViewColumn" id="pol_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title" translatable="yes">System</property>
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">Pol</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
<property name="sort_column_id">13</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="system_cellrenderertex">
|
||||
<object class="GtkCellRendererText" id="pol_cellrenderertext">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<attributes>
|
||||
@@ -1138,18 +1499,55 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="fec_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">FEC</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
<property name="sort_column_id">14</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="fec_cellrenderertext">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">14</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="system_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">System</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="reorderable">True</property>
|
||||
<property name="sort_column_id">15</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="system_cellrenderertex">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">15</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="pos_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">Pos</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="sort_column_id">14</property>
|
||||
<property name="sort_column_id">16</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="pos_cellrenderertext1">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">14</attribute>
|
||||
<attribute name="text">16</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
@@ -1161,7 +1559,7 @@
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="data_id_cellrenderertext"/>
|
||||
<attributes>
|
||||
<attribute name="text">15</attribute>
|
||||
<attribute name="text">17</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
@@ -1173,7 +1571,7 @@
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="fav_id_cellrenderertext"/>
|
||||
<attributes>
|
||||
<attribute name="text">16</attribute>
|
||||
<attribute name="text">18</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
@@ -1185,7 +1583,7 @@
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="transponder_cellrenderertext"/>
|
||||
<attributes>
|
||||
<attribute name="text">17</attribute>
|
||||
<attribute name="text">19</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
@@ -1199,9 +1597,78 @@
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkInfoBar" id="filter_info_bar">
|
||||
<property name="app_paintable">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="filter_infobar_action_area">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="content_area">
|
||||
<object class="GtkBox" id="filter_infobar_content_area">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">16</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="filter_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_name">tools-check-spelling</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">False</property>
|
||||
<signal name="search-changed" handler="on_filter_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="services_bar_box">
|
||||
<property name="height_request">25</property>
|
||||
<property name="height_request">20</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resize_mode">queue</property>
|
||||
@@ -1224,12 +1691,14 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">CAS</property>
|
||||
<property name="width_chars">10</property>
|
||||
<property name="width_chars">20</property>
|
||||
<property name="max_width_chars">20</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">2</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
@@ -1323,11 +1792,24 @@
|
||||
<property name="position">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="separator2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
@@ -1362,6 +1844,7 @@
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="fav_tree_view">
|
||||
@@ -1405,6 +1888,12 @@
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Service</property>
|
||||
<property name="expand">True</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererPixbuf" id="fav_picon_cellrendererpixbuf"/>
|
||||
<attributes>
|
||||
<attribute name="pixbuf">8</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCellRendererPixbuf" id="fav_coded_cellrendererpixbuf"/>
|
||||
<attributes>
|
||||
@@ -1482,7 +1971,7 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="fav_bar_box">
|
||||
<property name="height_request">25</property>
|
||||
<property name="height_request">20</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">2</property>
|
||||
@@ -1503,7 +1992,8 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">0</property>
|
||||
<property name="width_chars">10</property>
|
||||
<property name="width_chars">15</property>
|
||||
<property name="max_width_chars">15</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -1549,6 +2039,7 @@
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="bouquets_tree_view">
|
||||
@@ -1619,7 +2110,7 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="bouquet_bar_box">
|
||||
<property name="height_request">25</property>
|
||||
<property name="height_request">20</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">2</property>
|
||||
@@ -1640,7 +2131,8 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">0</property>
|
||||
<property name="width_chars">5</property>
|
||||
<property name="width_chars">10</property>
|
||||
<property name="max_width_chars">10</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -1676,7 +2168,7 @@
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">1</property>
|
||||
<property name="position">3</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -1689,7 +2181,7 @@
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">2</property>
|
||||
<property name="position">4</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -1698,8 +2190,6 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_start">10</property>
|
||||
<property name="margin_end">10</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="margin_bottom">6</property>
|
||||
<property name="spacing">2</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
@@ -1742,7 +2232,7 @@
|
||||
<object class="GtkLabel" id="ver_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Ver. 0.2.1 Pre-alpha</property>
|
||||
<property name="label" translatable="yes">Ver. 0.2.3 Pre-alpha</property>
|
||||
<property name="xalign">0.94999998807907104</property>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -1755,71 +2245,10 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkMenu" id="services_popup_menu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_to_fav_move_popup_item">
|
||||
<property name="label">gtk-go-forward</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_to_fav_move" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_copy_popup_item">
|
||||
<property name="label">gtk-copy</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_copy" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_edit_popup_item">
|
||||
<property name="label">gtk-edit</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resize_mode">immediate</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_edit" object="services_tree_view" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="services_remove_popup_item">
|
||||
<property name="label">gtk-remove</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_delete" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
<column type="GdkPixbuf"/>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name pos -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name url -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name on_id -->
|
||||
@@ -153,55 +155,175 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="format_box">
|
||||
<object class="GtkGrid" id="format_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="column_spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<object class="GtkBox" id="name_format_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Picons name format:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">5</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="enigma2_radio_button">
|
||||
<property name="label" translatable="yes">Enigma2 (default)</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">neutrino_mp_radio_button</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="neutrino_mp_radio_button">
|
||||
<property name="label" translatable="yes">Neutrino-MP</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">enigma2_radio_button</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="resize_format_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Resize: </property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="resize_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="resize_no_radio_button">
|
||||
<property name="label" translatable="yes">No(default)</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">resize_100_60_radio_button</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="resize_220_132_radio_button">
|
||||
<property name="label" translatable="yes">220x132</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">resize_100_60_radio_button</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="resize_100_60_radio_button">
|
||||
<property name="label" translatable="yes">100x60</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">resize_no_radio_button</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="separator3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="label" translatable="yes">Picons name format:</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="enigma2_radio_button">
|
||||
<property name="label" translatable="yes">Enigma2 (default)</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">neutrino_mp_radio_button</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="neutrino_mp_radio_button">
|
||||
<property name="label" translatable="yes">Neutrino-MP</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">enigma2_radio_button</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
@@ -210,7 +332,7 @@
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
@@ -231,6 +353,9 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Satellite url (www.lyngsat.com):</property>
|
||||
<property name="xalign">0.019999999552965164</property>
|
||||
<style>
|
||||
<class name="primary-toolbar"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@@ -289,14 +414,30 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="pos_column">
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Position</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="pos_cellrenderertext1">
|
||||
<property name="xalign">0.50999999046325684</property>
|
||||
<property name="editable">True</property>
|
||||
<signal name="edited" handler="on_position_edited" swapped="no"/>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="url_column">
|
||||
<property name="visible">False</property>
|
||||
<property name="title" translatable="yes">Url</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cellrenderertext1"/>
|
||||
<object class="GtkCellRendererText" id="url_cellrenderertext"/>
|
||||
<attributes>
|
||||
<attribute name="text">2</attribute>
|
||||
<attribute name="text">3</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
@@ -306,9 +447,9 @@
|
||||
<property name="visible">False</property>
|
||||
<property name="title" translatable="yes">ONID</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cellrenderertext2"/>
|
||||
<object class="GtkCellRendererText" id="onid_cellrenderertext"/>
|
||||
<attributes>
|
||||
<attribute name="text">3</attribute>
|
||||
<attribute name="text">4</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
@@ -321,7 +462,7 @@
|
||||
<signal name="toggled" handler="on_selected_toggled" swapped="no"/>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="active">4</attribute>
|
||||
<attribute name="active">5</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
@@ -332,7 +473,7 @@
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">7</property>
|
||||
<property name="position">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -344,7 +485,7 @@
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">2</property>
|
||||
<property name="position">10</property>
|
||||
<property name="position">11</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -442,7 +583,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">11</property>
|
||||
<property name="position">12</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -479,7 +620,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">12</property>
|
||||
<property name="position">13</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -545,7 +686,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">13</property>
|
||||
<property name="position">14</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -556,7 +697,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">14</property>
|
||||
<property name="position">15</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
@@ -569,4 +710,10 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkListStore" id="sat_position_list_store">
|
||||
<columns>
|
||||
<!-- column-name pos -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
</interface>
|
||||
|
||||
@@ -15,7 +15,8 @@ from .main_helper import update_entry_data
|
||||
|
||||
|
||||
class PiconsDialog:
|
||||
def __init__(self, transient, options, profile=Profile.ENIGMA_2):
|
||||
def __init__(self, transient, options, picon_ids, profile=Profile.ENIGMA_2):
|
||||
self._picon_ids = picon_ids
|
||||
self._TMP_DIR = tempfile.gettempdir() + "/"
|
||||
self._BASE_URL = "www.lyngsat.com/packages/"
|
||||
self._PATTERN = re.compile("^https://www\.lyngsat\.com/[\w-]+\.html$")
|
||||
@@ -31,7 +32,8 @@ class PiconsDialog:
|
||||
"on_info_bar_close": self.on_info_bar_close,
|
||||
"on_picons_dir_open": self.on_picons_dir_open,
|
||||
"on_selected_toggled": self.on_selected_toggled,
|
||||
"on_url_changed": self.on_url_changed}
|
||||
"on_url_changed": self.on_url_changed,
|
||||
"on_position_edited": self.on_position_edited}
|
||||
|
||||
builder = Gtk.Builder()
|
||||
builder.add_objects_from_file(UI_RESOURCES_PATH + "picons_dialog.glade",
|
||||
@@ -54,6 +56,9 @@ class PiconsDialog:
|
||||
self._receive_tool_button = builder.get_object("receive_tool_button")
|
||||
self._enigma2_radio_button = builder.get_object("enigma2_radio_button")
|
||||
self._neutrino_mp_radio_button = builder.get_object("neutrino_mp_radio_button")
|
||||
self._resize_no_radio_button = builder.get_object("resize_no_radio_button")
|
||||
self._resize_220_132_radio_button = builder.get_object("resize_220_132_radio_button")
|
||||
self._resize_100_60_radio_button = builder.get_object("resize_100_60_radio_button")
|
||||
# style
|
||||
self._style_provider = Gtk.CssProvider()
|
||||
self._style_provider.load_from_path(UI_RESOURCES_PATH + "style.css")
|
||||
@@ -90,8 +95,7 @@ class PiconsDialog:
|
||||
providers = parse_providers(self._TMP_DIR + url[url.find("w"):])
|
||||
if providers:
|
||||
for p in providers:
|
||||
logo = self.get_pixbuf(p[0])
|
||||
model.append((logo, p.name, p.url, p.on_id, p.selected))
|
||||
model.append((self.get_pixbuf(p[0]), p.name, p.pos, p.url, p.on_id, p.selected))
|
||||
self.update_receive_button_state()
|
||||
|
||||
def get_pixbuf(self, img_url):
|
||||
@@ -116,8 +120,8 @@ class PiconsDialog:
|
||||
break
|
||||
self.process_provider(Provider(*prv))
|
||||
|
||||
def process_provider(self, provider):
|
||||
url = provider.url
|
||||
def process_provider(self, prv):
|
||||
url = prv.url
|
||||
self.show_info_message("Please, wait...", Gtk.MessageType.INFO)
|
||||
self._current_process = subprocess.Popen(["wget", "-pkP", self._TMP_DIR, url],
|
||||
stdout=subprocess.PIPE,
|
||||
@@ -126,7 +130,10 @@ class PiconsDialog:
|
||||
GLib.io_add_watch(self._current_process.stderr, GLib.IO_IN, self.write_to_buffer)
|
||||
self._current_process.wait()
|
||||
path = self._TMP_DIR + self._BASE_URL + url[url.rfind("/") + 1:]
|
||||
PiconsParser.parse(path, self._picons_path, self._TMP_DIR, provider.on_id, self.get_picons_format())
|
||||
pos = "".join(c for c in prv.pos if c.isdigit())
|
||||
PiconsParser.parse(path, self._picons_path, self._TMP_DIR, prv.on_id, pos,
|
||||
self._picon_ids, self.get_picons_format())
|
||||
self.resize(self._picons_path)
|
||||
self.show_info_message("Done", Gtk.MessageType.INFO)
|
||||
|
||||
def write_to_buffer(self, fd, condition):
|
||||
@@ -147,6 +154,16 @@ class PiconsDialog:
|
||||
insert = buf.get_insert()
|
||||
self._text_view.scroll_to_mark(insert, 0.0, True, 0.0, 1.0)
|
||||
|
||||
def resize(self, path):
|
||||
if self._resize_no_radio_button.get_active():
|
||||
return
|
||||
|
||||
self.show_info_message("Resizing...", Gtk.MessageType.INFO)
|
||||
command = "mogrify -resize {}! *.png".format(
|
||||
"320x240" if self._resize_220_132_radio_button.get_active() else "100x60").split()
|
||||
self._current_process = subprocess.Popen(command, universal_newlines=True, cwd=path)
|
||||
self._current_process.wait()
|
||||
|
||||
@run_task
|
||||
def on_cancel(self, item):
|
||||
if self._current_process:
|
||||
@@ -192,7 +209,7 @@ class PiconsDialog:
|
||||
@run_idle
|
||||
def on_selected_toggled(self, toggle, path):
|
||||
model = self._providers_tree_view.get_model()
|
||||
model.set_value(model.get_iter(path), 4, not toggle.get_active())
|
||||
model.set_value(model.get_iter(path), 5, not toggle.get_active())
|
||||
self.update_receive_button_state()
|
||||
|
||||
def on_url_changed(self, entry):
|
||||
@@ -200,13 +217,17 @@ class PiconsDialog:
|
||||
entry.set_name("GtkEntry" if suit else "digit-entry")
|
||||
self._load_providers_tool_button.set_sensitive(suit if suit else False)
|
||||
|
||||
def on_position_edited(self, render, path, value):
|
||||
model = self._providers_tree_view.get_model()
|
||||
model.set_value(model.get_iter(path), 2, value)
|
||||
|
||||
@run_idle
|
||||
def update_receive_button_state(self):
|
||||
self._receive_tool_button.set_sensitive(len(self.get_selected_providers()) > 0)
|
||||
|
||||
def get_selected_providers(self):
|
||||
""" returns selected providers """
|
||||
return [r for r in self._providers_tree_view.get_model() if r[4]]
|
||||
return [r for r in self._providers_tree_view.get_model() if r[5]]
|
||||
|
||||
@run_idle
|
||||
def show_dialog(self, message, dialog_type):
|
||||
|
||||
@@ -243,6 +243,8 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -741,6 +743,17 @@
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="separator5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/env bash
|
||||
VER="0.2.1_Pre-alpha"
|
||||
VER="0.2.3_Pre-alpha"
|
||||
B_PATH="dist/DemonEditor"
|
||||
DEB_PATH="$B_PATH/usr/share/demoneditor"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Package: DemonEditor
|
||||
Version: 0.2.1-Pre-alpha
|
||||
Version: 0.2.3-Pre-alpha
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
|
||||
Reference in New Issue
Block a user