mirror of
https://github.com/DYefremov/DemonEditor.git
synced 2026-07-06 00:09:28 +02:00
added epg page
This commit is contained in:
@@ -97,6 +97,10 @@
|
||||
<attribute name="label" translatable="yes">Picons</attribute>
|
||||
<attribute name="action">app.show_picons</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">EPG</attribute>
|
||||
<attribute name="action">app.show_epg</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Timers</attribute>
|
||||
<attribute name="action">app.show_timers</attribute>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.2
|
||||
<!-- Generated with glade 3.22.2
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -34,114 +34,165 @@ Author: Dmitriy Yefremov
|
||||
<!-- interface-description Enigma2 channel and satellites list editor for GNU/Linux. -->
|
||||
<!-- interface-copyright 2018-2020 Dmitriy Yefremov -->
|
||||
<!-- interface-authors Dmitriy Yefremov -->
|
||||
<object class="GtkImage" id="add_timer_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">alarm-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="epg_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="epg_view_scrolled_window">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkViewport" id="epg_view_port">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="epg_list_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="selection_mode">multiple</property>
|
||||
<property name="activate_on_single_click">False</property>
|
||||
<signal name="button-press-event" handler="on_epg_press" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</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="epg_action_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="epg_filter_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Filter</property>
|
||||
<property name="primary_icon_stock">gtk-spell-check</property>
|
||||
<property name="primary_icon_name">tools-check-spelling</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">False</property>
|
||||
<property name="placeholder_text" translatable="yes">Filter</property>
|
||||
<signal name="search-changed" handler="on_epg_filter_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="epg_add_timer_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Add timer</property>
|
||||
<property name="action_name">app.on_timer_add_from_event</property>
|
||||
<property name="image">add_timer_image</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="back_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-back</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="begins_hour_adjustment">
|
||||
<property name="upper">23</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="down_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-down</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="end_hour_adjustment">
|
||||
<property name="upper">23</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="forward_image">
|
||||
<object class="GtkListStore" id="epg_model">
|
||||
<columns>
|
||||
<!-- column-name title -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name time -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name description -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name data -->
|
||||
<column type="PyObject"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkFrame" id="epg_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-forward</property>
|
||||
<property name="margin_top">2</property>
|
||||
<property name="label_xalign">0.49000000953674316</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="epg_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">7</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="epg_action_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">15</property>
|
||||
<property name="margin_right">15</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="epg_add_timer_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Add timer</property>
|
||||
<property name="action_name">app.on_timer_add_from_event</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="add_timer_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">alarm-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="epg_view_scrolled_window">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="epg_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="model">epg_model</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
<property name="tooltip_column">2</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="epg_selection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="epg_title_column">
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">Title</property>
|
||||
<property name="alignment">0.49000000953674316</property>
|
||||
<property name="sort_column_id">0</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="epg_title_renderer">
|
||||
<property name="xpad">5</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="epg_time_column">
|
||||
<property name="min_width">25</property>
|
||||
<property name="title" translatable="yes">Time</property>
|
||||
<property name="alignment">0.49000000953674316</property>
|
||||
<property name="sort_column_id">1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="epg_time_renderer">
|
||||
<property name="xpad">10</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="epg_desc_column">
|
||||
<property name="title" translatable="yes">Description</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="alignment">0.49000000953674316</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="epg_desc_renderer">
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<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">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="epg_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">EPG</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="min_begins_adjustment">
|
||||
<property name="upper">59</property>
|
||||
@@ -1007,18 +1058,6 @@ Author: Dmitriy Yefremov
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<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>
|
||||
<object class="GtkImage" id="remove_recording_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">user-trash</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="recordings_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
@@ -1091,8 +1130,14 @@ Author: Dmitriy Yefremov
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Remove</property>
|
||||
<property name="action_name">app.on_recording_remove</property>
|
||||
<property name="image">remove_recording_image</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="remove_recording_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">user-trash</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@@ -1109,26 +1154,6 @@ Author: Dmitriy Yefremov
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<object class="GtkBox" id="timers_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
@@ -1216,23 +1241,11 @@ Author: Dmitriy Yefremov
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="up_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-up</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="volume_adjustment">
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<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>
|
||||
<object class="GtkBox" id="control_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
@@ -1256,7 +1269,15 @@ Author: Dmitriy Yefremov
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Standby</property>
|
||||
<property name="action_name">app.on_standby</property>
|
||||
<property name="image">standby_image</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>
|
||||
@@ -1272,7 +1293,15 @@ Author: Dmitriy Yefremov
|
||||
<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="image">wake_up_image</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>
|
||||
@@ -1281,14 +1310,22 @@ Author: Dmitriy Yefremov
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="reboot_butto">
|
||||
<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>
|
||||
<property name="image">reboot_image</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>
|
||||
@@ -1304,7 +1341,15 @@ Author: Dmitriy Yefremov
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Restart GUI</property>
|
||||
<property name="action_name">app.on_restart_gui</property>
|
||||
<property name="image">restart_gui_image</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>
|
||||
@@ -1320,7 +1365,14 @@ Author: Dmitriy Yefremov
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Shutdown</property>
|
||||
<property name="action_name">app.on_shutdown</property>
|
||||
<property name="image">shutdown_image</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>
|
||||
@@ -1554,7 +1606,13 @@ Author: Dmitriy Yefremov
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.on_up</property>
|
||||
<property name="image">up_image</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="up_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-up</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
@@ -1567,7 +1625,13 @@ Author: Dmitriy Yefremov
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.on_down</property>
|
||||
<property name="image">down_image</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="down_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-down</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
@@ -1580,8 +1644,14 @@ Author: Dmitriy Yefremov
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.on_right</property>
|
||||
<property name="image">forward_image</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="forward_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-forward</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
@@ -1594,7 +1664,13 @@ Author: Dmitriy Yefremov
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.on_left</property>
|
||||
<property name="image">back_image</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="back_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-back</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
|
||||
@@ -29,208 +29,73 @@
|
||||
""" Receiver control module via HTTP API. """
|
||||
import os
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from urllib.parse import quote
|
||||
|
||||
from gi.repository import GLib
|
||||
|
||||
from .dialogs import show_dialog, DialogType, get_message, get_builder
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, Column
|
||||
from .dialogs import get_builder
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH
|
||||
from ..commons import run_task, run_with_delay, log, run_idle
|
||||
from ..connections import HttpAPI, UtfFTP
|
||||
from ..eparser.ecommons import BqServiceType
|
||||
from ..connections import HttpAPI
|
||||
|
||||
|
||||
class EpgBox(Gtk.Box):
|
||||
def __init__(self, app, http_api, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._http_api = http_api
|
||||
self._app = app
|
||||
self._app.connect("fav-changed", self.on_service_changed)
|
||||
|
||||
handlers = {"on_epg_press": self.on_epg_press}
|
||||
|
||||
builder = get_builder(UI_RESOURCES_PATH + "control.glade", handlers, objects=("epg_frame", "epg_model"))
|
||||
self._view = builder.get_object("epg_view")
|
||||
self.add(builder.get_object("epg_frame"))
|
||||
self.show()
|
||||
|
||||
def on_epg_press(self, list_box, event):
|
||||
if event.get_event_type() == Gdk.EventType.DOUBLE_BUTTON_PRESS and len(list_box) > 0:
|
||||
row = list_box.get_selected_row()
|
||||
if row:
|
||||
self.set_timer_from_event_data(row.event_data)
|
||||
|
||||
def on_service_changed(self, app, ref):
|
||||
self._app._wait_dialog.show()
|
||||
self._http_api.send(HttpAPI.Request.EPG, quote(ref), self.update_epg_data)
|
||||
|
||||
@run_idle
|
||||
def update_epg_data(self, epg):
|
||||
model = self._view.get_model()
|
||||
model.clear()
|
||||
list(map(model.append, (self.get_event_row(e) for e in epg.get("event_list", []))))
|
||||
self._app._wait_dialog.hide()
|
||||
|
||||
def get_event_row(self, event):
|
||||
title = event.get("e2eventtitle", "")
|
||||
desc = event.get("e2eventdescription", "")
|
||||
|
||||
start = int(event.get("e2eventstart", "0"))
|
||||
start_time = datetime.fromtimestamp(start)
|
||||
end_time = datetime.fromtimestamp(start + int(event.get("e2eventduration", "0")))
|
||||
time = "{} - {}".format(start_time.strftime("%A, %H:%M"), end_time.strftime("%H:%M"))
|
||||
|
||||
return title, time, desc, event
|
||||
|
||||
|
||||
class ControlBox(Gtk.HBox):
|
||||
_TIME_STR = "%Y-%m-%d %H:%M"
|
||||
|
||||
class Tool(Enum):
|
||||
""" The currently displayed tool. """
|
||||
REMOTE = "control"
|
||||
EPG = "epg"
|
||||
TIMERS = "timers"
|
||||
TIMER = "timer"
|
||||
RECORDINGS = "recordings"
|
||||
|
||||
class EpgRow(Gtk.ListBoxRow):
|
||||
def __init__(self, event: dict, **properties):
|
||||
super().__init__(**properties)
|
||||
|
||||
self._event_data = event
|
||||
h_box = Gtk.HBox()
|
||||
h_box.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
self._title = event.get("e2eventtitle", "")
|
||||
title_label = Gtk.Label(self._title)
|
||||
|
||||
self._desc = event.get("e2eventdescription", "")
|
||||
description = Gtk.Label()
|
||||
description.set_markup("<i>{}</i>".format(self._desc))
|
||||
description.set_line_wrap(True)
|
||||
description.set_max_width_chars(25)
|
||||
|
||||
start = int(event.get("e2eventstart", "0"))
|
||||
start_time = datetime.fromtimestamp(start)
|
||||
end_time = datetime.fromtimestamp(start + int(event.get("e2eventduration", "0")))
|
||||
time_label = Gtk.Label()
|
||||
time_label.set_margin_top(5)
|
||||
self._time_header = "{} - {}".format(start_time.strftime("%A, %H:%M"), end_time.strftime("%H:%M"))
|
||||
time_label.set_markup("<b>{}</b>".format(self._time_header))
|
||||
|
||||
h_box.add(time_label)
|
||||
h_box.add(title_label)
|
||||
h_box.add(description)
|
||||
sep = Gtk.Separator()
|
||||
sep.set_margin_top(5)
|
||||
h_box.add(sep)
|
||||
h_box.set_spacing(5)
|
||||
|
||||
self.add(h_box)
|
||||
self.show_all()
|
||||
|
||||
@property
|
||||
def event_data(self):
|
||||
return self._event_data or {}
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
return self._title or ""
|
||||
|
||||
@property
|
||||
def desc(self):
|
||||
return self._desc or ""
|
||||
|
||||
@property
|
||||
def time_header(self):
|
||||
return self._time_header or ""
|
||||
|
||||
class TimerRow(Gtk.ListBoxRow):
|
||||
|
||||
_UI_PATH = UI_RESOURCES_PATH + "timer_row.glade"
|
||||
|
||||
def __init__(self, timer, **properties):
|
||||
super().__init__(**properties)
|
||||
|
||||
self._timer = timer
|
||||
|
||||
builder = get_builder(self._UI_PATH, None, use_str=True)
|
||||
row_box = builder.get_object("timer_row_box")
|
||||
name_label = builder.get_object("timer_name_label")
|
||||
description_label = builder.get_object("timer_description_label")
|
||||
service_name_label = builder.get_object("timer_service_name_label")
|
||||
time_label = builder.get_object("timer_time_label")
|
||||
|
||||
name_label.set_text(timer.get("e2name", "") or "")
|
||||
description_label.set_text(timer.get("e2description", "") or "")
|
||||
service_name_label.set_text(timer.get("e2servicename", "") or "")
|
||||
# Time
|
||||
start_time = datetime.fromtimestamp(int(timer.get("e2timebegin", "0")))
|
||||
end_time = datetime.fromtimestamp(int(timer.get("e2timeend", "0")))
|
||||
time_label.set_text("{} - {}".format(start_time.strftime("%A, %H:%M"), end_time.strftime("%H:%M")))
|
||||
|
||||
self.add(row_box)
|
||||
self.show()
|
||||
|
||||
@property
|
||||
def timer(self):
|
||||
return self._timer
|
||||
|
||||
class TimerAction(Enum):
|
||||
ADD = 0
|
||||
EVENT = 1
|
||||
CHANGE = 2
|
||||
|
||||
class RecordingsRow(Gtk.ListBoxRow):
|
||||
def __init__(self, movie: dict, **properties):
|
||||
super().__init__(**properties)
|
||||
|
||||
self._movie = movie
|
||||
h_box = Gtk.HBox()
|
||||
h_box.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
self._service = movie.get("e2servicename")
|
||||
service_label = Gtk.Label()
|
||||
service_label.set_markup("<b>{}</b>".format(self._service))
|
||||
|
||||
self._title = movie.get("e2title", "")
|
||||
title_label = Gtk.Label(self._title)
|
||||
|
||||
self._desc = movie.get("e2description", "")
|
||||
description = Gtk.Label()
|
||||
description.set_markup("<i>{}</i>".format(self._desc))
|
||||
description.set_line_wrap(True)
|
||||
description.set_max_width_chars(25)
|
||||
|
||||
start_time = datetime.fromtimestamp(int(movie.get("e2time", "0")))
|
||||
start_time_label = Gtk.Label()
|
||||
start_time_label.set_margin_top(5)
|
||||
start_time_label.set_markup("<b>{}</b>".format(start_time.strftime("%A, %H:%M")))
|
||||
|
||||
time_label = Gtk.Label()
|
||||
time_label.set_margin_top(5)
|
||||
time_label.set_markup("<b>{}</b>".format(movie.get("e2length", "0")))
|
||||
|
||||
info_box = Gtk.HBox()
|
||||
info_box.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
info_box.set_spacing(10)
|
||||
info_box.pack_start(start_time_label, False, True, 5)
|
||||
info_box.pack_end(time_label, False, True, 5)
|
||||
|
||||
h_box.add(service_label)
|
||||
h_box.add(title_label)
|
||||
h_box.add(description)
|
||||
h_box.add(info_box)
|
||||
sep = Gtk.Separator()
|
||||
sep.set_margin_top(5)
|
||||
h_box.add(sep)
|
||||
h_box.set_spacing(5)
|
||||
|
||||
self.set_tooltip_text(movie.get("e2filename", ""))
|
||||
self.add(h_box)
|
||||
self.show_all()
|
||||
|
||||
@property
|
||||
def movie(self):
|
||||
return self._movie
|
||||
|
||||
@property
|
||||
def service(self):
|
||||
return self._service or ""
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
return self._title or ""
|
||||
|
||||
@property
|
||||
def desc(self):
|
||||
return self._desc or ""
|
||||
|
||||
@property
|
||||
def file(self):
|
||||
return self._movie.get("e2filename", "")
|
||||
|
||||
def __init__(self, app, http_api, settings, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._http_api = http_api
|
||||
self._settings = settings
|
||||
self._update_epg = False
|
||||
self._app = app
|
||||
self._last_tool = self.Tool.REMOTE
|
||||
self._timer_action = self.TimerAction.ADD
|
||||
self._current_timer = {}
|
||||
|
||||
handlers = {"on_visible_tool": self.on_visible_tool,
|
||||
"on_volume_changed": self.on_volume_changed,
|
||||
"on_epg_press": self.on_epg_press,
|
||||
"on_epg_filter_changed": self.on_epg_filter_changed,
|
||||
"on_timers_press": self.on_timers_press,
|
||||
"on_timers_drag_data_received": self.on_timers_drag_data_received,
|
||||
"on_recordings_press": self.on_recordings_press,
|
||||
"on_recording_filter_changed": self.on_recording_filter_changed,
|
||||
"on_recordings_dir_changed": self.on_recordings_dir_changed}
|
||||
handlers = {"on_volume_changed": self.on_volume_changed}
|
||||
|
||||
builder = get_builder(UI_RESOURCES_PATH + "control.glade", handlers)
|
||||
builder = get_builder(UI_RESOURCES_PATH + "control.glade", handlers,
|
||||
objects=("control_box", "volume_adjustment"))
|
||||
|
||||
self.add(builder.get_object("control_box"))
|
||||
self._stack = builder.get_object("stack")
|
||||
@@ -242,55 +107,7 @@ class ControlBox(Gtk.HBox):
|
||||
self._ber_value_label = builder.get_object("ber_value_label")
|
||||
self._agc_value_label = builder.get_object("agc_value_label")
|
||||
self._volume_button = builder.get_object("volume_button")
|
||||
self._epg_list_box = builder.get_object("epg_list_box")
|
||||
self._epg_list_box.set_filter_func(self.epg_filter_function)
|
||||
self._epg_filter_entry = builder.get_object("epg_filter_entry")
|
||||
self._timers_list_box = builder.get_object("timers_list_box")
|
||||
# Timers
|
||||
self._timer_remove_button = builder.get_object("timer_remove_button")
|
||||
self._timer_remove_button.bind_property("visible", builder.get_object("timer_edit_button"), "visible")
|
||||
# Timer
|
||||
self._timer_name_entry = builder.get_object("timer_name_entry")
|
||||
self._timer_desc_entry = builder.get_object("timer_desc_entry")
|
||||
self._timer_service_entry = builder.get_object("timer_service_entry")
|
||||
self._timer_service_ref_entry = builder.get_object("timer_service_ref_entry")
|
||||
self._timer_event_id_entry = builder.get_object("timer_event_id_entry")
|
||||
self._timer_begins_entry = builder.get_object("timer_begins_entry")
|
||||
self._timer_ends_entry = builder.get_object("timer_ends_entry")
|
||||
self._timer_begins_calendar = builder.get_object("timer_begins_calendar")
|
||||
self._timer_begins_hr_button = builder.get_object("timer_begins_hr_button")
|
||||
self._timer_begins_min_button = builder.get_object("timer_begins_min_button")
|
||||
self._timer_ends_calendar = builder.get_object("timer_ends_calendar")
|
||||
self._timer_ends_hr_button = builder.get_object("timer_ends_hr_button")
|
||||
self._timer_ends_min_button = builder.get_object("timer_ends_min_button")
|
||||
self._timer_enabled_switch = builder.get_object("timer_enabled_switch")
|
||||
self._timer_action_combo_box = builder.get_object("timer_action_combo_box")
|
||||
self._timer_after_combo_box = builder.get_object("timer_after_combo_box")
|
||||
self._timer_mo_check_button = builder.get_object("timer_mo_check_button")
|
||||
self._timer_tu_check_button = builder.get_object("timer_tu_check_button")
|
||||
self._timer_we_check_button = builder.get_object("timer_we_check_button")
|
||||
self._timer_th_check_button = builder.get_object("timer_th_check_button")
|
||||
self._timer_fr_check_button = builder.get_object("timer_fr_check_button")
|
||||
self._timer_sa_check_button = builder.get_object("timer_sa_check_button")
|
||||
self._timer_su_check_button = builder.get_object("timer_su_check_button")
|
||||
self._timer_location_switch = builder.get_object("timer_location_switch")
|
||||
self._timer_location_entry = builder.get_object("timer_location_entry")
|
||||
self._timer_location_switch.bind_property("active", self._timer_location_entry, "sensitive")
|
||||
# Disable DnD for timer entries.
|
||||
self._timer_name_entry.drag_dest_unset()
|
||||
self._timer_desc_entry.drag_dest_unset()
|
||||
self._timer_service_entry.drag_dest_unset()
|
||||
# DnD initialization for the timer list.
|
||||
self._timers_list_box.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.DEFAULT | Gdk.DragAction.COPY)
|
||||
self._timers_list_box.drag_dest_add_text_targets()
|
||||
# Recordings.
|
||||
self._recordings_list_box = builder.get_object("recordings_list_box")
|
||||
self._recordings_list_box.set_filter_func(self.recording_filter_function)
|
||||
self._recordings_filter_entry = builder.get_object("recordings_filter_entry")
|
||||
self._recordings_dir_box = builder.get_object("recordings_dir_box")
|
||||
|
||||
self.init_actions(app)
|
||||
self.connect("hide", self.on_hide)
|
||||
self.show()
|
||||
|
||||
def init_actions(self, app):
|
||||
@@ -316,37 +133,6 @@ class ControlBox(Gtk.HBox):
|
||||
app.set_action("on_screenshot_all", self.on_screenshot_all)
|
||||
app.set_action("on_screenshot_video", self.on_screenshot_video)
|
||||
app.set_action("on_screenshot_osd", self.on_screenshot_osd)
|
||||
# Timers
|
||||
app.set_action("on_timer_add", self.on_timer_add)
|
||||
app.set_action("on_timer_add_from_event", self.on_timer_add_from_event)
|
||||
app.set_action("on_timer_remove", self.on_timer_remove)
|
||||
app.set_action("on_timer_edit", self.on_timer_edit)
|
||||
app.set_action("on_timer_save", self.on_timer_save)
|
||||
app.set_action("on_timer_cancel", self.on_timer_cancel)
|
||||
app.set_action("on_timer_begins_set", self.on_timer_begins_set)
|
||||
app.set_action("on_timer_ends_set", self.on_timer_ends_set)
|
||||
# Recordings
|
||||
app.set_action("on_recording_remove", self.on_recording_remove)
|
||||
|
||||
@property
|
||||
def update_epg(self):
|
||||
return self._update_epg
|
||||
|
||||
def on_visible_tool(self, stack, param):
|
||||
tool = self.Tool(stack.get_visible_child_name())
|
||||
self._update_epg = tool is self.Tool.EPG
|
||||
|
||||
if tool is self.Tool.TIMERS:
|
||||
self.update_timer_list()
|
||||
|
||||
if tool is self.Tool.RECORDINGS:
|
||||
self.update_recordings_list()
|
||||
|
||||
if tool is not self.Tool.TIMER:
|
||||
self._last_tool = tool
|
||||
|
||||
def on_hide(self, item):
|
||||
self._update_epg = False
|
||||
|
||||
# ***************** Remote controller ********************* #
|
||||
|
||||
@@ -443,412 +229,3 @@ class ControlBox(Gtk.HBox):
|
||||
self._snr_value_label.set_text(sig.get("e2snrdb", "0 dB").strip())
|
||||
self._ber_value_label.set_text(str(sig.get("e2ber", None) or "0").strip())
|
||||
self._agc_value_label.set_text(sig.get("e2acg", "0 %").strip())
|
||||
|
||||
# ************************ EPG **************************** #
|
||||
|
||||
def on_service_changed(self, ref):
|
||||
self._app._wait_dialog.show()
|
||||
self._http_api.send(HttpAPI.Request.EPG, quote(ref), self.update_epg_data)
|
||||
|
||||
@run_idle
|
||||
def update_epg_data(self, epg):
|
||||
list(map(self._epg_list_box.remove, (r for r in self._epg_list_box)))
|
||||
list(map(lambda e: self._epg_list_box.add(self.EpgRow(e)), epg.get("event_list", [])))
|
||||
self._app._wait_dialog.hide()
|
||||
|
||||
def on_epg_press(self, list_box, event):
|
||||
if event.get_event_type() == Gdk.EventType.DOUBLE_BUTTON_PRESS and len(list_box) > 0:
|
||||
row = list_box.get_selected_row()
|
||||
if row:
|
||||
self.set_timer_from_event_data(row.event_data)
|
||||
|
||||
def on_epg_filter_changed(self, entry):
|
||||
self._epg_list_box.invalidate_filter()
|
||||
|
||||
def epg_filter_function(self, row):
|
||||
txt = self._epg_filter_entry.get_text().upper()
|
||||
return any((not txt, txt in row.time_header.upper(), txt in row.title.upper(), txt in row.desc.upper()))
|
||||
|
||||
def on_timer_add_from_event(self, action, value=None):
|
||||
rows = self._epg_list_box.get_selected_rows()
|
||||
if not rows:
|
||||
self._app.show_error_message("No selected item!")
|
||||
return
|
||||
|
||||
refs = []
|
||||
for row in rows:
|
||||
event = row.event_data
|
||||
ref = "timeraddbyeventid?sRef={}&eventid={}&justplay=0".format(event.get("e2eventservicereference", ""),
|
||||
event.get("e2eventid", ""))
|
||||
refs.append(ref)
|
||||
|
||||
gen = self.write_timers_list(refs)
|
||||
GLib.idle_add(lambda: next(gen, False))
|
||||
|
||||
def write_timers_list(self, refs):
|
||||
self._app._wait_dialog.show()
|
||||
tasks = list(refs)
|
||||
for ref in refs:
|
||||
self._http_api.send(HttpAPI.Request.TIMER, ref, lambda x: tasks.pop())
|
||||
yield True
|
||||
|
||||
while tasks:
|
||||
yield True
|
||||
|
||||
self._stack.set_visible_child_name(self.Tool.TIMERS.value)
|
||||
|
||||
# *********************** Timers *************************** #
|
||||
|
||||
def on_timers_press(self, list_box, event):
|
||||
if event.get_event_type() == Gdk.EventType.DOUBLE_BUTTON_PRESS and len(list_box) > 0:
|
||||
self.on_timer_edit()
|
||||
|
||||
def update_timer_list(self):
|
||||
self._app._wait_dialog.show()
|
||||
self._http_api.send(HttpAPI.Request.TIMER_LIST, "", self.update_timers_data)
|
||||
|
||||
@run_idle
|
||||
def update_timers_data(self, timers):
|
||||
list(map(self._timers_list_box.remove, (r for r in self._timers_list_box)))
|
||||
list(map(lambda t: self._timers_list_box.add(self.TimerRow(t)), timers.get("timer_list", [])))
|
||||
self._timer_remove_button.set_visible(len(self._timers_list_box))
|
||||
self._app._wait_dialog.hide()
|
||||
|
||||
def on_timer_add(self, action=None, value=None):
|
||||
self._timer_action = self.TimerAction.ADD
|
||||
date = datetime.now()
|
||||
self.set_begins_date(date)
|
||||
self.set_ends_date(date)
|
||||
self._timer_event_id_entry.set_text("")
|
||||
self._timer_location_switch.set_active(False)
|
||||
self.set_repetition_flags(0)
|
||||
self._stack.set_visible_child_name(self.Tool.TIMER.value)
|
||||
|
||||
def on_timer_remove(self, action, value=None):
|
||||
rows = self._timers_list_box.get_selected_rows()
|
||||
if not rows or show_dialog(DialogType.QUESTION, self._app._main_window) != Gtk.ResponseType.OK:
|
||||
return
|
||||
|
||||
refs = {}
|
||||
for row in rows:
|
||||
timer = row.timer
|
||||
ref = "timerdelete?sRef={}&begin={}&end={}".format(quote(timer.get("e2servicereference", "")),
|
||||
timer.get("e2timebegin", ""),
|
||||
timer.get("e2timeend", ""))
|
||||
refs[ref] = row
|
||||
|
||||
self._app._wait_dialog.show("Deleting data...")
|
||||
gen = self.remove_timers(refs)
|
||||
GLib.idle_add(lambda: next(gen, False))
|
||||
|
||||
def remove_timers(self, refs):
|
||||
tasks = list(refs)
|
||||
removed = set()
|
||||
for ref in refs:
|
||||
yield from self.remove_timer(ref, removed, tasks)
|
||||
|
||||
while tasks:
|
||||
yield True
|
||||
|
||||
list(map(self._timers_list_box.remove, (refs[ref] for ref in refs if ref in removed)))
|
||||
self._app._wait_dialog.hide()
|
||||
self._timer_remove_button.set_visible(len(self._timers_list_box))
|
||||
yield True
|
||||
|
||||
def remove_timer(self, ref, removed, tasks=None):
|
||||
def callback(resp):
|
||||
if resp.get("e2state", "") == "True":
|
||||
log(resp.get("e2statetext", ""))
|
||||
removed.add(ref)
|
||||
else:
|
||||
log(resp.get("e2statetext", None) or "Timer deletion error.")
|
||||
if tasks:
|
||||
tasks.pop()
|
||||
|
||||
self._http_api.send(HttpAPI.Request.TIMER, ref, callback)
|
||||
yield True
|
||||
|
||||
def on_timer_edit(self, action=None, value=None):
|
||||
row = self._timers_list_box.get_selected_row()
|
||||
if row:
|
||||
self._timer_action = self.TimerAction.CHANGE
|
||||
|
||||
timer = row.timer
|
||||
self._current_timer = timer
|
||||
self._timer_name_entry.set_text(timer.get("e2name", ""))
|
||||
self._timer_desc_entry.set_text(timer.get("e2description", "") or "")
|
||||
self._timer_service_entry.set_text(timer.get("e2servicename", "") or "")
|
||||
self._timer_service_ref_entry.set_text(timer.get("e2servicereference", ""))
|
||||
self._timer_event_id_entry.set_text(timer.get("e2eit", ""))
|
||||
self._timer_enabled_switch.set_active((timer.get("e2disabled", "0") == "0"))
|
||||
self._timer_action_combo_box.set_active_id(timer.get("e2justplay", "0"))
|
||||
self._timer_after_combo_box.set_active_id(timer.get("e2afterevent", "0"))
|
||||
self.set_time_data(int(timer.get("e2timebegin", "0")), int(timer.get("e2timeend", "0")))
|
||||
location = timer.get("e2location", "")
|
||||
self._timer_location_entry.set_text("" if location == "None" else location)
|
||||
# Days
|
||||
self.set_repetition_flags(int(timer.get("e2repeated", "0")))
|
||||
self._stack.set_visible_child_name(self.Tool.TIMER.value)
|
||||
|
||||
def on_timer_save(self, action, value=None):
|
||||
args = []
|
||||
t_data = self.get_timer_data()
|
||||
s_ref = quote(t_data.get("sRef", ""))
|
||||
|
||||
if self._timer_action is self.TimerAction.EVENT:
|
||||
args.append("timeraddbyeventid?sRef={}".format(s_ref))
|
||||
args.append("eventid={}".format(t_data.get("eit", "0")))
|
||||
args.append("justplay={}".format(t_data.get("justplay", "")))
|
||||
args.append("tags={}".format(""))
|
||||
else:
|
||||
if self._timer_action is self.TimerAction.ADD:
|
||||
args.append("timeradd?sRef={}".format(s_ref))
|
||||
args.append("deleteOldOnSave={}".format(0))
|
||||
elif self._timer_action is self.TimerAction.CHANGE:
|
||||
args.append("timerchange?sRef={}".format(s_ref))
|
||||
args.append("channelOld={}".format(s_ref))
|
||||
args.append("beginOld={}".format(self._current_timer.get("e2timebegin", "0")))
|
||||
args.append("endOld={}".format(self._current_timer.get("e2timeend", "0")))
|
||||
args.append("deleteOldOnSave={}".format(1))
|
||||
|
||||
args.append("begin={}".format(t_data.get("begin", "")))
|
||||
args.append("end={}".format(t_data.get("end", "")))
|
||||
args.append("name={}".format(quote(t_data.get("name", ""))))
|
||||
args.append("description={}".format(quote(t_data.get("description", ""))))
|
||||
args.append("tags={}".format(""))
|
||||
args.append("eit={}".format("0"))
|
||||
args.append("disabled={}".format(t_data.get("disabled", "1")))
|
||||
args.append("justplay={}".format(t_data.get("justplay", "1")))
|
||||
args.append("afterevent={}".format(t_data.get("afterevent", "0")))
|
||||
args.append("repeated={}".format(self.get_repetition_flags()))
|
||||
|
||||
if self._timer_location_switch.get_active():
|
||||
args.append("dirname={}".format(self._timer_location_entry.get_text()))
|
||||
|
||||
self._http_api.send(HttpAPI.Request.TIMER, "&".join(args), self.timer_add_edit_callback)
|
||||
|
||||
@run_idle
|
||||
def timer_add_edit_callback(self, resp):
|
||||
if "error_code" in resp:
|
||||
msg = "Error getting timer status.\n{}".format(resp.get("error_code"))
|
||||
self._app.show_error_message(msg)
|
||||
log(msg)
|
||||
return
|
||||
|
||||
state = resp.get("e2state", None)
|
||||
if state == "False":
|
||||
msg = resp.get("e2statetext", "")
|
||||
self._app.show_error_message(msg)
|
||||
log(msg)
|
||||
if state == "True":
|
||||
log(resp.get("e2statetext", ""))
|
||||
self._stack.set_visible_child_name(self._last_tool.value)
|
||||
else:
|
||||
log("Error getting timer status. No response!")
|
||||
|
||||
def on_timer_cancel(self, action, value=None):
|
||||
self._stack.set_visible_child_name(self._last_tool.value)
|
||||
|
||||
def on_timer_begins_set(self, action, value=None):
|
||||
self.set_begins_date(self.get_begins_date())
|
||||
|
||||
def on_timer_ends_set(self, action, value=None):
|
||||
self.set_ends_date(self.get_ends_date())
|
||||
|
||||
def get_begins_date(self):
|
||||
date = self._timer_begins_calendar.get_date()
|
||||
return datetime(year=date.year, month=date.month + 1, day=date.day,
|
||||
hour=int(self._timer_begins_hr_button.get_value()),
|
||||
minute=int(self._timer_begins_min_button.get_value()))
|
||||
|
||||
def set_begins_date(self, date):
|
||||
hour = date.hour
|
||||
minute = date.minute
|
||||
self._timer_begins_hr_button.set_value(hour)
|
||||
self._timer_begins_min_button.set_value(minute)
|
||||
self._timer_begins_calendar.select_day(date.day)
|
||||
self._timer_begins_calendar.select_month(date.month - 1, date.year)
|
||||
self._timer_begins_entry.set_text("{}-{}-{} {}:{:02d}".format(date.year, date.month, date.day, hour, minute))
|
||||
|
||||
def get_ends_date(self):
|
||||
date = self._timer_ends_calendar.get_date()
|
||||
return datetime(year=date.year, month=date.month + 1, day=date.day,
|
||||
hour=int(self._timer_ends_hr_button.get_value()),
|
||||
minute=int(self._timer_ends_min_button.get_value()))
|
||||
|
||||
def set_ends_date(self, date):
|
||||
hour = date.hour
|
||||
minute = date.minute
|
||||
self._timer_ends_hr_button.set_value(hour)
|
||||
self._timer_ends_min_button.set_value(minute)
|
||||
self._timer_ends_calendar.select_day(date.day)
|
||||
self._timer_ends_calendar.select_month(date.month - 1, date.year)
|
||||
self._timer_ends_entry.set_text("{}-{}-{} {}:{:02d}".format(date.year, date.month, date.day, hour, minute))
|
||||
|
||||
def set_timer_from_event_data(self, timer):
|
||||
self._stack.set_visible_child_name(self.Tool.TIMER.value)
|
||||
self._timer_action = self.TimerAction.EVENT
|
||||
self._timer_name_entry.set_text(timer.get("e2eventtitle", ""))
|
||||
self._timer_desc_entry.set_text(timer.get("e2eventdescription", ""))
|
||||
self._timer_service_entry.set_text(timer.get("e2eventservicename", ""))
|
||||
self._timer_service_ref_entry.set_text(timer.get("e2eventservicereference", ""))
|
||||
self._timer_event_id_entry.set_text(timer.get("e2eventid", ""))
|
||||
self._timer_action_combo_box.set_active_id("1")
|
||||
self._timer_after_combo_box.set_active_id("3")
|
||||
start_time = int(timer.get("e2eventstart", "0"))
|
||||
self.set_time_data(start_time, start_time + int(timer.get("e2eventduration", "0")))
|
||||
|
||||
def set_time_data(self, start_time, end_time):
|
||||
""" Sets values for time widgets. """
|
||||
ev_time_start = datetime.fromtimestamp(start_time) or datetime.now()
|
||||
ev_time_end = datetime.fromtimestamp(end_time) or datetime.now()
|
||||
self._timer_begins_entry.set_text(ev_time_start.strftime(self._TIME_STR))
|
||||
self._timer_ends_entry.set_text(ev_time_end.strftime(self._TIME_STR))
|
||||
self._timer_begins_calendar.select_day(ev_time_start.day)
|
||||
self._timer_begins_calendar.select_month(ev_time_start.month - 1, ev_time_start.year)
|
||||
self._timer_ends_calendar.select_day(ev_time_end.day)
|
||||
self._timer_ends_calendar.select_month(ev_time_end.month - 1, ev_time_end.year)
|
||||
self._timer_begins_hr_button.set_value(ev_time_start.hour)
|
||||
self._timer_begins_min_button.set_value(ev_time_start.minute)
|
||||
self._timer_ends_hr_button.set_value(ev_time_end.hour)
|
||||
self._timer_ends_min_button.set_value(ev_time_end.minute)
|
||||
|
||||
def get_timer_data(self):
|
||||
""" Returns timer data as a dict. """
|
||||
return {"sRef": self._timer_service_ref_entry.get_text(),
|
||||
"begin": int(datetime.strptime(self._timer_begins_entry.get_text(), self._TIME_STR).timestamp()),
|
||||
"end": int(datetime.strptime(self._timer_ends_entry.get_text(), self._TIME_STR).timestamp()),
|
||||
"name": self._timer_name_entry.get_text(),
|
||||
"description": self._timer_desc_entry.get_text(),
|
||||
"dirname": "",
|
||||
"eit": self._timer_event_id_entry.get_text(),
|
||||
"disabled": int(not self._timer_enabled_switch.get_active()),
|
||||
"justplay": self._timer_action_combo_box.get_active_id(),
|
||||
"afterevent": self._timer_after_combo_box.get_active_id(),
|
||||
"repeated": self.get_repetition_flags()}
|
||||
|
||||
def get_repetition_flags(self):
|
||||
""" Returns flags for repetition. """
|
||||
day_flags = 0
|
||||
for i, box in enumerate((self._timer_mo_check_button,
|
||||
self._timer_tu_check_button,
|
||||
self._timer_we_check_button,
|
||||
self._timer_th_check_button,
|
||||
self._timer_fr_check_button,
|
||||
self._timer_sa_check_button,
|
||||
self._timer_su_check_button)):
|
||||
|
||||
if box.get_active():
|
||||
day_flags = day_flags | (1 << i)
|
||||
|
||||
return day_flags
|
||||
|
||||
def set_repetition_flags(self, flags):
|
||||
for i, box in enumerate((self._timer_mo_check_button,
|
||||
self._timer_tu_check_button,
|
||||
self._timer_we_check_button,
|
||||
self._timer_th_check_button,
|
||||
self._timer_fr_check_button,
|
||||
self._timer_sa_check_button,
|
||||
self._timer_su_check_button)):
|
||||
box.set_active(flags & 1 == 1)
|
||||
flags = flags >> 1
|
||||
|
||||
# ***************** Drag-and-drop ********************* #
|
||||
|
||||
def on_timers_drag_data_received(self, box, context, x, y, data, info, time):
|
||||
txt = data.get_text()
|
||||
if txt:
|
||||
itr_str, sep, source = txt.partition(self._app.DRAG_SEP)
|
||||
if not source:
|
||||
return
|
||||
|
||||
itrs = itr_str.split(",")
|
||||
if len(itrs) > 1:
|
||||
self._app.show_error_message("Please, select only one item!")
|
||||
return
|
||||
|
||||
fav_id = None
|
||||
if source == self._app.FAV_MODEL_NAME:
|
||||
model = self._app.fav_view.get_model()
|
||||
fav_id = model.get_value(model.get_iter_from_string(itrs[0]), Column.FAV_ID)
|
||||
elif source == self._app.SERVICE_MODEL_NAME:
|
||||
model = self._app.services_view.get_model()
|
||||
fav_id = model.get_value(model.get_iter_from_string(itrs[0]), Column.SRV_FAV_ID)
|
||||
|
||||
service = self._app.current_services.get(fav_id, None)
|
||||
if service:
|
||||
if service.service_type == BqServiceType.ALT.name:
|
||||
msg = "Alternative service.\n\n {}".format(get_message("Not implemented yet!"))
|
||||
show_dialog(DialogType.ERROR, transient=self._app._main_window, text=msg)
|
||||
context.finish(False, False, time)
|
||||
return
|
||||
|
||||
self._timer_name_entry.set_text(service.service)
|
||||
self._timer_service_entry.set_text(service.service)
|
||||
self._timer_service_ref_entry.set_text(service.picon_id.rstrip(".png").replace("_", ":"))
|
||||
self.on_timer_add()
|
||||
context.finish(True, False, time)
|
||||
|
||||
# *********************** Recordings *************************** #
|
||||
|
||||
def on_recordings_press(self, list_box, event):
|
||||
if event.get_event_type() == Gdk.EventType.DOUBLE_BUTTON_PRESS and len(list_box) > 0:
|
||||
row = list_box.get_selected_row()
|
||||
if row:
|
||||
self._http_api.send(HttpAPI.Request.STREAM_TS,
|
||||
row.movie.get("e2filename", ""),
|
||||
self.on_play_recording)
|
||||
|
||||
def on_recording_filter_changed(self, entry):
|
||||
self._recordings_list_box.invalidate_filter()
|
||||
|
||||
def recording_filter_function(self, row):
|
||||
txt = self._recordings_filter_entry.get_text().upper()
|
||||
return any((not txt, txt in row.service.upper(), txt in row.title.upper(), txt in row.desc.upper()))
|
||||
|
||||
def on_recording_remove(self, action, value=None):
|
||||
""" Removes recordings via FTP. """
|
||||
if show_dialog(DialogType.QUESTION, self._app._main_window) != Gtk.ResponseType.OK:
|
||||
return
|
||||
|
||||
rows = self._recordings_list_box.get_selected_rows()
|
||||
if rows:
|
||||
settings = self._app._settings
|
||||
|
||||
with UtfFTP(host=settings.host, user=settings.user, passwd=settings.password) as ftp:
|
||||
ftp.encoding = "utf-8"
|
||||
for r in rows:
|
||||
resp = ftp.delete_file(r.file)
|
||||
if resp.startswith("2"):
|
||||
GLib.idle_add(self._recordings_list_box.remove, r)
|
||||
else:
|
||||
show_dialog(DialogType.ERROR, transient=self._app._main_window, text=resp)
|
||||
break
|
||||
|
||||
def on_recordings_dir_changed(self, box: Gtk.ComboBoxText):
|
||||
self._http_api.send(HttpAPI.Request.RECORDINGS, quote(box.get_active_id()), self.update_recordings_data)
|
||||
|
||||
def update_recordings_list(self):
|
||||
if not len(self._recordings_dir_box.get_model()):
|
||||
self._http_api.send(HttpAPI.Request.REC_CURRENT, "", self.update_current_rec_dir)
|
||||
|
||||
def update_current_rec_dir(self, current):
|
||||
cur = current.get("e2location", None)
|
||||
if cur:
|
||||
self._recordings_dir_box.append(cur, cur)
|
||||
self._http_api.send(HttpAPI.Request.REC_DIRS, "", self.update_rec_dirs)
|
||||
|
||||
def update_rec_dirs(self, dirs):
|
||||
for d in dirs.get("rec_dirs", []):
|
||||
self._recordings_dir_box.append(d, d)
|
||||
|
||||
@run_idle
|
||||
def update_recordings_data(self, recordings):
|
||||
list(map(self._recordings_list_box.remove, (r for r in self._recordings_list_box)))
|
||||
list(map(lambda r: self._recordings_list_box.add(self.RecordingsRow(r)), recordings.get("recordings", [])))
|
||||
|
||||
def on_play_recording(self, m3u):
|
||||
url = self._app.get_url_from_m3u(m3u)
|
||||
if url:
|
||||
self._app.play(url)
|
||||
|
||||
@@ -2380,6 +2380,64 @@ Author: Dmitriy Yefremov
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="epg_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>
|
||||
<signal name="realize" handler="on_epg_realize" swapped="no"/>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">epg</property>
|
||||
<property name="title" translatable="yes">EPG</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="timers_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>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">timers</property>
|
||||
<property name="title" translatable="yes">Timers</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="recordings_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>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">recordings</property>
|
||||
<property name="title" translatable="yes">Recordings</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="ftp_box">
|
||||
<property name="visible">True</property>
|
||||
@@ -2397,7 +2455,7 @@ Author: Dmitriy Yefremov
|
||||
<packing>
|
||||
<property name="name">ftp</property>
|
||||
<property name="title" translatable="yes">FTP</property>
|
||||
<property name="position">5</property>
|
||||
<property name="position">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -2416,7 +2474,7 @@ Author: Dmitriy Yefremov
|
||||
<packing>
|
||||
<property name="name">control</property>
|
||||
<property name="title" translatable="yes">Control</property>
|
||||
<property name="position">6</property>
|
||||
<property name="position">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
@@ -48,7 +48,7 @@ from app.eparser.neutrino.bouquets import BqType
|
||||
from app.settings import (SettingsType, Settings, SettingsException, PlayStreamsMode, SettingsReadException,
|
||||
IS_DARWIN)
|
||||
from app.tools.media import Player, Recorder
|
||||
from app.ui.control import ControlBox
|
||||
from app.ui.control import ControlBox, EpgBox
|
||||
from app.ui.epg_dialog import EpgDialog
|
||||
from app.ui.ftp import FtpClientBox
|
||||
from app.ui.transmitter import LinksTransmitter
|
||||
@@ -199,6 +199,7 @@ class Application(Gtk.Application):
|
||||
"on_add_alternatives": self.on_add_alternatives,
|
||||
"on_satellites_realize": self.on_satellites_realize,
|
||||
"on_picons_realize": self.on_picons_realize,
|
||||
"on_epg_realize": self.on_epg_realize,
|
||||
"on_control_realize": self.on_control_realize,
|
||||
"on_ftp_realize": self.on_ftp_realize,
|
||||
"on_visible_page": self.on_visible_page}
|
||||
@@ -232,6 +233,7 @@ class Application(Gtk.Application):
|
||||
self._links_transmitter = None
|
||||
self._satellite_tool = None
|
||||
self._picon_manager = None
|
||||
self._epg_box = None
|
||||
self._control_box = None
|
||||
self._ftp_client = None
|
||||
# Player
|
||||
@@ -255,6 +257,8 @@ class Application(Gtk.Application):
|
||||
# Signals.
|
||||
GObject.signal_new("profile-changed", self, GObject.SIGNAL_RUN_LAST,
|
||||
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
|
||||
GObject.signal_new("fav-changed", self, GObject.SIGNAL_RUN_LAST,
|
||||
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
|
||||
|
||||
builder = get_builder(UI_RESOURCES_PATH + "main.glade", handlers)
|
||||
self._main_window = builder.get_object("main_window")
|
||||
@@ -365,6 +369,12 @@ class Application(Gtk.Application):
|
||||
self._stack_satellite_box.set_visible(self._settings.get("show_satellites", True))
|
||||
self._stack_picon_box = builder.get_object("picon_box")
|
||||
self._stack_picon_box.set_visible(self._settings.get("show_picons", True))
|
||||
self._stack_epg_box = builder.get_object("epg_box")
|
||||
self._stack_epg_box.set_visible(self._settings.get("show_epg", True))
|
||||
self._stack_timers_box = builder.get_object("timers_box")
|
||||
self._stack_timers_box.set_visible(self._settings.get("show_timers", True))
|
||||
self._stack_recordings_box = builder.get_object("recordings_box")
|
||||
self._stack_timers_box.set_visible(self._settings.get("show_recordings", True))
|
||||
self._stack_ftp_box = builder.get_object("ftp_box")
|
||||
self._stack_ftp_box.set_visible(self._settings.get("show_ftp", True))
|
||||
self._stack_control_box = builder.get_object("control_box")
|
||||
@@ -468,8 +478,12 @@ class Application(Gtk.Application):
|
||||
sa.connect("change-state", lambda a, v: self._stack_satellite_box.set_visible(v))
|
||||
sa = self.set_state_action("show_picons", self.on_page_show, self._settings.get("show_picons", True))
|
||||
sa.connect("change-state", lambda a, v: self._stack_picon_box.set_visible(v))
|
||||
sa = self.set_state_action("show_epg", self.on_page_show, self._settings.get("show_epg", True))
|
||||
sa.connect("change-state", lambda a, v: self._stack_epg_box.set_visible(v))
|
||||
sa = self.set_state_action("show_timers", self.on_page_show, self._settings.get("show_timers", True))
|
||||
sa.connect("change-state", lambda a, v: self._stack_timers_box.set_visible(v))
|
||||
sa = self.set_state_action("show_recordings", self.on_page_show, self._settings.get("show_recordings", True))
|
||||
sa.connect("change-state", lambda a, v: self._stack_recordings_box.set_visible(v))
|
||||
sa = self.set_state_action("show_ftp", self.on_page_show, self._settings.get("show_ftp", True))
|
||||
sa.connect("change-state", lambda a, v: self._stack_ftp_box.set_visible(v))
|
||||
sa = self.set_state_action("show_control", self.on_page_show, self._settings.get("show_control", True))
|
||||
@@ -716,6 +730,10 @@ class Application(Gtk.Application):
|
||||
self._picon_manager = PiconManager(self, self._settings, ids, self._sat_positions)
|
||||
box.pack_start(self._picon_manager, True, True, 0)
|
||||
|
||||
def on_epg_realize(self, box):
|
||||
self._epg_box = EpgBox(self, self._http_api)
|
||||
box.pack_start(self._epg_box, True, True, 0)
|
||||
|
||||
def on_ftp_realize(self, box):
|
||||
self._ftp_client = FtpClientBox(self, self._settings)
|
||||
box.pack_start(self._ftp_client, True, True, 0)
|
||||
@@ -726,7 +744,7 @@ class Application(Gtk.Application):
|
||||
|
||||
def on_visible_page(self, stack, param):
|
||||
self._page = Page(stack.get_visible_child_name())
|
||||
self._fav_paned.set_visible(self._page in (Page.SERVICES, Page.PICONS, Page.PLAYBACK))
|
||||
self._fav_paned.set_visible(self._page in (Page.SERVICES, Page.PICONS, Page.PLAYBACK, Page.EPG))
|
||||
self._save_tool_button.set_visible(self._page in (Page.SERVICES, Page.SATELLITE))
|
||||
|
||||
def on_page_show(self, action, value):
|
||||
@@ -1952,11 +1970,12 @@ class Application(Gtk.Application):
|
||||
else:
|
||||
self._alt_revealer.set_visible(False)
|
||||
|
||||
if self._control_box and self._control_box.update_epg:
|
||||
if self._page is Page.EPG:
|
||||
ref = self.get_service_ref(path)
|
||||
if not ref:
|
||||
return
|
||||
self._control_box.on_service_changed(ref)
|
||||
|
||||
self.emit("fav-changed", ref)
|
||||
|
||||
def on_services_selection(self, model, path, column):
|
||||
self.update_service_bar(model, path)
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.2 -->
|
||||
<interface domain="demon-editor">
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<object class="GtkBox" id="timer_row_box">
|
||||
<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="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="timer_name_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="timer_name_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="semibold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</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="timer_description_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="timer_description_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<attributes>
|
||||
<attribute name="style" value="italic"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="timer_service_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="timer_service_name_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="timer_time_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<attributes>
|
||||
<attribute name="size" value="8000"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="timer_row_separator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -126,6 +126,9 @@ class Page(Enum):
|
||||
SATELLITE = "satellite"
|
||||
PICONS = "picons"
|
||||
PLAYBACK = "playback"
|
||||
EPG = "epg"
|
||||
TIMERS = "timers"
|
||||
RECORDINGS = "recordings"
|
||||
FTP = "ftp"
|
||||
CONTROL = "control"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user