source: n4dgtklogin/trunk/fuentes/debian/python3-n4dgtklogin/usr/local/lib/python3.5/dist-packages/edupals/ui/n4dgtklogin.py @ 6244

Last change on this file since 6244 was 6244, checked in by Juanma, 3 years ago

Initial release

File size: 10.2 KB
Line 
1#!/usr/bin/env python3
2###
3#This class returns a HBox whith a standarized login form
4###
5import os,sys
6import threading
7import gi
8gi.require_version('Gtk', '3.0')
9gi.require_version('PangoCairo', '1.0')
10import json
11import cairo
12#import commands
13from gi.repository import Gtk, Gdk, GdkPixbuf, GObject, GLib, PangoCairo, Pango
14try:
15        import xmlrpc.client as n4d
16except ImportError:
17        raise ImportError("xmlrpc not available. Disabling server queries")
18import ssl
19import time
20import gettext
21import pam
22
23gettext.textdomain('nezumi.ui.common')
24_ = gettext.gettext
25GObject.threads_init()
26
27class N4dGtkLogin():
28        def __init__(self):
29                threading.Thread.__init__(self)
30                self.sw_n4d=True
31                if hasattr(sys,'last_value'):
32                #If there's any error at this point it only could be an ImportError caused by xmlrpc
33                        self.sw_n4d=False
34                self.default_spacing=12
35                self.username_placeholder=_("Username")
36                self.server_placeholder=_("Server IP (Default value : server)")
37                self.login_banner_default="llx-avatar"
38                self.info_msg=''
39                self.info_background=''
40                self.mw_background=''
41                self.form_background=''
42                self.info_box=Gtk.Box(spacing=self.default_spacing,orientation=Gtk.Orientation.VERTICAL)
43                self.info_box.set_homogeneous(False)
44                self.txt_username=Gtk.Entry()
45                self.txt_server=Gtk.Entry()
46                self.login_banner=Gtk.Image()
47                if not self._lookup_user_face():
48                        self.set_login_banner(self.login_banner_default)
49                self.login_banner.set_margin_bottom(self.default_spacing)
50                self.info_banner=None
51                self.sw_info=False
52                self.left_span=2
53                self.right_span=1
54        #def __init__
55
56        def set_mw_proportion_ratio(self,left_span,right_span):
57                self.left_span=left_span
58                self.right_span=right_span
59       
60        def set_mw_background(self,image=None,cover=False,from_color='#ffffff',to_color='silver',gradient='linear'):
61                self.mw_background=self._set_background(image,cover,from_color,to_color,gradient)
62        #def set_mw_background
63
64        def set_login_background(self,image=None,cover=False,from_color='#ffffff',to_color='@silver',gradient='linear'):
65                self.form_background=self._set_background(image,cover,from_color,to_color,gradient)
66        #def set_login_background
67
68        def set_info_background(self,image=None,cover=False,from_color='#ffffff',to_color='@silver',gradient='linear'):
69                self.info_background=self._set_background(image,cover,from_color,to_color,gradient)
70        #def set_info_background
71
72        def _set_background(self,image=None,cover=False,from_color='#ffffff',to_color='silver',gradient='linear'):
73                bg=''
74                if image and os.path.isfile(image):
75                        if cover:
76                                bg='background-image:url("'+image+'"); background-repeat:no-repeat; background-size:100% 100%'
77                        else:
78                                bg='background-image:url("'+image+'"); background-repeat:no-repeat;'
79                else:
80                        if gradient=='linear':
81                                bg='background-image:-gtk-gradient (linear, left top, left bottom, from ('+from_color+'),  to ('+to_color+'))'
82                        elif gradient=='radial':
83                                bg='background-image:-gtk-gradient (radial, center center,0,center center,1, from ('+from_color+'),  to ('+to_color+'))'
84                return bg
85
86        def set_default_username(self,username):
87                self.username_placeholder=username
88                self._set_text_for_entry(self.txt_username,username)
89        #def set_default_username
90
91        def set_default_server(self,server):
92                self.server_placeholder=server
93                if self.txt_server:
94                        self._set_text_for_entry(self.txt_server,server)
95        #def set_default_server
96       
97        def _set_text_for_entry(self,widget,text):
98                widget.set_placeholder_text(text)
99        #def _set_text_for_entry
100
101        def _lookup_user_face(self):
102                sw_ok=False
103                if os.path.isfile(os.path.expanduser('~/.face')):
104                        sw_ok=True
105                        self.set_login_banner(os.path.expanduser('~/.face'))
106                return sw_ok
107
108        def set_login_banner(self,banner):
109                self.login_banner=self._get_image(banner)
110        #def set_banner
111
112        def set_info_banner(self,image,x=72,y=72):
113                self.info_banner=self._get_image(image,x,y)
114        #def set_info_banner
115
116        def _get_image(self,image,x=72,y=72):
117                icon_theme=Gtk.IconTheme.get_default()
118                img=Gtk.Image()
119                if icon_theme.has_icon(image):
120                        img.set_from_icon_name(image,Gtk.IconSize.DIALOG)
121                else:
122                        if os.path.isfile(image):
123                                pixbuf=GdkPixbuf.Pixbuf.new_from_file_at_scale(image,x,y,True)
124                                img.set_from_pixbuf(pixbuf)
125                return img
126       
127        def set_info_text(self,title,subtitle,text):
128                sw_ok=True
129                try:
130                        msg="<b><big>"+title+"</big></b>"
131                        self.info_msg=msg+'\n'+subtitle+'\n\n'+text
132                        self.sw_info=True
133                except Exception as e:
134                        sw_ok=False
135                        print(e)
136                return sw_ok
137        #def set_info_text
138
139        def get_action_area(self):
140                self.sw_info=True
141                return self.info_box
142
143        def render_form(self,show_server=True):
144                mw_box=Gtk.Box(spacing=0,orientation=Gtk.Orientation.HORIZONTAL)
145                (mw_bg,form_bg)=('','')
146
147                main_box=Gtk.Grid()
148                main_box.set_hexpand(True)
149                main_box.set_vexpand(True)
150                main_box.set_column_homogeneous(True)
151                main_box.set_row_homogeneous(True)
152                form_box=self._render_login_form(show_server)
153                if self.sw_info:
154                        info_box=self._render_info_form()
155                        main_box.attach(info_box,1,1,self.left_span,1)
156                main_box.attach(form_box,1+self.left_span,1,self.right_span,1)
157                mw_box.pack_start(main_box,True,True,0)
158                if self.mw_background:
159                        mw_bg='#mw {'+self.mw_background+';;}'
160                        mw_box.set_name("mw")
161                if self.form_background:
162                        form_bg='#main {'+self.form_background+';;}'
163                        form_box.set_name("main")
164                if mw_bg or form_bg:
165                        css=eval('b"""'+mw_bg+form_bg+'"""')
166                        style_provider=Gtk.CssProvider()
167                        style_provider.load_from_data(css)
168                        Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),style_provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
169                return (mw_box)
170        #def render_form
171
172        def _render_login_form(self,show_server):
173                form_box=Gtk.Box(spacing=0,orientation=Gtk.Orientation.VERTICAL)
174                self.set_default_username(self.username_placeholder)
175                self.txt_username.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,"emblem-personal")
176                self.txt_password=Gtk.Entry()
177                self.txt_password.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,"badge-small")
178                self._set_text_for_entry(self.txt_password,_("Password"))
179                self.txt_server=Gtk.Entry()
180                self.set_default_server(self.server_placeholder)
181                self.txt_server.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,"server")
182                self.btn_sign=Gtk.Button(stock=Gtk.STOCK_OK)
183                self.btn_sign.connect('clicked',self._validate)
184                self.frame=Gtk.Frame()
185               
186                self.frame.set_shadow_type(Gtk.ShadowType.OUT)   
187                hbox=Gtk.Grid()
188                hbox.set_margin_left(self.default_spacing)
189                hbox.set_margin_right(self.default_spacing)
190                hbox.set_margin_top(self.default_spacing)
191                hbox.set_margin_bottom(self.default_spacing)
192                self.spinner=Gtk.Spinner()
193                color=Gdk.Color(0,0,1)
194                self.spinner.modify_bg(Gtk.StateType.NORMAL,color)
195                hbox.attach(self.spinner,0,1,1,5)
196                hbox.attach(self.login_banner,0,0,1,1)
197                hbox.attach(self.txt_username,0,1,1,1)
198                self._set_widget_default_props(self.txt_username,_("Username"))
199                self.txt_username.connect('activate',self._validate)
200                hbox.attach(self.txt_password,0,2,1,1)
201                self._set_widget_default_props(self.txt_password,_("Password"))
202                self.txt_password.set_visibility(False)
203                self.txt_password.props.caps_lock_warning=True
204                self.txt_password.connect('activate',self._validate)
205                if show_server:
206                        hbox.attach(self.txt_server,0,3,1,1)
207                        self._set_widget_default_props(self.txt_server,_("Master Server IP"))
208                        self.txt_server.connect('activate',self._validate)
209                self.btn_sign.set_margin_top(self.default_spacing)
210                hbox.attach(self.btn_sign,0,4,1,1)
211#               self.frame.add(hbox)
212                self.sta_info=Gtk.InfoBar()
213                self.sta_info.set_show_close_button(True)
214                self.sta_info.set_message_type(Gtk.MessageType.ERROR)
215                self.lbl_error=Gtk.Label(_("Login failed"))
216                self.sta_info.get_action_area().add(self.lbl_error)
217                self.sta_info.set_visible(False)
218                self.sta_info.set_no_show_all(True)
219                self.sta_info.connect('response',self._info_hide)
220                self.sta_info.set_valign(True)
221                hbox.props.valign=Gtk.Align.CENTER
222                hbox.props.halign=Gtk.Align.CENTER
223                form_box.pack_start(self.sta_info,False,True,0)
224                form_box.pack_start(hbox,True,True,0)
225                return(form_box)
226        #def _render_login_form
227
228        def _render_info_form(self):
229                hbox=Gtk.Box(spacing=self.default_spacing,orientation=Gtk.Orientation.VERTICAL)
230                if self.info_banner:
231                        hbox.pack_start(self.info_banner,False,False,0)
232                if self.info_msg:
233                        lbl_msg=Gtk.Label()
234                        lbl_msg.set_use_markup(True)
235                        lbl_msg.set_line_wrap(True)
236                        lbl_msg.set_width_chars(25)
237                        lbl_msg.set_max_width_chars(25)
238                        lbl_msg.set_markup(self.info_msg)
239                        hbox.pack_start(lbl_msg,True,True,0)
240                lbl_bg='#label {background-color:rgba(200,200,200,0.5);;}'
241                lbl_msg.set_name("label")
242                css=eval('b"""#info {'+self.info_background+';;}'+lbl_bg+'"""')
243                style_provider=Gtk.CssProvider()
244                style_provider.load_from_data(css)
245                Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),style_provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
246                self.info_box.set_name("info")
247                hbox.props.valign=Gtk.Align.CENTER
248                hbox.props.halign=Gtk.Align.CENTER
249                self.info_box.pack_start(hbox,True,True,0)
250                return(self.info_box)
251        #def _render_info_form
252
253        def _set_widget_default_props(self,widget,tooltip=None):
254                widget.set_valign(True)
255                widget.set_halign(True)
256                widget.set_tooltip_text(tooltip)
257        #def _set_widget_default_props
258
259        def _info_hide(self,widget,data):
260                self.sta_info.hide()
261                self.frame.set_sensitive(True)
262        #def _info_hide
263
264        def _validate(self,widget=None):
265                user=self.txt_username.get_text()
266                pwd=self.txt_password.get_text()
267                server=self.txt_server.get_text()
268                if not server:
269                        server='server'
270                self.spinner.start()
271                self.frame.set_sensitive(False)
272                th=threading.Thread(target=self._t_validate,args=[user,pwd,server])
273                th.start()
274        #def _validate
275
276        def _t_validate(self,user,pwd,server):
277                ret=[False]
278                if self.sw_n4d:
279                        self.n4dclient=self._n4d_connect(server)
280                        try:
281                                loginMethod='N4d'
282                                ret=self.n4dclient.validate_user(user,pwd)
283                        except Exception as e:
284                                ret=[False,str(e)]
285                else:
286                        loginMethod='PAM'
287                        p=pam.pam()
288                        if p.authenticate(user,pwd):
289                                ret=[True]
290
291                self.spinner.stop()
292                if not ret[0]:
293                        self.lbl_error.show()
294                        self.sta_info.show()
295                if ret[0]:
296                        self.after_validate(loginMethod,user,pwd)
297                #local validation
298        #def _t_validate
299
300        def after_validation_goto(self,func,data=None):
301                self.after_validate=func
302        #def after_validation_func
303
304        def _n4d_connect(self,server):
305                context=ssl._create_unverified_context()
306                c = n4d.ServerProxy("https://"+server+":9779",context=context,allow_none=True)
307                return c
Note: See TracBrowser for help on using the repository browser.