window.py 8.46 KB
Newer Older
Todd Weaver's avatar
Todd Weaver committed
1
2
# window.py
#
3
# Copyright 2021 Purism, SPC
Todd Weaver's avatar
Todd Weaver committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import gi
19
gi.require_version('Gdk', '3.0')
Todd Weaver's avatar
Todd Weaver committed
20
21
gi.require_version('Gtk', '3.0')
gi.require_version('Handy', '1')
22
from gi.repository import Gdk, Gtk, Handy
23

Todd Weaver's avatar
Todd Weaver committed
24
25
Handy.init()

26
27
import json

28
from .menu import Menu
29
30
31
32
33
34
from .scrollers import ScrollerBox
from .instances import Instances

# plugin style
from .search import Search as DefaultSearch
from .iteroni import Search as PluginSearch
Todd Weaver's avatar
Todd Weaver committed
35
36
37
38
39

@Gtk.Template(resource_path='/sm/puri/Stream/ui/window.ui')
class StreamWindow(Handy.ApplicationWindow):
    __gtype_name__ = 'StreamWindow'

40
    header_bar = Gtk.Template.Child()
41
42
43
    navigation_previous = Gtk.Template.Child()
    navigation_current = Gtk.Template.Child()
    navigation_next = Gtk.Template.Child()
44

45
    search_bar_toggle = Gtk.Template.Child()
Todd Weaver's avatar
Todd Weaver committed
46
47
    search_bar = Gtk.Template.Child()

48
49
    menu_button = Gtk.Template.Child()

Todd Weaver's avatar
Todd Weaver committed
50
    status_page = Gtk.Template.Child()
51
    spinner = Gtk.Template.Child()
52
53
54
    error_box = Gtk.Template.Child()
    error_heading = Gtk.Template.Child()
    error_text = Gtk.Template.Child()
55
56
57

    scroller_stack = Gtk.Template.Child()

Todd Weaver's avatar
Todd Weaver committed
58

59
    @Gtk.Template.Callback()
60
    def search_toggle(self, toggle_button):
Todd Weaver's avatar
Todd Weaver committed
61
        # toggle the True/False from what is current
62
        self.search_bar.set_visible(self.search_bar_toggle.get_active())
Todd Weaver's avatar
Todd Weaver committed
63

64
65
66
67
68
    def clear_scroll_stacks(self):
        children = self.scroller_stack.get_children()
        for child in children:
            child.destroy()

69
70
    @Gtk.Template.Callback()
    def search_entry(self, search_box):
71
        self.stacks_list = []
72
        self.status_page.set_visible(False)
73

74
        self.hide_error_box()
75
        self.spinner.set_visible(True)
76

77
        search_query = search_box.get_text()
78

79
80
81
        self.clear_scroll_stacks()

        if not self.strong_instances:
82
83
            self.show_error_box("Service Failure",
                "No strong video server instances found yet. Try again shortly.")
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
        else:
            instance_index = 0
            for sort_by in ["relevance", "view_count"]:
                key = sort_by + str(instance_index)
                self.stacks_list.append(key)
                self.scroller = ScrollerBox(self, instance_index)
                self.scroller_stack.add_named(self.scroller, key)

                search = DefaultSearch(app_window = self,
                                       instance_index = instance_index,
                                       sort_by = sort_by,
                                       set_headerbar_color = self.set_headerbar_color,
                                       spinner = self.spinner,
                                       add_result = self.scroller.add_result,
                                       scroller_stack = self.scroller_stack)
                search.do_search(query = search_query)
                instance_index += 1

            key = 'plugin' + str(instance_index)
            self.stacks_list.append(key)
            self.scroller = ScrollerBox(self, instance_index)
            self.scroller_stack.add_named(self.scroller, key)

            plugin = PluginSearch(set_headerbar_color = self.set_headerbar_color,
                                  add_result = self.scroller.add_result,
                                  hide_scroller_error_box = self.scroller.hide_scroller_error_box,
                                  show_scroller_error_box = self.scroller.show_scroller_error_box)
            plugin.do_search(query = search_query)

    def set_headerbar_color(self):
        self.get_visible_scroller()
        self.navigation_previous.set_sensitive(True)
        self.navigation_next.set_sensitive(True)
        nav_current_context = self.navigation_current.get_style_context()
        css_classes = nav_current_context.list_classes()
        for css_class in css_classes:
            if css_class.startswith('color'):
                nav_current_context.remove_class(css_class)

        if self.scroller_index < 8:
            nav_current_context.add_class("color" + str(self.scroller_index))

    def get_visible_scroller(self):
        visible_scroller = self.scroller_stack.get_visible_child_name()
        self.scroller_index = self.stacks_list.index(visible_scroller)

    @Gtk.Template.Callback()
    def show_previous_results(self, button):
        self.get_visible_scroller()
        if self.scroller_index > 0:
            previous_name = self.stacks_list[self.scroller_index-1]
            previous_scroller = self.scroller_stack.get_child_by_name(str(previous_name))
            self.scroller_stack.set_visible_child(previous_scroller)
            self.set_headerbar_color()

    @Gtk.Template.Callback()
    def show_next_results(self, button):
        self.get_visible_scroller()
        if self.scroller_index < len(self.scroller_stack) - 1:
            next_name = self.stacks_list[self.scroller_index+1]
            next_scroller = self.scroller_stack.get_child_by_name(str(next_name))
            self.scroller_stack.set_visible_child(next_scroller)
            self.set_headerbar_color()

148
149
150
151
152
    def fullscreen_toggle(self, focus_child):
        if self.is_fullscreen:
            focus_child.get_child().unfullscreen_button(None)
        else:
            focus_child.get_child().fullscreen_button(None)
153

154
155
    def play_pause_toggle(self, focus_child):
        if self.is_playing:
156
            focus_child.get_child().pause_button(None)
157
158
159
        else:
            focus_child.get_child().play_button(None)

160
161
162
163
#    @Gtk.Template.Callback()
#    def open_primary_menu(self, widget, ev):
#        print("in open primary menu")

164
165
166
    @Gtk.Template.Callback()
    def keypress_listener(self, widget, ev):
        key = Gdk.keyval_name(ev.keyval)
167
168
169
170
171
172
173
174
175
176
177
        if self.scroller_stack:
            visible_scroller = self.scroller_stack.get_visible_child()
            if visible_scroller:
                focus_child = visible_scroller.results_list.get_focus_child()
                if focus_child:
                    if key == "Escape":
                        focus_child.get_child().unfullscreen_button(None)
                    if key == "space":
                        self.play_pause_toggle(focus_child)
                    if key == "f":
                        self.fullscreen_toggle(focus_child)
178
179

    def pause_all(self):
180
181
182
183
184
        if self.scroller_stack:
            scrollers = self.scroller_stack.get_children()
            for scroller in scrollers:
                flowboxes = scroller.results_list.get_children()
                for flowbox in flowboxes:
185
                    flowbox.get_child().null_out_player()
186

187
188
189
190
191
192
193
194
195
196
197
198
    def inhibit_app(self):
        self.application.inhibit(self,
                Gtk.ApplicationInhibitFlags.IDLE |
                Gtk.ApplicationInhibitFlags.LOGOUT,
                "Stream-ing Video")

    def uninhibit_app(self):
        self.application.inhibit(self,
                Gtk.ApplicationInhibitFlags.IDLE |
                Gtk.ApplicationInhibitFlags.LOGOUT,
                "Stream-ing Video")

199
200
201
202
203
204
205
206
207
208
209
    def hide_error_box(self):
        self.error_box.set_visible(False)
        self.error_heading.set_label("Error")
        self.error_text.set_label("...")

    def show_error_box(self, heading, text):
        self.spinner.set_visible(False)
        self.error_box.set_visible(True)
        self.error_heading.set_label(heading)
        self.error_text.set_label(text)

210
211
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
212
        self.application = kwargs.get('application', None)
213

214
        self.is_playing = False
215
        self.is_fullscreen = False
216
217
218
219
        self.strong_instances = []
        instances = Instances(app_window = self)
        instances.get_strong_instances()

220
221
222
        menu = Menu(app_window = self)
        self.menu_button.set_popover(menu)

223
224
225
226
227
228
        provider = Gtk.CssProvider()
        provider.load_from_resource('/sm/puri/Stream/ui/stream.css')
        styleContext = Gtk.StyleContext()
        styleContext.add_provider_for_screen(
            Gdk.Screen.get_default(), provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)