source: repoman/trunk/fuentes/src/repoman.py @ 7952

Last change on this file since 7952 was 7952, checked in by Juanma, 15 months ago

Fix ppa build

  • Property svn:executable set to *
File size: 21.8 KB
Line 
1#! /usr/bin/python3
2# -*- coding: utf-8 -*-
3
4import os
5import gi
6gi.require_version('Gtk', '3.0')
7from gi.repository import Gtk,Gdk,GdkPixbuf,GObject,GLib
8gi.require_version('PangoCairo', '1.0')
9import json
10from edupals.ui.n4dgtklogin import *
11#import repomanager.RepoManager as RepoManager
12import xmlrpc.client as n4d
13import ssl
14import threading
15import time
16import subprocess
17from collections import OrderedDict
18
19import gettext
20gettext.textdomain('repoman')
21_ = gettext.gettext
22
23RSRC_DIR='/usr/share/repoman/rsrc'
24#RSRC_DIR='/home/lliurex/trabajo/repoman/rsrc'
25JSON_SRC_DIR='/usr/share/repoman/sources.d'
26APT_SRC_DIR='/etc/apt/sources.list.d'
27LOGIN_IMG=RSRC_DIR+'/repoman_login.png'
28LOGIN_BACKGROUND=RSRC_DIR+'/repoman_background.png'
29
30SPACING=6
31MARGIN=6
32
33class main:
34
35        def __init__(self):
36                self.dbg=True
37                self.default_editor=''
38                self.err_msg={1:_("Invalid Url"),
39                                                2:_("Can't add repository information.\nCheck your permissions"),
40                                                3:_("Can't write sources file.\nCheck your permissions"),
41                                                4:_("Repository not found at given Url"),
42                                                5:_("Repositories failed to update"),
43                                                6:_("Mirror not availabe"),
44                                                7:("This repository could'nt be overwrited")
45                                                }
46                self.result={}         
47                self._set_css_info()
48                self.stack_dir=Gtk.StackTransitionType.SLIDE_LEFT
49                self.n4d=None
50                self.credentials=[]
51                self.server=None
52                self.repos={}
53                self._render_gui()
54        #def __init__
55
56        def _debug(self,msg):
57                if self.dbg:
58                        print("repoman: %s"%msg)
59
60        def _render_gui(self):
61                self.mw=Gtk.Window()
62                self.mw.set_title("RepoMan")
63                self.mw.set_hexpand(True)
64                self.mw.connect("destroy",self._on_destroy)
65                self.mw.set_resizable(False)
66                self.overlay=Gtk.Stack()
67                self.mw.add(self.overlay)
68                vbox=Gtk.VBox(False,True)
69                self.overlay.set_name("WHITE_BACKGROUND")
70                self.overlay.add_titled(vbox,"vbox","vbox")
71                self.overlay.add_titled(self._render_login(),"login","login")
72                self.overlay.set_visible_child_name("login")
73                pb=GdkPixbuf.Pixbuf.new_from_file("%s/repoman.png"%RSRC_DIR)
74                img_banner=Gtk.Image.new_from_pixbuf(pb)
75                img_banner.props.halign=Gtk.Align.CENTER
76                img_banner.set_margin_left(MARGIN*2)
77                vbox.add(img_banner)
78                toolbarbox=self._render_toolbar()
79                vbox.add(toolbarbox)
80                self.rev_question=Gtk.InfoBar()
81                lbl_question=Gtk.Label()
82                lbl_question.set_name("NOTIF_LABEL")
83                lbl_question.set_halign(Gtk.Align.START)
84                self.rev_question.props.no_show_all=True
85                self.rev_question.get_content_area().add(lbl_question)
86                img_cancel=Gtk.Image()
87                img_cancel.set_from_icon_name(Gtk.STOCK_CANCEL,Gtk.IconSize.BUTTON)
88                btn_cancel=Gtk.Button()
89                btn_cancel.add(img_cancel)
90                btn_cancel.set_halign(Gtk.Align.END)
91                btn_cancel.props.no_show_all=False
92                self.rev_question.add_action_widget(btn_cancel,Gtk.ResponseType.CANCEL)
93                img_ok=Gtk.Image()
94                img_ok.set_from_icon_name(Gtk.STOCK_OK,Gtk.IconSize.BUTTON)
95                btn_ok=Gtk.Button()
96                btn_ok.props.no_show_all=False
97                btn_ok.set_halign(Gtk.Align.START)
98                btn_ok.add(img_ok)
99                self.rev_question.add_action_widget(btn_ok,Gtk.ResponseType.OK)
100                self.rev_question.connect('response',self._manage_response)
101                vbox.add(self.rev_question)
102                self.stack = Gtk.Stack()
103                self.stack.set_hexpand(True)
104                self.stack.set_transition_duration(1000)
105                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
106#               self.stack.set_visible_child_name("login")
107                vbox.add(self.stack)
108                self.rev_info=Gtk.Revealer()
109                vbox.add(self.rev_info)
110                lbl_update=Gtk.Label()
111                lbl_update.set_name("NOTIF_LABEL")
112                self.rev_info.add(lbl_update)
113                self.rev_info.set_transition_duration(1000)
114                self.mw.show_all()
115                self.rev_info.set_reveal_child(False)
116#               toolbarbox.hide()
117#               img_banner.hide()
118                self.box_info=Gtk.Grid()
119                self.box_info.set_margin_bottom(MARGIN)
120                self.box_info.set_margin_left(MARGIN)
121                self.box_info.set_column_spacing(MARGIN)
122                lbl_info=Gtk.Label()
123                info=_("Repositories must be updated. Update now?")
124                lbl_info.set_markup('<span color="grey">%s</span>'%info)
125#               img_info=Gtk.Image().new_from_icon_name(Gtk.STOCK_REFRESH,Gtk.IconSize.BUTTON)
126                pb_info=GdkPixbuf.Pixbuf.new_from_file_at_scale("%s/stock_refresh.png"%RSRC_DIR,16,16,True)
127                img_info=Gtk.Image().new_from_pixbuf(pb_info)
128                btn_info=Gtk.Button()
129                btn_info.set_name("BLUEBUTTON")
130                btn_info.set_tooltip_text(_("Update repositories"))
131                btn_info.add(img_info)
132                spn_info=Gtk.Spinner()
133                self.box_info.attach(lbl_info,0,0,1,1)
134                self.box_info.attach(btn_info,1,0,1,1)
135                self.box_info.attach(spn_info,0,0,2,1)
136                self.box_info.set_no_show_all(True)
137                btn_info.connect("clicked",self._begin_update_repos,spn_info)
138                vbox.add(self.box_info)
139                Gtk.main()
140        #def _render_gui
141
142        def _render_toolbar(self):
143                self.toolbar=Gtk.Box()
144                self.toolbar=Gtk.Box(spacing=SPACING)
145                self.toolbar.set_margin_top(MARGIN)
146                self.toolbar.set_margin_bottom(MARGIN)
147                self.toolbar.set_margin_left(MARGIN)
148               
149                btn_return=Gtk.Button()#.new_from_stock(Gtk.STOCK_GO_BACK)
150                btn_return.add(Gtk.Image().new_from_icon_name(Gtk.STOCK_HOME,Gtk.IconSize.BUTTON))
151                btn_return.connect("clicked",self._load_screen,"sources")
152                btn_return.props.halign=Gtk.Align.START
153                btn_return.set_tooltip_text(_("Default repositories"))
154                self.toolbar.add(btn_return)
155
156                btn_manage=Gtk.Button()
157                btn_manage.props.halign=Gtk.Align.START
158                btn_manage.add(Gtk.Image().new_from_icon_name(Gtk.STOCK_PROPERTIES,Gtk.IconSize.BUTTON))
159                btn_manage.connect("clicked",self._load_screen,"repolist")
160                btn_manage.set_tooltip_text(_("External repositories"))
161                self.toolbar.add(btn_manage)
162               
163                btn_add=Gtk.Button()#.new_from_stock(Gtk.STOCK_ADD)
164                btn_add.props.halign=Gtk.Align.START
165                btn_add.add(Gtk.Image().new_from_icon_name(Gtk.STOCK_ADD,Gtk.IconSize.BUTTON))
166                btn_add.connect("clicked",self._load_screen,"newrepo")
167                btn_add.set_tooltip_text(_("Add external repository"))
168                self.toolbar.add(btn_add)
169               
170                return(self.toolbar)
171        #def _render_toolbar
172
173        def _render_login(self):
174                login=N4dGtkLogin(orientation=Gtk.Orientation.VERTICAL)
175#               login=N4dGtkLogin()
176                login.set_mw_proportion_ratio(1,1)
177                login.set_allowed_groups(['adm','teachers'])
178                login.set_login_banner(image=LOGIN_IMG)
179                login.set_label_background(255,255,255,0.3)
180                login.set_mw_background(image=LOGIN_BACKGROUND,cover=True)
181                desc=_("From here you can invoke RepoMan's mighty powers to manage your repositories.")
182                login.set_info_text("<span foreground='black'>RepoMan</span>",_("Repositories Manager"),"<span foreground='black'>"+desc+"</span>\n")
183                login.after_validation_goto(self._signin)
184                login.hide_server_entry()
185                login.show_all()
186                return (login)
187
188        def _signin(self,user=None,pwd=None,server=None,data=None):
189#               self.scheduler.set_credentials(user,pwd,server)
190#               self.stack.set_visible_child_name("sources")
191                self.credentials=[user,pwd]
192                self.server=server
193                context=ssl._create_unverified_context()
194                self.n4d=n4d.ServerProxy("https://%s:9779"%server,context=context,allow_none=True)
195                self.stack.add_titled(self._render_sources(), "sources", "Sources")
196                self.stack.add_titled(self._render_newrepo(), "newrepo", "Newrepo")
197                self.stack.add_titled(self._render_repolist(), "repolist", "Repolist")
198                self.overlay.set_transition_duration(1000)
199                self.overlay.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
200                self.overlay.set_visible_child_name("vbox")
201                self.mw.show_all()
202        #def _signin
203
204        def _render_sources(self):
205                gridbox=Gtk.Grid()
206                gridbox.set_column_homogeneous(False)
207                gridbox.set_column_spacing(MARGIN)
208                gridbox.set_name("WHITE_BACKGROUND")
209                gridbox.set_margin_top(MARGIN)
210                gridbox.set_margin_left(MARGIN)
211                gridbox.set_margin_right(MARGIN)
212                gridbox.set_margin_bottom(MARGIN)
213                self.repos=self.n4d.list_default_repos(self.credentials,"RepoManager")['data']
214                        #Sort by relevancy (Lliurex, Local, Ubuntu-*)
215                sort_repos=OrderedDict()
216                for repo in sorted(self.repos.keys()):
217                        sort_repos.update({repo:self.repos[repo]})
218                self.repos=sort_repos.copy()
219                row=0
220                for source,sourcedata in self.repos.items():
221                        desc=''
222                        if sourcedata['desc']:
223                                desc=_(sourcedata['desc'])
224                        self._insert_sourceslist_item(gridbox,source,desc,'',sourcedata['enabled'],row)
225                        row+=1
226                gridbox.set_margin_top(MARGIN)
227                gridbox.set_margin_bottom(MARGIN*2)
228                return(gridbox)
229        #def _render_sources
230
231        def _repo_state_changed(self,*args):
232                self.stack.set_sensitive(False)
233                self.box_info.set_no_show_all(False)
234                reponame=args[-1]
235                state=args[-2]
236                widget=args[0]
237                err=0
238                if reponame.lower()=="lliurex mirror":
239                        ret=subprocess.run(["lliurex-version","-m"],universal_newlines=True,stdout=subprocess.PIPE)
240                        if ret.stdout.strip()=="False":
241                                err=6
242                if err==0:
243                        self.repos[reponame].update({'enabled':str(state)})
244                        repo={}
245                        repo={reponame:self.repos[reponame]}
246                        self._debug("New state: %s"%repo)
247                        self._debug("Saving repo json: %s"%repo)
248                        if self.n4d.write_repo_json(self.credentials,"RepoManager",repo)['status']:
249                                if self.n4d.write_repo(self.credentials,"RepoManager",repo)['status']!=True:
250                                        err=3
251                        else:
252                                err=2
253                if err:
254                        self.toolbar.set_sensitive(False)
255                        GLib.timeout_add(3000,self.show_info,(self.err_msg[err]),"ERROR_LABEL")
256                        widget.set_state(not(state))
257                        return True
258                else:
259                        self.stack.set_sensitive(True)
260                        self.box_info.show_all()
261        #def _repo_state_changed
262
263        def _render_repolist(self):
264                scrollbox=Gtk.ScrolledWindow()
265                scrollbox.set_min_content_height(280)
266                scrollbox.set_min_content_width(280)
267                self.repobox=Gtk.Grid()
268                self.repobox.set_hexpand(True)
269                self.repobox.set_row_spacing(MARGIN)
270                self.repobox.set_margin_left(MARGIN)
271                self.repobox.set_margin_right(MARGIN)
272                self.repobox.set_margin_top(MARGIN)
273                self.repobox.set_row_spacing(0)
274                self.repobox.set_name("WHITE_BACKGROUND")
275                sourcefiles=self.n4d.list_sources(self.credentials,"RepoManager")['data']
276                sort_repos=OrderedDict()
277                for repo in sorted(sourcefiles.keys()):
278                        sort_repos.update({repo:sourcefiles[repo]})
279                sourcefiles=sort_repos.copy()
280                self.repos.update(sourcefiles)
281                row=0
282                for sourcefile,sourcedata in sourcefiles.items():
283                        desc=''
284                        if sourcedata['desc']:
285                                desc=_(sourcedata['desc'])
286                        edit=True
287                        if 'protected' in sourcedata.keys():
288                                if sourcedata['protected'].lower()=='true':
289                                        edit=False
290                        self._insert_sourceslist_item(self.repobox,sourcefile,desc,'',sourcedata['enabled'],row,edit)
291                        row+=1
292                scrollbox.add(self.repobox)
293                return scrollbox
294        #def _render_repolist
295
296        def _render_newrepo(self):
297                def del_icon(*args):
298                        args[-1].set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,None)
299                        args[-1].set_placeholder_text("")
300
301                gridbox=Gtk.Grid()
302                gridbox.set_hexpand(True)
303                gridbox.set_row_spacing(MARGIN)
304                gridbox.set_margin_left(MARGIN)
305                gridbox.set_margin_right(MARGIN)
306                gridbox.set_margin_top(MARGIN)
307                boxname=Gtk.VBox(True,True)
308                boxname.set_name("WHITE_BACKGROUND")
309                boxname.set_hexpand(True)
310                lbl_name=Gtk.Label()
311                lbl_name.set_name("ENTRY_LABEL")
312                lbl_name.set_halign(Gtk.Align.START)
313                lbl_name.set_markup("<sup>%s</sup>"%_("Name for the repo"))
314                boxname.add(lbl_name)
315                inp_name=Gtk.Entry()
316                inp_name.connect("focus-in-event",del_icon,inp_name)
317                boxname.add(inp_name)
318                gridbox.add(boxname)
319                boxdesc=Gtk.VBox(True,True)
320                boxdesc.set_name("WHITE_BACKGROUND")
321                lbl_desc=Gtk.Label()
322                lbl_desc.set_name("ENTRY_LABEL")
323                lbl_desc.set_halign(Gtk.Align.START)
324                lbl_desc.set_markup("<sup>%s</sup>"%_("Description"))
325                boxdesc.add(lbl_desc)
326                inp_desc=Gtk.Entry()
327                boxdesc.add(inp_desc)
328                gridbox.attach_next_to(boxdesc,boxname,Gtk.PositionType.BOTTOM,1,1)
329                boxurl=Gtk.VBox(True,True)
330                boxurl.set_name("WHITE_BACKGROUND")
331                lbl_url=Gtk.Label()
332                lbl_url.set_name("ENTRY_LABEL")
333                lbl_url.set_halign(Gtk.Align.START)
334                lbl_url.set_markup("<sup>%s</sup>"%_("Url"))
335                boxurl.add(lbl_url)
336                inp_url=Gtk.Entry()
337                inp_url.connect("focus-in-event",del_icon,inp_url)
338                inp_url.connect("activate",self._begin_add_repo,inp_name,inp_desc,inp_url)
339                boxurl.add(inp_url)
340                gridbox.attach_next_to(boxurl,boxdesc,Gtk.PositionType.BOTTOM,1,1)
341                boxbtn=Gtk.Box()
342                btn_add=Gtk.Button.new_from_stock(Gtk.STOCK_APPLY)
343                btn_add.connect("clicked",self._begin_add_repo,inp_name,inp_desc,inp_url)
344#               btn_add.connect("clicked",self._add_repo,inp_name,inp_desc,inp_url)
345                boxbtn.set_halign(Gtk.Align.END)
346                boxbtn.add(btn_add)
347               
348                gridbox.attach_next_to(boxbtn,boxurl,Gtk.PositionType.BOTTOM,1,1)
349                return(gridbox)
350        #def _render_newrepo
351
352        def _begin_add_repo(self,*args):
353                name=args[-3].get_text()
354                desc=args[-2].get_text()
355                url=args[-1].get_text()
356                sw_err=False
357                if not name:
358                        args[-3].set_placeholder_text(_("Name is mandatory"))
359                        args[-3].set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,Gtk.STOCK_DIALOG_ERROR)
360                        sw_err=True
361                elif len(name)>40:
362                        args[-3].set_placeholder_text(_("Name is too long"))
363                        args[-3].set_text("")
364                        args[-3].set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,Gtk.STOCK_DIALOG_ERROR)
365                        sw_err=True
366
367                desc_array=desc.split(' ')
368                for element in desc_array:
369                        if len(element)>40:
370                                args[-2].set_placeholder_text(_("Description is too long"))
371                                args[-2].set_text("")
372                                args[-2].set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,Gtk.STOCK_DIALOG_ERROR)
373                                sw_err=True
374
375                if not url:
376                        args[-1].set_placeholder_text(_("Url is mandatory"))
377                        args[-1].set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,Gtk.STOCK_DIALOG_ERROR)
378                        sw_err=True
379                if not sw_err:
380                        listfiles=os.listdir(JSON_SRC_DIR)
381                        lowfiles=[]
382                        for jsonfile in listfiles:
383                                lowfile=jsonfile.lower()
384                                lowfiles.append(lowfile)
385                        if name.replace(' ','_').lower()+'.json' in lowfiles:
386                                #see if the repo is protected
387                                for repo in self.repos.keys():
388                                        if name.lower().replace('_',' ')==repo.lower():
389                                                if 'protected' in self.repos[repo]:
390                                                        if self.repos[repo]['protected'].lower()=='true':
391                                                                self.stack.set_sensitive(False)
392                                                                self.toolbar.set_sensitive(False)
393                                                                err=7
394                                                                GLib.timeout_add(3000,self.show_info,(self.err_msg[err]),"ERROR_LABEL")
395                                                                return
396
397                                self.result.pop('response',None)
398                                try:
399                                        self.rev_question.disconnect_by_func(self._manage_response)
400                                except:
401                                        pass
402                                self.rev_question.grab_add()
403                                self.rev_question.connect('response',self._manage_response,self._add_repo,*args)
404                                self.show_question(_("%s already exists. Overwrite it?")%name)
405                        else:
406                                self._add_repo(*args)
407
408        def _add_repo(self,*args):
409                name=args[-3].get_text()
410                desc=args[-2].get_text()
411                url=args[-1].get_text()
412                self.stack.set_sensitive(False)
413                self.toolbar.set_sensitive(False)
414                listfiles=os.listdir(JSON_SRC_DIR)
415                lowfiles={}
416                for jsonfile in listfiles:
417                        lowfile=jsonfile.lower()
418                        lowfiles[lowfile]=jsonfile
419                lowname=name.replace(' ','_').lower()+'.json'
420                if lowname in lowfiles.keys():
421                        name=lowfiles[lowname].replace('.json','').replace('_',' ')
422                err=self.n4d.add_repo(self.credentials,"RepoManager",name,desc,url)['status']
423                if err==0:
424                        row=(len(self.repos.keys())*2)
425                        if name in self.repos.keys():
426                                row=-1
427                        sourcefiles=self.n4d.list_sources(self.credentials,"RepoManager")['data']
428                        self.repos.update(sourcefiles)
429                        if row>=0:
430                                self._insert_sourceslist_item(self.repobox,name,desc,url,'true',row,True)
431                        GLib.timeout_add(2000,self.show_info,(_("Added repository %s"%name)),"NOTIF_LABEL",True)
432                else:
433                        #err=1 -> Bad url
434                        #err=2 -> Can't write json
435                        #err=3 -> Can't write sources
436                        #err=4 -> Repository not found at given url
437                        GLib.timeout_add(3000,self.show_info,(self.err_msg[err]),"ERROR_LABEL")
438        #def _add_repo
439
440        def _insert_sourceslist_item(self,sourcebox,name,desc,url,enabled='false',index=0,edit=False):
441                index*=2
442                repobox=Gtk.VBox(True,True)
443                repobox.set_margin_left(MARGIN)
444                repobox.set_margin_right(MARGIN)
445                repobox.set_margin_bottom(MARGIN)
446                repobox.set_margin_top(MARGIN)
447                lbl_source=Gtk.Label()
448                lbl_source.set_markup('<span size="larger">%s</span>'%name)
449                lbl_source.set_halign(Gtk.Align.START)
450                lbl_source.set_hexpand(True)
451                lbl_source.set_margin_left(MARGIN)
452                lbl_source.set_margin_bottom(MARGIN)
453                lbl_source.set_margin_top(MARGIN)
454                lbl_source.props.halign=Gtk.Align.START
455                repobox.add(lbl_source)
456                lbl_desc=Gtk.Label()
457                lbl_desc.set_ellipsize(3)
458                lbl_desc.set_markup('<span size="medium">%s</span>'%desc)
459                lbl_desc.set_tooltip_text('%s'%desc)
460                lbl_desc.set_halign(Gtk.Align.START)
461                repobox.add(lbl_desc)
462                if edit:
463                        img_edit=Gtk.Image.new_from_icon_name(Gtk.STOCK_EDIT,Gtk.IconSize.BUTTON)
464                        btn_edit=Gtk.Button()
465                        btn_edit.add(img_edit)
466                        btn_edit.set_tooltip_text(_("Edit sources file"))
467                        btn_edit.set_valign(Gtk.Align.CENTER)
468                        btn_edit.connect("clicked",self._edit_source_file,name)
469                        sourcebox.attach(btn_edit,1,index,1,1)
470                swt_repo=Gtk.Switch()
471                swt_repo.set_tooltip_text(_("Enable/disable repository"))
472                swt_repo.set_halign(Gtk.Align.END)
473                if enabled.lower()=="true":
474                        swt_repo.set_active(True)
475                else:
476                        swt_repo.set_active(False)
477                swt_repo.connect("state_set",self._repo_state_changed,name)
478                sourcebox.attach(repobox,0,index,1,1)
479                sourcebox.attach(swt_repo,2,index,1,1)
480                sourcebox.attach(Gtk.Separator(),0,index+1,1,1)
481                sourcebox.show_all()
482        #def _insert_sourceslist_item
483
484        def _load_screen(self,*args):
485                self.stack.set_transition_type(self.stack_dir)
486                if self.stack_dir==Gtk.StackTransitionType.SLIDE_RIGHT:
487                        self.stack_dir=Gtk.StackTransitionType.SLIDE_LEFT
488                else:
489                        self.stack_dir=Gtk.StackTransitionType.SLIDE_RIGHT
490                screen=args[-1]
491                self.stack.set_visible_child_name(screen)
492        #def _load_screen
493
494        def _begin_update_repos(self,*args):
495                spinner=args[-1]
496                spinner.show()
497                spinner.start()
498                self.stack.set_sensitive(False)
499                self.toolbar.set_sensitive(False)
500                th=threading.Thread(target=self._update_repos,args=[spinner])
501                th.start()
502                GLib.timeout_add(1500,self._check_update,th,spinner)
503        #def _begin_update_repos
504
505        def _update_repos(self,spinner):
506                self.result['update']=self.n4d.update_repos(self.credentials,"RepoManager")['status']
507        #def _update_repos
508
509        def _check_update(self,th,spinner):
510                if th.is_alive():
511                        return True
512                spinner.stop()
513                self.stack.set_sensitive(True)
514                self.toolbar.set_sensitive(True)
515                self.box_info.hide()
516                if self.result['update']:
517                        return(self.show_info(_("Repositories updated")))
518                else:
519                        return(self.show_info(self.err_msg[5],"ERROR_LABEL"))
520        #def _check_update
521
522        def _edit_source_file(self,*args):
523                sfile=args[-1].replace(' ','_')
524                self._debug("Editing %s.list"%sfile)
525                if os.path.isfile("%s/%s.list"%(APT_SRC_DIR,sfile)):
526                        edit=True
527                        try:
528                                display=os.environ['DISPLAY']
529                                if self.default_editor=='':
530                                        self.default_editor=subprocess.check_output(["xdg-mime","query","default","text/plain"],universal_newlines=True).strip().rstrip('.desktop;')
531                                subprocess.run(["xhost","+"])
532                                subprocess.run(["pkexec",self.default_editor,"%s/%s.list"%(APT_SRC_DIR,sfile),"--display=%s"%display],check=True)
533                                subprocess.run(["xhost","-"])
534                        except Exception as e:
535                                self._debug("_edit_source_file error: %s"%e)
536                                edit=False
537                        if edit:
538                                newrepos=[]
539                                try:
540                                        with open("%s/%s.list"%(APT_SRC_DIR,sfile),'r') as f:
541                                                for line in f:
542                                                        newrepos.append(line.strip())
543                                except Exception as e:
544                                        self._debug("_edit_source_file failed: %s"%e)
545                                if sorted(self.repos[args[-1]]['repos'])!=sorted(newrepos):
546                                        self.repos[args[-1]]['repos']=newrepos
547                                        self.n4d.write_repo_json(self.credentials,"RepoManager",{args[-1]:self.repos[args[-1]]})
548                                        self.box_info.show_all()
549                else:
550                        self._debug("File %s/%s not found"%(APT_SRC_DIR,sfile))
551        #def _edit_source_file
552
553        def show_info(self,msg='',style="NOTIF_LABEL",show_info=False):
554                if self.rev_info.get_reveal_child():
555                        self.rev_info.set_reveal_child(False)
556                        self.stack.set_sensitive(True)
557                        self.toolbar.set_sensitive(True)
558                        if show_info:
559                                self.box_info.show_all()
560                        return False
561                lbl=None
562                for child in self.rev_info.get_children():
563                        if type(child)==type(Gtk.Label()):
564                                lbl=child
565                if lbl:
566                        lbl.set_name(style)
567                        lbl.set_markup(msg)
568                        self.rev_info.set_reveal_child(True)
569                return True
570        #def show_info
571       
572        def show_question(self,msg='',style="NOTIF_LABEL"):
573                self.rev_question.grab_add()
574                for child in self.rev_question.get_content_area():
575                        if type(child)==type(Gtk.Label()):
576                                lbl=child
577                for child in self.rev_question.get_action_area():
578                        if type(child)==type(Gtk.Button()):
579                                child.show_all()
580
581                lbl.set_markup(msg)
582                lbl.set_line_wrap(True)
583                lbl.set_lines(-1)
584                lbl.set_max_width_chars(20)
585                lbl.show()
586                self.rev_question.show()
587        #def show_question
588
589        def _manage_response(self,*args):
590                self.rev_question.grab_remove()
591                response=args[1]
592                self.rev_question.hide()
593                if response==Gtk.ResponseType.OK:
594                        args[2](args[-3],args[-2],args[-1])
595                else:
596                        return False
597
598        def _on_destroy(self,*args):
599                Gtk.main_quit()
600
601        def _set_css_info(self):
602       
603                css = b"""
604
605                GtkEntry{
606                        font-family: Roboto;
607                        border:0px;
608                        border-bottom:1px grey solid;
609                        margin-top:0px;
610                        padding-top:0px;
611                }
612
613                GtkLabel {
614                        font-family: Roboto;
615                }
616
617                #NOTIF_LABEL{
618                        background-color: #3366cc;
619                        font: 11px Roboto;
620                        color:white;
621                        border: dashed 1px silver;
622                        padding:6px;
623                }
624
625                #ERROR_LABEL{
626                        background-color: red;
627                        font: 11px Roboto;
628                        color:white;
629                        border: dashed 1px silver;
630                        padding:6px;
631                }
632
633                #ENTRY_LABEL{
634                        color:grey;
635                        padding:6px;
636                        padding-bottom:0px;
637                }
638
639                #PLAIN_BTN,#PLAIN_BTN:active{
640                        border:0px;
641                        padding:0px;
642                        background:white;
643                }
644               
645                #PLAIN_BTN_DISABLED,#PLAIN_BTN_DISABLED:active{
646                        border:0px;
647                        padding:0px;
648                        background:white;
649                        font:grey;
650                }
651
652                #COMPONENT{
653                        padding:3px;
654                        border: dashed 1px silver;
655
656                }
657
658                #WHITE_BACKGROUND {
659                        background-color:rgba(255,255,255,1);
660               
661                }
662
663                #BLUE_FONT {
664                        color: #3366cc;
665                        font: Roboto Bold 11;
666                       
667                }       
668               
669
670                #TASKGRID_FONT {
671                        color: #3366cc;
672                        font: Roboto 11;
673                       
674                }
675
676                #LABEL #LABEL_INSTALL{
677                        padding: 6px;
678                        margin:6px;
679                        font: 12px Roboto;
680                }
681
682                #LABEL_OPTION{
683               
684                        font: 48px Roboto;
685                        padding: 6px;
686                        margin:6px;
687                        font-weight:bold;
688                }
689
690                #ERROR_FONT {
691                        color: #CC0000;
692                        font: Roboto Bold 11;
693                }
694
695                #MENUITEM {
696                        padding: 12px;
697                        margin:6px;
698                        font: 24px Roboto;
699                        background:white;
700                }
701
702                #BLUEBUTTON {
703                        background-color: #3366cc;
704                        color:white;
705                        font: 11px Roboto Bold;
706                }
707
708                """
709                self.style_provider=Gtk.CssProvider()
710                self.style_provider.load_from_data(css)
711                Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),self.style_provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
712        #def set_css_info       
713
714GObject.threads_init()
715main()
Note: See TracBrowser for help on using the repository browser.