source: lliurex-store/trunk/fuentes/lliurex-store-gui/usr/share/lliurex-store/lliurex-store-gui/DetailsBox.py @ 7440

Last change on this file since 7440 was 7440, checked in by hectorgh, 22 months ago

fixing scrolled windows and character width limit in pkg results when searching

File size: 16.3 KB
Line 
1import gi
2gi.require_version('Gtk', '3.0')
3
4from gi.repository import Gtk, Pango, GdkPixbuf, Gdk, Gio,GLib
5import Screenshot
6import ImageManager
7
8import Core
9
10import signal
11signal.signal(signal.SIGINT, signal.SIG_DFL)
12
13import time
14import threading
15from subprocess import Popen
16import os
17import html2text
18
19import gettext
20gettext.textdomain('lliurex-store')
21_ = gettext.gettext
22
23
24
25class DetailsBox(Gtk.VBox):
26
27        def __init__(self):
28               
29                Gtk.VBox.__init__(self)
30               
31                self.core=Core.Core.get_core()
32               
33                self.banner_full_size=250
34                self.screenshot_small=100
35                self.banner_small=135
36                self.icon_size=64
37               
38                self.details_max_width=25
39                self.app_max_width=8
40                self.short_description_max_width=10
41               
42                self.full_info_box=Gtk.HBox()
43                self.pack_start(self.full_info_box,True,True,5)
44               
45                # ####### LEFT SIDE ######
46               
47                self.app_details=Gtk.VBox()
48                self.app_details.set_margin_left(10)
49                self.app_details.set_margin_bottom(10)
50                self.app_details.set_margin_top(5)
51                self.full_info_box.pack_start(self.app_details,False,False,0)
52
53                self.app_banner=Screenshot.ScreenshotNeo()
54                self.app_banner.set_size_request(self.banner_full_size,self.banner_full_size)
55
56                self.app_details.pack_start(self.app_banner,False,False,0)
57                self.install_button=Gtk.Button()
58                self.install_button_label=Gtk.Label(_("Install"))
59                self.install_button.add(self.install_button_label)
60                self.install_button.connect("clicked",self.install_clicked)
61               
62                vbox=Gtk.VBox()
63                self.install_label=Gtk.Label(_("Installing..."))
64                vbox.pack_start(self.install_label,False,False,0)
65                vbox.set_valign(Gtk.Align.FILL)
66                vbox.set_halign(Gtk.Align.FILL)
67               
68                self.install_label.set_halign(Gtk.Align.START)
69                self.install_pbar=Gtk.ProgressBar()
70                self.install_pbar.set_valign(Gtk.Align.FILL)
71                self.install_pbar.set_halign(Gtk.Align.FILL)
72                vbox.pack_start(self.install_pbar,True,True,0)
73
74                hbox=Gtk.HBox()
75                self.uninstall_button=Gtk.Button(_("Uninstall"))
76                self.uninstall_button.connect("clicked",self.uninstall_clicked)
77                self.open_button=Gtk.Button(_("Open"))
78                self.open_button.connect("clicked",self.open_clicked)
79                self.open_button.set_margin_right(10)
80                hbox.pack_start(self.open_button,True,True,0)
81                hbox.pack_start(self.uninstall_button,True,True,0)
82               
83                self.install_stack=Gtk.Stack()
84                self.install_stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
85                self.install_stack.set_transition_duration(500)
86                self.install_stack.add_titled(self.install_button,"install","Install")
87                self.install_stack.add_titled(vbox,"progress","Progress")
88                self.install_stack.add_titled(hbox,"installed","Open/Uninstall")
89               
90                self.app_details.pack_start(self.install_stack,False,False,10)
91               
92                self.details_label=Gtk.Label("Details")
93                self.details_label.set_alignment(0,0.5)
94                self.details_label.set_margin_left(0)
95                self.app_details.pack_start(self.details_label,False,False,0)
96               
97                self.details_divider=Gtk.HBox()
98                self.details_divider.set_size_request(0,1)
99                self.app_details.pack_start(self.details_divider,False,False,5)
100               
101                self.version_label=Gtk.Label(_("Version"))
102                self.version_label.set_alignment(0,0.5)
103                self.category_label=Gtk.Label(_("Category"))
104                self.category_label.set_alignment(0,0.5)
105                self.license_label=Gtk.Label(_("License"))
106                self.license_label.set_alignment(0,0.5)
107                self.size_label=Gtk.Label(_("Size"))
108                self.size_label.set_alignment(0,0.5)
109                self.website_label=Gtk.Label(_("Website"))
110                self.website_label.set_alignment(0,0.5)
111
112                self.version_value_label=Gtk.Label()
113                self.version_value_label.set_alignment(1,0.5)
114                self.version_value_label.set_max_width_chars(self.details_max_width)
115                self.version_value_label.set_ellipsize(Pango.EllipsizeMode.END)
116                self.category_value_label=Gtk.Label()
117                self.category_value_label.set_alignment(1,0.5)
118                self.category_value_label.set_max_width_chars(self.details_max_width)
119                self.category_value_label.set_ellipsize(Pango.EllipsizeMode.END)
120                self.license_value_label=Gtk.Label()
121                self.license_value_label.set_alignment(1,0.5)
122                self.license_value_label.set_max_width_chars(self.details_max_width)
123                self.license_value_label.set_ellipsize(Pango.EllipsizeMode.END)
124                self.size_value_label=Gtk.Label()
125                self.size_value_label.set_alignment(1,0.5)
126                self.size_value_label.set_max_width_chars(self.details_max_width)
127                self.size_value_label.set_ellipsize(Pango.EllipsizeMode.END)
128                self.website_value_label=Gtk.Label()
129                self.website_value_label.set_alignment(1,0.5)
130                self.website_value_label.set_max_width_chars(self.details_max_width)
131                self.website_value_label.set_ellipsize(Pango.EllipsizeMode.END)
132               
133                hbox=Gtk.HBox()
134                hbox.pack_start(self.version_label,False,False,0)
135                hbox.pack_end(self.version_value_label,False,False,0)
136                self.app_details.pack_start(hbox,False,False,0)
137                hbox=Gtk.HBox()
138                hbox.pack_start(self.category_label,False,False,0)
139                hbox.pack_end(self.category_value_label,False,False,0)
140                self.app_details.pack_start(hbox,False,False,0)
141                hbox=Gtk.HBox()
142                hbox.pack_start(self.license_label,False,False,0)
143                hbox.pack_end(self.license_value_label,False,False,0)
144                self.app_details.pack_start(hbox,False,False,0)
145                hbox=Gtk.HBox()
146                hbox.pack_start(self.size_label,False,False,0)
147                hbox.pack_end(self.size_value_label,False,False,0)
148                self.app_details.pack_start(hbox,False,False,0)
149                hbox=Gtk.HBox()
150                hbox.pack_start(self.website_label,False,False,0)
151                hbox.pack_end(self.website_value_label,False,False,0)
152                self.app_details.pack_start(hbox,False,False,0)
153               
154               
155                # ############# #
156               
157                # ####### RIGHT SIDE ######
158               
159                self.app_details_r=Gtk.VBox()
160                self.app_details_r.set_margin_top(5)
161                self.full_info_box.pack_start(self.app_details_r,True,True,20)
162               
163                hbox=Gtk.HBox()
164                self.app_icon=Screenshot.ScreenshotNeo()
165                self.app_icon.set_size_request(64,64)
166               
167                hbox.pack_start(self.app_icon,False,False,0)
168               
169                self.app_name_label=Gtk.Label("")
170                self.app_name_label.set_max_width_chars(self.app_max_width)
171                self.app_name_label.set_ellipsize(Pango.EllipsizeMode.END)
172                self.app_name_label.set_alignment(0,1)
173                self.short_description_label=Gtk.Label("")
174                self.short_description_label.set_alignment(0,0)
175                self.short_description_label.set_max_width_chars(self.short_description_max_width)
176                self.short_description_label.set_ellipsize(Pango.EllipsizeMode.END)
177               
178                vbox=Gtk.VBox()
179                vbox.pack_start(self.app_name_label,True,True,0)
180                vbox.pack_start(self.short_description_label,True,True,0)
181                hbox.pack_start(vbox,True,True,5)
182               
183                self.app_details_r.pack_start(hbox,False,False,0)
184               
185                self.full_description_label=Gtk.Label()
186                self.full_description_label.set_margin_right(10)
187                self.full_description_label.set_alignment(0,1)
188                self.full_description_label.set_justify(Gtk.Justification.FILL)
189                self.full_description_label.set_line_wrap(True)
190                self.full_description_label.set_valign(Gtk.Align.START)
191                self.full_description_label.set_halign(Gtk.Align.FILL)
192               
193                sw=Gtk.ScrolledWindow()
194                sw.set_shadow_type(Gtk.ShadowType.NONE)
195                sw.set_overlay_scrolling(True)
196                sw.set_kinetic_scrolling(True)
197                vp=Gtk.Viewport()
198                sw.add(vp)
199                sw.set_size_request(0,100)
200                vp.add(self.full_description_label)
201               
202                self.app_details_r.pack_start(sw,True,True,10)
203               
204                self.description_divider=Gtk.HBox()
205                self.description_divider.set_size_request(0,1)
206                self.description_divider.set_valign(Gtk.Align.START)
207                self.app_details_r.pack_start(self.description_divider,False,False,5)
208               
209                ss_sw=Gtk.ScrolledWindow()
210                ss_sw.set_shadow_type(Gtk.ShadowType.NONE)
211                ss_vp=Gtk.Viewport()
212               
213                ss_sw.add(ss_vp)
214               
215                self.screenshots_box=Gtk.HBox()
216               
217                ss_sw.set_size_request(0,130)
218                vbox=Gtk.VBox()
219                vbox.pack_start(self.screenshots_box,True,False,0)
220                ss_vp.add(vbox)
221                self.app_details_r.set_valign(Gtk.Align.FILL)
222                self.app_details_r.pack_start(ss_sw,False,False,5)
223               
224               
225                # ####################### #
226               
227                # ## RELATED #######
228               
229                related_vbox=Gtk.VBox()
230                related_vbox.set_margin_left(10)
231               
232                self.related_label=Gtk.Label(_("Related"))
233                self.related_label.set_alignment(0,1)
234               
235                related_vbox.pack_start(self.related_label,False,False,0)
236                               
237                self.related_divider=Gtk.HBox()
238                self.related_divider.set_size_request(0,1)
239                self.related_divider.set_margin_right(20)
240                related_vbox.pack_start(self.related_divider,False,False,5)
241               
242                self.related_sw=Gtk.ScrolledWindow()
243                self.related_sw.set_shadow_type(Gtk.ShadowType.NONE)
244                self.related_sw.set_size_request(0,self.banner_small+40)
245                self.related_sw.set_margin_right(20)
246                related_vp=Gtk.Viewport()
247                self.related_sw.add(related_vp)
248               
249                self.related_box=Gtk.HBox()
250                self.related_box.set_margin_bottom(10)
251               
252                related_vp.add(self.related_box)
253               
254                related_vbox.pack_start(self.related_sw,False,False,5)
255                self.pack_start(related_vbox,True,True,0)
256               
257                # #################
258
259                self.set_css_info()
260               
261        #def  init
262       
263        def set_package_info(self,pkg):
264               
265                info={}
266               
267                info["image_url"]=pkg["banner_small"]
268                info["image_id"]=pkg["package"]+"_banner_small"
269                info["x"]=self.banner_full_size
270                info["y"]=self.banner_full_size
271                info["aspect_ratio"]=False
272                info["name"]=pkg["package"].capitalize()
273                info["installed"]=True if pkg["state"]=="installed" else False
274               
275                if pkg["banner_small"] !=None:
276                        self.app_banner.download_image(info)
277                else:
278                        info["name"]=None
279                        if os.path.exists(self.core.tmp_store_dir+info["image_id"]):
280                               
281                                info["image_path"]=self.core.tmp_store_dir+info["image_id"]
282                                self.app_banner.set_from_file(info)
283                        else:
284                                info["image_path"]=self.core.resources.get_icon(pkg)
285                       
286                                self.app_banner.create_banner_from_file(info)
287               
288                self.version_value_label.set_text(pkg["version"])
289                self.category_value_label.set_text(pkg["category"])
290                self.license_value_label.set_text(pkg["license"])
291                try:
292                        size= "{:.2f} MB".format(float(pkg["size"])/1000000) 
293                        self.size_value_label.set_text(size)
294                except:
295                        pass
296                self.website_value_label.set_markup("<a href=\"%s\">%s</a>"%(pkg["homepage"],pkg["homepage"]))
297                self.app_name_label.set_text(pkg["name"])
298                self.short_description_label.set_text(pkg["summary"])
299                h=html2text.HTML2Text()
300                h.body_width=500
301                txt=h.handle(pkg["description"])
302                txt=txt.replace("&lt;", "<")
303                txt=txt.replace("&gt;", ">")
304                txt=txt.replace("&amp;", "&")
305                self.full_description_label.set_text(txt)
306               
307                if info["installed"]:
308                        self.install_stack.set_visible_child_name("installed")
309                else:
310                        self.install_stack.set_visible_child_name("install")
311                       
312               
313                info["image_path"]=self.core.resources.get_icon(pkg)
314                info["image_id"]=pkg["icon"]+"_icon"
315                info["x"]=self.icon_size
316                info["y"]=self.icon_size
317               
318                self.app_icon.set_from_file(info)
319               
320                for s in self.screenshots_box.get_children():
321                        self.screenshots_box.remove(s)
322               
323                count=0
324                for v in pkg["videos"]:
325                       
326                        image=Screenshot.ScreenshotNeo()
327                        info["video_url"]=v["url"].replace("http://metadata.tanglu.org/appstream/media/xenial/","").replace("https://www.youtube.com/watch?v=","https://www.youtube.com/embed/")
328                        info["image_url"]=v["preview"]
329                        info["image_id"]=pkg["package"]+"_video_"+str(count)
330                        info["x"]=self.screenshot_small
331                        info["y"]=self.screenshot_small
332                       
333                        image.set_video_info(info)
334                       
335                        b=Gtk.Button()
336                        b.set_name("RELATED_BUTTON")
337                        b.add(image)
338                        self.screenshots_box.pack_start(b,False,False,5)
339                       
340                        count+=1
341                       
342                count=0
343                for s in pkg["screenshots"]:
344                       
345                        image=Screenshot.ScreenshotNeo()
346                        i={}
347                       
348                        i["image_url"]=s
349                        i["image_id"]=pkg["package"]+"_screenshot_"+str(count)
350                        i["x"]=self.screenshot_small
351                        i["y"]=self.screenshot_small
352                        i["aspect_ratio"]=False
353                                               
354                        image.download_image(i)
355                        b=Gtk.Button()
356                        b.set_name("RELATED_BUTTON")
357                        b.add(image)
358                        self.screenshots_box.pack_start(b,False,False,5)
359                        count+=1
360               
361                self.screenshots_box.show_all()
362
363                for p in self.related_box.get_children():
364                        self.related_box.remove(p)
365                       
366                for p in pkg["related_packages"]:
367                       
368                        image=Screenshot.ScreenshotNeo()
369
370                        i={}
371                        i["image_id"]=p["package"]+"_banner_small"
372                        i["x"]=self.banner_small
373                        i["y"]=self.banner_small
374                        i["name"]=p["package"].capitalize()
375                        i["package"]=p["package"]
376                        i["icon"]=p["icon"]
377                        i["component"]=p["component"]
378
379                        if p["banner"]!=None:
380                                i["image_url"]=p["banner"]
381                                i["custom_frame"]=False
382                        else:
383                                i["image_path"]=self.core.resources.get_icon(p)
384                                i["custom_frame"]=True
385                               
386                        if not i["custom_frame"]:
387                                image.download_image(i)
388                        else:
389                                i["force_text"]=True
390                                image.create_banner_from_file(i)
391                       
392                        b=Gtk.Button()
393                        b.add(image)
394                        b.set_size_request(self.banner_small,self.banner_small)
395                        b.set_margin_top(10)
396                        b.connect("clicked",self.related_app_clicked,p)
397                        b.set_name("RELATED_BUTTON")
398                        b.set_valign(Gtk.Align.CENTER)
399                        b.set_tooltip_text(p["name"])
400                        self.related_box.pack_start(b,False,False,3)
401               
402                self.related_sw.get_hadjustment().set_value(0)
403                self.related_box.show_all()
404               
405                for x in self.screenshots_box.get_children():
406                        x.connect("clicked",self.core.main_window.screenshot_clicked)
407               
408               
409        #def set_values
410       
411       
412        def set_css_info(self):
413               
414                self.style_provider=Gtk.CssProvider()
415                f=Gio.File.new_for_path(self.core.rsrc_dir+"lliurex-store.css")
416                self.style_provider.load_from_file(f)
417                Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),self.style_provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
418               
419                self.set_name("DETAILS_BOX")
420               
421                self.details_divider.set_name("DIVIDER")
422                self.description_divider.set_name("DIVIDER")
423                self.related_divider.set_name("DIVIDER")
424               
425                self.details_label.set_name("DETAILS_LABEL")
426                self.version_label.set_name("DETAILS_OPTIONS")
427                self.category_label.set_name("DETAILS_OPTIONS")
428                self.license_label.set_name("DETAILS_OPTIONS")
429                self.size_label.set_name("DETAILS_OPTIONS")
430                self.website_label.set_name("DETAILS_OPTIONS")
431               
432                self.version_value_label.set_name("DETAILS_VALUES")
433                self.category_value_label.set_name("DETAILS_VALUES")
434                self.license_value_label.set_name("DETAILS_VALUES")
435                self.size_value_label.set_name("DETAILS_VALUES")
436                self.website_value_label.set_name("DETAILS_VALUES")
437               
438                self.app_name_label.set_name("TITLE")
439                self.short_description_label.set_name("SHORT_DESCRIPTION")
440                self.full_description_label.set_name("FULL_DESCRIPTION")
441               
442                self.related_label.set_name("RELATED_LABEL")
443               
444                self.install_button.set_name("INSTALL_BUTTON")
445                self.install_label.set_name("DETAILS_LABEL")
446                self.uninstall_button.set_name("UNINSTALL_BUTTON")
447                self.open_button.set_name("INSTALL_BUTTON")
448               
449        #def set-css_info
450       
451       
452        def related_app_clicked(self,widget,app):
453               
454                self.core.main_window.load_pkg_data(app["package"])
455               
456        #def related_app_clicked
457       
458       
459        def install_clicked(self,widget):
460               
461                self.install_label.set_text("Installing...")
462                self.install_stack.set_visible_child_name("progress")
463               
464                t=threading.Thread(target=self.install_pkg)
465                t.daemon=True
466                t.start()
467                GLib.timeout_add(100,self.pulse_pbar,t,"installed","install")
468               
469        #def install_clicked
470       
471       
472        def uninstall_clicked(self,widget):
473               
474                self.install_label.set_text("Uninstalling...")
475                self.install_stack.set_visible_child_name("progress")
476               
477                t=threading.Thread(target=self.uninstall_pkg)
478                t.daemon=True
479                t.start()
480                GLib.timeout_add(100,self.pulse_pbar,t,"install","installed")
481               
482        #def install_clicked
483       
484               
485        def pulse_pbar(self,t,target,fallback):
486               
487                if t.is_alive():
488                        self.install_pbar.pulse()
489                        return True
490               
491               
492                if self.thread_ret:
493                        self.install_stack.set_visible_child_name(target)
494                else:
495                        self.install_stack.set_visible_child_name(fallback)
496               
497                return False
498               
499        #def pulse_pbar
500       
501       
502        def install_pkg(self):
503               
504                pkg=self.core.main_window.current_pkg["package"]
505                self.thread_ret=self.core.store.install_package(pkg)
506               
507        #def install_pkg
508       
509       
510        def uninstall_pkg(self):
511               
512                pkg=self.core.main_window.current_pkg["package"]
513                self.thread_ret=self.core.store.uninstall_package(pkg)
514               
515        #def uninstall_pkg
516       
517       
518        def open_clicked(self,widget):
519                if self.core.main_window.current_pkg["name"].endswith('.snap'):
520                        snap=self.core.main_window.current_pkg["name"].replace('.snap','')
521                        if os.path.exists("/snap/bin/%s"%snap):
522                                Popen(["/snap/bin/%s"%snap])
523                elif self.core.main_window.current_pkg["name"].endswith('.appimage'):
524                        appimg=self.core.main_window.current_pkg["name"].lower()
525                        if os.path.exists(os.getenv("HOME")+"/.local/bin/%s"%appimg):
526                                Popen([os.getenv("HOME")+"/.local/bin/%s"%appimg])
527#                               os.system(os.getenv("HOME")+"/.local/bin/%s"%appimg)
528                elif 'Zomando' in self.core.main_window.current_pkg["categories"]:
529                        zmd=self.core.main_window.current_pkg["id"]+".zmd"
530                        if os.path.exists("/usr/share/zero-center/zmds/%s"%zmd):
531                                Popen(["pe", "/usr/share/zero-center/zmds/%s"%zmd])
532                else:
533                        desktop=self.core.main_window.current_pkg["id"]
534                        if os.path.exists("/usr/share/applications/%s"%desktop):
535                                os.system("gtk-launch %s"%desktop)
536               
537        #def open_clicked
538       
Note: See TracBrowser for help on using the repository browser.