source: lliurex-store/trunk/fuentes/lliurex-store-gui/MainWindow.py @ 4114

Last change on this file since 4114 was 4114, checked in by hectorgh, 2 years ago

wip

File size: 15.0 KB
Line 
1import gi
2gi.require_version('Gtk', '3.0')
3from gi.repository import Gtk, Pango, GdkPixbuf, Gdk, Gio, GObject,GLib
4
5import Core
6import Package
7
8import threading
9import multiprocessing
10import signal
11import time
12
13signal.signal(signal.SIGINT, signal.SIG_DFL)
14
15
16import gettext
17gettext.textdomain('zero-center')
18_ = gettext.gettext
19
20
21
22class MainWindow:
23       
24        def __init__(self):
25               
26                self.core=Core.Core.get_core()
27                self.load_thread=threading.Thread()
28                self.search_process=multiprocessing.Process()
29                self.thread_aborted=False
30                self.search_aborted=False
31                self.last_search=""
32                self.path_followed=["main"]
33                self.load_gui()
34               
35        #def init
36       
37
38       
39        # ### MAIN UI FUNCTIONS # ####################
40       
41        def load_gui(self):
42               
43                builder=Gtk.Builder()
44                ui_path=self.core.ui_path
45                builder.add_from_file(ui_path)
46               
47                self.window=builder.get_object("window1")
48                self.menu_button=builder.get_object("menu_button")
49               
50                self.main_scroll=builder.get_object("main_scrolledwindow")
51                self.location_label=builder.get_object("location_label")
52                self.search_entry=builder.get_object("search_entry")
53                self.main_box=builder.get_object("main_box")
54                self.header_box=builder.get_object("header_box")
55                self.go_back_button=builder.get_object("go_back_button")
56               
57               
58               
59                self.main_menu=self.core.main_menu
60                self.loading_box=self.core.loading_box
61                self.details_box=self.core.details_box
62                self.popup_menu=self.core.popup_menu
63                self.screenshot_viewer=self.core.screenshot_viewer
64                self.search_box=self.core.search_box
65               
66                self.stack=Gtk.Stack()
67                self.stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
68                self.stack.set_transition_duration(500)
69               
70                self.stack.add_titled(self.loading_box,"loading","Loading")
71                self.stack.add_titled(self.main_menu,"main","Main")
72                self.stack.add_titled(self.details_box,"details","Details")
73                self.stack.add_titled(self.search_box,"search","Search")
74                self.main_scroll.add(self.stack)
75       
76                self.overlay=Gtk.Overlay()
77                self.main_eb=Gtk.EventBox()
78                self.main_eb.add(self.main_box)
79               
80                self.main_eb.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
81                self.main_eb.connect("button-press-event",self.main_eb_clicked)
82               
83                self.overlay.add(self.main_eb)
84                self.overlay.show_all()
85               
86                self.fade_box_revealer=Gtk.Revealer()
87                self.fade_box_revealer.set_valign(Gtk.Align.END)
88                self.fade_box_revealer.set_halign(Gtk.Align.END)
89               
90                self.fade_box=Gtk.HBox()
91                self.fade_eb=Gtk.EventBox()
92                self.fade_eb.add(self.fade_box)
93                self.fade_eb.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
94                self.fade_eb.connect("button-press-event",self.main_eb_clicked)
95               
96                self.fade_box_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_UP)
97                self.fade_box_revealer.set_transition_duration(self.popup_menu.revealer.get_transition_duration())
98                self.fade_box_revealer.add(self.fade_eb)
99                self.fade_box_revealer.show_all()
100               
101               
102                self.overlay.add_overlay(self.fade_box_revealer)
103                self.overlay.add_overlay(self.popup_menu)
104                self.overlay.add_overlay(self.screenshot_viewer)
105
106                self.window.add(self.overlay)
107               
108                self.connect_signals()
109                self.set_css_info()
110                self.build_home()
111               
112                self.window.show_all()
113                #self.location_label.hide()
114               
115        #def load_gui
116
117       
118        def set_css_info(self):
119               
120                self.style_provider=Gtk.CssProvider()
121                f=Gio.File.new_for_path("lliurex-store.css")
122                self.style_provider.load_from_file(f)
123                Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),self.style_provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
124               
125                self.window.set_name("MAIN_BOX")
126                self.header_box.set_name("HEADER_MENU")
127                self.menu_button.set_name("MENU_BUTTON")
128                self.location_label.set_name("RELATED_LABEL")
129                self.fade_box.set_name("FADE_BOX")
130               
131                self.go_back_button.set_name("BACK_BUTTON")
132               
133               
134        #def set-css_info       
135
136       
137        def connect_signals(self):
138               
139                self.window.connect("size-allocate",self.window_size_changed)
140                self.window.connect("destroy",Gtk.main_quit)
141                self.menu_button.connect("clicked",self.menu_button_clicked)
142                self.search_entry.connect("changed",self.search_entry_changed)
143                self.search_entry.connect("activate",self.entries_press_event)
144                self.go_back_button.connect("clicked",self.go_back)
145               
146        #def connect_signals
147       
148       
149        def start_gui(self):
150               
151                GObject.threads_init()
152                Gtk.main()
153               
154        #def start_gui
155
156        # #################################################### ##
157
158
159
160        # #### STACK FAST ACCESS FUNCTIONS # #################
161       
162        def go_back(self,widget=None):
163               
164                if len(self.path_followed)>1:
165                       
166                       
167                        current_txt=self.location_label.get_text().split(" > ")
168                        current_txt=" > ".join(current_txt[0:-1])
169                        self.location_label.set_text(current_txt)
170                        dest=self.path_followed[-2]
171                        self.stack.set_visible_child_name(dest)
172                        self.path_followed.pop(-1)
173                       
174                        if dest=="main":
175                                self.search_entry.set_text("")
176                       
177                       
178               
179        #def go_back
180       
181        def show_loading(self):
182               
183                self.stack.set_visible_child_name("loading")
184               
185        #def kk
186
187
188        def show_details_box(self):
189               
190                self.thread_aborted=True
191                self.search_aborted=True
192                current_txt=self.location_label.get_text()
193                if self.path_followed[-1]!="details":
194                        self.location_label.set_text(current_txt + " > " + _("Details"))
195                        self.path_followed.append("details")
196                self.stack.set_visible_child_name("details")
197               
198        #def show_details_box
199
200
201        def show_home(self):
202               
203                self.thread_aborted=True
204                self.search_aborted=True
205               
206                self.search_entry.set_text("")
207                self.location_label.set_text(_("Home"))
208                self.path_followed=["main"]
209                self.stack.set_visible_child_name("main")
210               
211        #def show_details_box
212       
213        def show_search_results(self,category=None):
214               
215                current_txt=self.location_label.get_text()
216               
217                if category==None:
218                        category="Search"
219               
220                if self.path_followed[-1]=="details":
221                        self.path_followed.pop(-1)
222                        current_txt=" > ".join(current_txt.split(" > ")[0:-1])
223               
224                if self.path_followed[-1]=="search":
225                        current_txt="".join(current_txt.split(" > ")[0:-1])
226                else:
227                        self.path_followed.append("search")
228                       
229                self.location_label.set_text(current_txt + " > " + category)
230                self.stack.set_visible_child_name("search")
231               
232        #def show_search_results
233       
234        # ############################################
235
236
237
238        # ### HOME LOADING FUNCTIONS # ##############
239       
240        def build_home(self):
241               
242                self.load_thread=threading.Thread(target=self.download_home_info_thread)
243                self.load_thread.daemon=True
244                self.load_thread.start()
245               
246                GLib.timeout_add(500,self.build_home_listener)
247               
248        #def build_home
249
250
251        def build_home_listener(self):
252               
253                if self.thread_aborted:
254                        self.thread_aborted=False
255                        return False
256               
257               
258                if self.load_thread.is_alive():
259                        return True
260               
261               
262                self.main_menu.build_banners()
263                self.show_home()
264                return False
265               
266        #def load_home
267
268       
269        def download_home_info_thread(self):
270               
271                self.main_menu.download_home_info()
272               
273                #time.sleep(2)
274
275        #def load_home_thread
276       
277        # #################################
278
279       
280       
281        # ### LOAD PKG FUNCTIONS # ##################
282       
283       
284        def set_pkg_data(self,pkg):
285               
286                self.current_pkg=Package.Package(pkg)
287                self.details_box.set_package_info(self.current_pkg)
288                self.show_details_box()
289                #self.stack.set_visible_child_name("details")
290               
291        #def set_data
292       
293        def load_pkg_data(self,pkg_id,pkg_data=None):
294               
295                self.current_pkg=None
296                self.thread_aborted=False
297                self.load_thread=threading.Thread(target=self.load_pkg_data_thread,args=(pkg_id,))
298                self.load_thread.daemon=True
299                self.load_thread.start()
300                self.show_loading()
301                GLib.timeout_add(500,self.load_pkg_listener)
302               
303        #def load_pkg_data
304       
305        def load_pkg_data_thread(self,pkg_id):
306               
307                #self.current_pkg=Package.Package.get_demo_package(pkg_id)
308                self.current_pkg=self.core.store.get_info(pkg_id)
309                #time.sleep(2)
310               
311        #def load_pkg_data_thread
312       
313        def load_pkg_listener(self):
314               
315                if self.thread_aborted:
316                        self.thread_aborted=False
317                        return False
318               
319                if self.load_thread.is_alive():
320                        return True
321                       
322                if self.current_pkg!=None:
323                        self.details_box.set_package_info(self.current_pkg)
324                        self.show_details_box()
325                        #self.stack.set_visible_child_name("details")
326               
327                return False
328               
329        #def load_pkg_listener
330       
331        # #################################
332
333
334        # ## SEARCH FUNCTIONS ######################
335       
336       
337        def entries_press_event(self,widget):
338               
339                self.last_search=None
340                self.search_entry_changed(None)
341               
342        #def entries_press_event
343       
344        def search_entry_changed(self,widget):
345               
346                txt=self.search_entry.get_text()
347                current_stack=self.stack.get_visible_child_name()
348                txt=txt.strip(" ")
349               
350                if self.last_search!=txt:
351                        self.last_search=txt
352                else:
353                        return
354               
355                if len(txt)==0:
356                        self.show_home()
357                        return
358                       
359                if len(txt)>2:
360                        self.search_aborted=False
361                        self.show_loading()
362                        self.search_package(txt)
363               
364        #def search_entry_changed
365       
366        def search_package(self,pkg_id):
367               
368                if self.search_process.is_alive():
369                        self.search_process.terminate()
370               
371                self.current_search_id=self.core.get_random_id()
372                self.counter=0
373                self.search_queue=multiprocessing.Queue()
374                self.search_process=multiprocessing.Process(target=self.search_package_thread,args=(pkg_id,self.search_queue,))
375                #self.search_process=threading.Thread(target=self.search_package_thread,args=(pkg_id,self.search_queue,))
376               
377                self.search_process.daemon=True
378                self.search_process.start()
379               
380                GLib.timeout_add(500, self.search_listener,self.current_search_id)
381               
382        #def search_package
383       
384        def search_package_thread(self,pkg_id,search_queue):
385               
386                ret=self.core.store.search_package(pkg_id)
387                self.core.dprint("Search complete")
388                search_queue.put(ret)
389               
390        #def search_package_thread
391       
392        def search_listener(self,search_id):
393               
394                if self.current_search_id!=search_id:
395                        return False
396               
397                if self.search_aborted:
398                        self.core.dprint("Search aborted [!]")
399                        self.thread_aborted=False
400                        return False
401               
402                if self.search_process.is_alive():
403                        self.counter+=1
404                       
405                        if self.search_queue.empty():
406                                return True
407                       
408                search_result=self.search_queue.get()
409               
410               
411                if search_result!=None:
412                        self.core.search_box.populate_search_results(search_result)
413                        self.show_search_results()
414               
415                return False
416               
417        #def search_listener
418       
419
420        # ########################################
421       
422        # ### SEARCH CATEGORIES #### #
423       
424        def search_category(self,category):
425       
426                if self.search_process.is_alive():
427                        self.search_process.terminate()
428       
429
430                self.search_aborted=False
431                self.show_loading()
432               
433                self.current_search_id=self.core.get_random_id()
434                self.counter=0
435                self.search_queue=multiprocessing.Queue()
436                self.search_process=multiprocessing.Process(target=self.search_category_thread,args=(category,self.search_queue,))
437                #self.search_process=threading.Thread(target=self.search_package_thread,args=(pkg_id,self.search_queue,))
438               
439                self.search_process.daemon=True
440                self.search_process.start()
441               
442                GLib.timeout_add(500, self.search_category_listener,self.current_search_id)
443       
444        #def search_category
445       
446        def search_category_thread(self,category,search_queue):
447               
448                ret=self.core.store.get_package_list_from_category(category)
449                self.core.dprint("Search complete")
450                '''
451                for p in ret:
452                        pkg["icon_url"]=self.core.resources.get_icon(p.dic)
453                        pkg["name"]=p.dic["name"]
454                        pkg["package"]=pkg_id
455                        pkg["short_description"]="Package that does a lot of things very well done askdjlaskl jdaklsdjkl asjkl dasjkl djkl asdjkl asdjkl asdjkl asdjkl asdjkl asdjkl asd"
456                        ret.append(pkg)
457                '''
458               
459                search_queue.put(ret)
460               
461
462               
463        #def search_package_thread
464       
465        def search_category_listener(self,search_id):
466               
467                if self.current_search_id!=search_id:
468                        return False
469               
470                if self.search_aborted:
471                        self.core.dprint("Search aborted [!]")
472                        self.thread_aborted=False
473                        return False
474               
475                if self.search_process.is_alive():
476                        self.counter+=1
477                       
478                        if self.search_queue.empty():
479                                return True
480                       
481                search_result=self.search_queue.get()
482               
483                if search_result!=None:
484                       
485                        search_result,categories=search_result
486                        self.core.search_box.populate_search_results(search_result,categories)
487                        self.show_search_results(self.core.search_box.current_category)
488               
489                return False
490               
491        #def search_listener
492       
493       
494       
495        # ########################
496       
497       
498        # ## INSTALLED LIST QUERY ## #
499       
500       
501        def get_installed_list(self):
502               
503                if self.search_process.is_alive():
504                        self.search_process.terminate()
505               
506                self.search_aborted=False
507                self.show_loading()
508               
509                self.current_search_id=self.core.get_random_id()
510                self.counter=0
511                self.search_queue=multiprocessing.Queue()
512                self.search_process=multiprocessing.Process(target=self.get_installed_list_thread,args=(self.search_queue,))
513                #self.search_process=threading.Thread(target=self.search_package_thread,args=(pkg_id,self.search_queue,))
514               
515                self.search_process.daemon=True
516                self.search_process.start()
517               
518                GLib.timeout_add(500, self.search_listener,self.current_search_id)
519               
520        #def search_package
521       
522        def get_installed_list_thread(self,search_queue):
523               
524                ret=self.core.store.get_installed_list()
525                self.core.dprint("Search complete")
526                '''
527                for p in ret:
528                        pkg["icon_url"]=self.core.resources.get_icon(p.dic)
529                        pkg["name"]=p.dic["name"]
530                        pkg["package"]=pkg_id
531                        pkg["short_description"]="Package that does a lot of things very well done askdjlaskl jdaklsdjkl asjkl dasjkl djkl asdjkl asdjkl asdjkl asdjkl asdjkl asdjkl asd"
532                        ret.append(pkg)
533                '''
534               
535                search_queue.put(ret)
536               
537
538        #def search_package_thread
539       
540       
541        # ##################### #
542       
543       
544       
545
546        # ## SCREENSHOTVIEWER FUNCTIONS ## ##############
547       
548        def window_size_changed(self,widget,allocation):
549               
550                x,y=self.window.get_size()
551                self.popup_menu.popup_menu.set_size_request(400,y)
552                self.screenshot_viewer.content_box.set_size_request(x,y)
553                self.screenshot_viewer.sw.set_size_request(x-20,150)
554                self.fade_box.set_size_request(x,y)
555               
556        #def window_size_allocation
557
558
559        def screenshot_clicked(self,widget):
560
561                if widget.get_children()[0].get_visible_child_name()=="image":
562                       
563                        if self.popup_menu.revealer.get_reveal_child():
564                                self.popup_menu.revealer.set_reveal_child(False)
565                                return
566                       
567                        if widget.get_children()[0].image_info["video_url"]==None:
568                                self.screenshot_viewer.set_screenshot(widget.get_children()[0].image_info["image_id"],self.details_box.screenshots_box)
569                        else:
570                                self.screenshot_viewer.set_screenshot(widget.get_children()[0].image_info["video_url"],self.details_box.screenshots_box,True)
571                               
572                        self.screenshot_viewer.revealer.set_reveal_child(True)
573                       
574                       
575        #def screenshot_clicked
576       
577        # ####################################### #
578
579
580
581        # ## POPUP MENU FUNCTIONS # #####################
582
583        def main_eb_clicked(self,widget,event):
584               
585                if self.popup_menu.revealer.get_reveal_child():
586                        self.popup_menu.revealer.set_reveal_child(False)
587                       
588                if self.fade_box_revealer.get_reveal_child():
589                        self.fade_box_revealer.set_transition_type(Gtk.RevealerTransitionType.CROSSFADE)
590                        GLib.timeout_add(30,self.check_fade_out)
591                        self.fade_box_revealer.set_reveal_child(False)
592                       
593        #def main_eb_clicked
594
595       
596        def menu_button_clicked(self,widget):
597               
598                self.fade_box_revealer.set_transition_type(Gtk.RevealerTransitionType.CROSSFADE)
599                self.popup_menu.revealer.set_reveal_child(not self.popup_menu.revealer.get_reveal_child())
600                self.fade_box_revealer.set_reveal_child(True)
601               
602        #def menu_button_clicked
603
604
605        def check_fade_out(self):
606               
607                if self.fade_box_revealer.get_child_revealed():
608                        return True
609                       
610                self.fade_box_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_UP)
611               
612        #def check_fade_out
613       
614        # ########################################## #
615       
616
617
618       
619       
620       
621#class LliurexStore
622
623if __name__=="__main__":
624       
625        llx_store=LliurexStore()
Note: See TracBrowser for help on using the repository browser.