From c3e880890ea7440af5bcb7bf5cd06f09bf4ab9ec Mon Sep 17 00:00:00 2001 From: DYefremov Date: Wed, 7 Mar 2018 22:43:42 +0300 Subject: [PATCH 01/18] little picons dialog changes --- app/ui/lang/ru/LC_MESSAGES/demon-editor.mo | Bin 8745 -> 9216 bytes app/ui/picons_dialog.py | 20 ++++++++++++------ app/ui/search.py | 3 +-- .../locale/ru/LC_MESSAGES/demon-editor.mo | Bin 8745 -> 9216 bytes po/ru/demon-editor.mo | Bin 8745 -> 9216 bytes po/ru/demon-editor.po | 12 +++++++++++ 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/ui/lang/ru/LC_MESSAGES/demon-editor.mo b/app/ui/lang/ru/LC_MESSAGES/demon-editor.mo index 9fc255985c41764b5be7bf505d65c3fc4816c083..21d5368a9c3049983f65c82c2bbe0a3f6f289da3 100644 GIT binary patch delta 3141 zcmZA1dr*{B7{~F$RRdGJAeNvnUPwhLQPZ@P$i(teO6CnOhzqU)OUsI(=7Kd@nc@sM z&e)WrRN7dX$d?dSbq1bW8^ui!U;W@_(crW*tFcxp3+Wn3CY0r3LW?&L_ z!{vAn7UCc*Lx%F38Y(?`P=|a>J(oV%fc@|b)DKT%44!kmh;(4Cpa#5-jBRc?&trRp z+s9*Xp7+K{I21L3Jd9<0vxy2Hvz3cFtU;};&bdE;Dcm1KP2elkK;NKN`~#}}uc(FG z!22+Yhx$GRwV*MmOl3LdU^L^KxvF3;D#eSCMVLGsfNLD99rvOJ2;fls4zQg+Mhy_bm+H7X>Un?EfCEwEWTGZE8PzVwPem(UfO`FwBa1PcoaftdJoj~|0ZyXY z*_eS>@BvKbgr(wi)R`zm_4@{D;lleQod$nl5%)c5 zZD9qnShEK;p+l$v8jz;uOVpN}My<3HccL0;;x(vtAL1yz|Hr8CF_*b$1^=KLq>}#; zI38(emZ47lYpB#6aBM`K=62NY&N^O0O*ESP%S2Q^X_$xeFkSEe$5b@qGdLRmL>;D~ zq(vQPq9!;Wr(zLmCGVsDNIFnka2|Eq<9KIB;t169`Do!r)Z6hE@-Zj4#52D6nF?c? z-%u%yVwpO0amXS}B5ES(jv%Ux2V0nfnza-{ZOVR;xt_7-0wkc?GaSJ zzu+U-If(p|B{PO!>9xo~t#C1_;TGq92Wp@u)a%vZco8+Bcq=^7VW^BvL_N<&Enq1= zh^44ZzJnyk9QISuVLE}KnPCR^oyelh5b~@JvT!BlqS`g1wx|QM@DgU@DE?>XVF^ya zW2lM$fm&EBv)5Tm$29b3Q&C55REla)hwv!Ur|Cep-(0{5REZ*4%0r%dSJKn8u~_Xqc^oG>^+fF9)O85&F8s^hDMi%g6B*8v zrMQmJ8?cBdBuwr4xc8DvD_mZm%WJK2`8K#*rB-QviOVYVcuVqq<$sPM6`|G6cW>lu?+p N-IyBqY4DuLe*sh%oj(8o delta 2747 zcmYk;duWzb9KiA8yUppG+nm!ab8}NuOY>INR?}u%W-T?-vYFS)GyeMbv(e|VC+!yOio4L~-okEp04L!`Xjff( zgwP#xFdd69Cxm1urovws!6hHdu>fn)FD$?eTpC@8cCZ#5Xd^O4*c|V_h(5m!d*Q2C zj(e~K&!7`d&kiA*@k0+P9Wz2#R2vLejPm@?anAyaep8V!b)^y3(!ohMz`h}bb#m3ly8ad z!~wK-qZ$1e3-K@}iSQE_S9l(s@kMk(|DpqQXL(dZ3HHVj=m1qX94DiDy#~$L2RIPF zK{Is;onST%$H_z6eRIjbd)SW~4mb#Hk3v^cjt)2;9dJ5cjde($p%F<^*o=L!1zkWZ z_Qk#E#M{vCe}#_o9h!+>a>>76yuc0jHZ$+?iu2JF4~^{#bV5_n0cM~b&yM$(paa&U z18qhp){H*)3c9dX^ex+m3>n&!@q<%n$3Mphe#McrvzWzDtiUo{h@OF`v7I|?hRPvVn z_9LIASc49<2z_l^&@Ffec{ChAGuV!vtrN%`!Vl;K{!qpbefYL18W){~u4sL1zk%1# z{tSI>&Y>$gk7njSbbx%)ScS!CCg4eIhe{RDo!BL@3Mo@l}|!D zYQVX;3Af<4cn>Zkzj_eOL-Q&*VcBHym&Wy0;(V z82l1VRTuKFW$0c`L_2K23T#5w5Z*@)dN__Q>@@mZH}=zZA=-Z>`W8(oA^%oZal?sh zM`ySfP1Psy{?T~<436UdUuX)4F)I(*IApG2I(AG9N78OW<`DLv{T_~=pF+3fT#`x^ zmHg5WZpRro9e3b3Jd4h_g#B>^qtL@O6Nlh3w4;~M%p61y-5KOBoa4f7g`9z85$_@_ zb1vigrxW5a!Y?|wr!<3jgjhwC60Xt-vhXmUu(5i5y$g5Q&lGjaoVE)REVn0m` zzm$r_{Yns~+p}P~o4AQ+Aj*kbh{c4(?XZyHj>7Lz*g$vyZzS#~u9O+E;_rtghp4mS z`sZ1pOd;+i{1Hhfe5HIVZYC_Ahtb4s#1LWtQAK$2eci4U|6SM^8&BX^;z43I;aOQo zR1yn_ M97?42m(?cz2mKG`J^%m! diff --git a/app/ui/picons_dialog.py b/app/ui/picons_dialog.py index 277215ad..62900811 100644 --- a/app/ui/picons_dialog.py +++ b/app/ui/picons_dialog.py @@ -93,12 +93,13 @@ class PiconsDialog: stderr=subprocess.PIPE, universal_newlines=True) GLib.io_add_watch(self._current_process.stderr, GLib.IO_IN, self.write_to_buffer) - self.append_providers(url) - - @run_task - def append_providers(self, url): model = self._providers_tree_view.get_model() model.clear() + self.update_receive_button_state() + self.append_providers(url, model) + + @run_task + def append_providers(self, url, model): self._current_process.wait() providers = parse_providers(self._TMP_DIR + url[url.find("w"):]) if providers: @@ -123,7 +124,14 @@ class PiconsDialog: self._terminate = False self._expander.set_expanded(True) - for prv in self.get_selected_providers(): + providers = self.get_selected_providers() + for prv in providers: + if not prv[2].isdigit(): + self.show_info_message( + get_message("Specify the correct position value for the provider!"), Gtk.MessageType.ERROR) + return + + for prv in providers: if self._terminate: break self.process_provider(Provider(*prv)) @@ -142,7 +150,7 @@ class PiconsDialog: 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) + self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO) def write_to_buffer(self, fd, condition): if condition == GLib.IO_IN: diff --git a/app/ui/search.py b/app/ui/search.py index 7e005f1c..24f00bf4 100644 --- a/app/ui/search.py +++ b/app/ui/search.py @@ -1,5 +1,4 @@ """ This is helper module for search features """ -from app.ui.main_helper import get_base_model class SearchProvider: @@ -17,7 +16,7 @@ class SearchProvider: self._current_index = -1 self._paths.clear() for view in self._srv_view, self._fav_view: - model = get_base_model(view.get_model()) + model = view.get_model() selection = view.get_selection() selection.unselect_all() if not text: diff --git a/deb/usr/share/locale/ru/LC_MESSAGES/demon-editor.mo b/deb/usr/share/locale/ru/LC_MESSAGES/demon-editor.mo index 9fc255985c41764b5be7bf505d65c3fc4816c083..21d5368a9c3049983f65c82c2bbe0a3f6f289da3 100644 GIT binary patch delta 3141 zcmZA1dr*{B7{~F$RRdGJAeNvnUPwhLQPZ@P$i(teO6CnOhzqU)OUsI(=7Kd@nc@sM z&e)WrRN7dX$d?dSbq1bW8^ui!U;W@_(crW*tFcxp3+Wn3CY0r3LW?&L_ z!{vAn7UCc*Lx%F38Y(?`P=|a>J(oV%fc@|b)DKT%44!kmh;(4Cpa#5-jBRc?&trRp z+s9*Xp7+K{I21L3Jd9<0vxy2Hvz3cFtU;};&bdE;Dcm1KP2elkK;NKN`~#}}uc(FG z!22+Yhx$GRwV*MmOl3LdU^L^KxvF3;D#eSCMVLGsfNLD99rvOJ2;fls4zQg+Mhy_bm+H7X>Un?EfCEwEWTGZE8PzVwPem(UfO`FwBa1PcoaftdJoj~|0ZyXY z*_eS>@BvKbgr(wi)R`zm_4@{D;lleQod$nl5%)c5 zZD9qnShEK;p+l$v8jz;uOVpN}My<3HccL0;;x(vtAL1yz|Hr8CF_*b$1^=KLq>}#; zI38(emZ47lYpB#6aBM`K=62NY&N^O0O*ESP%S2Q^X_$xeFkSEe$5b@qGdLRmL>;D~ zq(vQPq9!;Wr(zLmCGVsDNIFnka2|Eq<9KIB;t169`Do!r)Z6hE@-Zj4#52D6nF?c? z-%u%yVwpO0amXS}B5ES(jv%Ux2V0nfnza-{ZOVR;xt_7-0wkc?GaSJ zzu+U-If(p|B{PO!>9xo~t#C1_;TGq92Wp@u)a%vZco8+Bcq=^7VW^BvL_N<&Enq1= zh^44ZzJnyk9QISuVLE}KnPCR^oyelh5b~@JvT!BlqS`g1wx|QM@DgU@DE?>XVF^ya zW2lM$fm&EBv)5Tm$29b3Q&C55REla)hwv!Ur|Cep-(0{5REZ*4%0r%dSJKn8u~_Xqc^oG>^+fF9)O85&F8s^hDMi%g6B*8v zrMQmJ8?cBdBuwr4xc8DvD_mZm%WJK2`8K#*rB-QviOVYVcuVqq<$sPM6`|G6cW>lu?+p N-IyBqY4DuLe*sh%oj(8o delta 2747 zcmYk;duWzb9KiA8yUppG+nm!ab8}NuOY>INR?}u%W-T?-vYFS)GyeMbv(e|VC+!yOio4L~-okEp04L!`Xjff( zgwP#xFdd69Cxm1urovws!6hHdu>fn)FD$?eTpC@8cCZ#5Xd^O4*c|V_h(5m!d*Q2C zj(e~K&!7`d&kiA*@k0+P9Wz2#R2vLejPm@?anAyaep8V!b)^y3(!ohMz`h}bb#m3ly8ad z!~wK-qZ$1e3-K@}iSQE_S9l(s@kMk(|DpqQXL(dZ3HHVj=m1qX94DiDy#~$L2RIPF zK{Is;onST%$H_z6eRIjbd)SW~4mb#Hk3v^cjt)2;9dJ5cjde($p%F<^*o=L!1zkWZ z_Qk#E#M{vCe}#_o9h!+>a>>76yuc0jHZ$+?iu2JF4~^{#bV5_n0cM~b&yM$(paa&U z18qhp){H*)3c9dX^ex+m3>n&!@q<%n$3Mphe#McrvzWzDtiUo{h@OF`v7I|?hRPvVn z_9LIASc49<2z_l^&@Ffec{ChAGuV!vtrN%`!Vl;K{!qpbefYL18W){~u4sL1zk%1# z{tSI>&Y>$gk7njSbbx%)ScS!CCg4eIhe{RDo!BL@3Mo@l}|!D zYQVX;3Af<4cn>Zkzj_eOL-Q&*VcBHym&Wy0;(V z82l1VRTuKFW$0c`L_2K23T#5w5Z*@)dN__Q>@@mZH}=zZA=-Z>`W8(oA^%oZal?sh zM`ySfP1Psy{?T~<436UdUuX)4F)I(*IApG2I(AG9N78OW<`DLv{T_~=pF+3fT#`x^ zmHg5WZpRro9e3b3Jd4h_g#B>^qtL@O6Nlh3w4;~M%p61y-5KOBoa4f7g`9z85$_@_ zb1vigrxW5a!Y?|wr!<3jgjhwC60Xt-vhXmUu(5i5y$g5Q&lGjaoVE)REVn0m` zzm$r_{Yns~+p}P~o4AQ+Aj*kbh{c4(?XZyHj>7Lz*g$vyZzS#~u9O+E;_rtghp4mS z`sZ1pOd;+i{1Hhfe5HIVZYC_Ahtb4s#1LWtQAK$2eci4U|6SM^8&BX^;z43I;aOQo zR1yn_ M97?42m(?cz2mKG`J^%m! diff --git a/po/ru/demon-editor.mo b/po/ru/demon-editor.mo index 9fc255985c41764b5be7bf505d65c3fc4816c083..21d5368a9c3049983f65c82c2bbe0a3f6f289da3 100644 GIT binary patch delta 3141 zcmZA1dr*{B7{~F$RRdGJAeNvnUPwhLQPZ@P$i(teO6CnOhzqU)OUsI(=7Kd@nc@sM z&e)WrRN7dX$d?dSbq1bW8^ui!U;W@_(crW*tFcxp3+Wn3CY0r3LW?&L_ z!{vAn7UCc*Lx%F38Y(?`P=|a>J(oV%fc@|b)DKT%44!kmh;(4Cpa#5-jBRc?&trRp z+s9*Xp7+K{I21L3Jd9<0vxy2Hvz3cFtU;};&bdE;Dcm1KP2elkK;NKN`~#}}uc(FG z!22+Yhx$GRwV*MmOl3LdU^L^KxvF3;D#eSCMVLGsfNLD99rvOJ2;fls4zQg+Mhy_bm+H7X>Un?EfCEwEWTGZE8PzVwPem(UfO`FwBa1PcoaftdJoj~|0ZyXY z*_eS>@BvKbgr(wi)R`zm_4@{D;lleQod$nl5%)c5 zZD9qnShEK;p+l$v8jz;uOVpN}My<3HccL0;;x(vtAL1yz|Hr8CF_*b$1^=KLq>}#; zI38(emZ47lYpB#6aBM`K=62NY&N^O0O*ESP%S2Q^X_$xeFkSEe$5b@qGdLRmL>;D~ zq(vQPq9!;Wr(zLmCGVsDNIFnka2|Eq<9KIB;t169`Do!r)Z6hE@-Zj4#52D6nF?c? z-%u%yVwpO0amXS}B5ES(jv%Ux2V0nfnza-{ZOVR;xt_7-0wkc?GaSJ zzu+U-If(p|B{PO!>9xo~t#C1_;TGq92Wp@u)a%vZco8+Bcq=^7VW^BvL_N<&Enq1= zh^44ZzJnyk9QISuVLE}KnPCR^oyelh5b~@JvT!BlqS`g1wx|QM@DgU@DE?>XVF^ya zW2lM$fm&EBv)5Tm$29b3Q&C55REla)hwv!Ur|Cep-(0{5REZ*4%0r%dSJKn8u~_Xqc^oG>^+fF9)O85&F8s^hDMi%g6B*8v zrMQmJ8?cBdBuwr4xc8DvD_mZm%WJK2`8K#*rB-QviOVYVcuVqq<$sPM6`|G6cW>lu?+p N-IyBqY4DuLe*sh%oj(8o delta 2747 zcmYk;duWzb9KiA8yUppG+nm!ab8}NuOY>INR?}u%W-T?-vYFS)GyeMbv(e|VC+!yOio4L~-okEp04L!`Xjff( zgwP#xFdd69Cxm1urovws!6hHdu>fn)FD$?eTpC@8cCZ#5Xd^O4*c|V_h(5m!d*Q2C zj(e~K&!7`d&kiA*@k0+P9Wz2#R2vLejPm@?anAyaep8V!b)^y3(!ohMz`h}bb#m3ly8ad z!~wK-qZ$1e3-K@}iSQE_S9l(s@kMk(|DpqQXL(dZ3HHVj=m1qX94DiDy#~$L2RIPF zK{Is;onST%$H_z6eRIjbd)SW~4mb#Hk3v^cjt)2;9dJ5cjde($p%F<^*o=L!1zkWZ z_Qk#E#M{vCe}#_o9h!+>a>>76yuc0jHZ$+?iu2JF4~^{#bV5_n0cM~b&yM$(paa&U z18qhp){H*)3c9dX^ex+m3>n&!@q<%n$3Mphe#McrvzWzDtiUo{h@OF`v7I|?hRPvVn z_9LIASc49<2z_l^&@Ffec{ChAGuV!vtrN%`!Vl;K{!qpbefYL18W){~u4sL1zk%1# z{tSI>&Y>$gk7njSbbx%)ScS!CCg4eIhe{RDo!BL@3Mo@l}|!D zYQVX;3Af<4cn>Zkzj_eOL-Q&*VcBHym&Wy0;(V z82l1VRTuKFW$0c`L_2K23T#5w5Z*@)dN__Q>@@mZH}=zZA=-Z>`W8(oA^%oZal?sh zM`ySfP1Psy{?T~<436UdUuX)4F)I(*IApG2I(AG9N78OW<`DLv{T_~=pF+3fT#`x^ zmHg5WZpRro9e3b3Jd4h_g#B>^qtL@O6Nlh3w4;~M%p61y-5KOBoa4f7g`9z85$_@_ zb1vigrxW5a!Y?|wr!<3jgjhwC60Xt-vhXmUu(5i5y$g5Q&lGjaoVE)REVn0m` zzm$r_{Yns~+p}P~o4AQ+Aj*kbh{c4(?XZyHj>7Lz*g$vyZzS#~u9O+E;_rtghp4mS z`sZ1pOd;+i{1Hhfe5HIVZYC_Ahtb4s#1LWtQAK$2eci4U|6SM^8&BX^;z43I;aOQo zR1yn_ M97?42m(?cz2mKG`J^%m! diff --git a/po/ru/demon-editor.po b/po/ru/demon-editor.po index a4c689fe..0dd7a6f2 100644 --- a/po/ru/demon-editor.po +++ b/po/ru/demon-editor.po @@ -377,6 +377,18 @@ msgstr "Путь для сохранения:" msgid "Path to Enigma2 picons:" msgstr "Путь к пиконам формата Enigma2:" +msgid "Specify the correct position value for the provider!" +msgstr "Укажите правильное значение позиции для провайдера!" + +msgid "Converter between name formats" +msgstr "Конвертер формата имен" + +msgid "Receive picons for providers" +msgstr "Получение пиконов для провайдеров" + +msgid "Load satellite providers." +msgstr "Загрузка провайдеров" + # Satellites editor msgid "Satellites edit tool" msgstr "Редактор спутников" From ae6f0e1ae24b6208d2a1d62447d5d91db47b548c Mon Sep 17 00:00:00 2001 From: DYefremov Date: Wed, 7 Mar 2018 23:56:21 +0300 Subject: [PATCH 02/18] pos fix for picons dialog --- app/picons/picons.py | 14 ++++++++------ app/ui/picons_dialog.py | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/picons/picons.py b/app/picons/picons.py index 62210654..4b946bde 100644 --- a/app/picons/picons.py +++ b/app/picons/picons.py @@ -4,6 +4,8 @@ import shutil from collections import namedtuple from html.parser import HTMLParser +import re + from app.commons import log, run_task from app.properties import Profile @@ -103,6 +105,8 @@ class PiconsParser(HTMLParser): class ProviderParser(HTMLParser): """ Parser for satellite html page. (https://www.lyngsat.com/*sat-name*.html) """ + _POSITION_PATTERN = re.compile("at\s\d+\..*(?:E|W)']") + def __init__(self, entities=False, separator=' '): HTMLParser.__init__(self) @@ -117,7 +121,6 @@ class ProviderParser(HTMLParser): self._current_cell = [] self.rows = [] self._ids = set() - self._counter = 0 self._positon = None def handle_starttag(self, tag, attrs): @@ -150,11 +153,10 @@ class ProviderParser(HTMLParser): 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 not self._positon: + pos = re.findall(self._POSITION_PATTERN, str(row)) + if pos: + self._positon = "".join(c for c in str(pos) if c.isdigit() or c in ".EW") if len(row) == 12: on_id, sep, tid = str(row[-2]).partition("-") diff --git a/app/ui/picons_dialog.py b/app/ui/picons_dialog.py index 62900811..4923fc2a 100644 --- a/app/ui/picons_dialog.py +++ b/app/ui/picons_dialog.py @@ -126,7 +126,7 @@ class PiconsDialog: providers = self.get_selected_providers() for prv in providers: - if not prv[2].isdigit(): + if not prv[2] and prv[2][:-2].isdigit(): self.show_info_message( get_message("Specify the correct position value for the provider!"), Gtk.MessageType.ERROR) return From 88e19e2fd11e24efc597a78d5fb0cab1093a13ce Mon Sep 17 00:00:00 2001 From: Dmitriy Yefremov Date: Fri, 9 Mar 2018 17:40:26 +0300 Subject: [PATCH 03/18] added warning message to the picons dialog --- app/picons/picons.py | 1 - app/ui/lang/ru/LC_MESSAGES/demon-editor.mo | Bin 9216 -> 9547 bytes app/ui/picons_dialog.glade | 26 +++++------------- app/ui/picons_dialog.py | 4 +++ build-deb.sh | 2 +- .../locale/ru/LC_MESSAGES/demon-editor.mo | Bin 9216 -> 9547 bytes po/ru/demon-editor.mo | Bin 9216 -> 9547 bytes po/ru/demon-editor.po | 3 ++ 8 files changed, 15 insertions(+), 21 deletions(-) diff --git a/app/picons/picons.py b/app/picons/picons.py index 4b946bde..342a017f 100644 --- a/app/picons/picons.py +++ b/app/picons/picons.py @@ -172,7 +172,6 @@ class ProviderParser(HTMLParser): def reset(self): super().reset() - self._counter = 0 def parse_providers(open_path): diff --git a/app/ui/lang/ru/LC_MESSAGES/demon-editor.mo b/app/ui/lang/ru/LC_MESSAGES/demon-editor.mo index 21d5368a9c3049983f65c82c2bbe0a3f6f289da3..8b8e9417fea02a5a515546b2c6bf99dfcdacbadb 100644 GIT binary patch delta 2545 zcmYk+e@sPTuCPhy6lhU+RknDhoTPqVe3C_CHtS;kDoyEp+Kc>aNp(f^4V82~7oC9sYUlfKJhmbqbAZbZ zJdPIrizII>R@KJJQ2{Er5X-!RdNkWn88_o$d>fTO0p(?$W0uoc%)naYHxol;^48b{ z(}j!ZUq;QlhdTY!sH;j?>RE|8)i0wqu)}jNYNLldPodW7!L54#Z_?1IeU|jK;{f{5 zK^>~kPz(2?HaLXO<9$>nOL<5252YIQD0ZPveFC4vbKdw6TJ$Hdd&Mil0^*wuH1tet zWG|)xRnm7*hcAI7ZBC&!a^CYhRHc6R%%3@ySp{l5fW>$a^}3xwCDene&;U9LkfKqA zw@@XWLm8gNQq%(5Q1jkEJu}^8Mk0L9!6E_3ci5DUf*I+kG2Z6 zZrwb`m`WPW3{XY$IqJ1=Q5pV#nwVjY_484IR-#_BYR`JqhK`{&+KsB%71a23)c8-h z6h|-{OC0J))yy)aI%Wfo?hMQ5HzUO`XHW}#joa}SYThdTuj&z1V--em4JL6TKE&m? zmfdRO`|&Dvpb}iMk*f|}BQC^4s0GiXN_7);7&90orkR2q6Z2GYVrJ%waV?3>nUTW1 z3~c4w#P>zM`cwM*6Sp%@7q`+wyX|mIWOtd_6!nK= zwZY`c+`1g+nA@M~u-vn5Z|Ze-!2QBKix*RGx_zlO_YxyXcffKl@v=7iYEP{`s7ZaPRu&$c j*lW3bl5W5DG`e=5rTf(+CNtR+*RyPi70MFn3;y{JCL4u! delta 2207 zcmYk+Z)lZO9Ki9jwq5V;YEIXj=4Sin(%m#1ie`{wloOL+8`2-A)Qg-IWgtX4^KQNA zA9KQ;2u6uBnqanai{4a9t3<5O7bfk6q+~;BfzFars_)mG7hUf2e9n39dCu?re&>1a z$<V}kghlLp`L8Yd_0MKkM*{eG;VKY%Xa8#K^KG~*x9@xP*pT*FzI z%SC^$KoeSkR;n@DjCsTlkJ`XCw8W1iNrZNsiJPL`(Y?CfE*S7lv?9CF8~34m{VAIHF|^cYVt))>*iAG*4nI0^ z61_eH4LBQ((||5)IXbR6L&J>MqOacuB$?0|ufL6p>Gz=lPN3sX;X)k8d$61*tO_4O zpNWm=yl(s1ub(G_3C+wgiE@HckQFJg2hzKkRr_Mi(ohz1x$ zhK8@vEjf#3I)OXUK`y)(9rq#D`~DxL!8csyWCs7D1FES1JY0+n4C~RS{tdKr{n3xn zr}<0tzH`wl=tA?Tzm}r&)L}ceVA}WpBO0!F6z|19(TAyqvN&-Ay1-U^5IfLJK0yCS zM$j#|fIjUh-r4y$553-smADOkJKjOQ;W(#4;)kDU5HtLSmNb_%edtn15}_1bNILom zTB+xwJ!ocwu|JA)>EA?Ov+BDh6RJZiv;>`h6=oV~w9&Aneb|8g=mclbfj7{-Oi-p; zEI}8rEczsx>2`FU_i;TQ!ChEPxz^zR=NY1ccE{^ z0km{OXu$8#y}gEuFrWRfQcH0KJ{J3X(5?Lpo%a{KA1CHef2tG~aF?$|Gn(NO=)fJZ z--8A^g1%lO(J^#Eg_V;Ftwk%g6usVrCa@0g!xzy?zK0Yi9Lmt}VLFbtR)!1dPasK! zYU=C+jrbI{q2q?pEgHc_yo60y&;M)-zJN>cD7x@J(8Lm~-e)b1by(j-!-<|nOVo=# zgr6gGh7n}@!^N6xeR6ru_Utps&9k<0p`GIuj)yt?nD(pL@#Ma_8CvGl#qs~orr5FI ko!L(c1`2l2@?U9N_UTkQCk*wZ%92ABC0mNKt+jvs2dmrBQUCw| diff --git a/app/ui/picons_dialog.glade b/app/ui/picons_dialog.glade index 866ece19..ea187745 100644 --- a/app/ui/picons_dialog.glade +++ b/app/ui/picons_dialog.glade @@ -768,22 +768,16 @@ True False + 2 True False - 6 end - - - - - - False @@ -794,25 +788,22 @@ False - 16 - - - True False - Info + Info + center + True + word-char + 2 False - True + False 1 - - - False @@ -820,9 +811,6 @@ 0 - - - False diff --git a/app/ui/picons_dialog.py b/app/ui/picons_dialog.py index 4923fc2a..a30afa37 100644 --- a/app/ui/picons_dialog.py +++ b/app/ui/picons_dialog.py @@ -79,6 +79,10 @@ class PiconsDialog: self._enigma2_picons_path = self._picons_path if profile is Profile.NEUTRINO_MP: self._enigma2_picons_path = options.get(Profile.ENIGMA_2.value).get("picons_dir_path", "") + if not len(self._picon_ids) and self._profile is Profile.ENIGMA_2: + message = get_message("To automatically set the identifiers for picons,\n" + "first load the required services list into the main application window.") + self.show_info_message(message, Gtk.MessageType.WARNING) def show(self): self._dialog.run() diff --git a/build-deb.sh b/build-deb.sh index a342c222..f5b95f72 100755 --- a/build-deb.sh +++ b/build-deb.sh @@ -5,7 +5,7 @@ DEB_PATH="$B_PATH/usr/share/demoneditor" mkdir -p $B_PATH cp -TRv deb $B_PATH -cp -Rv app $DEB_PATH +rsync --exclude=app/ui/lang -arv app $DEB_PATH cp -Rv start.py $DEB_PATH cd dist diff --git a/deb/usr/share/locale/ru/LC_MESSAGES/demon-editor.mo b/deb/usr/share/locale/ru/LC_MESSAGES/demon-editor.mo index 21d5368a9c3049983f65c82c2bbe0a3f6f289da3..8b8e9417fea02a5a515546b2c6bf99dfcdacbadb 100644 GIT binary patch delta 2545 zcmYk+e@sPTuCPhy6lhU+RknDhoTPqVe3C_CHtS;kDoyEp+Kc>aNp(f^4V82~7oC9sYUlfKJhmbqbAZbZ zJdPIrizII>R@KJJQ2{Er5X-!RdNkWn88_o$d>fTO0p(?$W0uoc%)naYHxol;^48b{ z(}j!ZUq;QlhdTY!sH;j?>RE|8)i0wqu)}jNYNLldPodW7!L54#Z_?1IeU|jK;{f{5 zK^>~kPz(2?HaLXO<9$>nOL<5252YIQD0ZPveFC4vbKdw6TJ$Hdd&Mil0^*wuH1tet zWG|)xRnm7*hcAI7ZBC&!a^CYhRHc6R%%3@ySp{l5fW>$a^}3xwCDene&;U9LkfKqA zw@@XWLm8gNQq%(5Q1jkEJu}^8Mk0L9!6E_3ci5DUf*I+kG2Z6 zZrwb`m`WPW3{XY$IqJ1=Q5pV#nwVjY_484IR-#_BYR`JqhK`{&+KsB%71a23)c8-h z6h|-{OC0J))yy)aI%Wfo?hMQ5HzUO`XHW}#joa}SYThdTuj&z1V--em4JL6TKE&m? zmfdRO`|&Dvpb}iMk*f|}BQC^4s0GiXN_7);7&90orkR2q6Z2GYVrJ%waV?3>nUTW1 z3~c4w#P>zM`cwM*6Sp%@7q`+wyX|mIWOtd_6!nK= zwZY`c+`1g+nA@M~u-vn5Z|Ze-!2QBKix*RGx_zlO_YxyXcffKl@v=7iYEP{`s7ZaPRu&$c j*lW3bl5W5DG`e=5rTf(+CNtR+*RyPi70MFn3;y{JCL4u! delta 2207 zcmYk+Z)lZO9Ki9jwq5V;YEIXj=4Sin(%m#1ie`{wloOL+8`2-A)Qg-IWgtX4^KQNA zA9KQ;2u6uBnqanai{4a9t3<5O7bfk6q+~;BfzFars_)mG7hUf2e9n39dCu?re&>1a z$<V}kghlLp`L8Yd_0MKkM*{eG;VKY%Xa8#K^KG~*x9@xP*pT*FzI z%SC^$KoeSkR;n@DjCsTlkJ`XCw8W1iNrZNsiJPL`(Y?CfE*S7lv?9CF8~34m{VAIHF|^cYVt))>*iAG*4nI0^ z61_eH4LBQ((||5)IXbR6L&J>MqOacuB$?0|ufL6p>Gz=lPN3sX;X)k8d$61*tO_4O zpNWm=yl(s1ub(G_3C+wgiE@HckQFJg2hzKkRr_Mi(ohz1x$ zhK8@vEjf#3I)OXUK`y)(9rq#D`~DxL!8csyWCs7D1FES1JY0+n4C~RS{tdKr{n3xn zr}<0tzH`wl=tA?Tzm}r&)L}ceVA}WpBO0!F6z|19(TAyqvN&-Ay1-U^5IfLJK0yCS zM$j#|fIjUh-r4y$553-smADOkJKjOQ;W(#4;)kDU5HtLSmNb_%edtn15}_1bNILom zTB+xwJ!ocwu|JA)>EA?Ov+BDh6RJZiv;>`h6=oV~w9&Aneb|8g=mclbfj7{-Oi-p; zEI}8rEczsx>2`FU_i;TQ!ChEPxz^zR=NY1ccE{^ z0km{OXu$8#y}gEuFrWRfQcH0KJ{J3X(5?Lpo%a{KA1CHef2tG~aF?$|Gn(NO=)fJZ z--8A^g1%lO(J^#Eg_V;Ftwk%g6usVrCa@0g!xzy?zK0Yi9Lmt}VLFbtR)!1dPasK! zYU=C+jrbI{q2q?pEgHc_yo60y&;M)-zJN>cD7x@J(8Lm~-e)b1by(j-!-<|nOVo=# zgr6gGh7n}@!^N6xeR6ru_Utps&9k<0p`GIuj)yt?nD(pL@#Ma_8CvGl#qs~orr5FI ko!L(c1`2l2@?U9N_UTkQCk*wZ%92ABC0mNKt+jvs2dmrBQUCw| diff --git a/po/ru/demon-editor.mo b/po/ru/demon-editor.mo index 21d5368a9c3049983f65c82c2bbe0a3f6f289da3..8b8e9417fea02a5a515546b2c6bf99dfcdacbadb 100644 GIT binary patch delta 2545 zcmYk+e@sPTuCPhy6lhU+RknDhoTPqVe3C_CHtS;kDoyEp+Kc>aNp(f^4V82~7oC9sYUlfKJhmbqbAZbZ zJdPIrizII>R@KJJQ2{Er5X-!RdNkWn88_o$d>fTO0p(?$W0uoc%)naYHxol;^48b{ z(}j!ZUq;QlhdTY!sH;j?>RE|8)i0wqu)}jNYNLldPodW7!L54#Z_?1IeU|jK;{f{5 zK^>~kPz(2?HaLXO<9$>nOL<5252YIQD0ZPveFC4vbKdw6TJ$Hdd&Mil0^*wuH1tet zWG|)xRnm7*hcAI7ZBC&!a^CYhRHc6R%%3@ySp{l5fW>$a^}3xwCDene&;U9LkfKqA zw@@XWLm8gNQq%(5Q1jkEJu}^8Mk0L9!6E_3ci5DUf*I+kG2Z6 zZrwb`m`WPW3{XY$IqJ1=Q5pV#nwVjY_484IR-#_BYR`JqhK`{&+KsB%71a23)c8-h z6h|-{OC0J))yy)aI%Wfo?hMQ5HzUO`XHW}#joa}SYThdTuj&z1V--em4JL6TKE&m? zmfdRO`|&Dvpb}iMk*f|}BQC^4s0GiXN_7);7&90orkR2q6Z2GYVrJ%waV?3>nUTW1 z3~c4w#P>zM`cwM*6Sp%@7q`+wyX|mIWOtd_6!nK= zwZY`c+`1g+nA@M~u-vn5Z|Ze-!2QBKix*RGx_zlO_YxyXcffKl@v=7iYEP{`s7ZaPRu&$c j*lW3bl5W5DG`e=5rTf(+CNtR+*RyPi70MFn3;y{JCL4u! delta 2207 zcmYk+Z)lZO9Ki9jwq5V;YEIXj=4Sin(%m#1ie`{wloOL+8`2-A)Qg-IWgtX4^KQNA zA9KQ;2u6uBnqanai{4a9t3<5O7bfk6q+~;BfzFars_)mG7hUf2e9n39dCu?re&>1a z$<V}kghlLp`L8Yd_0MKkM*{eG;VKY%Xa8#K^KG~*x9@xP*pT*FzI z%SC^$KoeSkR;n@DjCsTlkJ`XCw8W1iNrZNsiJPL`(Y?CfE*S7lv?9CF8~34m{VAIHF|^cYVt))>*iAG*4nI0^ z61_eH4LBQ((||5)IXbR6L&J>MqOacuB$?0|ufL6p>Gz=lPN3sX;X)k8d$61*tO_4O zpNWm=yl(s1ub(G_3C+wgiE@HckQFJg2hzKkRr_Mi(ohz1x$ zhK8@vEjf#3I)OXUK`y)(9rq#D`~DxL!8csyWCs7D1FES1JY0+n4C~RS{tdKr{n3xn zr}<0tzH`wl=tA?Tzm}r&)L}ceVA}WpBO0!F6z|19(TAyqvN&-Ay1-U^5IfLJK0yCS zM$j#|fIjUh-r4y$553-smADOkJKjOQ;W(#4;)kDU5HtLSmNb_%edtn15}_1bNILom zTB+xwJ!ocwu|JA)>EA?Ov+BDh6RJZiv;>`h6=oV~w9&Aneb|8g=mclbfj7{-Oi-p; zEI}8rEczsx>2`FU_i;TQ!ChEPxz^zR=NY1ccE{^ z0km{OXu$8#y}gEuFrWRfQcH0KJ{J3X(5?Lpo%a{KA1CHef2tG~aF?$|Gn(NO=)fJZ z--8A^g1%lO(J^#Eg_V;Ftwk%g6usVrCa@0g!xzy?zK0Yi9Lmt}VLFbtR)!1dPasK! zYU=C+jrbI{q2q?pEgHc_yo60y&;M)-zJN>cD7x@J(8Lm~-e)b1by(j-!-<|nOVo=# zgr6gGh7n}@!^N6xeR6ru_Utps&9k<0p`GIuj)yt?nD(pL@#Ma_8CvGl#qs~orr5FI ko!L(c1`2l2@?U9N_UTkQCk*wZ%92ABC0mNKt+jvs2dmrBQUCw| diff --git a/po/ru/demon-editor.po b/po/ru/demon-editor.po index 0dd7a6f2..80083d05 100644 --- a/po/ru/demon-editor.po +++ b/po/ru/demon-editor.po @@ -389,6 +389,9 @@ msgstr "Получение пиконов для провайдеров" msgid "Load satellite providers." msgstr "Загрузка провайдеров" +msgid "To automatically set the identifiers for picons,\nfirst load the required services list into the main application window." +msgstr "Для автоматического именования пиконов,\nзагрузите список необходимых сервисов в главное окно программы." + # Satellites editor msgid "Satellites edit tool" msgstr "Редактор спутников" From f7f230f40efdec3cf46e992c1e9155d84d1d9a62 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Sat, 10 Mar 2018 17:49:53 +0300 Subject: [PATCH 04/18] Separation of service creation and editing --- app/ui/main_app_window.py | 19 ++++++++++++++++--- app/ui/main_window.glade | 16 ++++++++++++++++ app/ui/service_details_dialog.glade | 3 +-- app/ui/service_details_dialog.py | 21 ++++++++++++++++++--- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index dd94a2d9..875b9ad2 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -21,7 +21,7 @@ from .main_helper import edit_marker, insert_marker, move_items, rename, ViewTar from .picons_dialog import PiconsDialog from .satellites_dialog import show_satellites_dialog from .settings_dialog import show_settings_dialog -from .service_details_dialog import ServiceDetailsDialog +from .service_details_dialog import ServiceDetailsDialog, Action class MainAppWindow: @@ -63,7 +63,8 @@ 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_picon_popup_item", "fav_picon_popup_item") + "services_copy_popup_item", "services_picon_popup_item", "fav_picon_popup_item", + "services_add_new_popup_item") def __init__(self): handlers = {"on_close_main_window": self.on_quit, @@ -112,7 +113,8 @@ class MainAppWindow: "on_search_down": self.on_search_down, "on_search_up": self.on_search_up, "on_search": self.on_search, - "on_service_edit": self.on_service_edit} + "on_service_edit": self.on_service_edit, + "on_services_add_new": self.on_services_add_new} self.__options = get_config() self.__profile = self.__options.get("profile") @@ -785,6 +787,8 @@ class MainAppWindow: for elem in self._COMMONS_ELEMENTS: self.__tool_elements[elem].set_sensitive(not_empty) + self.__tool_elements["services_add_new_popup_item"].set_sensitive(len(self.__bouquets_model)) + def on_hide(self, item): self.set_service_flags(Flag.HIDE) @@ -932,6 +936,15 @@ class MainAppWindow: self.__bouquets) dialog.show() + def on_services_add_new(self, item): + dialog = ServiceDetailsDialog(self.__main_window, + self.__options, + self.__services_view, + self.__services, + self.__bouquets, + action=Action.ADD) + dialog.show() + @run_idle def update_picons(self): update_picons(self.__options.get(self.__profile).get("picons_dir_path"), self.__picons, self.__services_model) diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade index a9f6e865..fb43dba6 100644 --- a/app/ui/main_window.glade +++ b/app/ui/main_window.glade @@ -355,6 +355,12 @@ + + + True + False + + gtk-edit @@ -367,6 +373,16 @@ + + + gtk-new + True + False + True + True + + + True diff --git a/app/ui/service_details_dialog.glade b/app/ui/service_details_dialog.glade index b87b1c3f..63e9ec36 100644 --- a/app/ui/service_details_dialog.glade +++ b/app/ui/service_details_dialog.glade @@ -261,9 +261,8 @@ - + gtk-new - True True True Create and save as new service diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 9d660599..387c5649 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -1,4 +1,5 @@ import re +from enum import Enum from functools import lru_cache from app.commons import run_idle @@ -11,6 +12,11 @@ from app.ui.main_helper import get_base_model from . import Gtk, Gdk, UI_RESOURCES_PATH, HIDE_ICON, TEXT_DOMAIN +class Action(Enum): + EDIT = 0 + ADD = 1 + + class ServiceDetailsDialog: _DATA_ID = "{:04x}:{:08x}:{:04x}:{:04x}:{}:{}" @@ -24,7 +30,7 @@ class ServiceDetailsDialog: "rate_entry", "pls_code_entry", "stream_id_entry", "tr_flag_entry", "namespace_entry", "srv_type_entry") - def __init__(self, transient, options, view, services, bouquets): + def __init__(self, transient, options, view, services, bouquets, action=Action.EDIT): handlers = {"on_system_changed": self.on_system_changed, "on_save": self.on_save, "on_create_new": self.on_create_new, @@ -41,6 +47,7 @@ class ServiceDetailsDialog: self._profile = Profile(options["profile"]) self._satellites_xml_path = options.get(self._profile.value)["data_dir_path"] + "satellites.xml" self._services_view = view + self._action = action self._old_service = None self._services = services self._bouquets = bouquets @@ -48,6 +55,8 @@ class ServiceDetailsDialog: self._current_model = None self._current_itr = None self._pattern = re.compile("\D") + self._apply_button = builder.get_object("apply_button") + self._create_button = builder.get_object("create_button") # style self._style_provider = Gtk.CssProvider() self._style_provider.load_from_path(UI_RESOURCES_PATH + "style.css") @@ -106,7 +115,13 @@ class ServiceDetailsDialog: self._network_id_entry, self._namespace_entry, self._fec_combo_box, self._rate_entry) - self.update_data_elements() + if self._action is Action.EDIT: + self.update_data_elements() + elif self._action is Action.ADD: + self._apply_button.set_visible(False) + self._create_button.set_visible(True) + self._tr_edit_switch.set_sensitive(False) + self.on_tr_edit_toggled(self._tr_edit_switch.set_active(True), True) def show(self): response = self._dialog.run() @@ -453,7 +468,7 @@ class ServiceDetailsDialog: @run_idle def on_tr_edit_toggled(self, switch: Gtk.Switch, active): - if active: + if active and self._action is Action.EDIT: self._transponder_services_iters = [] response = TransponderServicesDialog(self._dialog, self._current_model, From b56685edb1dcaa87b4cc469084f4cf5818325a51 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Sat, 10 Mar 2018 19:12:56 +0300 Subject: [PATCH 05/18] Ui skeleton for IPTV dialog --- app/ui/dialogs.glade | 398 ++++++++++++++++++++++++++++++++++++++ app/ui/main_app_window.py | 6 +- app/ui/main_window.glade | 15 ++ 3 files changed, 416 insertions(+), 3 deletions(-) diff --git a/app/ui/dialogs.glade b/app/ui/dialogs.glade index 36ecde7b..1bcb62e1 100644 --- a/app/ui/dialogs.glade +++ b/app/ui/dialogs.glade @@ -613,6 +613,404 @@ dmitry.v.yefremov@gmail.com + + + + + + + + DVB/TS + + + non-TS + + + + + 480 + False + Stream data + False + True + True + dialog + True + True + + + False + vertical + 2 + + + False + end + + + gtk-cancel + True + True + True + True + True + + + True + True + 0 + + + + + gtk-add + True + True + True + True + True + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + vertical + 2 + + + True + False + Service data: + 0.0099999997764825821 + + + + False + True + 0 + + + + + True + False + 2 + + + True + False + Name: + 7 + 7 + 1 + + + 0 + 0 + + + + + True + True + gtk-edit + + + 1 + 0 + + + + + True + False + Type: + + + 2 + 0 + + + + + True + False + 5 + stream_type_liststore + 0 + 0 + + + + 0 + + + + + 3 + 0 + + + + + True + False + Reference: + + + 4 + 0 + + + + + True + True + + + 5 + 0 + + + + + False + True + 1 + + + + + True + False + + + True + False + Url: + 7 + 7 + 1 + + + False + True + 0 + + + + + True + True + gtk-edit + + + True + True + 1 + + + + + True + True + 2 + + + + + True + False + + + False + True + 2 + 4 + + + + + True + False + DVB/TS data: + 0.0099999997764825821 + + + + False + True + 5 + + + + + True + False + 2 + 2 + True + + + True + False + Service type + + + 0 + 0 + + + + + True + False + SID + + + 1 + 0 + + + + + True + False + Tr. ID + + + 2 + 0 + + + + + True + False + Net. ID + + + 3 + 0 + + + + + True + False + Namespace + + + 4 + 0 + + + + + True + True + 10 + 10 + + + 0 + 1 + + + + + True + True + 10 + 10 + + + 1 + 1 + + + + + True + True + 10 + 10 + + + 2 + 1 + + + + + True + True + 10 + 10 + + + 3 + 1 + + + + + True + True + 10 + 10 + + + 4 + 1 + + + + + False + True + 6 + + + + + True + False + + + False + True + 2 + 7 + + + + + False + True + 1 + + + + + 1 11 diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index 875b9ad2..5d607d72 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -46,11 +46,11 @@ 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_picon_popup_item") + "fav_locate_popup_item", "fav_picon_popup_item", "fav_add_iptv_popup_item") _FAV_ENIGMA_ELEMENTS = ("fav_insert_marker_popup_item", "fav_edit_marker_popup_item") - _FAV_M3U_ELEMENTS = ("import_m3u_tool_button", "fav_import_m3u_popup_item") + _FAV_M3U_ELEMENTS = ("import_m3u_tool_button", "fav_import_m3u_popup_item", "fav_add_iptv_popup_item") _LOCK_HIDE_ELEMENTS = ("locked_tool_button", "hide_tool_button") @@ -64,7 +64,7 @@ class MainAppWindow: "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_picon_popup_item", "fav_picon_popup_item", - "services_add_new_popup_item") + "services_add_new_popup_item", "fav_add_iptv_popup_item") def __init__(self): handlers = {"on_close_main_window": self.on_quit, diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade index fb43dba6..1a1c2195 100644 --- a/app/ui/main_window.glade +++ b/app/ui/main_window.glade @@ -117,6 +117,11 @@ False gtk-copy + + True + False + network-transmit-receive + True False @@ -238,6 +243,16 @@ + + + Add IPTV or stream + True + False + False + image17 + False + + True From 1d577750c0e11ce3e6e90ed004c7c78c3f2fea82 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Sun, 11 Mar 2018 21:52:10 +0300 Subject: [PATCH 06/18] Iptv dialog skeleton --- app/ui/dialogs.glade | 37 ++++++++++++++++++------- app/ui/dialogs.py | 6 +++++ app/ui/iptv.py | 46 ++++++++++++++++++++++++++++++++ app/ui/main_app_window.py | 19 ++++++++++--- app/ui/main_window.glade | 1 + app/ui/service_details_dialog.py | 10 ++----- 6 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 app/ui/iptv.py diff --git a/app/ui/dialogs.glade b/app/ui/dialogs.glade index 1bcb62e1..7d42d62e 100644 --- a/app/ui/dialogs.glade +++ b/app/ui/dialogs.glade @@ -664,7 +664,6 @@ dmitry.v.yefremov@gmail.com gtk-add - True True True True @@ -676,6 +675,21 @@ dmitry.v.yefremov@gmail.com 1 + + + gtk-save + True + True + True + True + True + + + True + True + 2 + + False @@ -725,7 +739,7 @@ dmitry.v.yefremov@gmail.com - + True True gtk-edit @@ -778,7 +792,7 @@ dmitry.v.yefremov@gmail.com - + True True @@ -795,7 +809,7 @@ dmitry.v.yefremov@gmail.com - + True False @@ -923,7 +937,7 @@ dmitry.v.yefremov@gmail.com - + True True 10 @@ -935,7 +949,7 @@ dmitry.v.yefremov@gmail.com - + True True 10 @@ -947,7 +961,7 @@ dmitry.v.yefremov@gmail.com - + True True 10 @@ -959,7 +973,7 @@ dmitry.v.yefremov@gmail.com - + True True 10 @@ -971,7 +985,7 @@ dmitry.v.yefremov@gmail.com - + True True 10 @@ -1010,6 +1024,11 @@ dmitry.v.yefremov@gmail.com + + iptv_dialog_cancel_button + iptv_dialog_add_button + iptv_dialog_save_button + 1 diff --git a/app/ui/dialogs.py b/app/ui/dialogs.py index 99383f2f..83420983 100644 --- a/app/ui/dialogs.py +++ b/app/ui/dialogs.py @@ -6,6 +6,11 @@ from app.commons import run_idle from . import Gtk, UI_RESOURCES_PATH, TEXT_DOMAIN +class Action(Enum): + EDIT = 0 + ADD = 1 + + class DialogType(Enum): INPUT = "input_dialog" CHOOSER = "path_chooser_dialog" @@ -13,6 +18,7 @@ class DialogType(Enum): QUESTION = "question_dialog" ABOUT = "about_dialog" WAIT = "wait_dialog" + IPTV = "iptv_dialog" class WaitDialog: diff --git a/app/ui/iptv.py b/app/ui/iptv.py new file mode 100644 index 00000000..d4c83317 --- /dev/null +++ b/app/ui/iptv.py @@ -0,0 +1,46 @@ +from .main_helper import get_base_model +from . import Gtk + +from app.properties import Profile +from .dialogs import get_dialog_from_xml, DialogType, Action + + +class IptvDialog: + def __init__(self, transient, view=None, services=None, bouquets=None, profile=Profile.ENIGMA_2, action=Action.ADD): + builder, dialog = get_dialog_from_xml(DialogType.IPTV, transient) + self._dialog = dialog + self._dialog.set_transient_for(transient) + self._name_entry = builder.get_object("name_entry") + self._url_entry = builder.get_object("url_entry") + self._reference_entry = builder.get_object("reference_entry") + self._srv_type_entry = builder.get_object("srv_type_entry") + self._sid_entry = builder.get_object("sid_entry") + self._tr_id_entry = builder.get_object("tr_id_entry") + self._net_id_entry = builder.get_object("net_id_entry") + self._namespace_entry = builder.get_object("namespace_entry") + self._stream_type_combobox = builder.get_object("stream_type_combobox") + self._add_button = builder.get_object("iptv_dialog_add_button") + self._save_button = builder.get_object("iptv_dialog_save_button") + self._action = action + + if self._action is Action.ADD: + self._save_button.set_visible(False) + self._add_button.set_visible(True) + elif self._action is Action.EDIT: + model, paths = view.get_selection().get_selected_rows() + model = get_base_model(model) + row = model[paths][:] + self._name_entry.set_text(row[2]) + + def show(self): + response = self._dialog.run() + if response == Gtk.ResponseType.OK: + self.save() + self._dialog.destroy() + + def save(self): + print(self._action) + + +if __name__ == "__main__": + pass diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index 5d607d72..8538bf2c 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -11,6 +11,7 @@ from app.eparser.ecommons import CAS, Flag from app.eparser.enigma.bouquets import BqServiceType from app.eparser.neutrino.bouquets import BqType from app.properties import get_config, write_config, Profile +from .iptv import IptvDialog from .search import SearchProvider from . import Gtk, Gdk, UI_RESOURCES_PATH, LOCKED_ICON, HIDE_ICON, IPTV_ICON from .dialogs import show_dialog, DialogType, get_chooser_dialog, WaitDialog, get_message @@ -114,7 +115,8 @@ class MainAppWindow: "on_search_up": self.on_search_up, "on_search": self.on_search, "on_service_edit": self.on_service_edit, - "on_services_add_new": self.on_services_add_new} + "on_services_add_new": self.on_services_add_new, + "on_iptv": self.on_iptv} self.__options = get_config() self.__profile = self.__options.get("profile") @@ -861,6 +863,9 @@ class MainAppWindow: bq_services.append(ch.fav_id) self.update_bouquet_channels(self.__fav_model, None, bq_selected) + def on_iptv(self, item): + IptvDialog(self.__main_window).show() + def on_insert_marker(self, view): """ Inserts marker into bouquet services list. """ insert_marker(view, self.__bouquets, self.is_bouquet_selected(), self.__services, self.__main_window) @@ -924,9 +929,15 @@ class MainAppWindow: model_name = get_base_model(model).get_name() if model_name == self._FAV_LIST_NAME: srv_type = model.get_value(model.get_iter(paths), 5) - if srv_type == BqServiceType.IPTV.name or srv_type == BqServiceType.MARKER.name: - self.on_rename(view) - return + if srv_type == BqServiceType.MARKER.name: + return self.on_rename(view) + elif srv_type == BqServiceType.IPTV.name: + return IptvDialog(self.__main_window, + self.__fav_view, + self.__services, + self.__bouquets, + Profile(self.__profile), + Action.EDIT).show() self.on_locate_in_services(view) dialog = ServiceDetailsDialog(self.__main_window, diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade index 1a1c2195..cbf16cec 100644 --- a/app/ui/main_window.glade +++ b/app/ui/main_window.glade @@ -251,6 +251,7 @@ False image17 False + diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 387c5649..f864c373 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -1,5 +1,4 @@ import re -from enum import Enum from functools import lru_cache from app.commons import run_idle @@ -7,16 +6,11 @@ from app.eparser import Service, get_satellites from app.eparser.ecommons import MODULATION, Inversion, ROLL_OFF, Pilot, Flag, Pids, POLARIZATION, \ get_key_by_value, get_value_by_name, FEC_DEFAULT, PLS_MODE from app.properties import Profile -from app.ui.dialogs import show_dialog, DialogType -from app.ui.main_helper import get_base_model +from .dialogs import show_dialog, DialogType, Action +from .main_helper import get_base_model from . import Gtk, Gdk, UI_RESOURCES_PATH, HIDE_ICON, TEXT_DOMAIN -class Action(Enum): - EDIT = 0 - ADD = 1 - - class ServiceDetailsDialog: _DATA_ID = "{:04x}:{:08x}:{:04x}:{:04x}:{}:{}" From d7635370ba932393a12aee5160164312c91bdd9e Mon Sep 17 00:00:00 2001 From: Dmitriy Yefremov Date: Mon, 12 Mar 2018 22:47:43 +0300 Subject: [PATCH 07/18] iptv dialog init data --- app/eparser/iptv.py | 14 +++++++--- app/ui/dialogs.glade | 64 +++++++++++++++++++++++++++++++------------- app/ui/dialogs.py | 8 +++--- app/ui/iptv.py | 38 +++++++++++++++++++++++--- 4 files changed, 95 insertions(+), 29 deletions(-) diff --git a/app/eparser/iptv.py b/app/eparser/iptv.py index 45e1cdce..f8257d84 100644 --- a/app/eparser/iptv.py +++ b/app/eparser/iptv.py @@ -1,11 +1,18 @@ -""" Module for m3u import """ +""" Module for IPTV and streams support """ +from enum import Enum + from app.properties import Profile from app.ui import IPTV_ICON from .ecommons import BqServiceType, Service # url, description, urlkey, account, usrname, psw, s_type, iconsrc, iconsrc_b, group NEUTRINO_FAV_ID_FORMAT = "{}::{}::{}::{}::{}::{}::{}::{}::{}::{}" -ENIGMA2_FAV_ID_FORMAT = " 1:0:1:0:0:0:0:0:0:0:{}:{}\n#DESCRIPTION: {}\n" +ENIGMA2_FAV_ID_FORMAT = " {}:0:{}:{}:{}:{}:{}:0:0:0:{}:{}\n#DESCRIPTION: {}\n" + + +class StreamType(Enum): + DVB_TS = "1" + NONE_TS = "4097" def parse_m3u(path, profile): @@ -22,7 +29,8 @@ def parse_m3u(path, profile): elif count == 1: count = 0 if profile is Profile.ENIGMA_2: - fav_id = ENIGMA2_FAV_ID_FORMAT.format(line.strip().replace(":", "%3a"), name, name, None) + fav_id = ENIGMA2_FAV_ID_FORMAT.format(StreamType.DVB_TS.value, 1, 0, 0, 0, 0, + line.strip().replace(":", "%3a"), name, name, None) elif profile is Profile.NEUTRINO_MP: fav_id = NEUTRINO_FAV_ID_FORMAT.format(line.strip(), "", 0, None, None, None, None, "", "", 1) srv = Service(None, None, IPTV_ICON, name, *aggr[0:3], BqServiceType.IPTV.name, *aggr, fav_id, None) diff --git a/app/ui/dialogs.glade b/app/ui/dialogs.glade index 7d42d62e..c38770d8 100644 --- a/app/ui/dialogs.glade +++ b/app/ui/dialogs.glade @@ -723,6 +723,7 @@ dmitry.v.yefremov@gmail.com True False + 2 2 @@ -731,7 +732,6 @@ dmitry.v.yefremov@gmail.com Name: 7 7 - 1 0 @@ -744,11 +744,33 @@ dmitry.v.yefremov@gmail.com True gtk-edit + + 0 + 1 + + + + + True + False + Description: + 1 0 + + + True + True + gtk-edit + + + 1 + 1 + + True @@ -769,15 +791,15 @@ dmitry.v.yefremov@gmail.com 0 0 - + 0 - 3 - 0 + 2 + 1 @@ -787,7 +809,7 @@ dmitry.v.yefremov@gmail.com Reference: - 4 + 3 0 @@ -795,10 +817,12 @@ dmitry.v.yefremov@gmail.com True True + 15 + 15 - 5 - 0 + 3 + 1 @@ -809,22 +833,25 @@ dmitry.v.yefremov@gmail.com - + True False + True - + True False Url: 7 7 - 1 + 0 + - False - True - 0 + 0 + 0 @@ -834,14 +861,13 @@ dmitry.v.yefremov@gmail.com gtk-edit - True - True - 1 + 0 + 1 - True + False True 2 @@ -859,7 +885,7 @@ dmitry.v.yefremov@gmail.com - + True False DVB/TS data: @@ -875,7 +901,7 @@ dmitry.v.yefremov@gmail.com - + True False 2 diff --git a/app/ui/dialogs.py b/app/ui/dialogs.py index 83420983..ec5bfe05 100644 --- a/app/ui/dialogs.py +++ b/app/ui/dialogs.py @@ -1,6 +1,7 @@ """ Common module for showing dialogs """ import locale from enum import Enum +from functools import lru_cache from app.commons import run_idle from . import Gtk, UI_RESOURCES_PATH, TEXT_DOMAIN @@ -56,7 +57,7 @@ def show_dialog(dialog_type: DialogType, transient, text=None, options=None, act path = path + "/" response = path - dialog.destroy() + dialog.hide() return response @@ -65,18 +66,19 @@ def show_dialog(dialog_type: DialogType, transient, text=None, options=None, act entry.set_text(text if text else "") response = dialog.run() txt = entry.get_text() - dialog.destroy() + dialog.hide() return txt if response == Gtk.ResponseType.OK else Gtk.ResponseType.CANCEL if text: dialog.set_markup(get_message(text)) response = dialog.run() - dialog.destroy() + dialog.hide() return response +@lru_cache(maxsize=10) def get_dialog_from_xml(dialog_type, transient): builder = Gtk.Builder() builder.set_translation_domain(TEXT_DOMAIN) diff --git a/app/ui/iptv.py b/app/ui/iptv.py index d4c83317..c70a22cf 100644 --- a/app/ui/iptv.py +++ b/app/ui/iptv.py @@ -11,6 +11,7 @@ class IptvDialog: self._dialog = dialog self._dialog.set_transient_for(transient) self._name_entry = builder.get_object("name_entry") + self._description_entry = builder.get_object("description_entry") self._url_entry = builder.get_object("url_entry") self._reference_entry = builder.get_object("reference_entry") self._srv_type_entry = builder.get_object("srv_type_entry") @@ -21,26 +22,55 @@ class IptvDialog: self._stream_type_combobox = builder.get_object("stream_type_combobox") self._add_button = builder.get_object("iptv_dialog_add_button") self._save_button = builder.get_object("iptv_dialog_save_button") + self._stream_type_combobox = builder.get_object("stream_type_combobox") self._action = action + self._profile = profile if self._action is Action.ADD: self._save_button.set_visible(False) self._add_button.set_visible(True) elif self._action is Action.EDIT: model, paths = view.get_selection().get_selected_rows() - model = get_base_model(model) - row = model[paths][:] - self._name_entry.set_text(row[2]) + self.init_data(get_base_model(model)[paths][:]) def show(self): response = self._dialog.run() if response == Gtk.ResponseType.OK: self.save() - self._dialog.destroy() + self._dialog.hide() def save(self): print(self._action) + def init_data(self, srv): + name, fav_id = srv[2], srv[7] + self._name_entry.set_text(name) + if self._profile is Profile.ENIGMA_2: + data, sep, desc = fav_id.partition("#DESCRIPTION:") + self._description_entry.set_text(desc.strip()) + data = data.split(":") + if len(data) < 12: + return + self._srv_type_entry.set_text(data[2]) + self._sid_entry.set_text(data[3]) + self._tr_id_entry.set_text(data[4]) + self._net_id_entry.set_text(data[5]) + self._namespace_entry.set_text(data[6]) + self._url_entry.set_text(data[10].replace("%3a", ":")) + self._update_reference_entry() + + def _update_reference_entry(self): + if self._profile is Profile.ENIGMA_2: + self._reference_entry.set_text("{}:0:{}:{}:{}:{}:{}:0:0:0".format(self.get_type(), + self._srv_type_entry.get_text(), + self._sid_entry.get_text(), + self._tr_id_entry.get_text(), + self._net_id_entry.get_text(), + self._namespace_entry.get_text())) + + def get_type(self): + return 1 + if __name__ == "__main__": pass From 47df44c202bf64d19651bf7e0e6bfea5a1c9e618 Mon Sep 17 00:00:00 2001 From: Dmitriy Yefremov Date: Tue, 13 Mar 2018 10:42:56 +0300 Subject: [PATCH 08/18] little optimisation --- app/eparser/satxml.py | 8 ++++++-- app/ui/dialogs.py | 12 ++++++------ app/ui/service_details_dialog.py | 4 +--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/eparser/satxml.py b/app/eparser/satxml.py index 27a8faed..8cc7145d 100644 --- a/app/eparser/satxml.py +++ b/app/eparser/satxml.py @@ -2,8 +2,11 @@ For more info see __COMMENT """ +from functools import lru_cache from xml.dom.minidom import parse, Document +import os + from .ecommons import POLARIZATION, FEC, SYSTEM, MODULATION, PLS_MODE, Transponder, Satellite, get_key_by_value __COMMENT = (" File was created in DemonEditor\n\n" @@ -29,7 +32,7 @@ __COMMENT = (" File was created in DemonEditor\n\n" def get_satellites(path): - return parse_satellites(path) + return parse_satellites(path, os.path.getsize(path)) def write_satellites(satellites, data_path): @@ -98,7 +101,8 @@ def parse_sat(elem): parse_transponders(elem)) -def parse_satellites(path): +@lru_cache(maxsize=1) +def parse_satellites(path, file_size): """ Parsing satellites from xml""" dom = parse(path) satellites = [] diff --git a/app/ui/dialogs.py b/app/ui/dialogs.py index ec5bfe05..e1349532 100644 --- a/app/ui/dialogs.py +++ b/app/ui/dialogs.py @@ -1,7 +1,6 @@ """ Common module for showing dialogs """ import locale from enum import Enum -from functools import lru_cache from app.commons import run_idle from . import Gtk, UI_RESOURCES_PATH, TEXT_DOMAIN @@ -57,7 +56,7 @@ def show_dialog(dialog_type: DialogType, transient, text=None, options=None, act path = path + "/" response = path - dialog.hide() + dialog.destroy() return response @@ -66,25 +65,25 @@ def show_dialog(dialog_type: DialogType, transient, text=None, options=None, act entry.set_text(text if text else "") response = dialog.run() txt = entry.get_text() - dialog.hide() + dialog.destroy() return txt if response == Gtk.ResponseType.OK else Gtk.ResponseType.CANCEL if text: dialog.set_markup(get_message(text)) response = dialog.run() - dialog.hide() + dialog.destroy() return response -@lru_cache(maxsize=10) def get_dialog_from_xml(dialog_type, transient): builder = Gtk.Builder() builder.set_translation_domain(TEXT_DOMAIN) - builder.add_from_file(UI_RESOURCES_PATH + "dialogs.glade") + builder.add_objects_from_file(UI_RESOURCES_PATH + "dialogs.glade", (dialog_type.value,)) dialog = builder.get_object(dialog_type.value) dialog.set_transient_for(transient) + return builder, dialog @@ -92,6 +91,7 @@ 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, diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index f864c373..ea0913ed 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -1,14 +1,13 @@ import re -from functools import lru_cache from app.commons import run_idle from app.eparser import Service, get_satellites from app.eparser.ecommons import MODULATION, Inversion, ROLL_OFF, Pilot, Flag, Pids, POLARIZATION, \ get_key_by_value, get_value_by_name, FEC_DEFAULT, PLS_MODE from app.properties import Profile +from . import Gtk, Gdk, UI_RESOURCES_PATH, HIDE_ICON, TEXT_DOMAIN from .dialogs import show_dialog, DialogType, Action from .main_helper import get_base_model -from . import Gtk, Gdk, UI_RESOURCES_PATH, HIDE_ICON, TEXT_DOMAIN class ServiceDetailsDialog: @@ -259,7 +258,6 @@ class ServiceDetailsDialog: model.append((pos,)) self.select_active_text(self._sat_pos_combo_box, sat_pos) - @lru_cache(maxsize=1) def get_sat_positions(self, path): try: return ["{:.1f}".format(float(x.position) / 10) for x in get_satellites(path)] From 791fa2b5f60e1add32b370adaafeb22f1f8ab492 Mon Sep 17 00:00:00 2001 From: Dmitriy Yefremov Date: Tue, 13 Mar 2018 23:27:55 +0300 Subject: [PATCH 09/18] init neutrino data skeleton for iptv dialog --- app/ui/dialogs.glade | 289 ++++++++++++++++++++------------------ app/ui/dialogs.py | 1 - app/ui/iptv.py | 100 +++++++++---- app/ui/main_app_window.py | 3 +- 4 files changed, 231 insertions(+), 162 deletions(-) diff --git a/app/ui/dialogs.glade b/app/ui/dialogs.glade index c38770d8..7cbeb76d 100644 --- a/app/ui/dialogs.glade +++ b/app/ui/dialogs.glade @@ -668,6 +668,7 @@ dmitry.v.yefremov@gmail.com True True True + True @@ -683,6 +684,7 @@ dmitry.v.yefremov@gmail.com True True True + True @@ -772,7 +774,7 @@ dmitry.v.yefremov@gmail.com - + True False Type: @@ -786,7 +788,6 @@ dmitry.v.yefremov@gmail.com True False - 5 stream_type_liststore 0 0 @@ -817,8 +818,7 @@ dmitry.v.yefremov@gmail.com True True - 15 - 15 + False 3 @@ -844,7 +844,7 @@ dmitry.v.yefremov@gmail.com Url: 7 7 - 0 + 0.0099999997764825821 @@ -873,160 +873,183 @@ dmitry.v.yefremov@gmail.com - + True False - - - False - True - 2 - 4 - - - - - True - False - DVB/TS data: - 0.0099999997764825821 - - - - False - True - 5 - - - - - True - False - 2 - 2 - True + vertical + 2 - + True False - Service type - 0 - 0 + False + True + 1 + 0 - + True False - SID + DVB/TS data: + 0.0099999997764825821 + - 1 - 0 + False + True + 1 - + True False - Tr. ID + 2 + 2 + True + + + True + False + Service type + + + 0 + 0 + + + + + True + False + SID + + + 1 + 0 + + + + + True + False + Tr. ID + + + 2 + 0 + + + + + True + False + Net. ID + + + 3 + 0 + + + + + True + False + Namespace + + + 4 + 0 + + + + + True + True + 10 + 10 + gtk-edit + + + + 0 + 1 + + + + + True + True + 10 + 10 + gtk-edit + + + + 1 + 1 + + + + + True + True + 10 + 10 + gtk-edit + + + + 2 + 1 + + + + + True + True + 10 + 10 + gtk-edit + + + + 3 + 1 + + + + + True + True + 10 + 10 + gtk-edit + + + + 4 + 1 + + - 2 - 0 - - - - - True - False - Net. ID - - - 3 - 0 - - - - - True - False - Namespace - - - 4 - 0 - - - - - True - True - 10 - 10 - - - 0 - 1 - - - - - True - True - 10 - 10 - - - 1 - 1 - - - - - True - True - 10 - 10 - - - 2 - 1 - - - - - True - True - 10 - 10 - - - 3 - 1 - - - - - True - True - 10 - 10 - - - 4 - 1 + False + True + 2 False True - 6 + 3 @@ -1052,8 +1075,6 @@ dmitry.v.yefremov@gmail.com iptv_dialog_cancel_button - iptv_dialog_add_button - iptv_dialog_save_button diff --git a/app/ui/dialogs.py b/app/ui/dialogs.py index e1349532..3eee74f5 100644 --- a/app/ui/dialogs.py +++ b/app/ui/dialogs.py @@ -18,7 +18,6 @@ class DialogType(Enum): QUESTION = "question_dialog" ABOUT = "about_dialog" WAIT = "wait_dialog" - IPTV = "iptv_dialog" class WaitDialog: diff --git a/app/ui/iptv.py b/app/ui/iptv.py index c70a22cf..b19c9f79 100644 --- a/app/ui/iptv.py +++ b/app/ui/iptv.py @@ -1,14 +1,21 @@ -from .main_helper import get_base_model -from . import Gtk +import re +from app.eparser.iptv import NEUTRINO_FAV_ID_FORMAT from app.properties import Profile -from .dialogs import get_dialog_from_xml, DialogType, Action +from . import Gtk, Gdk, TEXT_DOMAIN, UI_RESOURCES_PATH +from .dialogs import Action, show_dialog, DialogType +from .main_helper import get_base_model class IptvDialog: def __init__(self, transient, view=None, services=None, bouquets=None, profile=Profile.ENIGMA_2, action=Action.ADD): - builder, dialog = get_dialog_from_xml(DialogType.IPTV, transient) - self._dialog = dialog + handlers = {"on_entry_changed": self.on_entry_changed, "on_save": self.on_save} + builder = Gtk.Builder() + builder.set_translation_domain(TEXT_DOMAIN) + builder.add_objects_from_file(UI_RESOURCES_PATH + "dialogs.glade", ("iptv_dialog", "stream_type_liststore")) + builder.connect_signals(handlers) + + self._dialog = builder.get_object("iptv_dialog") self._dialog.set_transient_for(transient) self._name_entry = builder.get_object("name_entry") self._description_entry = builder.get_object("description_entry") @@ -25,39 +32,61 @@ class IptvDialog: self._stream_type_combobox = builder.get_object("stream_type_combobox") self._action = action self._profile = profile + self._model, self._paths = view.get_selection().get_selected_rows() + self._current_srv = get_base_model(self._model)[self._paths][:] + + self._pattern = re.compile("(?:^[\s]*$|\D)") + # style + self._style_provider = Gtk.CssProvider() + self._style_provider.load_from_path(UI_RESOURCES_PATH + "style.css") + for el in (self._srv_type_entry, self._sid_entry, self._tr_id_entry, self._net_id_entry, self._namespace_entry): + el.get_style_context().add_provider_for_screen(Gdk.Screen.get_default(), self._style_provider, + Gtk.STYLE_PROVIDER_PRIORITY_USER) + if profile is Profile.NEUTRINO_MP: + builder.get_object("iptv_data_box").set_visible(False) + builder.get_object("iptv_type_label").set_visible(False) + self._stream_type_combobox.set_visible(False) if self._action is Action.ADD: self._save_button.set_visible(False) self._add_button.set_visible(True) elif self._action is Action.EDIT: - model, paths = view.get_selection().get_selected_rows() - self.init_data(get_base_model(model)[paths][:]) + self.init_data(self._current_srv) def show(self): - response = self._dialog.run() - if response == Gtk.ResponseType.OK: - self.save() - self._dialog.hide() + self._dialog.run() + self._dialog.destroy() - def save(self): - print(self._action) + def on_save(self, item): + if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL: + return + + self.save_enigma2_data()if self._profile is Profile.ENIGMA_2 else self.save_neutrino_data() + self._dialog.destroy() def init_data(self, srv): name, fav_id = srv[2], srv[7] self._name_entry.set_text(name) - if self._profile is Profile.ENIGMA_2: - data, sep, desc = fav_id.partition("#DESCRIPTION:") - self._description_entry.set_text(desc.strip()) - data = data.split(":") - if len(data) < 12: - return - self._srv_type_entry.set_text(data[2]) - self._sid_entry.set_text(data[3]) - self._tr_id_entry.set_text(data[4]) - self._net_id_entry.set_text(data[5]) - self._namespace_entry.set_text(data[6]) - self._url_entry.set_text(data[10].replace("%3a", ":")) - self._update_reference_entry() + self.init_enigma2_data(fav_id) if self._profile is Profile.ENIGMA_2 else self.init_neutrino_data(fav_id) + + def init_enigma2_data(self, fav_id): + data, sep, desc = fav_id.partition("#DESCRIPTION:") + self._description_entry.set_text(desc.strip()) + data = data.split(":") + if len(data) < 12: + return + self._srv_type_entry.set_text(data[2]) + self._sid_entry.set_text(data[3]) + self._tr_id_entry.set_text(data[4]) + self._net_id_entry.set_text(data[5]) + self._namespace_entry.set_text(data[6]) + self._url_entry.set_text(data[10].replace("%3a", ":")) + self._update_reference_entry() + + def init_neutrino_data(self, fav_id): + data = fav_id.split("::") + self._url_entry.set_text(data[0]) + self._description_entry.set_text(data[1]) def _update_reference_entry(self): if self._profile is Profile.ENIGMA_2: @@ -71,6 +100,25 @@ class IptvDialog: def get_type(self): return 1 + def on_entry_changed(self, entry): + if self._pattern.search(entry.get_text()): + entry.set_name("digit-entry") + else: + entry.set_name("GtkEntry") + self._update_reference_entry() + + def save_enigma2_data(self): + pass + + def save_neutrino_data(self): + name = self._name_entry.get_text() + if self._action is Action.EDIT: + id_data = self._current_srv[7].split("::") + id_data[0] = self._url_entry.get_text() + id_data[1] = self._description_entry.get_text() + fav_id = NEUTRINO_FAV_ID_FORMAT.format(*id_data) + self._model.set_value(self._model.get_iter(self._paths), 2, name) + if __name__ == "__main__": pass diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index 8538bf2c..e315e313 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -864,7 +864,8 @@ class MainAppWindow: self.update_bouquet_channels(self.__fav_model, None, bq_selected) def on_iptv(self, item): - IptvDialog(self.__main_window).show() + pass + # IptvDialog(self.__main_window).show() def on_insert_marker(self, view): """ Inserts marker into bouquet services list. """ From 72ebdceb6eaa40db930f19f7c0ea3c55b5bb82fb Mon Sep 17 00:00:00 2001 From: DYefremov Date: Thu, 15 Mar 2018 23:10:22 +0300 Subject: [PATCH 10/18] edit impl for iptv --- app/ui/dialogs.glade | 41 ++++++++++++++------------ app/ui/iptv.py | 49 +++++++++++++++++++++++++------- app/ui/main_app_window.py | 2 +- app/ui/main_helper.py | 8 +++--- app/ui/service_details_dialog.py | 1 + 5 files changed, 67 insertions(+), 34 deletions(-) diff --git a/app/ui/dialogs.glade b/app/ui/dialogs.glade index 7cbeb76d..0acba720 100644 --- a/app/ui/dialogs.glade +++ b/app/ui/dialogs.glade @@ -731,7 +731,7 @@ dmitry.v.yefremov@gmail.com True False - Name: + Name 7 7 @@ -742,8 +742,10 @@ dmitry.v.yefremov@gmail.com + -1 True True + True gtk-edit @@ -752,10 +754,10 @@ dmitry.v.yefremov@gmail.com - + True False - Description: + Description 1 @@ -766,6 +768,7 @@ dmitry.v.yefremov@gmail.com True True + True gtk-edit @@ -777,7 +780,7 @@ dmitry.v.yefremov@gmail.com True False - Type: + Stream type 2 @@ -791,6 +794,7 @@ dmitry.v.yefremov@gmail.com stream_type_liststore 0 0 + @@ -804,10 +808,10 @@ dmitry.v.yefremov@gmail.com - + True False - Reference: + Reference 3 @@ -818,6 +822,7 @@ dmitry.v.yefremov@gmail.com True True + True False @@ -827,7 +832,7 @@ dmitry.v.yefremov@gmail.com - False + True True 1 @@ -917,7 +922,7 @@ dmitry.v.yefremov@gmail.com True False - Service type + Type 0 @@ -972,8 +977,8 @@ dmitry.v.yefremov@gmail.com True True - 10 - 10 + 5 + 5 gtk-edit @@ -986,8 +991,8 @@ dmitry.v.yefremov@gmail.com True True - 10 - 10 + 5 + 5 gtk-edit @@ -1000,8 +1005,8 @@ dmitry.v.yefremov@gmail.com True True - 10 - 10 + 5 + 5 gtk-edit @@ -1014,8 +1019,8 @@ dmitry.v.yefremov@gmail.com True True - 10 - 10 + 5 + 5 gtk-edit @@ -1028,8 +1033,8 @@ dmitry.v.yefremov@gmail.com True True - 10 - 10 + 5 + 5 gtk-edit diff --git a/app/ui/iptv.py b/app/ui/iptv.py index b19c9f79..cbb7262a 100644 --- a/app/ui/iptv.py +++ b/app/ui/iptv.py @@ -1,6 +1,6 @@ import re -from app.eparser.iptv import NEUTRINO_FAV_ID_FORMAT +from app.eparser.iptv import NEUTRINO_FAV_ID_FORMAT, StreamType, ENIGMA2_FAV_ID_FORMAT from app.properties import Profile from . import Gtk, Gdk, TEXT_DOMAIN, UI_RESOURCES_PATH from .dialogs import Action, show_dialog, DialogType @@ -8,8 +8,11 @@ from .main_helper import get_base_model class IptvDialog: - def __init__(self, transient, view=None, services=None, bouquets=None, profile=Profile.ENIGMA_2, action=Action.ADD): - handlers = {"on_entry_changed": self.on_entry_changed, "on_save": self.on_save} + def __init__(self, transient, view, services, bouquet, profile=Profile.ENIGMA_2, action=Action.ADD): + handlers = {"on_entry_changed": self.on_entry_changed, + "on_save": self.on_save, + "on_stream_type_changed": self.on_stream_type_changed} + builder = Gtk.Builder() builder.set_translation_domain(TEXT_DOMAIN) builder.add_objects_from_file(UI_RESOURCES_PATH + "dialogs.glade", ("iptv_dialog", "stream_type_liststore")) @@ -32,6 +35,8 @@ class IptvDialog: self._stream_type_combobox = builder.get_object("stream_type_combobox") self._action = action self._profile = profile + self._bouquet = bouquet + self._services = services self._model, self._paths = view.get_selection().get_selected_rows() self._current_srv = get_base_model(self._model)[self._paths][:] @@ -45,7 +50,12 @@ class IptvDialog: if profile is Profile.NEUTRINO_MP: builder.get_object("iptv_data_box").set_visible(False) builder.get_object("iptv_type_label").set_visible(False) + builder.get_object("reference_entry").set_visible(False) + builder.get_object("iptv_reference_label").set_visible(False) self._stream_type_combobox.set_visible(False) + else: + self._description_entry.set_visible(False) + builder.get_object("iptv_description_label").set_visible(False) if self._action is Action.ADD: self._save_button.set_visible(False) @@ -61,7 +71,7 @@ class IptvDialog: if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL: return - self.save_enigma2_data()if self._profile is Profile.ENIGMA_2 else self.save_neutrino_data() + self.save_enigma2_data() if self._profile is Profile.ENIGMA_2 else self.save_neutrino_data() self._dialog.destroy() def init_data(self, srv): @@ -75,6 +85,7 @@ class IptvDialog: data = data.split(":") if len(data) < 12: return + self._stream_type_combobox.set_active(0 if StreamType(data[0].strip()) is StreamType.DVB_TS else 1) self._srv_type_entry.set_text(data[2]) self._sid_entry.set_text(data[3]) self._tr_id_entry.set_text(data[4]) @@ -98,7 +109,7 @@ class IptvDialog: self._namespace_entry.get_text())) def get_type(self): - return 1 + return 1 if self._stream_type_combobox.get_active() == 0 else 4097 def on_entry_changed(self, entry): if self._pattern.search(entry.get_text()): @@ -107,16 +118,32 @@ class IptvDialog: entry.set_name("GtkEntry") self._update_reference_entry() + def on_stream_type_changed(self, item): + self._update_reference_entry() + def save_enigma2_data(self): - pass + name = self._name_entry.get_text().strip() + fav_id = ENIGMA2_FAV_ID_FORMAT.format(self.get_type(), + self._srv_type_entry.get_text(), + self._sid_entry.get_text(), + self._tr_id_entry.get_text(), + self._net_id_entry.get_text(), + self._namespace_entry.get_text(), + self._url_entry.get_text().replace(":", "%3a"), + name, name) + self.update_bouquet_data(name, fav_id) def save_neutrino_data(self): - name = self._name_entry.get_text() + id_data = self._current_srv[7].split("::") + id_data[0] = self._url_entry.get_text() + id_data[1] = self._description_entry.get_text() + self.update_bouquet_data(self._name_entry.get_text(), NEUTRINO_FAV_ID_FORMAT.format(*id_data)) + + def update_bouquet_data(self, name, fav_id): if self._action is Action.EDIT: - id_data = self._current_srv[7].split("::") - id_data[0] = self._url_entry.get_text() - id_data[1] = self._description_entry.get_text() - fav_id = NEUTRINO_FAV_ID_FORMAT.format(*id_data) + old_srv = self._services.pop(self._current_srv[7]) + self._services[fav_id] = old_srv._replace(service=name, fav_id=fav_id) + self._bouquet[self._paths[0][0]] = fav_id self._model.set_value(self._model.get_iter(self._paths), 2, name) diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index e315e313..0d08d54e 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -936,7 +936,7 @@ class MainAppWindow: return IptvDialog(self.__main_window, self.__fav_view, self.__services, - self.__bouquets, + self.__bouquets.get(self.is_bouquet_selected(), None), Profile(self.__profile), Action.EDIT).show() self.on_locate_in_services(view) diff --git a/app/ui/main_helper.py b/app/ui/main_helper.py index ae9fa068..4cf8a99a 100644 --- a/app/ui/main_helper.py +++ b/app/ui/main_helper.py @@ -59,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:17], old_ch.data_id, new_fav_id, None) + channels[new_fav_id] = old_ch._replace(service=response, fav_id=new_fav_id) bq_services.pop(index) bq_services.insert(index, new_fav_id) @@ -143,7 +143,7 @@ def rename(view, parent_window, target, fav_view=None, service_view=None, channe old_ch = channels.get(f_id, None) if old_ch: - channels[f_id] = Service(*old_ch[0:3], channel_name, *old_ch[4:]) + channels[f_id] = old_ch._replace(service=channel_name) # ***************** Flags *******************# @@ -196,7 +196,7 @@ def set_lock(blacklist, channels, model, paths, target, services_model): 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:]) + channels[fav_id] = channel._replace(locked=None if locked else LOCKED_ICON) ids.append(fav_id) if target is ViewTarget.FAV and ids: @@ -244,7 +244,7 @@ def set_hide(channels, model, paths): 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:]) + channels[fav_id] = channel._replace(hide=None if hide else HIDE_ICON) def has_locked_hide(model, paths, col_num): diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index ea0913ed..6dd55b4a 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -409,6 +409,7 @@ class ServiceDetailsDialog: return self._old_service.fav_id, self._old_service.data_id def get_fav_id(self): + """ TODO Needs implementation!!! """ if self._profile is Profile.ENIGMA_2: return self._old_service.fav_id elif self._profile is Profile.NEUTRINO_MP: From 1531548e510b2b946fc35ba30aa61352f841db27 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Fri, 16 Mar 2018 00:10:33 +0300 Subject: [PATCH 11/18] add impl for iptv --- app/ui/dialogs.glade | 5 +++++ app/ui/iptv.py | 25 ++++++++++++++++++++----- app/ui/main_app_window.py | 10 ++++++++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/app/ui/dialogs.glade b/app/ui/dialogs.glade index 0acba720..eb772d09 100644 --- a/app/ui/dialogs.glade +++ b/app/ui/dialogs.glade @@ -979,6 +979,7 @@ dmitry.v.yefremov@gmail.com True 5 5 + 1 gtk-edit @@ -993,6 +994,7 @@ dmitry.v.yefremov@gmail.com True 5 5 + 0 gtk-edit @@ -1007,6 +1009,7 @@ dmitry.v.yefremov@gmail.com True 5 5 + 0 gtk-edit @@ -1021,6 +1024,7 @@ dmitry.v.yefremov@gmail.com True 5 5 + 0 gtk-edit @@ -1035,6 +1039,7 @@ dmitry.v.yefremov@gmail.com True 5 5 + 0 gtk-edit diff --git a/app/ui/iptv.py b/app/ui/iptv.py index cbb7262a..75a9e11c 100644 --- a/app/ui/iptv.py +++ b/app/ui/iptv.py @@ -1,8 +1,9 @@ import re +from app.eparser.ecommons import BqServiceType, Service from app.eparser.iptv import NEUTRINO_FAV_ID_FORMAT, StreamType, ENIGMA2_FAV_ID_FORMAT from app.properties import Profile -from . import Gtk, Gdk, TEXT_DOMAIN, UI_RESOURCES_PATH +from . import Gtk, Gdk, TEXT_DOMAIN, UI_RESOURCES_PATH, IPTV_ICON from .dialogs import Action, show_dialog, DialogType from .main_helper import get_base_model @@ -38,9 +39,8 @@ class IptvDialog: self._bouquet = bouquet self._services = services self._model, self._paths = view.get_selection().get_selected_rows() - self._current_srv = get_base_model(self._model)[self._paths][:] - self._pattern = re.compile("(?:^[\s]*$|\D)") + self._PATTERN = re.compile("(?:^[\s]*$|\D)") # style self._style_provider = Gtk.CssProvider() self._style_provider.load_from_path(UI_RESOURCES_PATH + "style.css") @@ -60,7 +60,10 @@ class IptvDialog: if self._action is Action.ADD: self._save_button.set_visible(False) self._add_button.set_visible(True) + if self._profile is Profile.ENIGMA_2: + self._update_reference_entry() elif self._action is Action.EDIT: + self._current_srv = get_base_model(self._model)[self._paths][:] self.init_data(self._current_srv) def show(self): @@ -112,7 +115,7 @@ class IptvDialog: return 1 if self._stream_type_combobox.get_active() == 0 else 4097 def on_entry_changed(self, entry): - if self._pattern.search(entry.get_text()): + if self._PATTERN.search(entry.get_text()): entry.set_name("digit-entry") else: entry.set_name("GtkEntry") @@ -134,7 +137,10 @@ class IptvDialog: self.update_bouquet_data(name, fav_id) def save_neutrino_data(self): - id_data = self._current_srv[7].split("::") + if self._action is Action.EDIT: + id_data = self._current_srv[7].split("::") + else: + id_data = ["", "", "0", None, None, None, None, "", "", "1"] id_data[0] = self._url_entry.get_text() id_data[1] = self._description_entry.get_text() self.update_bouquet_data(self._name_entry.get_text(), NEUTRINO_FAV_ID_FORMAT.format(*id_data)) @@ -145,6 +151,15 @@ class IptvDialog: self._services[fav_id] = old_srv._replace(service=name, fav_id=fav_id) self._bouquet[self._paths[0][0]] = fav_id self._model.set_value(self._model.get_iter(self._paths), 2, name) + else: + aggr = [None] * 10 + s_type = BqServiceType.IPTV.name + srv = (None, None, name, None, None, s_type, None, fav_id, None) + itr = self._model.insert_after(self._model.get_iter(self._paths[0]), + srv) if self._paths else self._model.insert(0, srv) + self._model.set_value(itr, 1, IPTV_ICON) + self._bouquet.insert(self._model.get_path(itr)[0], fav_id) + self._services[fav_id] = Service(None, None, IPTV_ICON, name, *aggr[0:3], s_type, *aggr, fav_id, None) if __name__ == "__main__": diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index 0d08d54e..0323a0d4 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -864,8 +864,14 @@ class MainAppWindow: self.update_bouquet_channels(self.__fav_model, None, bq_selected) def on_iptv(self, item): - pass - # IptvDialog(self.__main_window).show() + response = IptvDialog(self.__main_window, + self.__fav_view, + self.__services, + self.__bouquets.get(self.is_bouquet_selected(), None), + Profile(self.__profile), + Action.ADD).show() + if response != Gtk.ResponseType.CANCEL: + self.update_fav_num_column(self.__fav_model) def on_insert_marker(self, view): """ Inserts marker into bouquet services list. """ From c120f42ee14395d5abb4473f8de90f94dc6a38c9 Mon Sep 17 00:00:00 2001 From: Dmitriy Yefremov Date: Sat, 17 Mar 2018 22:18:10 +0300 Subject: [PATCH 12/18] skeleton of getting transponder data for neutrino --- app/ui/iptv.py | 3 ++- app/ui/service_details_dialog.py | 37 ++++++++++++++++---------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/app/ui/iptv.py b/app/ui/iptv.py index 75a9e11c..3e9fafa1 100644 --- a/app/ui/iptv.py +++ b/app/ui/iptv.py @@ -144,13 +144,14 @@ class IptvDialog: id_data[0] = self._url_entry.get_text() id_data[1] = self._description_entry.get_text() self.update_bouquet_data(self._name_entry.get_text(), NEUTRINO_FAV_ID_FORMAT.format(*id_data)) + self._dialog.destroy() def update_bouquet_data(self, name, fav_id): if self._action is Action.EDIT: old_srv = self._services.pop(self._current_srv[7]) self._services[fav_id] = old_srv._replace(service=name, fav_id=fav_id) self._bouquet[self._paths[0][0]] = fav_id - self._model.set_value(self._model.get_iter(self._paths), 2, name) + self._model.set(self._model.get_iter(self._paths), {2: name, 7: fav_id}) else: aggr = [None] * 10 s_type = BqServiceType.IPTV.name diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 6dd55b4a..0320d317 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -11,11 +11,15 @@ from .main_helper import get_base_model class ServiceDetailsDialog: - _DATA_ID = "{:04x}:{:08x}:{:04x}:{:04x}:{}:{}" + _ENIGMA2_DATA_ID = "{:04x}:{:08x}:{:04x}:{:04x}:{}:{}" - _FAV_ID = "{:X}:{:X}:{:X}:{:X}" + _ENIGMA2_FAV_ID = "{:X}:{:X}:{:X}:{:X}" - _TRANSPONDER_DATA = "{} {}:{}:{}:{}:{}:{}:{}" + _ENIGMA2_TRANSPONDER_DATA = "{} {}:{}:{}:{}:{}:{}:{}" + + _NEUTRINO_FAV_ID = "{:x}:{:x}:{:x}" + + _NEUTRINO_TRANSPONDER_DATA = "{:04x}:{:04x}:{}:{}:{}:{}:{}:{}:{}" _DIGIT_ENTRY_ELEMENTS = ("sid_entry", "bitstream_entry", "pcm_entry", "video_pid_entry", "pcr_pid_entry", "audio_pid_entry", "ac3_pid_entry", "ac3plus_pid_entry", "acc_pid_entry", "freq_entry", @@ -238,6 +242,7 @@ class ServiceDetailsDialog: self._reference_entry.set_text(srv.picon_id.rstrip(".png")) self._transponder_id_entry.set_text(str(int(tr_data[0], 16))) self._network_id_entry.set_text(str(int(tr_data[1], 16))) + self.select_active_text(self._invertion_combo_box, Inversion(tr_data[3]).name) def init_enigma_ui_elements(self): self._pids_grid.set_sensitive(False) @@ -396,24 +401,17 @@ class ServiceDetailsDialog: def get_srv_data(self): ssid = int(self._sid_entry.get_text()) - namespace = int(self._namespace_entry.get_text()) - transponder_id = int(self._transponder_id_entry.get_text()) - network_id = int(self._network_id_entry.get_text()) + net_id, tr_id = int(self._network_id_entry.get_text()), int(self._transponder_id_entry.get_text()) service_type = self._srv_type_entry.get_text() if self._profile is Profile.ENIGMA_2: - data_id = self._DATA_ID.format(ssid, namespace, transponder_id, network_id, service_type, 0) - fav_id = self._FAV_ID.format(ssid, transponder_id, network_id, namespace) + namespace = int(self._namespace_entry.get_text()) + data_id = self._ENIGMA2_DATA_ID.format(ssid, namespace, tr_id, net_id, service_type, 0) + fav_id = self._ENIGMA2_FAV_ID.format(ssid, tr_id, net_id, namespace) return fav_id, data_id elif self._profile is Profile.NEUTRINO_MP: - return self._old_service.fav_id, self._old_service.data_id - - def get_fav_id(self): - """ TODO Needs implementation!!! """ - if self._profile is Profile.ENIGMA_2: - return self._old_service.fav_id - elif self._profile is Profile.NEUTRINO_MP: - return self._old_service.fav_id + fav_id = self._NEUTRINO_FAV_ID.format(tr_id, net_id, ssid) + return fav_id, self._old_service.data_id def get_transponder_data(self): sys = self._sys_combo_box.get_active_id() @@ -426,7 +424,7 @@ class ServiceDetailsDialog: srv_sys = "0" # !!! if self._profile is Profile.ENIGMA_2: - dvb_s_tr = self._TRANSPONDER_DATA.format("s", freq, rate, pol, fec, sat_pos, inv, srv_sys) + dvb_s_tr = self._ENIGMA2_TRANSPONDER_DATA.format("s", freq, rate, pol, fec, sat_pos, inv, srv_sys) if sys == "DVB-S": return dvb_s_tr if sys == "DVB-S2": @@ -440,7 +438,10 @@ class ServiceDetailsDialog: pls = ":{}:{}:{}".format(st_id, pls_code, pls_mode) if pls_mode and pls_code and st_id else "" return "{}:{}:{}:{}:{}{}".format(dvb_s_tr, flag, mod, roll_off, pilot, pls) elif self._profile is Profile.NEUTRINO_MP: - return self._old_service.transponder + on_id, tr_id = int(self._network_id_entry.get_text()), int(self._transponder_id_entry.get_text()) + mod = self.get_value_from_combobox_id(self._mod_combo_box, MODULATION) if sys == "DVB-S2" else None + srv_sys = None + return self._NEUTRINO_TRANSPONDER_DATA.format(tr_id, on_id, freq, inv, rate, fec, pol, mod, srv_sys) # ***************** Others *********************# From e37abef359f58b50eb5c0bf3b491c03f5c86db6f Mon Sep 17 00:00:00 2001 From: DYefremov Date: Sun, 18 Mar 2018 17:13:21 +0300 Subject: [PATCH 13/18] decoupling for [on save] in service dialog --- app/ui/service_details_dialog.py | 97 +++++++++++++++++++------------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 0320d317..7112bb15 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -27,6 +27,8 @@ class ServiceDetailsDialog: "rate_entry", "pls_code_entry", "stream_id_entry", "tr_flag_entry", "namespace_entry", "srv_type_entry") + _DIGIT_ENTRY_NAME = "digit-entry" + def __init__(self, transient, options, view, services, bouquets, action=Action.EDIT): handlers = {"on_system_changed": self.on_system_changed, "on_save": self.on_save, @@ -284,55 +286,22 @@ class ServiceDetailsDialog: # ***************** Save data *********************# def on_save(self, item): + if not self.is_data_correct(): + show_dialog(DialogType.ERROR, self._dialog, "Error. Verify the data!") + return + if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL: return fav_id, data_id = self.get_srv_data() # transponder transponder = self._old_service.transponder - freq = self._freq_entry.get_text() - rate = self._rate_entry.get_text() - pol = self._pol_combo_box.get_active_id() - fec = self._fec_combo_box.get_active_id() - system = self._sys_combo_box.get_active_id() - pos = self._sat_pos_combo_box.get_active_id() - if self._tr_edit_switch.get_active(): transponder = self.get_transponder_data() if self._transponder_services_iters: - for itr in self._transponder_services_iters: - srv = self._current_model[itr][:] - srv[-9] = freq - srv[-8] = rate - srv[-7] = pol - srv[-6] = fec - srv[-5] = system - srv[-4] = pos - srv[-1] = transponder - srv = Service(*srv) - self._services[srv.fav_id] = srv - self._current_model.set(itr, {i: v for i, v in enumerate(srv)}) + self.update_transponder_services(transponder) - service = Service(flags_cas=self.get_flags(), - transponder_type="s", - coded=self._old_service.coded, - service=self._name_entry.get_text(), - locked=self._old_service.locked, - hide=HIDE_ICON if self._hide_check_button.get_active() else None, - package=self._package_entry.get_text(), - service_type=self._service_type_combo_box.get_active_id(), - picon=self._old_service.picon, - picon_id=self._old_service.picon_id, - ssid="{:x}".format(int(self._sid_entry.get_text())), - freq=freq, - rate=rate, - pol=pol, - fec=fec, - system=system, - pos=pos, - data_id=data_id, - fav_id=fav_id, - transponder=transponder) + service = self.get_service(fav_id, data_id, transponder) old_fav_id = self._old_service.fav_id if old_fav_id != fav_id: @@ -349,12 +318,44 @@ class ServiceDetailsDialog: self._current_model.set(self._current_itr, {i: v for i, v in enumerate(service)}) self._old_service = service + def update_transponder_services(self, transponder): + for itr in self._transponder_services_iters: + srv = self._current_model[itr][:] + srv[-9], srv[-8], srv[-7], srv[-6], srv[-5], srv[-4] = self.get_transponder_values() + srv[-1] = transponder + srv = Service(*srv) + self._services[srv.fav_id] = self._services.pop(srv.fav_id)._replace(transponder=transponder) + self._current_model.set(itr, {i: v for i, v in enumerate(srv)}) + def on_create_new(self, item): if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL: return show_dialog(DialogType.ERROR, transient=self._dialog, text="Not implemented yet!") + def get_service(self, fav_id, data_id, transponder): + freq, rate, pol, fec, system, pos = self.get_transponder_values() + return Service(flags_cas=self.get_flags(), + transponder_type="s", + coded=self._old_service.coded, + service=self._name_entry.get_text(), + locked=self._old_service.locked, + hide=HIDE_ICON if self._hide_check_button.get_active() else None, + package=self._package_entry.get_text(), + service_type=self._service_type_combo_box.get_active_id(), + picon=self._old_service.picon, + picon_id=self._old_service.picon_id, + ssid="{:x}".format(int(self._sid_entry.get_text())), + freq=freq, + rate=rate, + pol=pol, + fec=fec, + system=system, + pos=pos, + data_id=data_id, + fav_id=fav_id, + transponder=transponder) + def get_flags(self): if self._profile is Profile.ENIGMA_2: return self.get_enigma2_flags() @@ -413,6 +414,16 @@ class ServiceDetailsDialog: fav_id = self._NEUTRINO_FAV_ID.format(tr_id, net_id, ssid) return fav_id, self._old_service.data_id + def get_transponder_values(self): + freq = self._freq_entry.get_text() + rate = self._rate_entry.get_text() + pol = self._pol_combo_box.get_active_id() + fec = self._fec_combo_box.get_active_id() + system = self._sys_combo_box.get_active_id() + pos = self._sat_pos_combo_box.get_active_id() + + return freq, rate, pol, fec, system, pos + def get_transponder_data(self): sys = self._sys_combo_box.get_active_id() freq = self._freq_entry.get_text() @@ -453,7 +464,7 @@ class ServiceDetailsDialog: break def on_digit_entry_changed(self, entry): - entry.set_name("digit-entry" if self._pattern.search(entry.get_text()) else "GtkEntry") + entry.set_name(self._DIGIT_ENTRY_NAME if self._pattern.search(entry.get_text()) else "GtkEntry") def get_value_from_combobox_id(self, box: Gtk.ComboBox, dc: dict): cb_id = box.get_active_id() @@ -478,6 +489,12 @@ class ServiceDetailsDialog: for elem in self._TRANSPONDER_ELEMENTS: elem.set_sensitive(active) + def is_data_correct(self): + for elem in self._digit_elements.values(): + if elem.get_name() == self._DIGIT_ENTRY_NAME: + return False + return True + class TransponderServicesDialog: def __init__(self, transient, model, transponder, tr_iters): From 1eeccd654af4832fc5764a59b2f38df9225a1690 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Sun, 18 Mar 2018 18:11:16 +0300 Subject: [PATCH 14/18] added validation for non empty entries in service dialog --- app/ui/service_details_dialog.glade | 10 ++-- app/ui/service_details_dialog.py | 79 ++++++++++++++++++----------- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/app/ui/service_details_dialog.glade b/app/ui/service_details_dialog.glade index 63e9ec36..f0730ae2 100644 --- a/app/ui/service_details_dialog.glade +++ b/app/ui/service_details_dialog.glade @@ -372,7 +372,7 @@ 10 10 gtk-edit - + 2 @@ -997,7 +997,7 @@ 12 12 gtk-edit - + 1 @@ -1023,7 +1023,7 @@ 12 12 gtk-edit - + 2 @@ -1232,7 +1232,7 @@ 8 10 gtk-edit - + 0 @@ -1258,7 +1258,7 @@ 8 10 gtk-edit - + 1 diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 7112bb15..34c8368d 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -21,11 +21,11 @@ class ServiceDetailsDialog: _NEUTRINO_TRANSPONDER_DATA = "{:04x}:{:04x}:{}:{}:{}:{}:{}:{}:{}" - _DIGIT_ENTRY_ELEMENTS = ("sid_entry", "bitstream_entry", "pcm_entry", "video_pid_entry", "pcr_pid_entry", - "audio_pid_entry", "ac3_pid_entry", "ac3plus_pid_entry", "acc_pid_entry", "freq_entry", - "he_acc_pid_entry", "teletext_pid_entry", "transponder_id_entry", "network_id_entry", - "rate_entry", "pls_code_entry", "stream_id_entry", "tr_flag_entry", "namespace_entry", - "srv_type_entry") + _DIGIT_ENTRY_ELEMENTS = ("bitstream_entry", "pcm_entry", "video_pid_entry", "pcr_pid_entry", "srv_type_entry", + "ac3_pid_entry", "ac3plus_pid_entry", "acc_pid_entry", "he_acc_pid_entry", + "teletext_pid_entry", "pls_code_entry", "stream_id_entry", "tr_flag_entry", + "audio_pid_entry", "namespace_entry") + _NOT_EMPTY_DIGIT_ELEMENTS = ("sid_entry", "freq_entry", "rate_entry", "transponder_id_entry", "network_id_entry") _DIGIT_ENTRY_NAME = "digit-entry" @@ -34,7 +34,8 @@ class ServiceDetailsDialog: "on_save": self.on_save, "on_create_new": self.on_create_new, "on_digit_entry_changed": self.on_digit_entry_changed, - "on_tr_edit_toggled": self.on_tr_edit_toggled} + "on_tr_edit_toggled": self.on_tr_edit_toggled, + "on_non_empty_entry_changed": self.on_non_empty_entry_changed} builder = Gtk.Builder() builder.set_translation_domain(TEXT_DOMAIN) @@ -53,18 +54,24 @@ class ServiceDetailsDialog: self._transponder_services_iters = None self._current_model = None self._current_itr = None - self._pattern = re.compile("\D") + self._DIGIT_PATTERN = re.compile("\D") + self._NON_EMPTY_PATTERN = re.compile("(?:^[\s]*$|\D)") self._apply_button = builder.get_object("apply_button") self._create_button = builder.get_object("create_button") # style self._style_provider = Gtk.CssProvider() self._style_provider.load_from_path(UI_RESOURCES_PATH + "style.css") - # initialize only digit elements + # initialization only digit elements self._digit_elements = {k: builder.get_object(k) for k in self._DIGIT_ENTRY_ELEMENTS} for elem in self._digit_elements.values(): elem.get_style_context().add_provider_for_screen(Gdk.Screen.get_default(), self._style_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER) - self._sid_entry = self._digit_elements.get("sid_entry") + # initialization of non empty elements + self._non_empty_elements = {k: builder.get_object(k) for k in self._NOT_EMPTY_DIGIT_ELEMENTS} + for elem in self._non_empty_elements.values(): + elem.get_style_context().add_provider_for_screen(Gdk.Screen.get_default(), self._style_provider, + Gtk.STYLE_PROVIDER_PRIORITY_USER) + self._sid_entry = self._non_empty_elements.get("sid_entry") self._bitstream_entry = self._digit_elements.get("bitstream_entry") self._pcm_entry = self._digit_elements.get("pcm_entry") self._video_pid_entry = self._digit_elements.get("video_pid_entry") @@ -75,10 +82,10 @@ class ServiceDetailsDialog: self._acc_pid_entry = self._digit_elements.get("acc_pid_entry") self._he_acc_pid_entry = self._digit_elements.get("he_acc_pid_entry") self._teletext_pid_entry = self._digit_elements.get("teletext_pid_entry") - self._transponder_id_entry = self._digit_elements.get("transponder_id_entry") - self._network_id_entry = self._digit_elements.get("network_id_entry") - self._freq_entry = self._digit_elements.get("freq_entry") - self._rate_entry = self._digit_elements.get("rate_entry") + self._transponder_id_entry = self._non_empty_elements.get("transponder_id_entry") + self._network_id_entry = self._non_empty_elements.get("network_id_entry") + self._freq_entry = self._non_empty_elements.get("freq_entry") + self._rate_entry = self._non_empty_elements.get("rate_entry") self._pls_code_entry = self._digit_elements.get("pls_code_entry") self._stream_id_entry = self._digit_elements.get("stream_id_entry") self._tr_flag_entry = self._digit_elements.get("tr_flag_entry") @@ -286,6 +293,12 @@ class ServiceDetailsDialog: # ***************** Save data *********************# def on_save(self, item): + self.save_data() + + def on_create_new(self, item): + self.save_data() + + def save_data(self): if not self.is_data_correct(): show_dialog(DialogType.ERROR, self._dialog, "Error. Verify the data!") return @@ -293,6 +306,10 @@ class ServiceDetailsDialog: if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL: return + self.on_edit() if self._action is Action.EDIT else self.on_new() + self._dialog.destroy() + + def on_edit(self): fav_id, data_id = self.get_srv_data() # transponder transponder = self._old_service.transponder @@ -300,9 +317,7 @@ class ServiceDetailsDialog: transponder = self.get_transponder_data() if self._transponder_services_iters: self.update_transponder_services(transponder) - service = self.get_service(fav_id, data_id, transponder) - old_fav_id = self._old_service.fav_id if old_fav_id != fav_id: self._services.pop(old_fav_id, None) @@ -313,24 +328,13 @@ class ServiceDetailsDialog: indexes.append(i) for i in indexes: bq[i] = fav_id - self._services[fav_id] = service self._current_model.set(self._current_itr, {i: v for i, v in enumerate(service)}) self._old_service = service - def update_transponder_services(self, transponder): - for itr in self._transponder_services_iters: - srv = self._current_model[itr][:] - srv[-9], srv[-8], srv[-7], srv[-6], srv[-5], srv[-4] = self.get_transponder_values() - srv[-1] = transponder - srv = Service(*srv) - self._services[srv.fav_id] = self._services.pop(srv.fav_id)._replace(transponder=transponder) - self._current_model.set(itr, {i: v for i, v in enumerate(srv)}) - - def on_create_new(self, item): - if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL: - return - + def on_new(self): + service = self.get_service(*self.get_srv_data(), self.get_transponder_data()) + print(service) show_dialog(DialogType.ERROR, transient=self._dialog, text="Not implemented yet!") def get_service(self, fav_id, data_id, transponder): @@ -454,6 +458,15 @@ class ServiceDetailsDialog: srv_sys = None return self._NEUTRINO_TRANSPONDER_DATA.format(tr_id, on_id, freq, inv, rate, fec, pol, mod, srv_sys) + def update_transponder_services(self, transponder): + for itr in self._transponder_services_iters: + srv = self._current_model[itr][:] + srv[-9], srv[-8], srv[-7], srv[-6], srv[-5], srv[-4] = self.get_transponder_values() + srv[-1] = transponder + srv = Service(*srv) + self._services[srv.fav_id] = self._services.pop(srv.fav_id)._replace(transponder=transponder) + self._current_model.set(itr, {i: v for i, v in enumerate(srv)}) + # ***************** Others *********************# def select_active_text(self, box: Gtk.ComboBox, text): @@ -464,7 +477,10 @@ class ServiceDetailsDialog: break def on_digit_entry_changed(self, entry): - entry.set_name(self._DIGIT_ENTRY_NAME if self._pattern.search(entry.get_text()) else "GtkEntry") + entry.set_name(self._DIGIT_ENTRY_NAME if self._DIGIT_PATTERN.search(entry.get_text()) else "GtkEntry") + + def on_non_empty_entry_changed(self, entry): + entry.set_name(self._DIGIT_ENTRY_NAME if self._NON_EMPTY_PATTERN.search(entry.get_text()) else "GtkEntry") def get_value_from_combobox_id(self, box: Gtk.ComboBox, dc: dict): cb_id = box.get_active_id() @@ -493,6 +509,9 @@ class ServiceDetailsDialog: for elem in self._digit_elements.values(): if elem.get_name() == self._DIGIT_ENTRY_NAME: return False + for elem in self._non_empty_elements.values(): + if elem.get_name() == self._DIGIT_ENTRY_NAME: + return False return True From 336aa47177fe6384096216bb5892b4872038d8e6 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Tue, 20 Mar 2018 00:33:00 +0300 Subject: [PATCH 15/18] added default init in service dialog --- app/ui/service_details_dialog.glade | 37 ++++++++++++++------------ app/ui/service_details_dialog.py | 40 +++++++++++++++++++---------- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/app/ui/service_details_dialog.glade b/app/ui/service_details_dialog.glade index f0730ae2..d70bfadb 100644 --- a/app/ui/service_details_dialog.glade +++ b/app/ui/service_details_dialog.glade @@ -154,6 +154,12 @@ + + -180 + 180 + 0.10000000000000001 + 10 + @@ -405,8 +411,8 @@ True True + True 15 - 22 gtk-edit @@ -637,10 +643,11 @@ True False 25 + True Delays (ms): 10 10 - 0 + 1 9 @@ -971,7 +978,7 @@ True False - Pos + Position 0 @@ -1157,8 +1164,8 @@ True False True - 17 - 17 + 14 + 14 gtk-edit @@ -1179,18 +1186,14 @@ - + True False - False - sat_pos_list_store - 0 - - - - 0 - - + True + number + sat_pos_adjustment + 1 + True 0 @@ -1402,8 +1405,8 @@ True False True - 5 - 5 + 8 + 9 gtk-edit diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 34c8368d..00855803 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -1,4 +1,5 @@ import re +from math import fabs from app.commons import run_idle from app.eparser import Service, get_satellites @@ -103,7 +104,7 @@ class ServiceDetailsDialog: self._new_check_button = builder.get_object("new_check_button") self._pids_grid = builder.get_object("pids_grid") # Transponder elements - self._sat_pos_combo_box = builder.get_object("sat_pos_combo_box") + self._sat_pos_button = builder.get_object("sat_pos_button") self._pol_combo_box = builder.get_object("pol_combo_box") self._fec_combo_box = builder.get_object("fec_combo_box") self._sys_combo_box = builder.get_object("sys_combo_box") @@ -113,10 +114,11 @@ class ServiceDetailsDialog: self._pilot_combo_box = builder.get_object("pilot_combo_box") self._pls_mode_combo_box = builder.get_object("pls_mode_combo_box") self._tr_edit_switch = builder.get_object("tr_edit_switch") + self._tr_extra_expander = builder.get_object("tr_extra_expander") self._DVB_S2_ELEMENTS = (self._mod_combo_box, self._rolloff_combo_box, self._pilot_combo_box, self._pls_mode_combo_box, self._pls_code_entry, self._stream_id_entry) - self._TRANSPONDER_ELEMENTS = (self._sat_pos_combo_box, self._pol_combo_box, self._invertion_combo_box, + self._TRANSPONDER_ELEMENTS = (self._sat_pos_button, self._pol_combo_box, self._invertion_combo_box, self._sys_combo_box, self._freq_entry, self._transponder_id_entry, self._network_id_entry, self._namespace_entry, self._fec_combo_box, self._rate_entry) @@ -124,10 +126,7 @@ class ServiceDetailsDialog: if self._action is Action.EDIT: self.update_data_elements() elif self._action is Action.ADD: - self._apply_button.set_visible(False) - self._create_button.set_visible(True) - self._tr_edit_switch.set_sensitive(False) - self.on_tr_edit_toggled(self._tr_edit_switch.set_active(True), True) + self.init_default_data_elements() def show(self): response = self._dialog.run() @@ -137,6 +136,23 @@ class ServiceDetailsDialog: return response + @run_idle + def init_default_data_elements(self): + self._apply_button.set_visible(False) + self._create_button.set_visible(True) + self._tr_edit_switch.set_sensitive(False) + self.on_tr_edit_toggled(self._tr_edit_switch.set_active(True), True) + for elem in self._non_empty_elements.values(): + elem.set_text(" ") + elem.set_text("") + self._new_check_button.set_active(True) + self._tr_extra_expander.activate() + self._service_type_combo_box.set_active(0) + self._pol_combo_box.set_active(0) + self._fec_combo_box.set_active(0) + self._sys_combo_box.set_active(0) + self._invertion_combo_box.set_active(2) + @run_idle def update_data_elements(self): model, paths = self._services_view.get_selection().get_selected_rows() @@ -266,11 +282,8 @@ class ServiceDetailsDialog: @run_idle def set_sat_positions(self, sat_pos): """ Sat positions initialisation """ - model = self._sat_pos_combo_box.get_model() - positions = self.get_sat_positions(self._satellites_xml_path) - for pos in positions: - model.append((pos,)) - self.select_active_text(self._sat_pos_combo_box, sat_pos) + pos = float(sat_pos) + self._sat_pos_button.set_value(fabs(pos)) def get_sat_positions(self, path): try: @@ -424,8 +437,7 @@ class ServiceDetailsDialog: pol = self._pol_combo_box.get_active_id() fec = self._fec_combo_box.get_active_id() system = self._sys_combo_box.get_active_id() - pos = self._sat_pos_combo_box.get_active_id() - + pos = str(round(self._sat_pos_button.get_value(), 1)) return freq, rate, pol, fec, system, pos def get_transponder_data(self): @@ -434,7 +446,7 @@ class ServiceDetailsDialog: rate = self._rate_entry.get_text() pol = self.get_value_from_combobox_id(self._pol_combo_box, POLARIZATION) fec = self.get_value_from_combobox_id(self._fec_combo_box, FEC_DEFAULT) - sat_pos = self._sat_pos_combo_box.get_active_id().replace(".", "") + sat_pos = str(round(self._sat_pos_button.get_value(), 1)).replace(".", "") inv = get_value_by_name(Inversion, self._invertion_combo_box.get_active_id()) srv_sys = "0" # !!! From d762f097d03d7e98deddb82f87980563e2cea71b Mon Sep 17 00:00:00 2001 From: Dmitriy Yefremov Date: Tue, 20 Mar 2018 23:42:06 +0300 Subject: [PATCH 16/18] state update for navigation buttons --- app/ui/main_app_window.py | 4 +++- app/ui/main_window.glade | 2 ++ app/ui/search.py | 9 ++++++++- app/ui/service_details_dialog.glade | 2 +- app/ui/service_details_dialog.py | 11 +++++------ 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index 0323a0d4..e38f9f69 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -175,7 +175,9 @@ class MainAppWindow: # Search self.__search_info_bar = builder.get_object("search_info_bar") self.__search_provider = SearchProvider(self.__services_view, self.__fav_view, self.__bouquets_view, - self.__services, self.__bouquets) + self.__services, self.__bouquets, + builder.get_object("search_down_button"), + builder.get_object("search_up_button")) self.__main_window.show() def init_drag_and_drop(self): diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade index cbf16cec..d90f924b 100644 --- a/app/ui/main_window.glade +++ b/app/ui/main_window.glade @@ -1247,6 +1247,7 @@ True + False True True @@ -1267,6 +1268,7 @@ True + False True True diff --git a/app/ui/search.py b/app/ui/search.py index 24f00bf4..5d1d106d 100644 --- a/app/ui/search.py +++ b/app/ui/search.py @@ -2,7 +2,7 @@ class SearchProvider: - def __init__(self, srv_view, fav_view, bqs_view, services, bouquets): + def __init__(self, srv_view, fav_view, bqs_view, services, bouquets, down_button, up_button): self._paths = [] self._current_index = -1 self._max_indexes = 0 @@ -11,6 +11,8 @@ class SearchProvider: self._bqs_view = bqs_view self._services = services self._bouquets = bouquets + self._up_button = up_button + self._down_button = down_button def search(self, text, ): self._current_index = -1 @@ -36,6 +38,7 @@ class SearchProvider: def scroll_to(self, index): view, path = self._paths[index] view.scroll_to_cell(path, None) + self.update_navigation_buttons() def on_search_down(self): if self._current_index < self._max_indexes: @@ -47,6 +50,10 @@ class SearchProvider: self._current_index -= 1 self.scroll_to(self._current_index) + def update_navigation_buttons(self): + self._up_button.set_sensitive(self._current_index > 0) + self._down_button.set_sensitive(self._current_index < self._max_indexes) + if __name__ == "__main__": pass diff --git a/app/ui/service_details_dialog.glade b/app/ui/service_details_dialog.glade index d70bfadb..18affe6f 100644 --- a/app/ui/service_details_dialog.glade +++ b/app/ui/service_details_dialog.glade @@ -1167,7 +1167,7 @@ 14 14 gtk-edit - + 7 diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 00855803..91b620a7 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -1,5 +1,4 @@ import re -from math import fabs from app.commons import run_idle from app.eparser import Service, get_satellites @@ -25,8 +24,9 @@ class ServiceDetailsDialog: _DIGIT_ENTRY_ELEMENTS = ("bitstream_entry", "pcm_entry", "video_pid_entry", "pcr_pid_entry", "srv_type_entry", "ac3_pid_entry", "ac3plus_pid_entry", "acc_pid_entry", "he_acc_pid_entry", "teletext_pid_entry", "pls_code_entry", "stream_id_entry", "tr_flag_entry", - "audio_pid_entry", "namespace_entry") - _NOT_EMPTY_DIGIT_ELEMENTS = ("sid_entry", "freq_entry", "rate_entry", "transponder_id_entry", "network_id_entry") + "audio_pid_entry") + _NOT_EMPTY_DIGIT_ELEMENTS = ("sid_entry", "freq_entry", "rate_entry", "transponder_id_entry", "network_id_entry", + "namespace_entry") _DIGIT_ENTRY_NAME = "digit-entry" @@ -90,7 +90,7 @@ class ServiceDetailsDialog: self._pls_code_entry = self._digit_elements.get("pls_code_entry") self._stream_id_entry = self._digit_elements.get("stream_id_entry") self._tr_flag_entry = self._digit_elements.get("tr_flag_entry") - self._namespace_entry = self._digit_elements.get("namespace_entry") + self._namespace_entry = self._non_empty_elements.get("namespace_entry") # Service elements self._name_entry = builder.get_object("name_entry") self._package_entry = builder.get_object("package_entry") @@ -282,8 +282,7 @@ class ServiceDetailsDialog: @run_idle def set_sat_positions(self, sat_pos): """ Sat positions initialisation """ - pos = float(sat_pos) - self._sat_pos_button.set_value(fabs(pos)) + self._sat_pos_button.set_value(float(sat_pos)) def get_sat_positions(self, path): try: From 9e0d8840f34f791477cf474b689bf6e1150abd13 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Fri, 23 Mar 2018 21:42:54 +0300 Subject: [PATCH 17/18] init neutrino ui elms for service dialog --- app/ui/service_details_dialog.glade | 71 +++++++++++++++-------------- app/ui/service_details_dialog.py | 16 +++---- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/app/ui/service_details_dialog.glade b/app/ui/service_details_dialog.glade index 18affe6f..a1e9da17 100644 --- a/app/ui/service_details_dialog.glade +++ b/app/ui/service_details_dialog.glade @@ -396,30 +396,6 @@ 0 - - - True - False - CA ID's - - - 4 - 0 - - - - - True - True - True - 15 - gtk-edit - - - 4 - 1 - - True @@ -453,6 +429,31 @@ 1 + + + True + False + Reference + + + 4 + 0 + + + + + True + True + True + False + 14 + 14 + + + 4 + 1 + + False @@ -461,7 +462,7 @@ - + True False @@ -764,7 +765,7 @@ - + True False @@ -853,11 +854,12 @@ False 2 - + True True - False - 24 + 15 + 26 + gtk-edit 1 @@ -865,10 +867,10 @@ - + True False - Reference: + CAID's: 0 @@ -923,8 +925,9 @@ True False + 5 Transponder data: - 0.0099999997764825821 + 0 False @@ -1220,7 +1223,7 @@ True False - Tr. ID + TID 0 @@ -1246,7 +1249,7 @@ True False - Net. ID + NID 1 diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 91b620a7..1cd46efe 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -42,6 +42,7 @@ class ServiceDetailsDialog: builder.set_translation_domain(TEXT_DOMAIN) builder.add_from_file(UI_RESOURCES_PATH + "service_details_dialog.glade") builder.connect_signals(handlers) + self._builder = builder self._dialog = builder.get_object("service_details_dialog") self._dialog.set_transient_for(transient) @@ -182,7 +183,7 @@ class ServiceDetailsDialog: self.init_enigma2_transponder_data(srv) elif self._profile is Profile.NEUTRINO_MP: self.init_neutrino_data(srv) - self.init_enigma_ui_elements() + self.init_neutrino_ui_elements() # ***************** Init Enigma2 data *********************# @@ -269,13 +270,12 @@ class ServiceDetailsDialog: self._network_id_entry.set_text(str(int(tr_data[1], 16))) self.select_active_text(self._invertion_combo_box, Inversion(tr_data[3]).name) - def init_enigma_ui_elements(self): - self._pids_grid.set_sensitive(False) - self._cas_entry.set_sensitive(False) - self._keep_check_button.set_sensitive(False) - self._hide_check_button.set_sensitive(False) - self._use_pids_check_button.set_sensitive(False) - self._new_check_button.set_sensitive(False) + def init_neutrino_ui_elements(self): + self._builder.get_object("flags_box").set_visible(False) + self._builder.get_object("pids_grid").set_visible(False) + self._builder.get_object("tr_grid").remove_column(7) + self._builder.get_object("extra_transponder_grid").remove_column(8) + self._builder.get_object("srv_separator").set_visible(False) # ***************** Init Sat positions *********************# From 24023d438dedc417545fb88a53a7dc033dec6925 Mon Sep 17 00:00:00 2001 From: Dmitriy Yefremov Date: Sun, 25 Mar 2018 10:46:30 +0300 Subject: [PATCH 18/18] ui changes for the service dialog --- app/ui/dialogs.glade | 2 +- app/ui/lang/ru/LC_MESSAGES/demon-editor.mo | Bin 9547 -> 9827 bytes app/ui/main_window.glade | 1 - app/ui/service_details_dialog.glade | 241 +++++++++--------- app/ui/service_details_dialog.py | 4 +- .../locale/ru/LC_MESSAGES/demon-editor.mo | Bin 9547 -> 9827 bytes po/ru/demon-editor.mo | Bin 9547 -> 9827 bytes po/ru/demon-editor.po | 92 ++----- 8 files changed, 142 insertions(+), 198 deletions(-) diff --git a/app/ui/dialogs.glade b/app/ui/dialogs.glade index eb772d09..604b09a5 100644 --- a/app/ui/dialogs.glade +++ b/app/ui/dialogs.glade @@ -780,7 +780,7 @@ dmitry.v.yefremov@gmail.com True False - Stream type + Type 2 diff --git a/app/ui/lang/ru/LC_MESSAGES/demon-editor.mo b/app/ui/lang/ru/LC_MESSAGES/demon-editor.mo index 8b8e9417fea02a5a515546b2c6bf99dfcdacbadb..b3248e890b8c4a551c16233b172e4a76aa7ec6e4 100644 GIT binary patch delta 3147 zcmYk;dr*{B7{~Dgh#-g{iI-AY!W&9drh=p*Dk@5vx76~&3ag^r7Zo#G@IGD8M6;Yi zn>6iaHXBA5I!!f=;^fOeTIN`eHD*@MH0Cr~+4r}5nCZ+u@8`T{U(V$@=Ur``awX4q zDZayQL)l97CT4dqrV(F=lP2eC# z;St;Z3F_}pU{}UBUr@=Q;T$p}6U(x+qBNw*47c~=P#xzYA2ZF~FTg(ByHOqcPy=p8 zWnu^NG5fh_fk&_xwqPvdoAXq((yOR}Z(BonS_4K}V^A50M{PxK)XH7h6H~1@))zr;aXC(Lg_-_UI?;ZNuSD%_8EU|4d%p>_ zkQY${?nDjv7T$+PkhPf8sKfqk9QoHC-=ZM_!^n?T+6%R!WbBTEQ7g$tbvPY0@LbgM z1*pF-LGArUR0ishk9pJHH=-tZ8rA<<9~E_c&VKPDYQSr#fpjo5!AR6|38DK^L|lNj8^I6T5+YeC8HcCS#(>pHkNswO1*qmFHj`&P1)` zGV1w%aWHlzU36hap;j~l^}QDd;TF_$AE4fb3#d%q#00(np)5l)>xudz1$FAvQ60^- zu0TDv-dcz1cpomn)2LHDkatlFn1!iWhRWb;sKa*{)&IxXjq%NSDr4|h)Cz|%P5lr} zM(x!y)Z4KgQ}BJ;ejZ)i-$f1Vx;OYckcS%3gDlcipi;gKHG%D@OgEs9ESk5eXhtWk z-=k7_*P6s~w9@gY_EPMRJ5aCZF;vIRsEnOL4R8_1;#E{;2eG=LI0E(eMZL+t9^6iY z_IfY&!$YWn&RBm(Wg?C=sG|&Ah!b%K9>6>tPTJ%KR7TEX1l~ctreUm7_c5pmCnS=8 z&A1;8dX3VNT`-eS1LmXld>cNDuOc7Q$|Vc0+xsD|;9gHfEu ziuhw4!a5v)2T}c<;gYKN{|_oUor!$QEJ8K~>RekE^`?TGW8ZqAG7yrN>=T z9}|7Oho{)R*6SKn;!Vjk6FlC6%A)eBqO#KZThZ@?7rU2vGwT~Vw??>2Jl=A5fq!XC zNLa*DPo<}{z~e8B`zNf^KIcT+2Iqv+>|fmNyO92SoTJW1PGeh*bIfUWn&`M7#W)Sl zNvEl;mhW1eCa2M#(S21&)B)!>4SuI7)BkRdYaucF+G^5VeEq4@=(PBE_PQ7z{YG1D Y+w(lu>>TwMCpLtHwr%ovPRi==9|0##fB*mh delta 2879 zcmZA2e@vBC9LMnkT%-h1B!2hn`OHoV+ksp;3VPIMG0|_Hi1c^YA5WP69)l7|U z&5;IwL|b8u>2>*sD|Oi)&b3jiKLB%>rSm^+CFN%I{yfjgxz6tQd7X23?sLxhp7UHT zmz^*5U7YUuz)*G(vxy{+F@uW-k>!<~=U@VjpT{{kDA!6KJ16J@7}=Kx3%PTtVG`6SWWz zjTsn?`g;ayLHVdmRah(0!}z9J6|6<2cq6hX(}?ldZtb=Xpa%FF@5i4|D-2?EWh@%? zoCT=orlYnX%bJUGX&0eSsa;Pc4jYhXncb+BcB5u|5H+D*)Bpph`%Ymrev2C55~krb z)ZWLid}Xc*=V1pbBOh_m1P7;*e+_ihcAP-%hwjE4fHRH*s8P7ny9qC9m&2rR$PowsD2WH`ZRHja20gl_YmriYMA?mrC z=lYDvrP4_USu|guUW;MW3V%l380K}`v8aLaP_J2;wHY;`_fZoaL}lzWs{cHy{})_{ z6BvOhKJrJ_Og54oQ-RLRFq3vCk_>YM^?-9&gBMWu<@39$Eh@u8Y{6m-;2OM%OR=9!I5W6m=NG=wwV2i5wHN2!l{1gs332QWEBD=+C)8k(BO8&n%XM#=^ z@01R%RYW`SsMF(a&rZGn`L-h)l>ruPo**6}Dv9TbdO~SbCUgK-5u7O}bNmoGWjWVY zLO)je=`AJ-2p#adOE3+cfodX^@y#S7*3y_PEFF2?t&t>|#+AgXXSobno1?X_OXJYpNMl2}CiSDvEMM3fLZ zFSW#4Vhgd3P5L&E$=(ZD!i43=k8s#w}i+EWLN)eGmyiUXr5rj&j%bjc7otpa( z>Pgy}w(kXOAoM0YOT0ojrKomGeOsNkxy8RJJlWq9e$9U<;!}U=lyiZE$iIUF$x*jL m0;w@0L4nk`)}X*=@mGTaeKSWx18;f{2L%rw3na}e@cau=eEHG< diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade index d90f924b..fea0e33f 100644 --- a/app/ui/main_window.glade +++ b/app/ui/main_window.glade @@ -392,7 +392,6 @@ gtk-new - True False True True diff --git a/app/ui/service_details_dialog.glade b/app/ui/service_details_dialog.glade index a1e9da17..93cfbe62 100644 --- a/app/ui/service_details_dialog.glade +++ b/app/ui/service_details_dialog.glade @@ -446,8 +446,8 @@ True True False - 14 - 14 + 8 + 10 4 @@ -849,7 +849,7 @@ - + True False 2 @@ -1100,75 +1100,13 @@ 1 - - - True - False - System - - - 5 - 0 - - - - - True - False - False - sys_list_store - 0 - - - - - 0 - - - - - 5 - 1 - - - - - True - False - Mod - - - 6 - 0 - - - - - True - False - False - 0.98999999999999999 - mod_list_store - 0 - - - - 0 - - - - - 6 - 1 - - True False True - 14 - 14 + 12 + 12 gtk-edit @@ -1203,6 +1141,58 @@ 1 + + + True + False + TID + + + 5 + 0 + + + + + True + False + True + 8 + 10 + gtk-edit + + + + 5 + 1 + + + + + True + False + NID + + + 6 + 0 + + + + + True + False + True + 8 + 10 + gtk-edit + + + + 6 + 1 + + False @@ -1219,58 +1209,6 @@ True False 2 - - - True - False - TID - - - 0 - 0 - - - - - True - False - True - 8 - 10 - gtk-edit - - - - 0 - 1 - - - - - True - False - NID - - - 1 - 0 - - - - - True - False - True - 8 - 10 - gtk-edit - - - - 1 - 1 - - True @@ -1409,7 +1347,7 @@ False True 8 - 9 + 10 gtk-edit @@ -1470,6 +1408,69 @@ 1 + + + True + False + System + + + 0 + 0 + + + + + True + False + False + True + sys_list_store + 0 + + + + + 0 + + + + + 0 + 1 + + + + + True + False + Mod + + + 1 + 0 + + + + + True + False + False + True + mod_list_store + 0 + + + + 0 + + + + + 1 + 1 + + diff --git a/app/ui/service_details_dialog.py b/app/ui/service_details_dialog.py index 1cd46efe..62a7bb08 100644 --- a/app/ui/service_details_dialog.py +++ b/app/ui/service_details_dialog.py @@ -154,7 +154,6 @@ class ServiceDetailsDialog: self._sys_combo_box.set_active(0) self._invertion_combo_box.set_active(2) - @run_idle def update_data_elements(self): model, paths = self._services_view.get_selection().get_selected_rows() itr = model.get_iter(paths) @@ -274,12 +273,11 @@ class ServiceDetailsDialog: self._builder.get_object("flags_box").set_visible(False) self._builder.get_object("pids_grid").set_visible(False) self._builder.get_object("tr_grid").remove_column(7) - self._builder.get_object("extra_transponder_grid").remove_column(8) + self._builder.get_object("tr_extra_expander").set_visible(False) self._builder.get_object("srv_separator").set_visible(False) # ***************** Init Sat positions *********************# - @run_idle def set_sat_positions(self, sat_pos): """ Sat positions initialisation """ self._sat_pos_button.set_value(float(sat_pos)) diff --git a/deb/usr/share/locale/ru/LC_MESSAGES/demon-editor.mo b/deb/usr/share/locale/ru/LC_MESSAGES/demon-editor.mo index 8b8e9417fea02a5a515546b2c6bf99dfcdacbadb..b3248e890b8c4a551c16233b172e4a76aa7ec6e4 100644 GIT binary patch delta 3147 zcmYk;dr*{B7{~Dgh#-g{iI-AY!W&9drh=p*Dk@5vx76~&3ag^r7Zo#G@IGD8M6;Yi zn>6iaHXBA5I!!f=;^fOeTIN`eHD*@MH0Cr~+4r}5nCZ+u@8`T{U(V$@=Ur``awX4q zDZayQL)l97CT4dqrV(F=lP2eC# z;St;Z3F_}pU{}UBUr@=Q;T$p}6U(x+qBNw*47c~=P#xzYA2ZF~FTg(ByHOqcPy=p8 zWnu^NG5fh_fk&_xwqPvdoAXq((yOR}Z(BonS_4K}V^A50M{PxK)XH7h6H~1@))zr;aXC(Lg_-_UI?;ZNuSD%_8EU|4d%p>_ zkQY${?nDjv7T$+PkhPf8sKfqk9QoHC-=ZM_!^n?T+6%R!WbBTEQ7g$tbvPY0@LbgM z1*pF-LGArUR0ishk9pJHH=-tZ8rA<<9~E_c&VKPDYQSr#fpjo5!AR6|38DK^L|lNj8^I6T5+YeC8HcCS#(>pHkNswO1*qmFHj`&P1)` zGV1w%aWHlzU36hap;j~l^}QDd;TF_$AE4fb3#d%q#00(np)5l)>xudz1$FAvQ60^- zu0TDv-dcz1cpomn)2LHDkatlFn1!iWhRWb;sKa*{)&IxXjq%NSDr4|h)Cz|%P5lr} zM(x!y)Z4KgQ}BJ;ejZ)i-$f1Vx;OYckcS%3gDlcipi;gKHG%D@OgEs9ESk5eXhtWk z-=k7_*P6s~w9@gY_EPMRJ5aCZF;vIRsEnOL4R8_1;#E{;2eG=LI0E(eMZL+t9^6iY z_IfY&!$YWn&RBm(Wg?C=sG|&Ah!b%K9>6>tPTJ%KR7TEX1l~ctreUm7_c5pmCnS=8 z&A1;8dX3VNT`-eS1LmXld>cNDuOc7Q$|Vc0+xsD|;9gHfEu ziuhw4!a5v)2T}c<;gYKN{|_oUor!$QEJ8K~>RekE^`?TGW8ZqAG7yrN>=T z9}|7Oho{)R*6SKn;!Vjk6FlC6%A)eBqO#KZThZ@?7rU2vGwT~Vw??>2Jl=A5fq!XC zNLa*DPo<}{z~e8B`zNf^KIcT+2Iqv+>|fmNyO92SoTJW1PGeh*bIfUWn&`M7#W)Sl zNvEl;mhW1eCa2M#(S21&)B)!>4SuI7)BkRdYaucF+G^5VeEq4@=(PBE_PQ7z{YG1D Y+w(lu>>TwMCpLtHwr%ovPRi==9|0##fB*mh delta 2879 zcmZA2e@vBC9LMnkT%-h1B!2hn`OHoV+ksp;3VPIMG0|_Hi1c^YA5WP69)l7|U z&5;IwL|b8u>2>*sD|Oi)&b3jiKLB%>rSm^+CFN%I{yfjgxz6tQd7X23?sLxhp7UHT zmz^*5U7YUuz)*G(vxy{+F@uW-k>!<~=U@VjpT{{kDA!6KJ16J@7}=Kx3%PTtVG`6SWWz zjTsn?`g;ayLHVdmRah(0!}z9J6|6<2cq6hX(}?ldZtb=Xpa%FF@5i4|D-2?EWh@%? zoCT=orlYnX%bJUGX&0eSsa;Pc4jYhXncb+BcB5u|5H+D*)Bpph`%Ymrev2C55~krb z)ZWLid}Xc*=V1pbBOh_m1P7;*e+_ihcAP-%hwjE4fHRH*s8P7ny9qC9m&2rR$PowsD2WH`ZRHja20gl_YmriYMA?mrC z=lYDvrP4_USu|guUW;MW3V%l380K}`v8aLaP_J2;wHY;`_fZoaL}lzWs{cHy{})_{ z6BvOhKJrJ_Og54oQ-RLRFq3vCk_>YM^?-9&gBMWu<@39$Eh@u8Y{6m-;2OM%OR=9!I5W6m=NG=wwV2i5wHN2!l{1gs332QWEBD=+C)8k(BO8&n%XM#=^ z@01R%RYW`SsMF(a&rZGn`L-h)l>ruPo**6}Dv9TbdO~SbCUgK-5u7O}bNmoGWjWVY zLO)je=`AJ-2p#adOE3+cfodX^@y#S7*3y_PEFF2?t&t>|#+AgXXSobno1?X_OXJYpNMl2}CiSDvEMM3fLZ zFSW#4Vhgd3P5L&E$=(ZD!i43=k8s#w}i+EWLN)eGmyiUXr5rj&j%bjc7otpa( z>Pgy}w(kXOAoM0YOT0ojrKomGeOsNkxy8RJJlWq9e$9U<;!}U=lyiZE$iIUF$x*jL m0;w@0L4nk`)}X*=@mGTaeKSWx18;f{2L%rw3na}e@cau=eEHG< diff --git a/po/ru/demon-editor.mo b/po/ru/demon-editor.mo index 8b8e9417fea02a5a515546b2c6bf99dfcdacbadb..b3248e890b8c4a551c16233b172e4a76aa7ec6e4 100644 GIT binary patch delta 3147 zcmYk;dr*{B7{~Dgh#-g{iI-AY!W&9drh=p*Dk@5vx76~&3ag^r7Zo#G@IGD8M6;Yi zn>6iaHXBA5I!!f=;^fOeTIN`eHD*@MH0Cr~+4r}5nCZ+u@8`T{U(V$@=Ur``awX4q zDZayQL)l97CT4dqrV(F=lP2eC# z;St;Z3F_}pU{}UBUr@=Q;T$p}6U(x+qBNw*47c~=P#xzYA2ZF~FTg(ByHOqcPy=p8 zWnu^NG5fh_fk&_xwqPvdoAXq((yOR}Z(BonS_4K}V^A50M{PxK)XH7h6H~1@))zr;aXC(Lg_-_UI?;ZNuSD%_8EU|4d%p>_ zkQY${?nDjv7T$+PkhPf8sKfqk9QoHC-=ZM_!^n?T+6%R!WbBTEQ7g$tbvPY0@LbgM z1*pF-LGArUR0ishk9pJHH=-tZ8rA<<9~E_c&VKPDYQSr#fpjo5!AR6|38DK^L|lNj8^I6T5+YeC8HcCS#(>pHkNswO1*qmFHj`&P1)` zGV1w%aWHlzU36hap;j~l^}QDd;TF_$AE4fb3#d%q#00(np)5l)>xudz1$FAvQ60^- zu0TDv-dcz1cpomn)2LHDkatlFn1!iWhRWb;sKa*{)&IxXjq%NSDr4|h)Cz|%P5lr} zM(x!y)Z4KgQ}BJ;ejZ)i-$f1Vx;OYckcS%3gDlcipi;gKHG%D@OgEs9ESk5eXhtWk z-=k7_*P6s~w9@gY_EPMRJ5aCZF;vIRsEnOL4R8_1;#E{;2eG=LI0E(eMZL+t9^6iY z_IfY&!$YWn&RBm(Wg?C=sG|&Ah!b%K9>6>tPTJ%KR7TEX1l~ctreUm7_c5pmCnS=8 z&A1;8dX3VNT`-eS1LmXld>cNDuOc7Q$|Vc0+xsD|;9gHfEu ziuhw4!a5v)2T}c<;gYKN{|_oUor!$QEJ8K~>RekE^`?TGW8ZqAG7yrN>=T z9}|7Oho{)R*6SKn;!Vjk6FlC6%A)eBqO#KZThZ@?7rU2vGwT~Vw??>2Jl=A5fq!XC zNLa*DPo<}{z~e8B`zNf^KIcT+2Iqv+>|fmNyO92SoTJW1PGeh*bIfUWn&`M7#W)Sl zNvEl;mhW1eCa2M#(S21&)B)!>4SuI7)BkRdYaucF+G^5VeEq4@=(PBE_PQ7z{YG1D Y+w(lu>>TwMCpLtHwr%ovPRi==9|0##fB*mh delta 2879 zcmZA2e@vBC9LMnkT%-h1B!2hn`OHoV+ksp;3VPIMG0|_Hi1c^YA5WP69)l7|U z&5;IwL|b8u>2>*sD|Oi)&b3jiKLB%>rSm^+CFN%I{yfjgxz6tQd7X23?sLxhp7UHT zmz^*5U7YUuz)*G(vxy{+F@uW-k>!<~=U@VjpT{{kDA!6KJ16J@7}=Kx3%PTtVG`6SWWz zjTsn?`g;ayLHVdmRah(0!}z9J6|6<2cq6hX(}?ldZtb=Xpa%FF@5i4|D-2?EWh@%? zoCT=orlYnX%bJUGX&0eSsa;Pc4jYhXncb+BcB5u|5H+D*)Bpph`%Ymrev2C55~krb z)ZWLid}Xc*=V1pbBOh_m1P7;*e+_ihcAP-%hwjE4fHRH*s8P7ny9qC9m&2rR$PowsD2WH`ZRHja20gl_YmriYMA?mrC z=lYDvrP4_USu|guUW;MW3V%l380K}`v8aLaP_J2;wHY;`_fZoaL}lzWs{cHy{})_{ z6BvOhKJrJ_Og54oQ-RLRFq3vCk_>YM^?-9&gBMWu<@39$Eh@u8Y{6m-;2OM%OR=9!I5W6m=NG=wwV2i5wHN2!l{1gs332QWEBD=+C)8k(BO8&n%XM#=^ z@01R%RYW`SsMF(a&rZGn`L-h)l>ruPo**6}Dv9TbdO~SbCUgK-5u7O}bNmoGWjWVY zLO)je=`AJ-2p#adOE3+cfodX^@y#S7*3y_PEFF2?t&t>|#+AgXXSobno1?X_OXJYpNMl2}CiSDvEMM3fLZ zFSW#4Vhgd3P5L&E$=(ZD!i43=k8s#w}i+EWLN)eGmyiUXr5rj&j%bjc7otpa( z>Pgy}w(kXOAoM0YOT0ojrKomGeOsNkxy8RJJlWq9e$9U<;!}U=lyiZE$iIUF$x*jL m0;w@0L4nk`)}X*=@mGTaeKSWx18;f{2L%rw3na}e@cau=eEHG< diff --git a/po/ru/demon-editor.po b/po/ru/demon-editor.po index 80083d05..0ed9a789 100644 --- a/po/ru/demon-editor.po +++ b/po/ru/demon-editor.po @@ -43,294 +43,222 @@ msgstr "№" msgid "Current IP:" msgstr "Текущий IP:" -#: main_window.glade:261 msgid "Assign" msgstr "Привязать" -#: main_window.glade:1826 msgid "Bouquet details" msgstr "Сервисы букета" -#: main_window.glade:2021 msgid "Bouquets" msgstr "Букеты" -#: main_window.glade:916 msgid "Copy" msgstr "Копировать" -#: main_window.glade:287 main_window.glade:416 msgid "Copy reference" msgstr "Копировать ссылку" -#: main_window.glade:1777 msgid "Data" msgstr "" -#: main_window.glade:744 msgid "Download" msgstr "Загрузить" -#: main_window.glade:1014 msgid "Edit" msgstr "Изменить" -#: main_window.glade:1015 msgid "Edit " msgstr "Изменить" -#: main_window.glade:213 msgid "Edit mаrker text" msgstr "Изменить текст маркера" -#: main_window.glade:543 main_window.glade:743 msgid "FTP-transfer" msgstr "Передача установок по FTP" -#: main_window.glade:808 msgid "Global search" msgstr "Глобальный поиск" -#: main_window.glade:973 msgid "Hide" msgstr "Пропустить" -#: main_window.glade:972 msgid "Hide/Skip On/Off Ctrl + H" msgstr "Скрыть/Пропустить Вкл/Выкл Ctrl + H" -#: main_window.glade:1113 msgid "IPTV" msgstr "" -#: main_window.glade:231 msgid "Import m3u" msgstr "Импортировать m3u" -#: main_window.glade:1111 msgid "Import m3u file" msgstr "Импортировать файл m3u" -#: main_window.glade:201 msgid "Insert marker" msgstr "Вставить маркер" -#: main_window.glade:184 msgid "Locate in services" msgstr "Найти в списке сервисов" -#: main_window.glade:957 msgid "Locked" msgstr "Заблокирован" -#: main_window.glade:834 msgid "Move" msgstr "Переместить" -#: main_window.glade:999 msgid "New" msgstr "Новый" -#: main_window.glade:998 msgid "New bouquet" msgstr "Новый букет" -#: main_window.glade:718 main_window.glade:719 msgid "Open" msgstr "Открыть" -#: main_window.glade:956 msgid "Parent lock On/Off Ctrl + L" msgstr "Родительский замок Вкл/Выкл Ctrl + L" -#: main_window.glade:931 msgid "Paste" msgstr "" -#: main_window.glade:1095 msgid "Picons" msgstr "Пиконы" -#: main_window.glade:650 main_window.glade:1096 msgid "Picons loader" msgstr "Загрузчик пиконов" -#: main_window.glade:1055 msgid "Preferences" msgstr "Настройки" -#: main_window.glade:2195 msgid "Profile:" msgstr "Профиль:" -#: main_window.glade:1751 msgid "Radio" msgstr "" -#: main_window.glade:271 main_window.glade:1030 msgid "Remove" msgstr "Удалить" -#: main_window.glade:640 main_window.glade:1079 main_window.glade:1080 msgid "Satellites editor" msgstr "Редактор спутников" -#: main_window.glade:768 main_window.glade:769 msgid "Save" msgstr "Сохранить" -#: main_window.glade:809 msgid "Search" msgstr "Поиск" -#: main_window.glade:1269 msgid "Services" msgstr "Сервисы" -#: main_window.glade:793 main_window.glade:794 msgid "Services filter" msgstr "Фильтр сервисов" -#: main_window.glade:1054 msgid "Settings" msgstr "Настройки" -#: main_window.glade:1725 msgid "TV" msgstr "" -#: main_window.glade:859 main_window.glade:860 msgid "Up" msgstr "Переместить вверх" msgid "Down" msgstr "Переместить вниз" -#: dialogs.glade:1101 msgid "Active profile:" msgstr "Активный профиль:" -#: dialogs.glade:175 msgid "All" msgstr "Все" -#: dialogs.glade:595 msgid "Are you sure?" msgstr "Вы уверены?" -#: dialogs.glade:127 msgid "Current data path:" msgstr "Текущий путь к данным:" -#: dialogs.glade:1192 msgid "Data dir:" msgstr "Путь к данным:" -#: dialogs.glade:164 msgid "Data:" msgstr "Данные:" -#: dialogs.glade:16 msgid "Enigma2 channel and satellites list editor for GNU/Linux" msgstr "Редактор списка каналов и спутников Enigma2\n для GNU/Linux" -#: dialogs.glade:814 msgid "FTP" msgstr "" -#: dialogs.glade:712 msgid "Host:" msgstr "Адрес ресивера:" -#: dialogs.glade:1328 msgid "Loading data..." msgstr "Загрузка данных..." -#: dialogs.glade:735 dialogs.glade:863 msgid "Login:" msgstr "Логин:" -#: dialogs.glade:625 msgid "Options" msgstr "Настройки" -#: dialogs.glade:746 dialogs.glade:874 msgid "Password:" msgstr "Пароль:" -#: dialogs.glade:1235 msgid "Picons dir:" msgstr "Директория пиконов:" -#: dialogs.glade:1050 msgid "Picons:" msgstr "Пиконы:" -#: dialogs.glade:769 dialogs.glade:830 msgid "Port:" msgstr "Порт:" -#: dialogs.glade:94 dialogs.glade:256 msgid "Receive" msgstr "Получить" -#: dialogs.glade:254 msgid "Receive files from receiver" msgstr "Получить файлы из ресивера" -#: dialogs.glade:100 msgid "Receiver IP:" msgstr "IP адрес ресивера:" -#: dialogs.glade:297 msgid "Remove unused bouquets" msgstr "Удалить не испрльзуемые букеты" -#: dialogs.glade:1148 msgid "Reset profile" msgstr "Сброс профиля" -#: dialogs.glade:208 msgid "Satellites" msgstr "Спутники" -#: dialogs.glade:1026 msgid "Satellites.xml file:" msgstr "Файл satellites.xml:" -#: dialogs.glade:1215 dialogs.glade:1216 msgid "Select" msgstr "" -#: dialogs.glade:271 msgid "Send" msgstr "Отправить" -#: dialogs.glade:269 msgid "Send files to receiver" -msgstr "Отправить вайлы в ресивер" +msgstr "Отправить файлы в ресивер" -#: dialogs.glade:978 msgid "Services and Bouquets files:" msgstr "Файлы сервисов и букетов:" -#: dialogs.glade:932 msgid "Telnet" msgstr "" -#: dialogs.glade:908 msgid "Timeout between commands in seconds" msgstr "Пауза между коммандами в сек." -#: dialogs.glade:897 msgid "Timeout:" msgstr "Тайм-аут:" -#: dialogs.glade:1002 msgid "User bouquet files:" msgstr "Файлы букетов:" -#: dialogs.glade:224 msgid "WebTV" msgstr "" @@ -433,6 +361,24 @@ msgstr "Данные транспондера" msgid "Changes will be applied to all services of this transponder!\nContinue?" msgstr "Изменения будут применены ко всем сервисам данного транспондера!\nПродолжить?" +msgid "Reference" +msgstr "Ссылка" + +msgid "Namespace" +msgstr "Пр. имен" + +msgid "Flags:" +msgstr "Флаги:" + +msgid "Delays (ms):" +msgstr "Задержки (mc)" + +msgid "Bitstream" +msgstr "Поток" + +msgid "Description" +msgstr "Описание" + # Dialogs messages msgid "Error. No bouquet is selected!" msgstr "Ошибка. Не выбран букет!"