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

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

wip

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