Compare commits

...

38 Commits

Author SHA1 Message Date
DYefremov
528f59d990 updated it *.mo file 2022-04-26 17:46:53 +03:00
mapi68
28802957fc Italian translation update (#99) 2022-04-26 17:42:33 +03:00
DYefremov
b763d9785d minor translation improvement (#97) 2022-04-26 16:52:48 +03:00
DYefremov
601a81beb9 bump version 2022-04-25 21:00:08 +03:00
DYefremov
ace38433a1 fixed layout switching for the control tab 2022-04-25 20:48:22 +03:00
DYefremov
536b23a845 minor fix 2022-04-25 20:19:36 +03:00
DYefremov
d71a1d5dac removed unused option 2022-04-25 20:18:34 +03:00
DYefremov
4a92084c75 updated pl *.mo file 2022-04-18 13:09:32 +03:00
lareq
e7b8412c11 Polish translation update (#96)
added missing polish translations
2022-04-18 12:51:37 +03:00
audi06_19
ef53de1796 Turkish translation update (#95) 2022-04-17 22:56:10 +03:00
DYefremov
8e7a116db7 multiple selection for picons explorer 2022-04-12 23:33:17 +03:00
DYefremov
285014480f win style correction 2022-04-12 13:42:44 +03:00
DYefremov
279c255ad0 minor fixes in the control panel 2022-04-11 15:04:47 +03:00
DYefremov
90a3053192 bump version 2022-04-11 11:23:11 +03:00
DYefremov
19c6a5bef9 disabling FlySat source (#55) 2022-04-11 10:52:20 +03:00
DYefremov
945ee13058 hooks config for *.spec file 2022-04-10 10:39:59 +03:00
DYefremov
c65b6c540c transponder menu fix 2022-04-09 12:57:45 +03:00
DYefremov
62091dfa96 mac style correction 2022-04-07 22:29:00 +03:00
DYefremov
6ca06fd2cd minor start script correction 2022-04-07 16:29:46 +03:00
DYefremov
4cab05fc09 minor mac style correction 2022-04-06 14:16:50 +03:00
DYefremov
81e714ebab updated it *.mo file 2022-04-04 15:26:15 +03:00
DYefremov
147430d4f3 README update 2022-04-04 15:14:32 +03:00
DYefremov
f8f209d288 build instruction for Windows (#87) 2022-04-04 14:58:29 +03:00
DYefremov
bd0e08e90b changed ssl context for Windows package (#89) 2022-04-03 19:15:27 +03:00
DYefremov
57020423d7 minor fix 2022-04-03 19:08:08 +03:00
mapi68
1fd3e45dd3 Italian translation сorrection (#88) 2022-04-02 09:17:36 +03:00
DYefremov
ac1725b3ef changed path for 7zip on Windows 2022-04-01 12:12:02 +03:00
DYefremov
39a592fd4d bump version 2022-03-30 17:42:09 +03:00
DYefremov
e40e0f2458 added force external themes option 2022-03-30 14:46:57 +03:00
DYefremov
d5889cd96c minor mac style changes 2022-03-30 02:17:10 +03:00
DYefremov
77a8bfe2c6 fixed name parsing for KingOfSat source 2022-03-27 11:33:09 +03:00
DYefremov
470d2d843b fixed translation missing (#85)
* Fixed translation missing for dropdown lists on Windows.
2022-03-26 12:12:22 +03:00
DYefremov
a908845b4e filtering support for recordings tab 2022-03-25 21:25:30 +03:00
DYefremov
8fee5033a4 updated it *.mo file 2022-03-24 21:20:56 +03:00
mapi68
a9b1f8b26c Italian translation сorrection (#84) 2022-03-24 21:13:23 +03:00
DYefremov
8fa306a9d1 updated it *.mo file 2022-03-23 11:02:15 +03:00
mapi68
383ea2b9b3 Italian translation update (#82) 2022-03-23 10:55:20 +03:00
DYefremov
a40ba2ff68 minor correction for settings dialog 2022-03-21 12:19:00 +03:00
44 changed files with 784 additions and 252 deletions

View File

@@ -36,7 +36,8 @@ Clipboard is **"rubber"**. There is an accumulation before the insertion!
beginning or inserts (creates) a new bouquet.
* **Ctrl + BackSpace** - copies the selected channels from the main list to the bouquet end.
* **Ctrl + E** - edit.
* **Ctrl + R, F2** - rename.
* **Ctrl + R, F2** - rename.
* **Ctrl + Alt + R** - rename for bouquet.
* **Ctrl + S, T** in Satellites edit tool for create satellite or transponder.
* **Ctrl + L** - parental lock.
* **Ctrl + H** - hide/skip.
@@ -85,7 +86,8 @@ Recommended copy the package to the **Application** directory.
Perhaps in the security settings it will be necessary to allow the launch of this application!
* ### MS Windows
**Windows users can also run this program.** One way is to use the [MSYS2](https://www.msys2.org/) platform.
**Windows users can also run this program.**
One way is to use the [MSYS2](https://www.msys2.org/) platform. You can use [this](https://github.com/DYefremov/DemonEditor/blob/master/build/BUILD_WIN.md) quick guide.
In addition, you can download a ready-made build (**64-bit**) from the [releases](https://github.com/DYefremov/DemonEditor/releases) page.
**All builds may contain components distributed under the GPL [v3](http://www.gnu.org/licenses/gpl-3.0.html) or lower license.

View File

@@ -57,7 +57,7 @@ class PiconsCzDownloader:
_PERM_URL = "https://picon.cz/download/7337"
_BASE_URL = "https://picon.cz/download/"
_BASE_LOGO_URL = "https://picon.cz/picon/0/"
_HEADER = {"User-Agent": "DemonEditor/2.2.1", "Referer": ""}
_HEADER = {"User-Agent": "DemonEditor/2.2.4", "Referer": ""}
_LINK_PATTERN = re.compile(r"((.*)-\d+x\d+)-(.*)_by_chocholousek.7z$")
_FILE_PATTERN = re.compile(b"\\s+(1_.*\\.png).*")
@@ -136,7 +136,7 @@ class PiconsCzDownloader:
raise PiconsError("7-zip [7z] archiver not found!")
if IS_WIN:
exe = f"C:{os.sep}Program Files{os.sep}7-Zip{os.sep}{exe}.exe"
exe = f"{exe}.exe" if GTK_PATH else f"C:{os.sep}Program Files{os.sep}7-Zip{os.sep}{exe}.exe"
if not os.path.isfile(exe):
raise PiconsError("7-Zip executable not found!")

View File

@@ -164,16 +164,15 @@ class SatellitesParser(HTMLParser):
for src in SatelliteSource.get_sources(self._source):
try:
request = requests.get(url=src, headers=_HEADERS, timeout=_TIMEOUT)
resp = requests.get(url=src, headers=_HEADERS, timeout=_TIMEOUT)
except requests.exceptions.RequestException as e:
log(f"Getting satellite list error: {repr(e)}")
return []
else:
reason = request.reason
reason = resp.reason
if reason == "OK":
self.feed(request.text)
self.feed(resp.text)
else:
log(reason)
log(f"Getting satellite list error: {reason} -> {resp.url}")
if self._rows:
if self._source is SatelliteSource.FLYSAT:
@@ -183,6 +182,8 @@ class SatellitesParser(HTMLParser):
elif source is SatelliteSource.KINGOFSAT:
return self.get_satellites_for_king_of_sat()
return []
def get_satellite(self, sat):
pos = sat[1]
return Satellite(name=f"{pos} {sat[0]}", flags="0",
@@ -478,9 +479,11 @@ class ServicesParser(HTMLParser):
if a[0] != "title":
continue
txt = a[1]
if txt and txt.startswith("Id: "):
sep = "Id: "
if txt and txt.startswith(sep):
# Saving the 'short' name.
self._current_cell.text = txt.lstrip("Id: ")
_, sep, name = txt.partition(sep)
self._current_cell.text = name
elif tag == "img":
img_link = attrs[0][1]
if self._source is SatelliteSource.LYNGSAT:

View File

@@ -1131,6 +1131,18 @@ Author: Dmitriy Yefremov
<placeholder/>
</child>
</object>
<object class="GtkListStore" id="network_model">
<columns>
<!-- column-name name -->
<column type="gchararray"/>
<!-- column-name ip -->
<column type="gchararray"/>
<!-- column-name status -->
<column type="gchararray"/>
<!-- column-name data -->
<column type="PyObject"/>
</columns>
</object>
<object class="GtkListStore" id="rec_paths_model">
<columns>
<!-- column-name icon -->
@@ -1161,6 +1173,12 @@ Author: Dmitriy Yefremov
<signal name="row-deleted" handler="on_recordings_model_changed" swapped="no"/>
<signal name="row-inserted" handler="on_recordings_model_changed" swapped="no"/>
</object>
<object class="GtkTreeModelFilter" id="recordings_filter_model">
<property name="child_model">recordings_model</property>
</object>
<object class="GtkTreeModelSort" id="recordings_sort_model">
<property name="model">recordings_filter_model</property>
</object>
<object class="GtkBox" id="recordings_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -1182,7 +1200,7 @@ Author: Dmitriy Yefremov
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">5</property>
<property name="margin_top">2</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="recordings_header_box">
@@ -1193,6 +1211,28 @@ Author: Dmitriy Yefremov
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="spacing">5</property>
<child>
<object class="GtkToggleButton" id="recordings_filter_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="focus_on_click">False</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Filter</property>
<signal name="toggled" handler="on_recordings_filter_toggled" swapped="no"/>
<child>
<object class="GtkImage" id="recordings_filter_button_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">edit-find-replace-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="recordings_remove_button">
<property name="visible">True</property>
@@ -1208,6 +1248,37 @@ Author: Dmitriy Yefremov
<property name="icon_name">user-trash-symbolic</property>
</object>
</child>
<accelerator key="Delete" signal="clicked"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="recordings_fs_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_bottom">5</property>
<property name="spacing">10</property>
<child>
<object class="GtkSearchEntry" id="recordings_filter_entry">
<property name="can_focus">True</property>
<property name="primary_icon_name">edit-find-replace-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
<property name="visible" bind-source="recordings_filter_button" bind-property="active"/>
<signal name="search-changed" handler="on_recordings_filter_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -1216,13 +1287,78 @@ Author: Dmitriy Yefremov
</packing>
</child>
<child>
<placeholder/>
<object class="GtkBox" id="recordings_search_box">
<property name="can_focus">False</property>
<property name="valign">center</property>
<child>
<object class="GtkSearchEntry" id="recordings_search_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="recordings_search_down_button">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkArrow" id="recordings_down_arrow">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="arrow_type">down</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="recordings_search_up_button">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkArrow" id="recordings_up_arrow">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="arrow_type">up</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<style>
<class name="group"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
@@ -1234,7 +1370,7 @@ Author: Dmitriy Yefremov
<object class="GtkTreeView" id="recordings_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">recordings_model</property>
<property name="model">recordings_sort_model</property>
<property name="enable_grid_lines">both</property>
<property name="tooltip_column">5</property>
<signal name="row-activated" handler="on_recordings_activated" swapped="no"/>
@@ -1245,9 +1381,11 @@ Author: Dmitriy Yefremov
</child>
<child>
<object class="GtkTreeViewColumn" id="rec_service_column">
<property name="resizable">True</property>
<property name="min_width">100</property>
<property name="title" translatable="yes">Service</property>
<property name="alignment">0.5</property>
<property name="sort_column_id">0</property>
<child>
<object class="GtkCellRendererText" id="rec_service_renderer">
<property name="xalign">0.49000000953674316</property>
@@ -1260,10 +1398,12 @@ Author: Dmitriy Yefremov
</child>
<child>
<object class="GtkTreeViewColumn" id="rec_title_column">
<property name="sizing">autosize</property>
<property name="resizable">True</property>
<property name="min_width">150</property>
<property name="title" translatable="yes">Title</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererText" id="rec_title_renderer">
<property name="xpad">5</property>
@@ -1280,6 +1420,7 @@ Author: Dmitriy Yefremov
<property name="min_width">100</property>
<property name="title" translatable="yes">Time</property>
<property name="alignment">0.5</property>
<property name="sort_column_id">2</property>
<child>
<object class="GtkCellRendererText" id="rec_time_renderer">
<property name="xpad">5</property>
@@ -1295,6 +1436,7 @@ Author: Dmitriy Yefremov
<property name="min_width">100</property>
<property name="title" translatable="yes">Length</property>
<property name="alignment">0.5</property>
<property name="sort_column_id">3</property>
<child>
<object class="GtkCellRendererText" id="rec_len_renderer">
<property name="xalign">0.49000000953674316</property>
@@ -1312,6 +1454,7 @@ Author: Dmitriy Yefremov
<property name="title" translatable="yes">File</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<property name="sort_column_id">4</property>
<child>
<object class="GtkCellRendererText" id="rec_file_renderer">
<property name="ellipsize">end</property>
@@ -1328,6 +1471,7 @@ Author: Dmitriy Yefremov
<property name="title" translatable="yes">Description</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<property name="sort_column_id">5</property>
<child>
<object class="GtkCellRendererText" id="rec_desc_renderer">
<property name="ellipsize">end</property>
@@ -1344,7 +1488,7 @@ Author: Dmitriy Yefremov
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
@@ -1386,7 +1530,7 @@ Author: Dmitriy Yefremov
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
</object>
@@ -1469,7 +1613,7 @@ Author: Dmitriy Yefremov
</object>
</child>
<child type="label">
<object class="GtkLabel">
<object class="GtkLabel" id="recordings_path_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Paths</property>
@@ -2297,59 +2441,163 @@ Author: Dmitriy Yefremov
<object class="GtkBox" id="control_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">2</property>
<property name="orientation">vertical</property>
<property name="spacing">10</property>
<child>
<object class="GtkBox" id="power_button_box">
<object class="GtkBox" id="control_header_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="margin_left">25</property>
<property name="margin_right">25</property>
<property name="margin_left">20</property>
<property name="margin_right">20</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="spacing">15</property>
<child>
<object class="GtkButton" id="standby_button">
<property name="width_request">70</property>
<property name="visible">True</property>
<object class="GtkToggleButton" id="control_network_button">
<property name="label">gtk-network</property>
<property name="width_request">100</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Standby</property>
<property name="action_name">app.on_standby</property>
<child>
<object class="GtkImage" id="standby_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">system-log-out</property>
<property name="icon_size">1</property>
</object>
</child>
<property name="valign">center</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="toggled" handler="on_network_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="wake_up_button">
<property name="width_request">70</property>
<child type="center">
<object class="GtkBox" id="power_button_box">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Wake Up</property>
<property name="action_name">app.on_wake_up</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child>
<object class="GtkImage" id="wake_up_image">
<object class="GtkButton" id="standby_button">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">document-revert</property>
<property name="icon_size">1</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Standby</property>
<property name="action_name">app.on_standby</property>
<child>
<object class="GtkImage" id="standby_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">system-log-out</property>
<property name="icon_size">1</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="wake_up_button">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Wake Up</property>
<property name="action_name">app.on_wake_up</property>
<child>
<object class="GtkImage" id="wake_up_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">document-revert</property>
<property name="icon_size">1</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="reboot_button">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Reboot</property>
<property name="action_name">app.on_reboot</property>
<child>
<object class="GtkImage" id="reboot_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">view-refresh</property>
<property name="icon_size">1</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="restart_gui_butto">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Restart GUI</property>
<property name="action_name">app.on_restart_gui</property>
<child>
<object class="GtkImage" id="restart_gui_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">window-new</property>
<property name="icon_size">1</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="shutdown_butto">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Shutdown</property>
<property name="action_name">app.on_shutdown</property>
<child>
<object class="GtkImage" id="shutdown_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">application-exit</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<style>
<class name="group"/>
</style>
</object>
<packing>
<property name="expand">False</property>
@@ -2357,80 +2605,6 @@ Author: Dmitriy Yefremov
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="reboot_button">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Reboot</property>
<property name="action_name">app.on_reboot</property>
<child>
<object class="GtkImage" id="reboot_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">view-refresh</property>
<property name="icon_size">1</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="restart_gui_butto">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Restart GUI</property>
<property name="action_name">app.on_restart_gui</property>
<child>
<object class="GtkImage" id="restart_gui_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">window-new</property>
<property name="icon_size">1</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="shutdown_butto">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Shutdown</property>
<property name="action_name">app.on_shutdown</property>
<child>
<object class="GtkImage" id="shutdown_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property>
<property name="icon_name">application-exit</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<style>
<class name="group"/>
</style>
</object>
<packing>
<property name="expand">False</property>
@@ -2443,11 +2617,108 @@ Author: Dmitriy Yefremov
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">10</property>
<child>
<object class="GtkFrame" id="control_network_frame">
<property name="width_request">240</property>
<property name="can_focus">False</property>
<property name="label_xalign">0.5</property>
<property name="shadow_type">in</property>
<property name="visible" bind-source="control_network_button" bind-property="active"/>
<child>
<object class="GtkBox" id="network_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow" id="network_scrolled_window">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="network_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">network_model</property>
<property name="enable_search">False</property>
<property name="tooltip_column">3</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="network_view_selection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="network_name_column">
<property name="title" translatable="yes">Name</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="network_name_renderer"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="network_ip_column">
<property name="title" translatable="yes">IP</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="network_ip_renderer"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="network_status_column">
<property name="title" translatable="yes">Status</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="network_status_renderer"/>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="info_box_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="label_xalign">0.5</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkBox" id="info_box">
@@ -2458,27 +2729,6 @@ Author: Dmitriy Yefremov
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkViewport" id="screenshot_view_port">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<child>
<object class="GtkDrawingArea" id="screenshot_area">
<property name="can_focus">False</property>
<signal name="draw" handler="on_screenshot_draw" swapped="no"/>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="remote_signal_box">
<property name="visible">True</property>
@@ -2628,6 +2878,27 @@ Author: Dmitriy Yefremov
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkViewport" id="screenshot_view_port">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">2</property>
<property name="margin_right">2</property>
<property name="margin_top">2</property>
<property name="margin_bottom">2</property>
<child>
<object class="GtkDrawingArea" id="screenshot_area">
<property name="can_focus">False</property>
<signal name="draw" handler="on_screenshot_draw" swapped="no"/>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child type="label_item">
@@ -2637,7 +2908,7 @@ Author: Dmitriy Yefremov
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
@@ -2645,7 +2916,7 @@ Author: Dmitriy Yefremov
<property name="width_request">300</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="label_xalign">0.5</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkBox" id="remote_control_box">
@@ -2654,8 +2925,8 @@ Author: Dmitriy Yefremov
<property name="valign">center</property>
<property name="margin_left">25</property>
<property name="margin_right">25</property>
<property name="margin_top">25</property>
<property name="margin_bottom">25</property>
<property name="margin_top">20</property>
<property name="margin_bottom">20</property>
<property name="orientation">vertical</property>
<property name="spacing">5</property>
<child>
@@ -2670,6 +2941,7 @@ Author: Dmitriy Yefremov
<property name="margin_bottom">5</property>
<property name="row_spacing">5</property>
<property name="column_spacing">5</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkButton" id="control_ok_button">
<property name="label" translatable="yes">OK</property>
@@ -3052,7 +3324,7 @@ audio-volume-medium-symbolic</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin_top">50</property>
<property name="margin_top">15</property>
<property name="label_xalign">0.5</property>
<property name="shadow_type">none</property>
<child>
@@ -3065,10 +3337,12 @@ audio-volume-medium-symbolic</property>
<property name="margin_right">5</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="homogeneous">True</property>
<property name="layout_style">expand</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">All</property>
<property name="width_request">75</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -3137,7 +3411,7 @@ audio-volume-medium-symbolic</property>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
</object>

View File

@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018-2021 Dmitriy Yefremov
# Copyright (c) 2018-2022 Dmitriy Yefremov
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -36,6 +36,7 @@ from urllib.parse import quote
from gi.repository import GLib
from .dialogs import get_builder, show_dialog, DialogType, get_message
from .main_helper import get_base_paths, get_base_model
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, Page, Column, KeyboardKey, IS_GNOME_SESSION
from ..commons import run_task, run_with_delay, log, run_idle
from ..connections import HttpAPI, UtfFTP
@@ -659,13 +660,20 @@ class RecordingsTool(Gtk.Box):
"on_path_activated": self.on_path_activated,
"on_recordings_activated": self.on_recordings_activated,
"on_recording_remove": self.on_recording_remove,
"on_recordings_model_changed": self.on_recordings_model_changed}
"on_recordings_model_changed": self.on_recordings_model_changed,
"on_recordings_filter_changed": self.on_recordings_filter_changed,
"on_recordings_filter_toggled": self.on_recordings_filter_toggled}
builder = get_builder(UI_RESOURCES_PATH + "control.glade", handlers,
objects=("recordings_box", "recordings_model", "rec_paths_model"))
objects=("recordings_box", "recordings_model", "rec_paths_model",
"recordings_sort_model", "recordings_filter_model"))
self._rec_view = builder.get_object("recordings_view")
self._paths_view = builder.get_object("recordings_paths_view")
self._paned = builder.get_object("recordings_paned")
self._model = builder.get_object("recordings_model")
self._filter_model = builder.get_object("recordings_filter_model")
self._filter_model.set_visible_func(self.recordings_filter_function)
self._filter_entry = builder.get_object("recordings_filter_entry")
self._recordings_count_label = builder.get_object("recordings_count_label")
self.pack_start(builder.get_object("recordings_box"), True, True, 0)
if settings.alternate_layout:
@@ -675,7 +683,7 @@ class RecordingsTool(Gtk.Box):
self.show()
def clear_data(self):
self._rec_view.get_model().clear()
self._model.clear()
self._paths_view.get_model().clear()
def on_layout_changed(self, app, alt_layout):
@@ -752,9 +760,8 @@ class RecordingsTool(Gtk.Box):
@run_idle
def update_recordings_data(self, recordings):
model = self._rec_view.get_model()
model.clear()
list(map(model.append, (self.get_recordings_row(r) for r in recordings.get("recordings", []))))
self._model.clear()
list(map(self._model.append, (self.get_recordings_row(r) for r in recordings.get("recordings", []))))
def get_recordings_row(self, rec):
service = rec.get("e2servicename")
@@ -781,6 +788,9 @@ class RecordingsTool(Gtk.Box):
return
model, paths = self._rec_view.get_selection().get_selected_rows()
paths = get_base_paths(paths, model)
model = get_base_model(model)
if paths and self._ftp:
for file, itr in ((model[p][-1].get("e2filename", ""), model.get_iter(p)) for p in paths):
resp = self._ftp.delete_file(file)
@@ -793,6 +803,17 @@ class RecordingsTool(Gtk.Box):
def on_recordings_model_changed(self, model, path, itr=None):
self._recordings_count_label.set_text(str(len(model)))
def on_recordings_filter_changed(self, entry):
self._filter_model.refilter()
def recordings_filter_function(self, model, itr, data):
txt = self._filter_entry.get_text().upper()
return next((s for s in model.get(itr, 0, 1, 2, 3, 4, 5) if s and txt in s.upper()), False)
def on_recordings_filter_toggled(self, button):
if not button.get_active():
self._filter_entry.set_text("")
def on_playback(self, box, state):
""" Updates state of the UI elements for playback mode. """
if self._settings.play_streams_mode is PlayStreamsMode.BUILT_IN:
@@ -820,10 +841,11 @@ class ControlTool(Gtk.Box):
self._pix = None
handlers = {"on_volume_changed": self.on_volume_changed,
"on_screenshot_draw": self.on_screenshot_draw}
"on_screenshot_draw": self.on_screenshot_draw,
"on_network_toggled": self.on_network_toggled}
builder = get_builder(UI_RESOURCES_PATH + "control.glade", handlers,
objects=("control_box", "volume_adjustment"))
objects=("control_box", "volume_adjustment", "network_model"))
self.pack_start(builder.get_object("control_box"), True, True, 0)
self._remote_box = builder.get_object("remote_box")
@@ -838,7 +860,10 @@ class ControlTool(Gtk.Box):
self._ber_level_bar = builder.get_object("ber_level_bar")
self._agc_level_bar = builder.get_object("agc_level_bar")
self._volume_button = builder.get_object("volume_button")
self._network_button = builder.get_object("control_network_button")
self._header_box = builder.get_object("control_header_box")
self.init_actions(app)
if settings.alternate_layout:
self.on_layout_changed(app, True)
@@ -876,7 +901,11 @@ class ControlTool(Gtk.Box):
app.set_action("on_screenshot_osd", self.on_screenshot_osd)
def on_layout_changed(self, app, alt_layout):
self._remote_box.reorder_child(self._remote_box.get_children()[0], 1)
children = self._remote_box.get_children()
self._remote_box.reorder_child(children[0], len(children) - 1)
self._remote_box.reorder_child(children[-1], 0)
pack_type = Gtk.PackType.END if alt_layout else Gtk.PackType.START
self._header_box.set_child_packing(self._network_button, False, False, 0, pack_type)
# ***************** Remote controller ********************* #
@@ -1006,3 +1035,9 @@ class ControlTool(Gtk.Box):
self._snr_level_bar.set_value(int(snr.strip("%N/A") or 0))
self._agc_level_bar.set_value(int(acg.rstrip("%N/A") or 0))
self._ber_level_bar.set_value(int(ber.rstrip("N/A") or 0))
# ***************** Network explorer ********************** #
@run_task
def on_network_toggled(self, button):
pass

View File

@@ -40,7 +40,7 @@ Author: Dmitriy Yefremov
<property name="icon_name">system-help</property>
<property name="type_hint">normal</property>
<property name="program_name">DemonEditor</property>
<property name="version">2.2.1 Beta</property>
<property name="version">2.2.4 Beta</property>
<property name="copyright">2018-2022 Dmitriy Yefremov
</property>
<property name="comments" translatable="yes">Enigma2 channel and satellite list editor.</property>

View File

@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018-2021 Dmitriy Yefremov
# Copyright (c) 2018-2022 Dmitriy Yefremov
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -28,10 +28,10 @@
""" Common module for showing dialogs """
import gettext
import xml.etree.ElementTree as ET
from enum import Enum
from functools import lru_cache
from pathlib import Path
import xml.etree.ElementTree as ET
from app.commons import run_idle
from app.settings import SEP, IS_WIN
@@ -238,15 +238,16 @@ def get_builder(path, handlers=None, use_str=False, objects=None, tag="property"
def translate_xml(path, tag="property"):
"""
Used to translate GUI from * .glade files in MS Windows.
""" Used to translate GUI from * .glade files in MS Windows.
More info: https://gitlab.gnome.org/GNOME/gtk/-/issues/569
"""
et = ET.parse(path)
root = et.getroot()
for e in root.iter(tag):
if e.attrib.get("translatable", None) == "yes":
for e in root.iter():
if e.tag == tag and e.attrib.get("translatable", None) == "yes":
e.text = get_message(e.text)
elif e.tag == "item" and e.attrib.get("translatable", None) == "yes":
e.text = get_message(e.text)
return ET.tostring(root, encoding="unicode", method="xml")

View File

@@ -108,7 +108,7 @@ class EpgDialog:
self._info_bar = builder.get_object("info_bar")
self._message_label = builder.get_object("info_bar_message_label")
self._assign_ref_popup_item = builder.get_object("bouquet_assign_ref_popup_item")
self._left_header_box = builder.get_object("left_header_box")
self._left_action_box = builder.get_object("left_action_box")
self._xml_download_progress_bar = builder.get_object("xml_download_progress_bar")
# Filter
self._filter_bar = builder.get_object("filter_bar")
@@ -500,7 +500,7 @@ class EpgDialog:
@run_idle
def update_active_header_elements(self, state):
self._left_header_box.set_sensitive(state)
self._left_action_box.set_sensitive(state)
self._xml_download_progress_bar.set_visible(not state)
self._source_info_label.set_text("" if state else "Downloading XML:")

View File

@@ -666,7 +666,7 @@ class M3uImportDialog(IptvListDialog):
progress_box.pack_start(load_label, False, False, 0)
# Picons
self._picons_switch = Gtk.Switch(visible=True)
self._picon_box = Gtk.HBox(visible=True, sensitive=False, spacing=2)
self._picon_box = Gtk.HBox(visible=True, sensitive=False, spacing=5)
self._picon_box.pack_end(self._picons_switch, False, False, 0)
self._picon_box.pack_end(Gtk.Label(visible=True, label=get_message("Download picons")), False, False, 0)
# Extra box

View File

@@ -1,19 +1,37 @@
* {
-GtkDialog-action-area-border: 6em;
background-clip: padding-box;
-GtkScrolledWindow-scrollbar-spacing: 0;
-GtkToolItemGroup-expander-size: 11;
-GtkWidget-text-handle-width: 20;
-GtkWidget-text-handle-height: 20;
-GtkDialog-button-spacing: 12;
-GtkDialog-action-area-border: 6;
}
entry {
min-height: 2.0em;
padding: 0.2em;
}
entry > image {
padding-left: 0.3em;
padding-right: 0.3em;
}
button {
min-height: 1.5em;
min-width: 1em;
padding-left: 0.4em;
padding-right: 0.4em;
padding-top: 0.1em;
padding-bottom: 0.1em;
min-height: 1.2em;
min-width: 1.5em;
padding-top: 0.3em;
padding-bottom: 0.3em;
}
button:active, button:checked {
color: @theme_selected_fg_color;
background-image: linear-gradient(@theme_selected_bg_color, @theme_selected_bg_color);
}
combobox {
min-height: 2.2em;
}
spinbutton {
@@ -33,11 +51,25 @@ infobar {
min-height: 2em;
}
revealer > box > button {
padding: 0.2em;
}
switch slider {
min-height: 1.5em;
min-width: 1.5em;
}
popover .view {
background-color: transparent;
}
.font > box {
min-height: 1.5em;
padding-top: 0.1em;
padding-bottom: 0.1em;
}
.dialog-action-area button {
margin-bottom: 0.6em;
}

View File

@@ -1587,7 +1587,7 @@ Author: Dmitriy Yefremov
<object class="GtkLabel" id="app_ver_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">2.2.1 Beta</property>
<property name="label">2.2.4 Beta</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>

View File

@@ -2671,7 +2671,7 @@ class Application(Gtk.Application):
elif key is KeyboardKey.DELETE:
self.on_delete(view)
elif ctrl and key is KeyboardKey.R or key is KeyboardKey.F2:
if event.state & Gdk.ModifierType.SHIFT_MASK:
if event.state & Gdk.ModifierType.MOD1_MASK: # ALT
self.on_rename_for_bouquet()
else:
self.on_rename(view)

View File

@@ -709,6 +709,7 @@ Author: Dmitriy Yefremov
<property name="tooltip_text" translatable="yes">Drag the services to the desired picon or picon to the list of selected services.</property>
<property name="model">picons_src_sort_model</property>
<property name="fixed_height_mode">True</property>
<property name="rubber_banding">True</property>
<property name="enable_grid_lines">horizontal</property>
<property name="tooltip_column">0</property>
<property name="activate_on_single_click">True</property>
@@ -720,7 +721,9 @@ Author: Dmitriy Yefremov
<signal name="key-press-event" handler="on_tree_view_key_press" swapped="no"/>
<signal name="query-tooltip" handler="on_view_query_tooltip" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection" id="picons_src_view_selection"/>
<object class="GtkTreeSelection" id="picons_src_view_selection">
<property name="mode">multiple</property>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="src_picon_column">
@@ -841,9 +844,10 @@ Author: Dmitriy Yefremov
<object class="GtkTreeView" id="picons_dest_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Drag the services to the desired picon or picon to the list of selected services. </property>
<property name="tooltip_text" translatable="yes">Drag the services to the desired picon or picon to the list of selected services.</property>
<property name="model">picons_dst_sort_model</property>
<property name="fixed_height_mode">True</property>
<property name="rubber_banding">True</property>
<property name="enable_grid_lines">horizontal</property>
<property name="tooltip_column">0</property>
<property name="activate_on_single_click">True</property>
@@ -856,7 +860,9 @@ Author: Dmitriy Yefremov
<signal name="key-press-event" handler="on_tree_view_key_press" swapped="no"/>
<signal name="query-tooltip" handler="on_view_query_tooltip" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection" id="picons_dest_view_selection"/>
<object class="GtkTreeSelection" id="picons_dest_view_selection">
<property name="mode">multiple</property>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="dest_picon_column">

View File

@@ -453,12 +453,12 @@ class PiconManager(Gtk.Box):
def on_send_button_drag_data_received(self, button, drag_context, x, y, data, info, time):
path = self.get_path_from_uris(data)
if path:
self.on_send(files_filter={path.name}, path=path.parent)
self.on_picons_send(files_filter={path.name}, path=path.parent)
def on_download_button_drag_data_received(self, button, drag_context, x, y, data, info, time):
path = self.get_path_from_uris(data)
if path:
self.on_download(files_filter={path.name})
self.on_picons_download(files_filter={path.name})
def on_remove_button_drag_data_received(self, button, drag_context, x, y, data, info, time):
path = self.get_path_from_uris(data)
@@ -526,12 +526,12 @@ class PiconManager(Gtk.Box):
def on_selective_send(self, view):
path = self.get_selected_path(view)
if path:
self.on_send(files_filter={path.name}, path=path.parent)
self.on_picons_send(files_filter={path.name}, path=path.parent)
def on_selective_download(self, view):
path = self.get_selected_path(view)
if path:
self.on_download(files_filter={path.name})
self.on_picons_download(files_filter={path.name})
def on_selective_remove(self, view):
path = self.get_selected_path(view)
@@ -541,20 +541,32 @@ class PiconManager(Gtk.Box):
def on_local_remove(self, view):
model, paths = view.get_selection().get_selected_rows()
if paths and show_dialog(DialogType.QUESTION, self._app_window) == Gtk.ResponseType.OK:
itr = model.get_iter(paths.pop())
p_path = Path(model.get_value(itr, 2)).resolve()
if p_path.is_file():
p_path.unlink()
base_model = get_base_model(model)
filter_model = model.get_model()
itr = filter_model.convert_iter_to_child_iter(model.convert_iter_to_child_iter(itr))
base_model.remove(itr)
self._app.update_picons()
base_model = get_base_model(model)
filter_model = model.get_model()
to_del = []
for p in paths:
itr = model.get_iter(p)
p_path = Path(model.get_value(itr, 2)).resolve()
if p_path.is_file():
p_path.unlink()
to_del.append(filter_model.convert_iter_to_child_iter(model.convert_iter_to_child_iter(itr)))
list(map(base_model.remove, to_del))
self._app.update_picons()
if view is self._picons_dest_view:
self._dst_count_label.set_text(str(len(model)))
def on_send(self, item=None, files_filter=None, path=None):
def on_send(self, item=None):
view = self._picons_src_view if self._picons_src_view.is_focus() else self._picons_dest_view
model, paths = view.get_selection().get_selected_rows()
if paths:
self.on_picons_send(files_filter={Path(model[p][-1]).resolve().name for p in paths})
else:
self._app.show_error_message("No selected item!")
def on_picons_send(self, item=None, files_filter=None, path=None):
dest_path = path or self._settings.profile_picons_path
settings = Settings(self._settings.settings)
settings.profile_picons_path = f"{dest_path}{SEP}"
@@ -567,7 +579,10 @@ class PiconManager(Gtk.Box):
Gtk.MessageType.INFO),
files_filter=files_filter))
def on_download(self, item=None, files_filter=None, path=None):
def on_download(self, item=None):
self.on_picons_download()
def on_picons_download(self, item=None, files_filter=None, path=None):
path = path or self._settings.profile_picons_path
settings = Settings(self._settings.settings)
settings.profile_picons_path = path + SEP

View File

@@ -195,7 +195,6 @@ Author: Dmitriy Yefremov
<object class="GtkMenu" id="transponder_popup_menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="reserve_toggle_size">False</property>
<child>
<object class="GtkImageMenuItem" id="add_tr_popup_menu_item">
<property name="label" translatable="yes">Add</property>
@@ -1468,7 +1467,6 @@ Author: Dmitriy Yefremov
<property name="tooltip_text" translatable="yes">Source</property>
<property name="active">0</property>
<items>
<item id="FLYSAT" translatable="yes">FlySat</item>
<item id="LYNGSAT" translatable="yes">LyngSat</item>
<item id="KINGOFSAT" translatable="yes">KingOfSat</item>
</items>

View File

@@ -530,11 +530,11 @@ class UpdateDialog:
@run_task
def get_sat_list(self, src, callback):
sat_src = SatelliteSource.FLYSAT
sat_src = SatelliteSource.LYNGSAT
if src == 1:
sat_src = SatelliteSource.LYNGSAT
elif src == 2:
sat_src = SatelliteSource.KINGOFSAT
elif src == 2:
sat_src = SatelliteSource.FLYSAT
sats = self._parser.get_satellites_list(sat_src)
callback(sats)
@@ -744,9 +744,7 @@ class ServicesUpdateDialog(UpdateDialog):
self._transponder_view.connect("select_all", lambda w: self.update_transponder_selection(True))
self._transponder_paned.set_visible(True)
self._source_box.remove(0)
self._source_box.connect("changed", self.on_update_satellites_list)
self._source_box.set_active(0)
@run_idle
def on_receive_data(self, item):
@@ -843,8 +841,8 @@ class ServicesUpdateDialog(UpdateDialog):
sat_src = SatelliteSource.LYNGSAT
if src == 1:
sat_src = SatelliteSource.KINGOFSAT
self._services_parser.source = sat_src
self._services_parser.source = sat_src
sats = self._parser.get_satellites_list(sat_src)
callback(sats)
self.is_download = False

View File

@@ -136,7 +136,7 @@ Author: Dmitriy Yefremov
<child>
<object class="GtkStackSwitcher" id="main_stack_switcher">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can_focus">True</property>
<property name="halign">center</property>
<property name="margin_left">15</property>
<property name="margin_right">15</property>
@@ -464,6 +464,7 @@ Author: Dmitriy Yefremov
<property name="can_focus">False</property>
<property name="row_spacing">5</property>
<property name="column_spacing">10</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkLabel" id="data_path_label">
<property name="visible">True</property>
@@ -590,6 +591,7 @@ Author: Dmitriy Yefremov
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="column_spacing">10</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkLabel" id="record_path_label">
<property name="visible">True</property>
@@ -625,7 +627,7 @@ Author: Dmitriy Yefremov
<object class="GtkLabel" id="record_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Record:</property>
<property name="label" translatable="yes">Recordings:</property>
</object>
</child>
</object>
@@ -1151,7 +1153,6 @@ Author: Dmitriy Yefremov
<object class="GtkComboBoxText" id="audio_codec_combo_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="active_id">mp3</property>
<items>
<item id="mp3" translatable="yes">mp3</item>
@@ -1178,7 +1179,6 @@ Author: Dmitriy Yefremov
<object class="GtkComboBoxText" id="audio_sample_rate_combo_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="active_id">44100</property>
<items>
<item id="8000" translatable="yes">8000</item>
@@ -1209,7 +1209,6 @@ Author: Dmitriy Yefremov
<property name="width_request">75</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="active_id">2</property>
<items>
<item id="1" translatable="yes">1</item>
@@ -2552,7 +2551,7 @@ Author: Dmitriy Yefremov
<object class="GtkBox" id="enable_yt_dl_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Enables parsing links using youtube-dl to get direct media links.</property>
<property name="tooltip_text" translatable="yes">Enables URL parsing using youtube-dl to get direct links to media.</property>
<child>
<object class="GtkLabel" id="enable_yt_dl_label">
<property name="visible">True</property>
@@ -2570,7 +2569,6 @@ Author: Dmitriy Yefremov
<object class="GtkSwitch" id="enable_yt_dl_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Enables parsing links using youtube-dl to get direct links to media</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
@@ -2649,7 +2647,7 @@ Author: Dmitriy Yefremov
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">1</property>
</packing>
</child>
<child>
@@ -2689,7 +2687,7 @@ Author: Dmitriy Yefremov
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
<property name="position">2</property>
</packing>
</child>
</object>
@@ -3392,7 +3390,7 @@ Author: Dmitriy Yefremov
<child>
<object class="GtkButton" id="test_connection_button">
<property name="label" translatable="yes">Test</property>
<property name="width_request">110</property>
<property name="width_request">120</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>

View File

@@ -309,7 +309,7 @@ class SettingsDialog:
self._record_data_path_field.set_text(self._settings.records_path)
self._before_save_switch.set_active(self._settings.backup_before_save)
self._before_downloading_switch.set_active(self._settings.backup_before_downloading)
self._play_streams_combo_box.set_active(self._settings.play_streams_mode.value)
self._play_streams_combo_box.set_active_id(str(self._settings.play_streams_mode.value))
self._stream_lib_combo_box.set_active_id(self._settings.stream_lib)
self._double_click_combo_box.set_active_id(str(self._settings.fav_click_mode))
self._allow_main_list_playback_switch.set_active(self._settings.main_list_playback)
@@ -373,7 +373,7 @@ class SettingsDialog:
self._ext_settings.profiles = self._settings.profiles
self._ext_settings.backup_before_save = self._before_save_switch.get_active()
self._ext_settings.backup_before_downloading = self._before_downloading_switch.get_active()
self._ext_settings.play_streams_mode = PlayStreamsMode(self._play_streams_combo_box.get_active())
self._ext_settings.play_streams_mode = PlayStreamsMode(int(self._play_streams_combo_box.get_active_id()))
self._ext_settings.stream_lib = self._stream_lib_combo_box.get_active_id()
self._ext_settings.fav_click_mode = int(self._double_click_combo_box.get_active_id())
self._ext_settings.main_list_playback = self._allow_main_list_playback_switch.get_active()

View File

@@ -9,3 +9,12 @@ switch {
spinbutton entry {
min-height: 16px;
}
button > image {
padding: 2px;
}
grid > button {
padding-left: 15px;
padding-right: 15px;
}

40
build/BUILD_WIN.md Normal file
View File

@@ -0,0 +1,40 @@
## Launch
The best way to run this program from source is using of [MSYS2](https://www.msys2.org/) platform.
1. Download and install the platform as described [here](https://www.msys2.org/) up to point 4.
2. Launch **mingw64** shell.
![mingw64](https://user-images.githubusercontent.com/7511379/161400639-898ceb10-7de8-4557-bde1-25fe32bdfb03.png)
3. Run first `pacman -Suy` After that, you may need to restart the terminal and re-run the update command.
4. Install minimal required packages:
`pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-gobject mingw-w64-x86_64-python3-pip mingw-w64-x86_64-python3-requests`
Optional: `pacman -S mingw-w64-x86_64-python3-pillow`
To support streams playback, install the following packages (the list may not be complete):
For [MPV](https://mpv.io/) `pacman -S mingw-w64-x86_64-mpv`,
For [GStreamer](https://gstreamer.freedesktop.org/) `pacman -S mingw-w64-x86_64-gst-libav mingw-w64-x86_64-gst-plugins-bad mingw-w64-x86_64-gst-plugins-base mingw-w64-x86_64-gst-plugins-good mingw-w64-x86_64-gstreamer`
5. Download and unzip the archive with sources from preferred branch (e.g. [master](https://github.com/DYefremov/DemonEditor/archive/refs/heads/master.zip)) in to folder where MSYS2 is installed. E.g: `c:\msys64\home\username\`
6. Run mingw64 shell. Go to the folder where the program was unpacked. E.g: `cd DemonEditor/`
And run: `./start.py`
## Building a package
To build a standalone package, we can use [PyInstaller](https://pyinstaller.readthedocs.io/en/stable/).
1. Launch mingw64 shell.
2. Install PyInstaller via pip: `pip3 install pyinstaller`
3. Go to the folder where the program was unpacked. E.g: `c:\msys64\home\username\DemonEditor\`
4. Сopy and replace the files from the /build/win/ folder to the root .
5. Go to the folder with the program in the running terminal: `cd DemonEditor/`
6. Give the following command: `pyinstaller.exe DemonEditor.spec`
7. Wait until the operation end. In the dist folder you will find a ready-made build.
### Appearance
To change the look we can use third party [Gtk3 themes and Icon sets](https://www.gnome-look.org).
To set the default theme:
1. Сreate a folder "`\etc\gtk-3.0\`" in the root of the finished build folder.
2. Create a _settings.ini_ file in this folder with the following content:
```
[Settings]
gtk-icon-theme-name = Adwaita
gtk-theme-name = Windows-10
```
In this case, we are using the default icon theme "Adwaita" and the [third party theme](https://github.com/B00merang-Project/Windows-10) "Windows-10".
Themes and icon sets should be located in the `share\themes` and `share\icons` folders respectively.
To fine-tune the default theme you use, you can use the _win_style.css_ file in the `ui` folder.
You can find more info about changing the appearance of Gtk applications on the Web yourself.

View File

@@ -1,5 +1,5 @@
#!/bin/bash
VER="2.2.1_Beta"
VER="2.2.4_Beta"
B_PATH="dist/DemonEditor"
DEB_PATH="$B_PATH/usr/share/demoneditor"

View File

@@ -1,5 +1,5 @@
Package: demon-editor
Version: 2.2.1-Beta
Version: 2.2.4-Beta
Section: utils
Priority: optional
Architecture: all

View File

@@ -32,6 +32,16 @@ a = Analysis([EXE_NAME],
hiddenimports=['fileinput', 'uuid'],
hookspath=[],
runtime_hooks=[],
hooksconfig={
"gi": {
"languages": ["en", "be", "es", "it", "nl",
"pl", "pt", "ru", "tr", "zh_CN"],
"module-versions": {
"Gtk": "3.0",
"GtkSource": "3",
},
},
},
excludes=excludes,
win_no_prefer_redirects=False,
win_private_assemblies=False,
@@ -69,7 +79,8 @@ app = BUNDLE(coll,
'CFBundleGetInfoString': "Enigma2 channel and satellite editor",
'LSApplicationCategoryType': 'public.app-category.utilities',
'LSMinimumSystemVersion': '10.13',
'CFBundleShortVersionString': f"2.2.1.{BUILD_DATE} Beta",
'CFBundleShortVersionString': f"2.2.4.{BUILD_DATE} Beta",
'NSHumanReadableCopyright': u"Copyright © 2022, Dmitriy Yefremov",
'NSRequiresAquaSystemAppearance': 'false'
'NSRequiresAquaSystemAppearance': 'false',
'NSHighResolutionCapable': 'true'
})

View File

@@ -30,6 +30,16 @@ a = Analysis([EXE_NAME],
hiddenimports=['fileinput', 'uuid', 'ctypes.wintypes'],
hookspath=[],
runtime_hooks=[],
hooksconfig={
"gi": {
"languages": ["en", "be", "es", "it", "nl",
"pl", "pt", "ru", "tr", "zh_CN"],
"module-versions": {
"Gtk": "3.0",
"GtkSource": "3",
},
},
},
excludes=excludes,
win_no_prefer_redirects=False,
win_private_assemblies=False,

View File

@@ -1,8 +1,14 @@
#!/usr/bin/env python3
import os
import ssl
if __name__ == "__main__":
from multiprocessing import freeze_support
from app.ui.main import start_app
os.environ["PYTHONUTF8"] = "1"
# TODO There needs to be a more "correct" way.
ssl._create_default_https_context = ssl._create_unverified_context
freeze_support()
start_app()

View File

@@ -1253,6 +1253,9 @@ msgstr "Выконваецца загрузка дадзеных!"
msgid "Recordings"
msgstr "Запісы"
msgid "Recordings:"
msgstr "Запісы:"
msgid "Help"
msgstr "Даведка"
@@ -1354,3 +1357,6 @@ msgstr "Усе букеты"
msgid "Playback from the main list"
msgstr "Прайграванне з асноўнага спіса"
msgid "Enables URL parsing using youtube-dl to get direct links to media."
msgstr "Улучае аналіз URL-адрасоў з дапамогай youtube-dl для атрымання прамых спасылак на медыя."

View File

@@ -1267,6 +1267,9 @@ msgstr "Daten werden geladen!"
msgid "Recordings"
msgstr "Aufnahmen"
msgid "Recordings:"
msgstr "Aufnahmen:"
msgid "Help"
msgstr "Hilfe"
@@ -1368,3 +1371,6 @@ msgstr "Alle Bouquets"
msgid "Playback from the main list"
msgstr "Wiedergabe aus der Hauptliste"
msgid "Enables URL parsing using youtube-dl to get direct links to media."
msgstr "Aktiviert URL-Parsing mit youtube-dl, um direkte Links zu Medien zu erhalten."

View File

@@ -53,7 +53,7 @@ msgstr "Assegna"
msgid "Assign file"
msgstr "Assegna file"
msgid "Bouquet Details"
msgid "Bouquet details"
msgstr "Dettagli bouquet"
msgid "Bouquets"
@@ -93,7 +93,7 @@ msgid "Import m3u"
msgstr "Importa m3u"
msgid "Import m3u file"
msgstr "Importa file m3u"
msgstr "Importa m3u"
msgid "List configuration"
msgstr "Visualizza configurazione"
@@ -294,7 +294,7 @@ msgid "Providers"
msgstr "Provider"
msgid "Receive picons"
msgstr "Ricevi picons"
msgstr "Scarica picons"
msgid "Picons name format:"
msgstr "Formato del nome:"
@@ -312,7 +312,7 @@ msgid "Picons download tool"
msgstr "Strumento per scaricare picons"
msgid "Transfer to receiver"
msgstr "Trasferisci al ricevitore"
msgstr "Trasferisci al ricevitore"
msgid "Downloader"
msgstr "Scarica"
@@ -330,13 +330,13 @@ msgid "Path to Enigma2 picons:"
msgstr "Persorso picons su Enigma2:"
msgid "Specify the correct position value for the provider!"
msgstr "Specificare il valore della posizione per il provider!"
msgstr "Specifica il valore della posizione per il provider!"
msgid "Converter between name formats"
msgstr "Convertitore per il formato dei nomi"
msgid "Receive picons for providers"
msgstr "Ricevi picons per providers"
msgstr "Scarica picons per providers"
msgid "Load satellite providers."
msgstr "Carica i providers satellitari"
@@ -654,7 +654,7 @@ msgid "No bouquet file is selected!"
msgstr "Non è stato selezionato alcun file contenente bouquet"
msgid "Remove all unused"
msgstr "Eliminare tutti quelli non usati"
msgstr "Elimina tutti quelli non usati"
msgid "Test"
msgstr "Test"
@@ -717,7 +717,7 @@ msgid "Url to *.xml.gz file:"
msgstr "Da URL a file *.xml.gz:"
msgid "Enable filtering"
msgstr "Abilitare filtri"
msgstr "Abilita filtri"
msgid "Filter by presence in the epg.dat file."
msgstr "Filtra in base alla presenza su epg.dat."
@@ -801,7 +801,7 @@ msgid "Enables direct sending and playback of media links on the receiver"
msgstr "Abilita l'invio e la riproduzione di links multimediali sul ricevitore"
msgid "Watch the channel in the program"
msgstr "Guardare il canale nel programma"
msgstr "Guarda il canale nel programma"
msgid "Zap and Play"
msgstr "Zap e riproduci"
@@ -876,7 +876,7 @@ msgid "Record"
msgstr "Registra"
msgid "Record:"
msgstr "Registra:"
msgstr "Registrazioni:"
msgid "Record to disk:"
msgstr "Registra su disco:"
@@ -1059,7 +1059,7 @@ msgid "Import from Web"
msgstr "Importa dal Web"
msgid "Control"
msgstr "Controllo ricevitore"
msgstr "Controllo"
msgid "Timers"
msgstr "Timers"
@@ -1250,6 +1250,8 @@ msgstr "Caricamento dati in corso!"
msgid "Recordings"
msgstr "Registrazioni"
msgid "Recordings:"
msgstr "Registrazioni:"
msgid "Help"
msgstr "Aiuto"
@@ -1278,7 +1280,10 @@ msgid "Automatically set the name selected in the favorites list."
msgstr "Imposta automaticamente il nome selezionato nell'elenco dei preferiti."
msgid "Playback"
msgstr "Playback"
msgstr "Riproduzione"
msgid "Playback:"
msgstr "Riproduzione:"
msgid "Audio"
msgstr "Audio"
@@ -1338,10 +1343,16 @@ msgid "Rename"
msgstr "Rinomina"
msgid "Bookmarks"
msgstr "Segnalibro"
msgstr "Segnalibri"
msgid "Add bookmark"
msgstr "Aggiungi segnalibro"
msgid "All bouquets"
msgstr "Tutti i bouquets"
msgid "Playback from the main list"
msgstr "Riproduzione dalla lista principale"
msgid "Enables URL parsing using youtube-dl to get direct links to media."
msgstr "Abilita l'analisi degli URL utilizzando youtube-dl per ottenere collegamenti diretti ai media."

View File

@@ -4,7 +4,7 @@
#
msgid ""
msgstr ""
"Last-Translator: wwns <https://github.com/wwns>\n"
"Last-Translator: lareq <lareq@lareq.eu>\n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -13,10 +13,12 @@ msgstr ""
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Language-Team: \n"
"X-Generator: Poedit 3.0\n"
"X-Generator: Poedit 2.3\n"
msgid "translator-credits"
msgstr "wwns"
msgstr ""
"lareq <lareq@lareq.eu>\n"
"wwns <https://github.com/wwns>"
# Main
msgid "Service"
@@ -215,7 +217,7 @@ msgid "Host:"
msgstr "Host:"
msgid "Loading data..."
msgstr "Ładowanie danych"
msgstr "Ładowanie danych..."
msgid "Receive"
msgstr "Pobierz"
@@ -542,10 +544,10 @@ msgid "Done!"
msgstr "Zrobione!"
msgid "Please, wait..."
msgstr "Proszę czekać"
msgstr "Proszę czekać..."
msgid "Resizing..."
msgstr "Zmiana rozmiaru"
msgstr "Zmiana rozmiaru..."
msgid "Select paths!"
msgstr "Wybierz ścieżki!"
@@ -573,7 +575,7 @@ msgstr "Nie znaleziono VLC. Sprawdź, czy jest zainstalowany!"
# Search unavailable streams dialog
msgid "Please wait, streams testing in progress..."
msgstr "Proszę czekać, trwa testowanie strumieni"
msgstr "Proszę czekać, trwa testowanie strumieni..."
msgid "Found"
msgstr "Znaleziono"
@@ -989,7 +991,7 @@ msgid "Gtk3 Themes and Icons:"
msgstr "Gtk3 motywy i ikony:"
msgid "Deleting data..."
msgstr "Usuwanie danych"
msgstr "Usuwanie danych..."
msgid "Download from the receiver"
msgstr "Pobierz z odbiornika"
@@ -1019,7 +1021,7 @@ msgid "EXPERIMENTAL!"
msgstr "EKSPERYMENTALNE!"
msgid "Sorting data..."
msgstr "Sortowanie danych"
msgstr "Sortowanie danych..."
msgid ""
"There are unsaved changes.\n"
@@ -1059,7 +1061,7 @@ msgid "Enable Dark Mode"
msgstr "Włącz tryb ciemny"
msgid "Extract..."
msgstr "Rozpakuj"
msgstr "Rozpakuj..."
msgid "Unsupported format!"
msgstr "Format nieobsługiwany!"
@@ -1331,3 +1333,45 @@ msgstr "Przeciągnij usługi na żądaną ikonę lub na listę wybranych usług.
msgid "Sets the profile folder as default to store picons, backups, etc."
msgstr "Ustawia folder profilu jako domyślny do przechowywania pikonów, kopii zapasowych itp."
msgid "New sub-bouquet"
msgstr "Nowy sub-bukiet"
msgid "Mark not presented in Bouquets"
msgstr "Zaznacz te, których nie ma w bukietach"
msgid "Not in Bouquets"
msgstr "Nie ma w bukietach"
msgid "Do not show services present in Bouquets."
msgstr "Nie pokazuj usług obecnych w bukietach."
msgid "IPTV services only"
msgstr "Tylko serwisy IPTV"
msgid "Display picons"
msgstr "Wyświetl pikony"
msgid "Alternate layout"
msgstr "Alternatywny wygląd"
msgid "Layout of elements has been changed!"
msgstr "Zmieniono układ elementów!"
msgid "Restart the program to apply all changes."
msgstr "Uruchom ponownie program, aby zastosować wszystkie zmiany."
msgid "New folder"
msgstr "Nowy katalog"
msgid "Bookmarks"
msgstr "Zakładki"
msgid "Add bookmark"
msgstr "Dodaj zakładkę"
msgid "All bouquets"
msgstr "Wszystkie bukiety"
msgid "Playback from the main list"
msgstr "Odtwarzanie z listy głównej"

View File

@@ -1250,6 +1250,9 @@ msgstr "Выполняется загрузка данных!"
msgid "Recordings"
msgstr "Записи"
msgid "Recordings:"
msgstr "Записи:"
msgid "Help"
msgstr "Справка"
@@ -1351,3 +1354,6 @@ msgstr "Все букеты"
msgid "Playback from the main list"
msgstr "Воспроизведение из основного списка"
msgid "Enables URL parsing using youtube-dl to get direct links to media."
msgstr "Включает анализ URL-адресов с помощью youtube-dl для получения прямых ссылок на медиа."

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: DemonEditor\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-16 15:59+0300\n"
"PO-Revision-Date: 2022-02-21 22:06+0300\n"
"PO-Revision-Date: 2022-04-17 22:05+0300\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -1312,6 +1312,9 @@ msgstr "Favoriler listesinde seçilen adı otomatik olarak ayarlayın."
msgid "Playback"
msgstr "Oynatım"
msgid "Playback:"
msgstr "Oynatım:"
msgid "Audio"
msgstr "Ses"
@@ -1362,3 +1365,21 @@ msgstr "Öğelerin düzeni değiştirildi!"
msgid "Restart the program to apply all changes."
msgstr "Tüm değişiklikleri uygulamak için programı yeniden başlatın."
msgid "New folder"
msgstr "Yeni dosya"
msgid "Rename"
msgstr "Düzenle"
msgid "Bookmarks"
msgstr "Yer imleri"
msgid "Add bookmark"
msgstr "Yer imleri ekle"
msgid "All bouquets"
msgstr "Tüm buketler"
msgid "Playback from the main list"
msgstr "Ana listeden oynatma"

View File

@@ -6,19 +6,19 @@ def update_icon():
need_update = False
icon_name = "DemonEditor.desktop"
with open(icon_name, "r") as f:
with open(icon_name, "r", encoding="utf-8") as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith("Icon="):
icon_path = line.lstrip("Icon=")
current_path = "{}/app/ui/icons/hicolor/96x96/apps/demon-editor.png".format(os.getcwd())
current_path = f"{os.getcwd()}/app/ui/icons/hicolor/96x96/apps/demon-editor.png"
if icon_path != current_path:
need_update = True
lines[i] = "Icon={}\n".format(current_path)
lines[i] = f"Icon={current_path}\n"
break
if need_update:
with open(icon_name, "w") as f:
with open(icon_name, "w", encoding="utf-8") as f:
f.writelines(lines)