class GenericColumn(gtk.VBox): def __init__(self, mainwin, label=''): gtk.VBox.__init__(self, False) self.mainwin = mainwin self.statuslist = StatusList(mainwin) self.waiting = CairoWaiting(mainwin) self.walign = gtk.Alignment(xalign=1, yalign=0.5) self.walign.add(self.waiting) self.errorbox = ErrorBox() self.label = gtk.Label(label) self.caption = label self.connect('expose-event', self.error_show) def error_show(self, widget, event): self.errorbox.show() def update_tweets(self, response): count = 0 if response.type == 'error': self.stop_update(True, response.errmsg) else: statuses = response.items if len(statuses) == 0: self.statuslist.clear() self.stop_update(True, _('No tweets available')) else: count = self.statuslist.update(statuses) self.stop_update() self.on_update() return count def update_user_pic(self, user, pic): self.statuslist.update_user_pic(user, pic) def update_wrap(self, width): self.statuslist.update_wrap(width) def start_update(self): self.waiting.start() self.errorbox.hide() def stop_update(self, error=False, msg=''): self.waiting.stop(error) self.errorbox.show_error(msg, error) def clear(self): self.statuslist.clear() def on_update(self, data=None): pass
def __init__(self, mainwin, label=''): gtk.VBox.__init__(self, False) self.mainwin = mainwin self.statuslist = StatusList(mainwin) self.waiting = CairoWaiting(mainwin) self.walign = gtk.Alignment(xalign=1, yalign=0.5) self.walign.add(self.waiting) self.errorbox = ErrorBox() self.label = gtk.Label(label) self.caption = label self.connect('expose-event', self.error_show)
def __init__(self, parent): gtk.Window.__init__(self) self.what = _('What is happening?') self.blocked = False self.mainwin = parent #self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.set_title(_('Update status')) self.set_resizable(False) #self.set_default_size(500, 120) self.set_size_request(500, 150) self.set_transient_for(parent) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.label = gtk.Label() self.label.set_use_markup(True) self.label.set_alignment(0, 0.5) self.label.set_markup('<span size="medium"><b>%s</b></span>' % self.what) self.label.set_justify(gtk.JUSTIFY_LEFT) self.num_chars = gtk.Label() self.num_chars.set_use_markup(True) self.num_chars.set_markup( '<span size="14000" foreground="#999"><b>140</b></span>') self.update_text = MessageTextView() self.update_text.set_border_width(2) self.update_text.set_left_margin(2) self.update_text.set_right_margin(2) self.update_text.set_wrap_mode(gtk.WRAP_WORD) buffer = self.update_text.get_buffer() scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.update_text) updatebox = gtk.HBox(False) updatebox.pack_start(scroll, True, True, 3) self.url = gtk.Entry() self.btn_url = gtk.Button(_('Shorten URL')) self.btn_url.set_tooltip_text(_('Shorten URL')) self.btn_pic = gtk.Button(_('Upload image')) self.btn_pic.set_tooltip_text(_('Upload image')) tools = gtk.HBox(False) tools.pack_start(self.url, True, True, 3) tools.pack_start(self.btn_url, False, False) tools.pack_start(gtk.HSeparator(), False, False) tools.pack_start(self.btn_pic, False, False, 3) self.toolbox = gtk.Expander() self.toolbox.set_label(_('Options')) self.toolbox.set_expanded(False) self.toolbox.add(tools) self.btn_clr = gtk.Button() self.btn_clr.set_image(self.mainwin.load_image('clear.png')) self.btn_clr.set_tooltip_text(_('Clear all')) self.btn_clr.set_relief(gtk.RELIEF_NONE) self.btn_frn = gtk.Button() self.btn_frn.set_image(self.mainwin.load_image('friends.png')) self.btn_frn.set_tooltip_text(_('Add friends')) self.btn_frn.set_relief(gtk.RELIEF_NONE) self.btn_upd = gtk.Button(_('Tweet')) chk_short = gtk.CheckButton(_('Autoshort URLs')) chk_short.set_sensitive(False) top = gtk.HBox(False) top.pack_start(self.label, True, True, 5) top.pack_start(self.num_chars, False, False, 5) self.waiting = CairoWaiting(parent) self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) error_align = gtk.Alignment(xalign=0.0) error_align.add(self.lblerror) buttonbox = gtk.HBox(False) buttonbox.pack_start(chk_short, False, False, 0) buttonbox.pack_start(self.btn_frn, False, False, 0) buttonbox.pack_start(self.btn_clr, False, False, 0) buttonbox.pack_start(gtk.HSeparator(), False, False, 2) buttonbox.pack_start(self.btn_upd, False, False, 0) abuttonbox = gtk.Alignment(1, 0.5) abuttonbox.add(buttonbox) bottom = gtk.HBox(False) bottom.pack_start(self.waiting, False, False, 5) bottom.pack_start(error_align, True, True, 4) bottom.pack_start(abuttonbox, True, True, 5) vbox = gtk.VBox(False) vbox.pack_start(top, False, False, 2) vbox.pack_start(updatebox, True, True, 2) vbox.pack_start(bottom, False, False, 2) vbox.pack_start(self.toolbox, False, False, 2) self.add(vbox) self.connect('delete-event', self.__unclose) buffer.connect('changed', self.count_chars) self.btn_frn.connect('clicked', self.show_friend_dialog) self.btn_clr.connect('clicked', self.clear) self.btn_upd.connect('clicked', self.update) self.btn_url.connect('clicked', self.short_url) self.btn_pic.connect('clicked', self.upload_pic) self.toolbox.connect('activate', self.show_options) self.update_text.connect('mykeypress', self.__on_key_pressed) if SPELLING: try: self.spell = gtkspell.Spell(self.update_text) except Exception, e_msg: # FIXME: Usar el log print 'DEBUG:UI:Can\'t load gtkspell -> %s' % e_msg
def show_login(self, global_config): self.mode = 1 if self.vbox is not None: self.remove(self.vbox) avatar = self.load_image('logo2.png') self.message = LoginLabel(self) lbl_user = gtk.Label() #lbl_user.set_justify(gtk.JUSTIFY_LEFT) lbl_user.set_use_markup(True) lbl_user.set_markup(u'<span size="small">%s</span>' % _('User and Password')) lbl_user.set_alignment(0, 0.5) self.username = gtk.Entry() self.password = gtk.Entry() self.password.set_visibility(False) self.remember = gtk.CheckButton(_('Remember my credentials')) self.btn_oauth = gtk.Button(_('Connect')) self.btn_settings = gtk.Button() self.btn_settings.set_relief(gtk.RELIEF_NONE) self.btn_settings.set_tooltip_text(_('Preferences')) self.btn_settings.set_image(self.load_image('settings-single.png')) settings_box = gtk.Alignment(xalign=1.0, yalign=0.5) settings_box.set_padding(70, 10, 40, 40) settings_box.add(self.btn_settings) self.waiting = CairoWaiting(self) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) hbox = gtk.HBox(False) hbox.pack_start(lbl_user, False, False, 2) hbox.pack_start(align, True, True, 2) table = gtk.Table(10, 1, False) table.attach(avatar, 0, 1, 0, 1, gtk.FILL, gtk.FILL, 10, 50) table.attach(self.message, 0, 1, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL, 20, 3) table.attach(hbox, 0, 1, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.username, 0, 1, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.password, 0, 1, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.btn_oauth, 0, 1, 7, 8, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(self.remember, 0, 1, 8, 9, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(settings_box, 0, 1, 9, 10, gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL, 0, 10) self.vbox = gtk.VBox(False, 5) self.vbox.pack_start(table, False, False, 2) self.add(self.vbox) self.show_all() self.btn_oauth.connect('clicked', self.oauth) self.password.connect('activate', self.oauth) self.remember.connect("toggled", self.__toogle_remember) self.btn_settings.connect('clicked', self.show_preferences, 'global') username = global_config.read('Login', 'username') password = global_config.read('Login', 'password') if username != '' and password != '': self.username.set_text(username) self.password.set_text(base64.b64decode(password)) self.remember.set_active(True)
class UpdateBox(gtk.Window): def __init__(self, parent): gtk.Window.__init__(self) self.what = _('What is happening?') self.blocked = False self.mainwin = parent self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.set_title(_('Update status')) self.set_resizable(False) #self.set_default_size(500, 120) self.set_size_request(500, 150) self.set_transient_for(parent) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.label = gtk.Label() self.label.set_use_markup(True) self.label.set_alignment(0, 0.5) self.label.set_markup('<span size="medium"><b>%s</b></span>' % self.what) self.label.set_justify(gtk.JUSTIFY_LEFT) self.num_chars = gtk.Label() self.num_chars.set_use_markup(True) self.num_chars.set_markup('<span size="14000" foreground="#999"><b>140</b></span>') #self.update_text = gtk.TextView() self.update_text = MessageTextView() self.update_text.set_border_width(2) self.update_text.set_left_margin(2) self.update_text.set_right_margin(2) self.update_text.set_wrap_mode(gtk.WRAP_WORD) buffer = self.update_text.get_buffer() scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.update_text) updatebox = gtk.HBox(False) updatebox.pack_start(scroll, True, True, 3) self.url = gtk.Entry() self.btn_url = gtk.Button(_('Shorten URL')) self.btn_url.set_tooltip_text(_('Shorten URL')) self.btn_pic = gtk.Button(_('Upload image')) self.btn_pic.set_tooltip_text(_('Upload image')) tools = gtk.HBox(False) tools.pack_start(self.url, True, True, 3) tools.pack_start(self.btn_url, False, False) tools.pack_start(gtk.HSeparator(), False, False) tools.pack_start(self.btn_pic, False, False, 3) self.toolbox = gtk.Expander() self.toolbox.set_label(_('Options')) self.toolbox.set_expanded(False) self.toolbox.add(tools) self.btn_clr = gtk.Button() self.btn_clr.set_image(self.mainwin.load_image('clear.png')) self.btn_clr.set_tooltip_text(_('Clear all')) self.btn_clr.set_relief(gtk.RELIEF_NONE) self.btn_upd = gtk.Button(_('Tweet')) chk_short = gtk.CheckButton(_('Autoshort URLs')) chk_short.set_sensitive(False) top = gtk.HBox(False) top.pack_start(self.label, True, True, 5) top.pack_start(self.num_chars, False, False, 5) self.waiting = CairoWaiting(parent) self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) error_align = gtk.Alignment(xalign=0.0) error_align.add(self.lblerror) buttonbox = gtk.HBox(False) buttonbox.pack_start(chk_short, False, False, 0) buttonbox.pack_start(self.btn_clr, False, False, 0) buttonbox.pack_start(gtk.HSeparator(), False, False, 2) buttonbox.pack_start(self.btn_upd, False, False, 0) abuttonbox = gtk.Alignment(1, 0.5) abuttonbox.add(buttonbox) bottom = gtk.HBox(False) bottom.pack_start(self.waiting, False, False, 5) bottom.pack_start(error_align, True, True, 4) bottom.pack_start(abuttonbox, True, True, 5) vbox = gtk.VBox(False) vbox.pack_start(top, False, False, 2) vbox.pack_start(updatebox, True, True, 2) vbox.pack_start(bottom, False, False, 2) vbox.pack_start(self.toolbox, False, False, 2) self.add(vbox) self.connect('delete-event', self.__unclose) buffer.connect('changed', self.count_chars) self.btn_clr.connect('clicked', self.clear) self.btn_upd.connect('clicked', self.update) self.btn_url.connect('clicked', self.short_url) self.btn_pic.connect('clicked', self.upload_pic) self.toolbox.connect('activate', self.show_options) self.update_text.connect('mykeypress', self.__on_key_pressed) def __on_key_pressed(self, widget, keyval, keymod): if keyval == gtk.keysyms.Return: self.update(widget) elif keyval == gtk.keysyms.Escape: self.__unclose(widget) return False def __unclose(self, widget, event=None): if not self.blocked: self.done() return True def block(self): self.blocked = True self.update_text.set_sensitive(False) self.toolbox.set_sensitive(False) self.btn_clr.set_sensitive(False) self.btn_upd.set_sensitive(False) self.btn_url.set_sensitive(False) def release(self): self.blocked = False self.update_text.set_sensitive(True) self.toolbox.set_sensitive(True) self.btn_clr.set_sensitive(True) self.btn_upd.set_sensitive(True) self.btn_url.set_sensitive(True) self.waiting.stop(error=True) self.lblerror.set_markup("<span size='small'>%s</span>" % _('Oh oh... I couldn\'t send the tweet')) self.set_focus(self.update_text) def show(self, text, id, user): self.in_reply_id = id self.in_reply_user = user if id != '' and user != '': self.label.set_markup('<span size="medium"><b>%s %s</b></span>' % (_('In reply to'), user)) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.set_focus(self.update_text) buffer = self.update_text.get_buffer() buffer.set_text(text) self.show_all() def done(self, widget=None, event=None): buffer = self.update_text.get_buffer() buffer.set_text('') self.url.set_text('') self.lblerror.set_markup('') self.label.set_markup(u'<span size="medium"><b>%s</b></span>' % self.what) self.waiting.stop() self.toolbox.set_expanded(False) self.in_reply_id = None self.in_reply_user = None self.hide() return True def count_chars(self, widget): buffer = self.update_text.get_buffer() remain = 140 - buffer.get_char_count() if remain >= 20: color = "#999" elif 0 < remain < 20: color = "#d4790d" else: color = "#D40D12" self.num_chars.set_markup('<span size="14000" foreground="%s"><b>%i</b></span>' % (color, remain)) def clear(self, widget): self.update_text.get_buffer().set_text('') def update(self, widget): buffer = self.update_text.get_buffer() start, end = buffer.get_bounds() tweet = buffer.get_text(start, end) if tweet == '': self.waiting.stop(error=True) self.lblerror.set_markup("<span size='small'>%s</span>" % _('Eyy... you must write something')) return self.waiting.start() self.mainwin.request_update_status(tweet, self.in_reply_id) self.block() def short_url(self, widget): self.waiting.start() self.mainwin.request_short_url(self.url.get_text(), self.update_shorten_url) def update_shorten_url(self, short): if short is None: self.waiting.stop(error=True) self.lblerror.set_markup("<span size='small'>%s</span>" % _('Oops... I couldn\'t shrink that URL')) return buffer = self.update_text.get_buffer() end_offset = buffer.get_property('cursor-position') start_offset = end_offset - 1 end = buffer.get_iter_at_offset(end_offset) start = buffer.get_iter_at_offset(start_offset) text = buffer.get_text(start, end) if (text != ' ') and (start_offset > 0): short = ' ' + short buffer.insert_at_cursor(short) self.waiting.stop() self.lblerror.set_markup("") self.toolbox.set_expanded(False) self.set_focus(self.update_text) def upload_pic(self, widget): filtro = gtk.FileFilter() filtro.set_name('PNG, JPEG & GIF Images') filtro.add_pattern('*.png') filtro.add_pattern('*.gif') filtro.add_pattern('*.jpg') filtro.add_pattern('*.jpeg') dia = gtk.FileChooserDialog(title=_('Select image to upload'), parent=self, action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) dia.add_filter(filtro) resp = dia.run() if resp == gtk.RESPONSE_OK: self.waiting.start() self.mainwin.request_upload_pic(dia.get_filename(), self.update_uploaded_pic) dia.destroy() def update_uploaded_pic(self, pic_url): if pic_url is None: self.waiting.stop(error=True) self.lblerror.set_markup("<span size='small'>%s</span>" % _('Oops... I couldn\'t upload that image')) return buffer = self.update_text.get_buffer() end_offset = buffer.get_property('cursor-position') start_offset = end_offset - 1 end = buffer.get_iter_at_offset(end_offset) start = buffer.get_iter_at_offset(start_offset) text = buffer.get_text(start, end) if (text != ' ') and (start_offset > 0): pic_url = ' ' + pic_url buffer.insert_at_cursor(pic_url) self.waiting.stop() self.lblerror.set_markup("") self.toolbox.set_expanded(False) self.set_focus(self.update_text) def show_options(self, widget, event=None): self.url.set_text('') self.url.grab_focus()
class UserForm(gtk.VBox): def __init__(self, mainwin, label='', profile=None): gtk.VBox.__init__(self, False) label_width = 75 self.mainwin = mainwin self.user = None self.label = gtk.Label(label) self.caption = label self.user_pic = gtk.Button() self.user_pic.set_size_request(60, 60) pic_box = gtk.VBox(False) pic_box.pack_start(self.user_pic, False, False, 10) self.screen_name = gtk.Label() self.screen_name.set_alignment(0, 0.5) self.tweets_count = gtk.Label() self.tweets_count.set_alignment(0, 0.5) self.tweets_count.set_padding(8, 0) self.following_count = gtk.Label() self.following_count.set_alignment(0, 0.5) self.following_count.set_padding(8, 0) self.followers_count = gtk.Label() self.followers_count.set_alignment(0, 0.5) self.followers_count.set_padding(8, 0) info_box = gtk.VBox(False) info_box.pack_start(self.screen_name, False, False, 5) info_box.pack_start(self.tweets_count, False, False) info_box.pack_start(self.following_count, False, False) info_box.pack_start(self.followers_count, False, False) top = gtk.HBox(False) top.pack_start(pic_box, False, False, 10) top.pack_start(info_box, False, False, 5) self.real_name = gtk.Entry() self.real_name.set_max_length(20) name_lbl = gtk.Label(_('Name')) name_lbl.set_size_request(label_width, -1) name_box = gtk.HBox(False) name_box.pack_start(name_lbl, False, False, 2) name_box.pack_start(self.real_name, True, True, 5) self.location = gtk.Entry() self.location.set_max_length(30) loc_lbl = gtk.Label(_('Location')) loc_lbl.set_size_request(label_width, -1) loc_box = gtk.HBox(False) loc_box.pack_start(loc_lbl, False, False, 2) loc_box.pack_start(self.location, True, True, 5) self.url = gtk.Entry() self.url.set_max_length(100) url_lbl = gtk.Label(_('URL')) url_lbl.set_size_request(label_width, -1) url_box = gtk.HBox(False) url_box.pack_start(url_lbl, False, False, 2) url_box.pack_start(self.url, True, True, 5) self.bio = gtk.TextView() self.bio.set_wrap_mode(gtk.WRAP_WORD) scrollwin = gtk.ScrolledWindow() scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER) scrollwin.set_shadow_type(gtk.SHADOW_IN) scrollwin.set_size_request(-1, 80) scrollwin.add(self.bio) bio_lbl = gtk.Label(_('Bio')) bio_lbl.set_size_request(label_width, -1) bio_box = gtk.HBox(False) bio_box.pack_start(bio_lbl, False, False, 2) bio_box.pack_start(scrollwin, True, True, 5) form = gtk.VBox(False) form.pack_start(name_box, False, False, 4) form.pack_start(loc_box, False, False, 4) form.pack_start(url_box, False, False, 4) form.pack_start(bio_box, False, False, 4) self.submit = gtk.Button(_('Save')) submit_box = gtk.Alignment(1.0, 0.5) submit_box.set_property('right-padding', 5) submit_box.add(self.submit) self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) self.waiting = CairoWaiting(mainwin) self.lblerror.set_markup("Hola mundo") self.waiting.stop(True) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) bottombox = gtk.HBox(False) bottombox.pack_start(self.lblerror, False, False, 2) bottombox.pack_start(align, True, True, 2) spacebox = gtk.VBox(False) self.pack_start(top, False, False) self.pack_start(form, False, False) self.pack_start(submit_box, False, False) self.pack_start(spacebox, True, True) self.pack_start(bottombox, False, False) self.submit.connect('clicked', self.save_user_profile) def update(self, response): # FIXME: Mejorar esta validación try: if response.type == 'error': self.stop_update(True, response.errmsg) return profile = response.items except: profile = response self.user = profile.username pix = self.mainwin.get_user_avatar(self.user, profile.avatar) avatar = gtk.Image() avatar.set_from_pixbuf(pix) self.user_pic.set_image(avatar) del pix self.screen_name.set_markup('<b>@%s</b>' % profile.username) self.tweets_count.set_markup( '<span size="9000">%i Tweets</span>' % profile.statuses_count ) self.following_count.set_markup( '<span size="9000">%i Following</span>' % profile.friends_count ) self.followers_count.set_markup( '<span size="9000">%i Followers</span>' % profile.followers_count ) self.real_name.set_text(profile.fullname) if profile.location: self.location.set_text(profile.location) if profile.url: self.url.set_text(profile.url) buffer = self.bio.get_buffer() if profile.bio: buffer.set_text(profile.bio) self.stop_update() def update_user_pic(self, user, pic): if self.user != user: return pix = self.mainwin.load_avatar(self.mainwin.imgdir, pic, True) self.user_pic.set_image(pix) def save_user_profile(self, widget): self.start_update() name = self.real_name.get_text() location = self.location.get_text() url = self.url.get_text() buffer = self.bio.get_buffer() bounds = buffer.get_bounds() bio = buffer.get_text(bounds[0], bounds[1])[:160] self.mainwin.request_update_profile(name, url, bio, location) def lock(self): self.user_pic.set_sensitive(False) self.real_name.set_sensitive(False) self.location.set_sensitive(False) self.url.set_sensitive(False) self.bio.set_sensitive(False) self.submit.set_label(_('Saving...')) self.submit.set_sensitive(False) def unlock(self): self.user_pic.set_sensitive(True) self.real_name.set_sensitive(True) self.location.set_sensitive(True) self.url.set_sensitive(True) self.bio.set_sensitive(True) self.submit.set_label(_('Save')) self.submit.set_sensitive(True) def update_wrap(self, w): pass def start_update(self): self.lock() self.waiting.start() self.lblerror.set_markup("") def stop_update(self, error=False, msg=''): self.unlock() self.waiting.stop(error) self.lblerror.set_markup(u"<span size='small'>%s</span>" % msg)
def __init__(self, parent): gtk.Window.__init__(self) self.mainwin = parent self.set_title(_('Secure Authentication')) ### self.set_default_size(800, 450) self.set_transient_for(parent) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.connect('delete-event', self.quit) self.settings = webkit.WebSettings() self.settings.enable_java_applet = False #self.settings.enable_plugins = False self.settings.enable_page_cache = True self.settings.enable_offline_web_application_cache = False self.settings.enable_html5_local_storage = False self.settings.enable_html5_database = False self.settings.enable_default_context_menu = False self.view = webkit.WebView() self.view.set_settings(self.settings) self.view.connect('load-started', self.__started) self.view.connect('load-finished', self.__finished) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.view) self.label = gtk.Label() self.label.set_use_markup(True) self.label.set_alignment(0, 0) self.label.set_markup(_('Autorize Turpial, copy the <b>PIN</b> in the \ text box below and click OK:')) self.waiting_label = gtk.Label() self.waiting_label.set_use_markup(True) self.waiting = CairoWaiting(parent) waiting_box = gtk.Alignment(xalign=1.0) waiting_box.add(self.waiting_label) lblbox = gtk.HBox(False, 2) lblbox.pack_start(self.label, True, True, 2) lblbox.pack_start(waiting_box, True, True, 2) lblbox.pack_start(self.waiting, False, False, 2) self.pin = gtk.Entry() cancel = gtk.Button(stock=gtk.STOCK_CANCEL) accept = gtk.Button(stock=gtk.STOCK_OK) hbox = gtk.HBox(False, 0) hbox.pack_start(self.pin, True, True, 2) hbox.pack_start(cancel, False, False, 2) hbox.pack_start(accept, False, False, 2) vbox = gtk.VBox(False, 5) vbox.pack_start(scroll, True, True, 0) vbox.pack_start(lblbox, False, False, 2) vbox.pack_start(hbox, False, False, 2) cancel.connect('clicked', self.quit) accept.connect('clicked', self.__accept) self.add(vbox)
class OAuthWindow(gtk.Window): def __init__(self, parent): gtk.Window.__init__(self) self.mainwin = parent self.set_title(_('Secure Authentication')) ### self.set_default_size(800, 450) self.set_transient_for(parent) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.connect('delete-event', self.quit) self.settings = webkit.WebSettings() self.settings.enable_java_applet = False #self.settings.enable_plugins = False self.settings.enable_page_cache = True self.settings.enable_offline_web_application_cache = False self.settings.enable_html5_local_storage = False self.settings.enable_html5_database = False self.settings.enable_default_context_menu = False self.view = webkit.WebView() self.view.set_settings(self.settings) self.view.connect('load-started', self.__started) self.view.connect('load-finished', self.__finished) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.view) self.label = gtk.Label() self.label.set_use_markup(True) self.label.set_alignment(0, 0) self.label.set_markup(_('Autorize Turpial, copy the <b>PIN</b> in the \ text box below and click OK:')) self.waiting_label = gtk.Label() self.waiting_label.set_use_markup(True) self.waiting = CairoWaiting(parent) waiting_box = gtk.Alignment(xalign=1.0) waiting_box.add(self.waiting_label) lblbox = gtk.HBox(False, 2) lblbox.pack_start(self.label, True, True, 2) lblbox.pack_start(waiting_box, True, True, 2) lblbox.pack_start(self.waiting, False, False, 2) self.pin = gtk.Entry() cancel = gtk.Button(stock=gtk.STOCK_CANCEL) accept = gtk.Button(stock=gtk.STOCK_OK) hbox = gtk.HBox(False, 0) hbox.pack_start(self.pin, True, True, 2) hbox.pack_start(cancel, False, False, 2) hbox.pack_start(accept, False, False, 2) vbox = gtk.VBox(False, 5) vbox.pack_start(scroll, True, True, 0) vbox.pack_start(lblbox, False, False, 2) vbox.pack_start(hbox, False, False, 2) cancel.connect('clicked', self.quit) accept.connect('clicked', self.__accept) self.add(vbox) def __cancel(self, widget): self.quit() def __accept(self, widget): self.view.stop_loading() verifier = self.pin.get_text() if verifier == '': self.mainwin.cancel_login(_('You must write a valid PIN')) else: self.mainwin.request_auth_token(verifier) self.quit(widget, done=True) def __started(self, widget, frame): self.waiting.start() self.waiting_label.set_markup(_('Loading...')) def __finished(self, widget, frame): self.waiting.stop() self.waiting_label.set_markup('') def open(self, uri): print uri self.show_all() self.view.open(uri) def quit(self, widget, event=None, done=False): if not done: self.view.stop_loading() self.mainwin.cancel_login(_('Login cancelled by user')) self.hide() return True
def __init__(self, mainwin): gtk.VBox.__init__(self, False, 5) self.mainwin = mainwin avatar = self.mainwin.load_image("logo2.png") self.message = LoginLabel(self) us, pw, rem = self.mainwin.request_remembered(0) lbl_user = gtk.Label() lbl_user.set_use_markup(True) lbl_user.set_markup(u'<span size="small">%s</span>' % _("User and Password")) lbl_user.set_alignment(0, 0.5) self.username = gtk.Entry() self.username.set_text(us) self.password = gtk.Entry() self.password.set_visibility(False) self.password.set_text(pw) self.remember = gtk.CheckButton(_("Remember my credentials")) self.btn_oauth = gtk.Button(_("Connect")) list = gtk.ListStore(gtk.gdk.Pixbuf, str, str) for p in PROTOCOLS: image = "%s.png" % p t_icon = self.mainwin.load_image(image, True) list.append([t_icon, p, p]) self.combo_protocol = gtk.ComboBox(list) icon_cell = gtk.CellRendererPixbuf() txt_cell = gtk.CellRendererText() self.combo_protocol.pack_start(icon_cell, False) self.combo_protocol.pack_start(txt_cell, False) self.combo_protocol.add_attribute(icon_cell, "pixbuf", 0) self.combo_protocol.add_attribute(txt_cell, "markup", 1) self.combo_protocol.set_active(0) self.btn_settings = gtk.Button() self.btn_settings.set_relief(gtk.RELIEF_NONE) self.btn_settings.set_tooltip_text(_("Preferences")) self.btn_settings.set_image(self.mainwin.load_image("dock-settings.png")) settings_box = gtk.Alignment(xalign=1.0, yalign=0.5) settings_box.set_padding(70, 10, 40, 40) settings_box.add(self.btn_settings) self.waiting = CairoWaiting(self.mainwin) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) hbox = gtk.HBox(False) hbox.pack_start(lbl_user, False, False, 2) hbox.pack_start(align, True, True, 2) table = gtk.Table(11, 1, False) table.attach(avatar, 0, 1, 0, 1, gtk.FILL, gtk.FILL, 10, 50) table.attach(self.message, 0, 1, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL, 20, 3) table.attach(hbox, 0, 1, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.username, 0, 1, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.password, 0, 1, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.combo_protocol, 0, 1, 7, 8, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(self.btn_oauth, 0, 1, 8, 9, gtk.EXPAND, gtk.FILL, 0, 3) table.attach(self.remember, 0, 1, 9, 10, gtk.EXPAND, gtk.FILL, 0, 3) table.attach(settings_box, 0, 1, 10, 11, gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL, 0, 10) self.pack_start(table, False, False, 2) self.btn_oauth.connect("clicked", self.signin) self.password.connect("activate", self.signin) self.rhandler = self.remember.connect("toggled", self.__toogle_remember) self.btn_settings.connect("clicked", self.mainwin.show_preferences, "global") self.combo_protocol.connect("changed", self.__change_protocol) self.remember.set_active(rem)
class Main(BaseGui, gtk.Window): __gsignals__ = dict(mykeypress=(gobject.SIGNAL_RUN_LAST | gobject.SIGNAL_ACTION, None, (str, ))) def __init__(self, controller, extend=False): BaseGui.__init__(self, controller) gtk.Window.__init__(self) self.extend = extend and extend_mode self.set_title('Turpial') self.set_size_request(280, 350) self.set_default_size(320, 480) self.current_width = 320 self.current_height = 480 self.set_icon(self.load_image('turpial_icon.png', True)) self.set_position(gtk.WIN_POS_CENTER) self.connect('delete-event', self.__close) self.connect('size-request', self.size_request) self.connect('configure-event', self.move_event) self.connect('mykeypress', self.__on_key_press) self.mode = 0 self.vbox = None self.contentbox = gtk.VBox(False) # Valores de config. por defecto self.showed = True self.minimize = 'on' self.workspace = 'single' self.link_color = 'ff6633' self.home_interval = -1 self.replies_interval = -1 self.directs_interval = -1 self.me = None self.version = None self.home_timer = None self.replies_timer = None self.directs_timer = None self.notify = Notification() self.home = Home(self, self.workspace) self.profile = Profile(self) self.contenido = self.home self.updatebox = UpdateBox(self) self.replybox = ReplyBox(self) if self.extend: log.debug('Cargado modo GTK Extendido') self.browser = OAuthWindow(self) else: log.debug('Cargado modo GTK Simple') self.dock = Dock(self, self.workspace) self.__create_trayicon() def __create_trayicon(self): if gtk.check_version(2, 10, 0) is not None: self.log.debug("Disabled Tray Icon. It needs PyGTK >= 2.10.0") return self.tray = gtk.StatusIcon() self.tray.set_from_pixbuf(self.load_image('turpial_icon.png', True)) self.tray.set_tooltip('Turpial') self.tray.connect("activate", self.__on_trayicon_click) self.tray.connect("popup-menu", self.__show_tray_menu) def __on_trayicon_click(self, widget): if (self.showed is True): self.showed = False self.hide() else: self.showed = True self.show() #self.present() def __show_tray_menu(self, widget, button, activate_time): menu = gtk.Menu() tweet = gtk.MenuItem(_('Tweet')) exit = gtk.MenuItem(_('Exit')) if self.mode == 2: menu.append(tweet) menu.append(exit) exit.connect('activate', self.quit) tweet.connect('activate', self.__show_update_box_from_menu) menu.show_all() menu.popup(None, None, None, button, activate_time) def __show_update_box_from_menu(self, widget): self.show_update_box() def __close(self, widget, event=None): if self.minimize == 'on': self.showed = False self.hide() else: self.quit(widget) return True def __save_size(self): if self.mode < 2: return wide_value = "%i, %i" % (self.wide_win_size[0], self.wide_win_size[1]) single_value = "%i, %i" % (self.single_win_size[0], self.single_win_size[1]) pos_value = "%i, %i" % (self.win_pos[0], self.win_pos[1]) log.debug('Guardando tamaño de la ventana') log.debug('--Single: %s' % single_value) log.debug('--Wide: %s' % wide_value) log.debug('--Position: %s' % pos_value) self.save_config( { 'General': { 'single-win-size': single_value, 'wide-win-size': wide_value, 'window-position': pos_value } }, update=False) def __toogle_remember(self, widget): if self.remember.get_active(): self.username.set_sensitive(False) self.password.set_sensitive(False) else: self.username.set_sensitive(True) self.password.set_sensitive(True) def load_image(self, path, pixbuf=False): img_path = os.path.realpath( os.path.join(os.path.dirname(__file__), '..', '..', 'data', 'pixmaps', path)) pix = gtk.gdk.pixbuf_new_from_file(img_path) if pixbuf: return pix avatar = gtk.Image() avatar.set_from_pixbuf(pix) del pix return avatar def load_avatar(self, dir, path, image=False): img_path = os.path.join(dir, path) pix = gtk.gdk.pixbuf_new_from_file(img_path) if not image: return pix avatar = gtk.Image() avatar.set_from_pixbuf(pix) del pix return avatar def resize_avatar(self, pic): ext = pic[-3:].lower() fullname = os.path.join(self.imgdir, pic) orig = gtk.gdk.pixbuf_new_from_file(fullname) pw, ph = orig.get_width(), orig.get_height() if pw >= ph: ratio = float(ph) / pw fw = util.AVATAR_SIZE fh = int(fw * ratio) else: ratio = float(pw) / ph fh = util.AVATAR_SIZE fw = int(fh * ratio) dest = orig.scale_simple(fw, fh, gtk.gdk.INTERP_BILINEAR) dest.save(fullname, 'png') del orig del dest def request_conversation(self, twt_id, user): self.replybox.show(twt_id, user) BaseGui.request_conversation(self, twt_id, user) def get_user_avatar(self, user, pic_url): pix = self.request_user_avatar(user, pic_url) if pix: # Try to load user avatar from file. If fail (by corrupt data, etc) # then load default image try: return self.load_avatar(self.imgdir, pix) except: return self.load_image('unknown.png', pixbuf=True) else: return self.load_image('unknown.png', pixbuf=True) def quit(self, widget): self.__save_size() gtk.main_quit() self.destroy() self.tray = None self.request_signout() def main_loop(self): #gtk.gdk.threads_enter() gtk.main() #gtk.gdk.threads_leave() def show_login(self, global_config): self.mode = 1 if self.vbox is not None: self.remove(self.vbox) avatar = self.load_image('logo2.png') self.message = LoginLabel(self) lbl_user = gtk.Label() #lbl_user.set_justify(gtk.JUSTIFY_LEFT) lbl_user.set_use_markup(True) lbl_user.set_markup(u'<span size="small">%s</span>' % _('User and Password')) lbl_user.set_alignment(0, 0.5) self.username = gtk.Entry() self.password = gtk.Entry() self.password.set_visibility(False) self.remember = gtk.CheckButton(_('Remember my credentials')) self.btn_oauth = gtk.Button(_('Connect')) self.btn_settings = gtk.Button() self.btn_settings.set_relief(gtk.RELIEF_NONE) self.btn_settings.set_tooltip_text(_('Preferences')) self.btn_settings.set_image(self.load_image('settings-single.png')) settings_box = gtk.Alignment(xalign=1.0, yalign=0.5) settings_box.set_padding(70, 10, 40, 40) settings_box.add(self.btn_settings) self.waiting = CairoWaiting(self) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) hbox = gtk.HBox(False) hbox.pack_start(lbl_user, False, False, 2) hbox.pack_start(align, True, True, 2) table = gtk.Table(10, 1, False) table.attach(avatar, 0, 1, 0, 1, gtk.FILL, gtk.FILL, 10, 50) table.attach(self.message, 0, 1, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL, 20, 3) table.attach(hbox, 0, 1, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.username, 0, 1, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.password, 0, 1, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.btn_oauth, 0, 1, 7, 8, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(self.remember, 0, 1, 8, 9, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(settings_box, 0, 1, 9, 10, gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL, 0, 10) self.vbox = gtk.VBox(False, 5) self.vbox.pack_start(table, False, False, 2) self.add(self.vbox) self.show_all() self.btn_oauth.connect('clicked', self.oauth) self.password.connect('activate', self.oauth) self.remember.connect("toggled", self.__toogle_remember) self.btn_settings.connect('clicked', self.show_preferences, 'global') username = global_config.read('Login', 'username') password = global_config.read('Login', 'password') if username != '' and password != '': self.username.set_text(username) self.password.set_text(base64.b64decode(password)) self.remember.set_active(True) def signin(self, widget, username, password): self.message.deactivate() self.waiting.start() self.btn_oauth.set_sensitive(False) self.username.set_sensitive(False) self.password.set_sensitive(False) self.request_signin(username.get_text(), password.get_text()) def oauth(self, widget): self.message.deactivate() self.waiting.start() self.btn_oauth.set_sensitive(False) self.username.set_sensitive(False) self.password.set_sensitive(False) self.remember.set_sensitive(False) self.btn_settings.set_sensitive(False) self.request_oauth(self.username.get_text(), self.password.get_text(), self.remember.get_active()) def cancel_login(self, error): self.message.set_error(error) self.waiting.stop(error=True) self.btn_oauth.set_sensitive(True) self.remember.set_sensitive(True) self.btn_settings.set_sensitive(True) if not self.remember.get_active(): self.username.set_sensitive(True) self.password.set_sensitive(True) def show_main(self, config, global_cfg, p): log.debug('Cargando ventana principal') self.mode = 2 self.update_config(config, global_cfg, True) gtk.gdk.threads_enter() self.contentbox.add(self.contenido) self.statusbar = gtk.Statusbar() self.statusbar.push(0, _('Wait a few seconds while I load everything...')) if (self.vbox is not None): self.remove(self.vbox) self.vbox = gtk.VBox(False, 0) self.vbox.pack_start(self.contentbox, True, True, 0) self.vbox.pack_start(self.dock, False, False, 0) self.vbox.pack_start(self.statusbar, False, False, 0) self.profile.set_user_profile(p) self.me = p['screen_name'] title = 'Turpial - %s' % self.me self.set_title(title) self.tray.set_tooltip(title) if config.read('General', 'profile-color') == 'on': self.link_color = p['profile_link_color'] self.add(self.vbox) self.show_all() if (self.win_pos[0] > 0 and self.win_pos[1] > 0): self.move(self.win_pos[0], self.win_pos[1]) gtk.gdk.threads_leave() self.notify.login(p) gobject.timeout_add(6 * 60 * 1000, self.download_rates) def show_home(self, widget): self.contentbox.remove(self.contenido) self.contenido = self.home self.contentbox.add(self.contenido) def show_profile(self, widget): self.contentbox.remove(self.contenido) self.contenido = self.profile self.contentbox.add(self.contenido) def show_update_box(self, text='', id='', user=''): if self.updatebox.get_property('visible'): self.updatebox.present() return self.updatebox.show(text, id, user) def show_preferences(self, widget, mode='user'): prefs = Preferences(self, mode) def show_oauth_pin_request(self, url): if self.extend: gtk.gdk.threads_enter() self.browser.open(url) gtk.gdk.threads_leave() else: webbrowser.open(url) gtk.gdk.threads_enter() p = InputPin(self) response = p.run() if response == gtk.RESPONSE_ACCEPT: verifier = p.pin.get_text() if verifier == '': self.cancel_login(_('Must write a valid PIN')) else: self.request_auth_token(verifier) else: self.cancel_login(_('Login cancelled by user')) p.destroy() gtk.gdk.threads_leave() def start_updating_timeline(self): self.home.timeline.start_update() def start_updating_replies(self): self.home.replies.start_update() def start_updating_directs(self): self.home.direct.start_update() def start_search(self): self.profile.topics.topics.waiting.start() def update_timeline(self, tweets): log.debug(u'Actualizando el timeline') gtk.gdk.threads_enter() last = self.home.timeline.last count = self.home.timeline.update_tweets(tweets) if count > 0 and self.updating['home']: tweet = None i = 0 while 1: if tweets[i]['user']['screen_name'] == self.me: if not util.has_tweet(last, tweets[i]): tweet = tweets[i] break else: tweet = tweets[i] break i += 1 p = self.parse_tweet(tweet) icon = self.current_avatar_path(p['avatar']) text = util.escape_text(p['text']) text = "<b>@%s</b> %s" % (p['username'], text) self.notify.new_tweets(count, text, icon) gtk.gdk.threads_leave() self.updating['home'] = False def update_replies(self, tweets): log.debug(u'Actualizando las replies') gtk.gdk.threads_enter() count = self.home.replies.update_tweets(tweets) if count > 0 and self.updating['replies']: p = self.parse_tweet(tweets[0]) icon = self.current_avatar_path(p['avatar']) text = util.escape_text(p['text']) text = "<b>@%s</b> %s" % (p['username'], text) self.notify.new_replies(count, text, icon) gtk.gdk.threads_leave() self.updating['replies'] = False def update_directs(self, recv): log.debug(u'Actualizando mensajes directos') gtk.gdk.threads_enter() count = self.home.direct.update_tweets(recv) if count > 0 and self.updating['directs']: p = self.parse_tweet(recv[0]) icon = self.current_avatar_path(p['avatar']) text = util.escape_text(p['text']) text = "<b>@%s</b> %s" % (p['username'], text) self.notify.new_directs(count, text, icon) gtk.gdk.threads_leave() self.updating['directs'] = False def update_favorites(self, tweets, replies, favs): log.debug(u'Actualizando favoritos') gtk.gdk.threads_enter() self.home.timeline.update_tweets(tweets) self.home.replies.update_tweets(replies) self.profile.favorites.update_tweets(favs) gtk.gdk.threads_leave() def update_user_profile(self, profile): log.debug(u'Actualizando perfil del usuario') gtk.gdk.threads_enter() self.profile.set_user_profile(profile) gtk.gdk.threads_leave() def update_follow(self, user, follow): self.notify.following(user, follow) def update_rate_limits(self, val): if val is None or val == []: return gtk.gdk.threads_enter() self.statusbar.push(0, util.get_rates(val)) gtk.gdk.threads_leave() def update_search_topics(self, val): log.debug(u'Mostrando resultados de la búsqueda') gtk.gdk.threads_enter() if val is None: self.profile.topics.update_tweets(val) else: self.profile.topics.update_tweets(val['results']) gtk.gdk.threads_leave() def update_search_people(self, val): self.search.people.update_profiles(val) #self.show_search(self) #if self.workspace != 'wide': # self.contenido.wrapper.set_current_page(1) def update_trends(self, current, day, week): self.search.trending.update_trends(current, day, week) def update_friends(self, friends): pass def update_user_avatar(self, user, pic): self.home.timeline.update_user_pic(user, pic) self.home.replies.update_user_pic(user, pic) self.home.direct.update_user_pic(user, pic) self.profile.favorites.update_user_pic(user, pic) self.profile.user_form.update_user_pic(user, pic) self.profile.topics.update_user_pic(user, pic) def update_in_reply_to(self, tweet): gtk.gdk.threads_enter() self.replybox.update([tweet]) gtk.gdk.threads_leave() def update_conversation(self, tweets): gtk.gdk.threads_enter() self.replybox.update(tweets) gtk.gdk.threads_leave() def tweet_changed(self, timeline, replies, favs): log.debug(u'Tweet modificado') gtk.gdk.threads_enter() log.debug(u'--Actualizando el timeline') self.home.timeline.update_tweets(timeline) log.debug(u'--Actualizando las replies') self.home.replies.update_tweets(replies) log.debug(u'--Actualizando favoritos') self.profile.favorites.update_tweets(favs) gtk.gdk.threads_leave() def tweet_done(self, tweets): log.debug(u'Actualizando nuevo tweet') gtk.gdk.threads_enter() self.updatebox.release() if tweets: self.updatebox.done() gtk.gdk.threads_leave() self.update_timeline(tweets) def set_mode(self): cur_x, cur_y = self.get_position() cur_w, cur_h = self.get_size() if self.workspace == 'wide': size = self.wide_win_size self.resize(size[0], size[1]) self.set_default_size(size[0], size[1]) x = (size[0] - cur_w) / 2 self.move(cur_x - x, cur_y) else: size = self.single_win_size self.resize(size[0], size[1]) self.set_default_size(size[0], size[1]) x = (cur_w - size[0]) / 2 self.move(cur_x + x, cur_y) log.debug('Cambiando a modo %s (%s)' % (self.workspace, size)) self.dock.change_mode(self.workspace) self.home.change_mode(self.workspace) self.profile.change_mode(self.workspace) self.show_all() def update_config(self, config, global_cfg=None, thread=False): log.debug('Actualizando configuracion') self.workspace = config.read('General', 'workspace') self.minimize = config.read('General', 'minimize-on-close') home_interval = int(config.read('General', 'home-update-interval')) replies_interval = int( config.read('General', 'replies-update-interval')) directs_interval = int( config.read('General', 'directs-update-interval')) self.notify.update_config(config.read_section('Notifications')) if thread: self.version = global_cfg.read('App', 'version') self.imgdir = config.imgdir single_size = config.read('General', 'single-win-size').split(',') wide_size = config.read('General', 'wide-win-size').split(',') win_pos = config.read('General', 'window-position').split(',') self.single_win_size = (int(single_size[0]), int(single_size[1])) self.wide_win_size = (int(wide_size[0]), int(wide_size[1])) self.win_pos = (int(win_pos[0]), int(win_pos[1])) gtk.gdk.threads_enter() self.set_mode() if (self.home_interval != home_interval): if self.home_timer: gobject.source_remove(self.home_timer) self.home_interval = home_interval self.home_timer = gobject.timeout_add( self.home_interval * 60 * 1000, self.download_timeline) log.debug('--Creado timer de Timeline cada %i min' % self.home_interval) if (self.replies_interval != replies_interval): if self.replies_timer: gobject.source_remove(self.replies_timer) self.replies_interval = replies_interval self.replies_timer = gobject.timeout_add( self.replies_interval * 60 * 1000, self.download_replies) log.debug('--Creado timer de Replies cada %i min' % self.replies_interval) if (self.directs_interval != directs_interval): if self.directs_timer: gobject.source_remove(self.directs_timer) self.directs_interval = directs_interval self.directs_timer = gobject.timeout_add( self.directs_interval * 60 * 1000, self.download_directs) log.debug('--Creado timer de Directs cada %i min' % self.directs_interval) if thread: gtk.gdk.threads_leave() def size_request(self, widget, event, data=None): """Callback when the window changes its sizes. We use it to set the proper word-wrapping for the message column.""" if self.mode < 2: return w, h = self.get_size() if self.workspace == 'single': if (w, h) == self.single_win_size: return self.single_win_size = (w, h) else: if (w, h) == self.wide_win_size: return self.wide_win_size = (w, h) self.win_pos = self.get_position() self.contenido.update_wrap(w, self.workspace) return def move_event(self, widget, event): self.win_pos = self.get_position() def __on_key_press(self, widget, keycomb): if self.mode < 2: return if keycomb == 'ctrl+n': self.show_update_box()
def __init__(self, mainwin): gtk.VBox.__init__(self, False, 5) self.mainwin = mainwin avatar = self.mainwin.load_image('logo2.png') self.message = LoginLabel(self) us, pw, rem, auto = self.mainwin.request_remembered(0) lbl_user = gtk.Label() lbl_user.set_use_markup(True) lbl_user.set_markup(u'<span size="small">%s</span>' % _('User and Password')) lbl_user.set_alignment(0, 0.5) self.username = gtk.Entry() self.username.set_text(us) self.password = gtk.Entry() self.password.set_visibility(False) self.password.set_text(pw) self.remember = gtk.CheckButton(_('Remember my credentials')) self.autologin = gtk.CheckButton(_('Automatic login')) self.autologin.set_sensitive(False) self.btn_oauth = gtk.Button(_('Connect')) list = gtk.ListStore(gtk.gdk.Pixbuf, str, str) for p in PROTOCOLS: image = '%s.png' % p t_icon = self.mainwin.load_image(image, True) list.append([t_icon, p, p]) self.combo_protocol = gtk.ComboBox(list) icon_cell = gtk.CellRendererPixbuf() txt_cell = gtk.CellRendererText() self.combo_protocol.pack_start(icon_cell, False) self.combo_protocol.pack_start(txt_cell, False) self.combo_protocol.add_attribute(icon_cell, 'pixbuf', 0) self.combo_protocol.add_attribute(txt_cell, 'markup', 1) self.combo_protocol.set_active(0) self.btn_settings = gtk.Button() self.btn_settings.set_relief(gtk.RELIEF_NONE) self.btn_settings.set_tooltip_text(_('Preferences')) self.btn_settings.set_image( self.mainwin.load_image('dock-settings.png')) settings_box = gtk.Alignment(xalign=1.0, yalign=0.5) settings_box.add(self.btn_settings) self.waiting = CairoWaiting(self.mainwin) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) hbox = gtk.HBox(False) hbox.pack_start(lbl_user, False, False, 2) hbox.pack_start(align, True, True, 2) table = gtk.Table(11, 1, False) table.attach(settings_box, 0, 1, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL, 0, 3) table.attach(avatar, 0, 1, 1, 2, gtk.FILL, gtk.FILL, 10, 50) table.attach(self.message, 0, 1, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL, 20, 3) table.attach(hbox, 0, 1, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.username, 0, 1, 4, 5, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.password, 0, 1, 6, 7, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.combo_protocol, 0, 1, 8, 9, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(self.btn_oauth, 0, 1, 9, 10, gtk.EXPAND, gtk.FILL, 0, 3) table.attach(self.remember, 0, 1, 10, 11, gtk.FILL, gtk.FILL, 60, 1) table.attach(self.autologin, 0, 1, 11, 12, gtk.FILL, gtk.FILL, 60, 1) self.pack_start(table, False, False, 2) self.btn_oauth.grab_focus() self.btn_oauth.connect('clicked', self.signin) self.password.connect('activate', self.signin) self.rhandler = self.remember.connect("toggled", self.__toogle_remember) self.btn_settings.connect('clicked', self.mainwin.show_preferences, 'global') self.combo_protocol.connect('changed', self.__change_protocol) self.autologin.connect('toggled', self.__remember) self.remember.set_active(rem) self.autologin.set_active(auto) if rem: self.btn_oauth.grab_focus() else: self.username.grab_focus() if auto: self.signin(None)
class TweetList(gtk.VBox): def __init__(self, mainwin, label='', menu='normal'): gtk.VBox.__init__(self, False) self.last = None # Last tweets updated self.mainwin = mainwin self.list = gtk.TreeView() self.list.set_headers_visible(False) self.list.set_events(gtk.gdk.POINTER_MOTION_MASK) self.list.set_level_indentation(0) self.list.set_rules_hint(True) self.list.set_resize_mode(gtk.RESIZE_IMMEDIATE) self.label = gtk.Label(label) self.caption = label self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) self.waiting = CairoWaiting(mainwin) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) bottombox = gtk.HBox(False) bottombox.pack_start(self.lblerror, False, False, 2) bottombox.pack_start(align, True, True, 2) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.list) self.model = gtk.ListStore( gtk.gdk.Pixbuf, # avatar str, #username str, #datetime str, #client str, #pango_message str, #real_message str, # id bool, #favorited? gobject.TYPE_PYOBJECT, # in_reply_to_id gobject.TYPE_PYOBJECT, # in_reply_to_user gobject.TYPE_PYOBJECT, # retweeted_by gtk.gdk.Color, #gobject.TYPE_PYOBJECT, #color ) self.list.set_model(self.model) cell_avatar = gtk.CellRendererPixbuf() cell_avatar.set_property('yalign', 0) self.cell_tweet = gtk.CellRendererText() self.cell_tweet.set_property('wrap-mode', pango.WRAP_WORD) self.cell_tweet.set_property('wrap-width', 260) self.cell_tweet.set_property('yalign', 0) self.cell_tweet.set_property('xalign', 0) column = gtk.TreeViewColumn('tweets') column.set_alignment(0.0) column.pack_start(cell_avatar, False) column.pack_start(self.cell_tweet, True) column.set_attributes(self.cell_tweet, markup=4, cell_background_gdk=11) column.set_attributes(cell_avatar, pixbuf=0) self.list.append_column(column) if menu == 'normal': self.list.connect("button-release-event", self.__popup_menu) elif menu == 'direct': self.list.connect("button-release-event", self.__direct_popup_menu) self.pack_start(scroll, True, True) self.pack_start(bottombox, False, False) def __highlight_hashtags(self, text): hashtags = util.detect_hashtags(text) if len(hashtags) == 0: return text for h in hashtags: torep = '%s' % h try: cad = '<span foreground="#%s">%s</span>' % \ (self.mainwin.link_color, h) text = text.replace(torep, cad) except: log.debug('Problemas para resaltar el hashtag: %s' % h) return text def __highlight_mentions(self, text): mentions = util.detect_mentions(text) if len(mentions) == 0: return text for h in mentions: if len(h) == 1: continue torep = '%s' % h cad = '<span foreground="#%s">%s</span>' % \ (self.mainwin.link_color, h) text = text.replace(torep, cad) return text def __highlight_urls(self, urls, text): #if len(urls) == 0: return text for u in urls: cad = '<span foreground="#%s">%s</span>' % \ (self.mainwin.link_color, u) text = text.replace(u, cad) return text def __build_open_menu(self, user, msg): open = gtk.MenuItem(_('Open')) open_menu = gtk.Menu() total_urls = util.detect_urls(msg) total_users = util.detect_mentions(msg) total_tags = util.detect_hashtags(msg) for u in total_urls: url = u if len(u) < 30 else u[:30] + '...' umenu = gtk.MenuItem(url) umenu.connect('button-release-event', self.__open_url_with_event, u) open_menu.append(umenu) if len(total_urls) > 0 and len(total_tags) > 0: open_menu.append(gtk.SeparatorMenuItem()) for h in total_tags: ht = "#search?q=%23" + h[1:] hashtag = '/'.join(['http://twitter.com', ht]) hmenu = gtk.MenuItem(h) hmenu.connect('button-release-event', self.__open_url_with_event, hashtag) open_menu.append(hmenu) if (len(total_urls) > 0 or len(total_tags) > 0) and \ len(total_users) > 0: open_menu.append(gtk.SeparatorMenuItem()) exist = [] for m in total_users: if m == user or m in exist: continue exist.append(m) user_prof = '/'.join(['http://www.twitter.com', m[1:]]) mentmenu = gtk.MenuItem(m) mentmenu.connect('button-release-event', self.__open_url_with_event, user_prof) open_menu.append(mentmenu) open.set_submenu(open_menu) if (len(total_urls) > 0) or (len(total_users) > 0) or \ (len(total_tags) > 0): return open else: return None def __direct_popup_menu(self, widget, event): model, row = widget.get_selection().get_selected() if (row is None): return False if (event.button == 3): user = model.get_value(row, 1) msg = model.get_value(row, 5) id = model.get_value(row, 6) #in_reply_to_id = model.get_value(row, 8) menu = gtk.Menu() rtn = self.mainwin.request_popup_info(id, user) if rtn.has_key('busy'): busymenu = gtk.MenuItem(rtn['busy']) busymenu.set_sensitive(False) menu.append(busymenu) else: dm = "D @%s " % user reply = gtk.MenuItem(_('Reply')) delete = gtk.MenuItem(_('Delete')) usermenu = gtk.MenuItem('@' + user) open = self.__build_open_menu(user, msg) if not rtn['own']: menu.append(reply) menu.append(delete) if open: menu.append(open) menu.append(gtk.SeparatorMenuItem()) menu.append(usermenu) user_profile = '/'.join(['http://www.twitter.com', user]) usermenu.connect('activate', self.__open_url, user_profile) reply.connect('activate', self.__show_update_box, dm) delete.connect('activate', self.__delete_direct, id) menu.show_all() menu.popup(None, None, None, event.button , event.time) def __popup_menu(self, widget, event): model, row = widget.get_selection().get_selected() if (row is None): return False if (event.button == 3): user = model.get_value(row, 1) msg = model.get_value(row, 5) id = model.get_value(row, 6) in_reply_to_id = model.get_value(row, 8) menu = gtk.Menu() rtn = self.mainwin.request_popup_info(id, user) if rtn.has_key('busy'): busymenu = gtk.MenuItem(rtn['busy']) busymenu.set_sensitive(False) menu.append(busymenu) else: re = "@%s " % user rt = "RT @%s %s" % (user, msg) dm = "D @%s " % user re_all, mentions = util.get_reply_all(re, self.mainwin.me, msg) reply = gtk.MenuItem(_('Reply')) reply_all = gtk.MenuItem(_('Reply All')) retweet_old = gtk.MenuItem(_('Retweet (Old)')) retweet = gtk.MenuItem(_('Retweet')) save = gtk.MenuItem(_('+ Fav')) unsave = gtk.MenuItem(_('- Fav')) delete = gtk.MenuItem(_('Delete')) direct = gtk.MenuItem(_('DM')) follow = gtk.MenuItem(_('Follow')) unfollow = gtk.MenuItem(_('Unfollow')) loading = gtk.MenuItem(_('Loading friends...')) loading.set_sensitive(False) usermenu = gtk.MenuItem('@' + user) inreplymenu = gtk.MenuItem(_('In reply to')) mutemenu = gtk.MenuItem(_('Mute')) open = self.__build_open_menu(user, msg) if not rtn['own']: menu.append(reply) if mentions > 0: menu.append(reply_all) menu.append(retweet_old) menu.append(retweet) menu.append(direct) if not rtn.has_key('friend'): item = loading elif rtn['friend'] is True: item = unfollow elif rtn['friend'] is False: item = follow else: menu.append(delete) if rtn['fav']: menu.append(unsave) else: menu.append(save) if open: menu.append(open) if in_reply_to_id: menu.append(inreplymenu) menu.append(gtk.SeparatorMenuItem()) menu.append(usermenu) if not rtn['own']: if item != loading and item != follow: menu.append(mutemenu) menu.append(item) user_profile = '/'.join(['http://www.twitter.com', user]) usermenu.connect('activate', self.__open_url, user_profile) reply.connect('activate', self.__show_update_box, re, id, user) reply_all.connect('activate', self.__show_update_box, re_all, id, user) retweet_old.connect('activate', self.__show_update_box, rt) retweet.connect('activate', self.__retweet, id) direct.connect('activate', self.__show_update_box, dm) save.connect('activate', self.__fav, True, id) unsave.connect('activate', self.__fav, False, id) delete.connect('activate', self.__delete, id) follow.connect('activate', self.__follow, True, user) unfollow.connect('activate', self.__follow, False, user) inreplymenu.connect('activate', self.__in_reply_to, user, in_reply_to_id) mutemenu.connect('activate', self.__mute, user) menu.show_all() menu.popup(None, None, None, event.button , event.time) def __open_url_with_event(self, widget, event, url): if (event.button == 1) or (event.button == 3): self.__open_url(widget, url) def __open_url(self, widget, url): self.mainwin.open_url(url) def __show_update_box(self, widget, text, in_reply_id='', in_reply_user=''): self.mainwin.show_update_box(text, in_reply_id, in_reply_user) def __retweet(self, widget, id): self.mainwin.request_retweet(id) def __delete(self, widget, id): self.mainwin.request_destroy_status(id) def __delete_direct(self, widget, id): self.mainwin.request_destroy_direct(id) def __fav(self, widget, fav, id): if fav: self.mainwin.request_fav(id) else: self.mainwin.request_unfav(id) def __follow(self, widget, follow, user): if follow: self.mainwin.request_follow(user) else: self.mainwin.request_unfollow(user) def __in_reply_to(self, widget, user, in_reply_to_id): self.mainwin.request_conversation(in_reply_to_id, user) def __mute(self, widget, user): self.mainwin.request_update_muted(user) def clear(self): self.model.clear() def update_wrap(self, val): self.cell_tweet.set_property('wrap-width', val - 85) iter = self.model.get_iter_first() while iter: path = self.model.get_path(iter) self.model.row_changed(path, iter) iter = self.model.iter_next(iter) def add_tweet(self, tweet): p = self.mainwin.parse_tweet(tweet) pix = self.mainwin.get_user_avatar(p['username'], p['avatar']) urls = [gobject.markup_escape_text(u) \ for u in util.detect_urls(p['text'])] pango_twt = util.unescape_text(p['text']) pango_twt = gobject.markup_escape_text(pango_twt) #pango_twt = '<span size="9000"><b>%s</b> %s</span>' % \ # (p['username'], pango_twt) user = '******' % \ (self.mainwin.link_color, p['username']) pango_twt = '<span size="9000">%s</span>' % pango_twt pango_twt = self.__highlight_hashtags(pango_twt) pango_twt = self.__highlight_mentions(pango_twt) pango_twt = self.__highlight_urls(urls, pango_twt) pango_twt += '<span size="2000">\n\n</span>' pango_twt = user + pango_twt footer = '<span size="small" foreground="#999">%s' % p['datetime'] if p['client']: footer += ' %s %s' % (_('from'), p['client']) if p['in_reply_to_user']: footer += ' %s %s' % (_('in reply to'), p['in_reply_to_user']) if p['retweet_by']: footer += '\n%s %s' % (_('Retweeted by'), p['retweet_by']) footer += '</span>' pango_twt += footer #color = gtk.gdk.Color(255*257, 242*257, 212*257) if p['fav'] else None if p['fav']: color = gtk.gdk.Color(250 * 257, 237 * 257, 187 * 257) else: color = None self.model.append([pix, p['username'], p['datetime'], p['client'], pango_twt, p['text'], p['id'], p['fav'], p['in_reply_to_id'], p['in_reply_to_user'], p['retweet_by'], color]) del pix def update_user_pic(self, user, pic): # Evaluar si es más eficiente esto o cargar toda la lista cada vez pix = self.mainwin.load_avatar(self.mainwin.imgdir, pic) iter = self.model.get_iter_first() while iter: u = self.model.get_value(iter, 1) if u == user: self.model.set_value(iter, 0, pix) iter = self.model.iter_next(iter) del pix def update_tweets(self, arr_tweets): if arr_tweets is None: self.stop_update(True, _('Something went wrong. I\'ll update again soon')) return 0 elif len(arr_tweets) == 0: self.stop_update(True, _('No tweets available')) return 0 else: count = util.count_new_tweets(arr_tweets, self.last) self.stop_update() self.clear() for tweet in arr_tweets: if not tweet: continue #print tweet #print "**************" self.add_tweet(tweet) self.last = arr_tweets return count def start_update(self): self.waiting.start() self.lblerror.set_markup("") def stop_update(self, error=False, msg=''): self.waiting.stop(error) self.lblerror.set_markup(u"<span size='small'>%s</span>" % msg)
def __init__(self, mainwin, label='', menu='normal'): gtk.VBox.__init__(self, False) self.last = None # Last tweets updated self.mainwin = mainwin self.list = gtk.TreeView() self.list.set_headers_visible(False) self.list.set_events(gtk.gdk.POINTER_MOTION_MASK) self.list.set_level_indentation(0) self.list.set_rules_hint(True) self.list.set_resize_mode(gtk.RESIZE_IMMEDIATE) self.label = gtk.Label(label) self.caption = label self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) self.waiting = CairoWaiting(mainwin) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) bottombox = gtk.HBox(False) bottombox.pack_start(self.lblerror, False, False, 2) bottombox.pack_start(align, True, True, 2) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.list) self.model = gtk.ListStore( gtk.gdk.Pixbuf, # avatar str, #username str, #datetime str, #client str, #pango_message str, #real_message str, # id bool, #favorited? gobject.TYPE_PYOBJECT, # in_reply_to_id gobject.TYPE_PYOBJECT, # in_reply_to_user gobject.TYPE_PYOBJECT, # retweeted_by gtk.gdk.Color, #gobject.TYPE_PYOBJECT, #color ) self.list.set_model(self.model) cell_avatar = gtk.CellRendererPixbuf() cell_avatar.set_property('yalign', 0) self.cell_tweet = gtk.CellRendererText() self.cell_tweet.set_property('wrap-mode', pango.WRAP_WORD) self.cell_tweet.set_property('wrap-width', 260) self.cell_tweet.set_property('yalign', 0) self.cell_tweet.set_property('xalign', 0) column = gtk.TreeViewColumn('tweets') column.set_alignment(0.0) column.pack_start(cell_avatar, False) column.pack_start(self.cell_tweet, True) column.set_attributes(self.cell_tweet, markup=4, cell_background_gdk=11) column.set_attributes(cell_avatar, pixbuf=0) self.list.append_column(column) if menu == 'normal': self.list.connect("button-release-event", self.__popup_menu) elif menu == 'direct': self.list.connect("button-release-event", self.__direct_popup_menu) self.pack_start(scroll, True, True) self.pack_start(bottombox, False, False)
def __init__(self, parent): gtk.Window.__init__(self) self.filename = '' self.pic_url = '' self.blocked = False self.mainwin = parent #self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.set_title(_('Upload picture')) self.set_resizable(False) self.set_size_request(300, 400) self.set_transient_for(parent) #self.set_modal(True) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) #self.btn_pic = gtk.Button(_('Click to select image')) self.btn_pic = gtk.Button() self.btn_pic.set_size_request(250, 250) pic_box = gtk.VBox(False) pic_box.pack_start(self.btn_pic, True, True, 0) self.label = gtk.Label() self.label.set_use_markup(True) self.label.set_alignment(0, 0.5) self.label.set_markup('<span size="medium"><b>%s</b></span>' % _('Message')) self.label.set_justify(gtk.JUSTIFY_LEFT) self.num_chars = gtk.Label() self.num_chars.set_use_markup(True) self.num_chars.set_markup( '<span size="14000" foreground="#999"><b>140</b></span>') self.update_text = MessageTextView() self.update_text.set_border_width(2) self.update_text.set_left_margin(2) self.update_text.set_right_margin(2) self.update_text.set_wrap_mode(gtk.WRAP_WORD) buffer = self.update_text.get_buffer() scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.update_text) updatebox = gtk.HBox(False) updatebox.pack_start(scroll, True, True, 3) self.btn_clr = gtk.Button() self.btn_clr.set_image(self.mainwin.load_image('action-clear.png')) self.btn_clr.set_tooltip_text(_('Clear all') + ' (Ctrl+L)') self.btn_clr.set_relief(gtk.RELIEF_NONE) self.btn_frn = gtk.Button() self.btn_frn.set_image( self.mainwin.load_image('action-add-friends.png')) self.btn_frn.set_tooltip_text(_('Add friends') + ' (Ctrl+F)') self.btn_frn.set_relief(gtk.RELIEF_NONE) self.btn_upd = gtk.Button(_('Upload')) self.btn_upd.set_tooltip_text(_('Update your status') + ' (Ctrl+T)') top = gtk.HBox(False) top.pack_start(self.label, True, True, 5) top.pack_start(self.num_chars, False, False, 5) self.waiting = CairoWaiting(parent) self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) error_align = gtk.Alignment(xalign=0.0) error_align.add(self.lblerror) buttonbox = gtk.HBox(False) buttonbox.pack_start(self.btn_frn, False, False, 0) buttonbox.pack_start(self.btn_clr, False, False, 0) buttonbox.pack_start(gtk.HSeparator(), False, False, 2) buttonbox.pack_start(self.btn_upd, False, False, 0) abuttonbox = gtk.Alignment(1, 0.5) abuttonbox.add(buttonbox) bottom = gtk.HBox(False) bottom.pack_start(self.waiting, False, False, 5) bottom.pack_start(error_align, True, True, 4) #bottom.pack_start(abuttonbox, True, True, 5) vbox = gtk.VBox(False) vbox.pack_start(pic_box, False, False, 2) vbox.pack_start(top, False, False, 2) vbox.pack_start(updatebox, True, True, 2) vbox.pack_start(abuttonbox, False, False, 2) vbox.pack_start(bottom, False, False, 2) self.add(vbox) self.connect('key-press-event', self.__detect_shortcut) self.connect('delete-event', self.__unclose) buffer.connect('changed', self.count_chars) self.btn_frn.connect('clicked', self.show_friend_dialog) self.btn_clr.connect('clicked', self.clear) self.btn_upd.connect('clicked', self.upload) self.btn_pic.connect('clicked', self.choose_pic) self.update_text.connect('mykeypress', self.__on_key_pressed) if SPELLING: try: self.spell = gtkspell.Spell(self.update_text) except Exception, e_msg: # FIXME: Usar el log print 'DEBUG:UI:Can\'t load gtkspell -> %s' % e_msg
def __init__(self, mainwin, label='', profile=None): gtk.VBox.__init__(self, False) label_width = 75 self.mainwin = mainwin self.user = None self.label = gtk.Label(label) self.caption = label self.user_pic = gtk.Button() self.user_pic.set_size_request(60, 60) pic_box = gtk.VBox(False) pic_box.pack_start(self.user_pic, False, False, 10) self.screen_name = gtk.Label() self.screen_name.set_alignment(0, 0.5) self.tweets_count = gtk.Label() self.tweets_count.set_alignment(0, 0.5) self.tweets_count.set_padding(8, 0) self.following_count = gtk.Label() self.following_count.set_alignment(0, 0.5) self.following_count.set_padding(8, 0) self.followers_count = gtk.Label() self.followers_count.set_alignment(0, 0.5) self.followers_count.set_padding(8, 0) info_box = gtk.VBox(False) info_box.pack_start(self.screen_name, False, False, 5) info_box.pack_start(self.tweets_count, False, False) info_box.pack_start(self.following_count, False, False) info_box.pack_start(self.followers_count, False, False) top = gtk.HBox(False) top.pack_start(pic_box, False, False, 10) top.pack_start(info_box, False, False, 5) self.real_name = gtk.Entry() self.real_name.set_max_length(20) name_lbl = gtk.Label(_('Name')) name_lbl.set_size_request(label_width, -1) name_box = gtk.HBox(False) name_box.pack_start(name_lbl, False, False, 2) name_box.pack_start(self.real_name, True, True, 5) self.location = gtk.Entry() self.location.set_max_length(30) loc_lbl = gtk.Label(_('Location')) loc_lbl.set_size_request(label_width, -1) loc_box = gtk.HBox(False) loc_box.pack_start(loc_lbl, False, False, 2) loc_box.pack_start(self.location, True, True, 5) self.url = gtk.Entry() self.url.set_max_length(100) url_lbl = gtk.Label(_('URL')) url_lbl.set_size_request(label_width, -1) url_box = gtk.HBox(False) url_box.pack_start(url_lbl, False, False, 2) url_box.pack_start(self.url, True, True, 5) self.bio = gtk.TextView() self.bio.set_wrap_mode(gtk.WRAP_WORD) scrollwin = gtk.ScrolledWindow() scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER) scrollwin.set_shadow_type(gtk.SHADOW_IN) scrollwin.set_size_request(-1, 80) scrollwin.add(self.bio) bio_lbl = gtk.Label(_('Bio')) bio_lbl.set_size_request(label_width, -1) bio_box = gtk.HBox(False) bio_box.pack_start(bio_lbl, False, False, 2) bio_box.pack_start(scrollwin, True, True, 5) form = gtk.VBox(False) form.pack_start(name_box, False, False, 4) form.pack_start(loc_box, False, False, 4) form.pack_start(url_box, False, False, 4) form.pack_start(bio_box, False, False, 4) self.submit = gtk.Button(_('Save')) submit_box = gtk.Alignment(1.0, 0.5) submit_box.set_property('right-padding', 5) submit_box.add(self.submit) self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) self.waiting = CairoWaiting(mainwin) self.lblerror.set_markup("Hola mundo") self.waiting.stop(True) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) bottombox = gtk.HBox(False) bottombox.pack_start(self.lblerror, False, False, 2) bottombox.pack_start(align, True, True, 2) spacebox = gtk.VBox(False) self.pack_start(top, False, False) self.pack_start(form, False, False) self.pack_start(submit_box, False, False) self.pack_start(spacebox, True, True) self.pack_start(bottombox, False, False) self.submit.connect('clicked', self.save_user_profile)
class UserForm(gtk.VBox): def __init__(self, mainwin, label='', profile=None): gtk.VBox.__init__(self, False) label_width = 75 self.mainwin = mainwin self.user = None self.label = gtk.Label(label) self.caption = label self.user_pic = gtk.Button() self.user_pic.set_size_request(60, 60) pic_box = gtk.VBox(False) pic_box.pack_start(self.user_pic, False, False, 10) self.screen_name = gtk.Label() self.screen_name.set_alignment(0, 0.5) self.tweets_count = gtk.Label() self.tweets_count.set_alignment(0, 0.5) self.tweets_count.set_padding(8, 0) self.following_count = gtk.Label() self.following_count.set_alignment(0, 0.5) self.following_count.set_padding(8, 0) self.followers_count = gtk.Label() self.followers_count.set_alignment(0, 0.5) self.followers_count.set_padding(8, 0) info_box = gtk.VBox(False) info_box.pack_start(self.screen_name, False, False, 5) info_box.pack_start(self.tweets_count, False, False) info_box.pack_start(self.following_count, False, False) info_box.pack_start(self.followers_count, False, False) top = gtk.HBox(False) top.pack_start(pic_box, False, False, 10) top.pack_start(info_box, False, False, 5) self.real_name = gtk.Entry() self.real_name.set_max_length(20) name_lbl = gtk.Label(_('Name')) name_lbl.set_size_request(label_width, -1) name_box = gtk.HBox(False) name_box.pack_start(name_lbl, False, False, 2) name_box.pack_start(self.real_name, True, True, 5) self.location = gtk.Entry() self.location.set_max_length(30) loc_lbl = gtk.Label(_('Location')) loc_lbl.set_size_request(label_width, -1) loc_box = gtk.HBox(False) loc_box.pack_start(loc_lbl, False, False, 2) loc_box.pack_start(self.location, True, True, 5) self.url = gtk.Entry() self.url.set_max_length(100) url_lbl = gtk.Label(_('URL')) url_lbl.set_size_request(label_width, -1) url_box = gtk.HBox(False) url_box.pack_start(url_lbl, False, False, 2) url_box.pack_start(self.url, True, True, 5) self.bio = gtk.TextView() self.bio.set_wrap_mode(gtk.WRAP_WORD) scrollwin = gtk.ScrolledWindow() scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER) scrollwin.set_shadow_type(gtk.SHADOW_IN) scrollwin.set_size_request(-1, 80) scrollwin.add(self.bio) bio_lbl = gtk.Label(_('Bio')) bio_lbl.set_size_request(label_width, -1) bio_box = gtk.HBox(False) bio_box.pack_start(bio_lbl, False, False, 2) bio_box.pack_start(scrollwin, True, True, 5) form = gtk.VBox(False) form.pack_start(name_box, False, False, 4) form.pack_start(loc_box, False, False, 4) form.pack_start(url_box, False, False, 4) form.pack_start(bio_box, False, False, 4) self.submit = gtk.Button(_('Save')) submit_box = gtk.Alignment(1.0, 0.5) submit_box.set_property('right-padding', 5) submit_box.add(self.submit) self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) self.waiting = CairoWaiting(mainwin) self.lblerror.set_markup("Hola mundo") self.waiting.stop(True) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) bottombox = gtk.HBox(False) bottombox.pack_start(self.lblerror, False, False, 2) bottombox.pack_start(align, True, True, 2) spacebox = gtk.VBox(False) self.pack_start(top, False, False) self.pack_start(form, False, False) self.pack_start(submit_box, False, False) self.pack_start(spacebox, True, True) self.pack_start(bottombox, False, False) self.submit.connect('clicked', self.save_user_profile) def update(self, response): # FIXME: Mejorar esta validación try: if response.type == 'error': self.stop_update(True, response.errmsg) return profile = response.items except: profile = response self.user = profile.username pix = self.mainwin.get_user_avatar(self.user, profile.avatar) avatar = gtk.Image() avatar.set_from_pixbuf(pix) self.user_pic.set_image(avatar) del pix self.screen_name.set_markup('<b>@%s</b>' % profile.username) self.tweets_count.set_markup('<span size="9000">%i Tweets</span>' % profile.statuses_count) self.following_count.set_markup( '<span size="9000">%i Following</span>' % profile.friends_count) self.followers_count.set_markup( '<span size="9000">%i Followers</span>' % profile.followers_count) self.real_name.set_text(profile.fullname) if profile.location: self.location.set_text(profile.location) if profile.url: self.url.set_text(profile.url) buffer = self.bio.get_buffer() if profile.bio: buffer.set_text(profile.bio) self.stop_update() def update_user_pic(self, user, pic): if self.user != user: return pix = self.mainwin.load_avatar(self.mainwin.imgdir, pic, True) self.user_pic.set_image(pix) def save_user_profile(self, widget): self.start_update() name = self.real_name.get_text() location = self.location.get_text() url = self.url.get_text() buffer = self.bio.get_buffer() bounds = buffer.get_bounds() bio = buffer.get_text(bounds[0], bounds[1])[:160] self.mainwin.request_update_profile(name, url, bio, location) def lock(self): self.user_pic.set_sensitive(False) self.real_name.set_sensitive(False) self.location.set_sensitive(False) self.url.set_sensitive(False) self.bio.set_sensitive(False) self.submit.set_label(_('Saving...')) self.submit.set_sensitive(False) def unlock(self): self.user_pic.set_sensitive(True) self.real_name.set_sensitive(True) self.location.set_sensitive(True) self.url.set_sensitive(True) self.bio.set_sensitive(True) self.submit.set_label(_('Save')) self.submit.set_sensitive(True) def update_wrap(self, w): pass def start_update(self): self.lock() self.waiting.start() self.lblerror.set_markup("") def stop_update(self, error=False, msg=''): self.unlock() self.waiting.stop(error) self.lblerror.set_markup(u"<span size='small'>%s</span>" % msg)
class OAuthWindow(gtk.Window): def __init__(self, parent): gtk.Window.__init__(self) self.mainwin = parent self.set_title(_('Secure Authentication')) ### self.set_default_size(800, 450) self.set_transient_for(parent) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.connect('delete-event', self.quit) self.settings = webkit.WebSettings() self.settings.enable_java_applet = False #self.settings.enable_plugins = False self.settings.enable_page_cache = True self.settings.enable_offline_web_application_cache = False self.settings.enable_html5_local_storage = False self.settings.enable_html5_database = False self.settings.enable_default_context_menu = False self.view = webkit.WebView() self.view.set_settings(self.settings) self.view.connect('load-started', self.__started) self.view.connect('load-finished', self.__finished) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.view) self.label = gtk.Label() self.label.set_use_markup(True) self.label.set_alignment(0, 0) self.label.set_markup( _('Autorize Turpial, copy the <b>PIN</b> in the \ text box below and click OK:')) self.waiting_label = gtk.Label() self.waiting_label.set_use_markup(True) self.waiting = CairoWaiting(parent) waiting_box = gtk.Alignment(xalign=1.0) waiting_box.add(self.waiting_label) lblbox = gtk.HBox(False, 2) lblbox.pack_start(self.label, True, True, 2) lblbox.pack_start(waiting_box, True, True, 2) lblbox.pack_start(self.waiting, False, False, 2) self.pin = gtk.Entry() cancel = gtk.Button(stock=gtk.STOCK_CANCEL) accept = gtk.Button(stock=gtk.STOCK_OK) hbox = gtk.HBox(False, 0) hbox.pack_start(self.pin, True, True, 2) hbox.pack_start(cancel, False, False, 2) hbox.pack_start(accept, False, False, 2) vbox = gtk.VBox(False, 5) vbox.pack_start(scroll, True, True, 0) vbox.pack_start(lblbox, False, False, 2) vbox.pack_start(hbox, False, False, 2) cancel.connect('clicked', self.quit) accept.connect('clicked', self.__accept) self.add(vbox) def __cancel(self, widget): self.quit() def __accept(self, widget): self.view.stop_loading() verifier = self.pin.get_text() if verifier == '': self.mainwin.cancel_login(_('You must write a valid PIN')) else: self.mainwin.request_auth_token(verifier) self.quit(widget, done=True) def __started(self, widget, frame): self.waiting.start() self.waiting_label.set_markup(_('Loading...')) def __finished(self, widget, frame): self.waiting.stop() self.waiting_label.set_markup('') def open(self, uri): print uri self.show_all() self.view.open(uri) def quit(self, widget, event=None, done=False): if not done: self.view.stop_loading() self.mainwin.cancel_login(_('Login cancelled by user')) self.hide() return True
def __init__(self, parent): gtk.Window.__init__(self) self.what = _('What is happening?') self.blocked = False self.mainwin = parent self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.set_title(_('Update status')) self.set_resizable(False) #self.set_default_size(500, 120) self.set_size_request(500, 150) self.set_transient_for(parent) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.label = gtk.Label() self.label.set_use_markup(True) self.label.set_alignment(0, 0.5) self.label.set_markup('<span size="medium"><b>%s</b></span>' % self.what) self.label.set_justify(gtk.JUSTIFY_LEFT) self.num_chars = gtk.Label() self.num_chars.set_use_markup(True) self.num_chars.set_markup('<span size="14000" foreground="#999"><b>140</b></span>') #self.update_text = gtk.TextView() self.update_text = MessageTextView() self.update_text.set_border_width(2) self.update_text.set_left_margin(2) self.update_text.set_right_margin(2) self.update_text.set_wrap_mode(gtk.WRAP_WORD) buffer = self.update_text.get_buffer() scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.update_text) updatebox = gtk.HBox(False) updatebox.pack_start(scroll, True, True, 3) self.url = gtk.Entry() self.btn_url = gtk.Button(_('Shorten URL')) self.btn_url.set_tooltip_text(_('Shorten URL')) self.btn_pic = gtk.Button(_('Upload image')) self.btn_pic.set_tooltip_text(_('Upload image')) tools = gtk.HBox(False) tools.pack_start(self.url, True, True, 3) tools.pack_start(self.btn_url, False, False) tools.pack_start(gtk.HSeparator(), False, False) tools.pack_start(self.btn_pic, False, False, 3) self.toolbox = gtk.Expander() self.toolbox.set_label(_('Options')) self.toolbox.set_expanded(False) self.toolbox.add(tools) self.btn_clr = gtk.Button() self.btn_clr.set_image(self.mainwin.load_image('clear.png')) self.btn_clr.set_tooltip_text(_('Clear all')) self.btn_clr.set_relief(gtk.RELIEF_NONE) self.btn_upd = gtk.Button(_('Tweet')) chk_short = gtk.CheckButton(_('Autoshort URLs')) chk_short.set_sensitive(False) top = gtk.HBox(False) top.pack_start(self.label, True, True, 5) top.pack_start(self.num_chars, False, False, 5) self.waiting = CairoWaiting(parent) self.lblerror = gtk.Label() self.lblerror.set_use_markup(True) error_align = gtk.Alignment(xalign=0.0) error_align.add(self.lblerror) buttonbox = gtk.HBox(False) buttonbox.pack_start(chk_short, False, False, 0) buttonbox.pack_start(self.btn_clr, False, False, 0) buttonbox.pack_start(gtk.HSeparator(), False, False, 2) buttonbox.pack_start(self.btn_upd, False, False, 0) abuttonbox = gtk.Alignment(1, 0.5) abuttonbox.add(buttonbox) bottom = gtk.HBox(False) bottom.pack_start(self.waiting, False, False, 5) bottom.pack_start(error_align, True, True, 4) bottom.pack_start(abuttonbox, True, True, 5) vbox = gtk.VBox(False) vbox.pack_start(top, False, False, 2) vbox.pack_start(updatebox, True, True, 2) vbox.pack_start(bottom, False, False, 2) vbox.pack_start(self.toolbox, False, False, 2) self.add(vbox) self.connect('delete-event', self.__unclose) buffer.connect('changed', self.count_chars) self.btn_clr.connect('clicked', self.clear) self.btn_upd.connect('clicked', self.update) self.btn_url.connect('clicked', self.short_url) self.btn_pic.connect('clicked', self.upload_pic) self.toolbox.connect('activate', self.show_options) self.update_text.connect('mykeypress', self.__on_key_pressed)
def __init__(self, parent): gtk.Window.__init__(self) self.mainwin = parent self.set_title(_('Secure Authentication')) ### self.set_default_size(800, 450) self.set_transient_for(parent) self.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.connect('delete-event', self.quit) self.settings = webkit.WebSettings() self.settings.enable_java_applet = False #self.settings.enable_plugins = False self.settings.enable_page_cache = True self.settings.enable_offline_web_application_cache = False self.settings.enable_html5_local_storage = False self.settings.enable_html5_database = False self.settings.enable_default_context_menu = False self.view = webkit.WebView() self.view.set_settings(self.settings) self.view.connect('load-started', self.__started) self.view.connect('load-finished', self.__finished) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.set_shadow_type(gtk.SHADOW_IN) scroll.add(self.view) self.label = gtk.Label() self.label.set_use_markup(True) self.label.set_alignment(0, 0) self.label.set_markup( _('Autorize Turpial, copy the <b>PIN</b> in the \ text box below and click OK:')) self.waiting_label = gtk.Label() self.waiting_label.set_use_markup(True) self.waiting = CairoWaiting(parent) waiting_box = gtk.Alignment(xalign=1.0) waiting_box.add(self.waiting_label) lblbox = gtk.HBox(False, 2) lblbox.pack_start(self.label, True, True, 2) lblbox.pack_start(waiting_box, True, True, 2) lblbox.pack_start(self.waiting, False, False, 2) self.pin = gtk.Entry() cancel = gtk.Button(stock=gtk.STOCK_CANCEL) accept = gtk.Button(stock=gtk.STOCK_OK) hbox = gtk.HBox(False, 0) hbox.pack_start(self.pin, True, True, 2) hbox.pack_start(cancel, False, False, 2) hbox.pack_start(accept, False, False, 2) vbox = gtk.VBox(False, 5) vbox.pack_start(scroll, True, True, 0) vbox.pack_start(lblbox, False, False, 2) vbox.pack_start(hbox, False, False, 2) cancel.connect('clicked', self.quit) accept.connect('clicked', self.__accept) self.add(vbox)
class Main(BaseGui, gtk.Window): __gsignals__ = dict(mykeypress=(gobject.SIGNAL_RUN_LAST | gobject.SIGNAL_ACTION, None, (str,))) def __init__(self, controller, extend=False): BaseGui.__init__(self, controller) gtk.Window.__init__(self) self.extend = extend and extend_mode self.set_title('Turpial') self.set_size_request(280, 350) self.set_default_size(320, 480) self.current_width = 320 self.current_height = 480 self.set_icon(self.load_image('turpial_icon.png', True)) self.set_position(gtk.WIN_POS_CENTER) self.connect('delete-event', self.__close) self.connect('size-request', self.size_request) self.connect('configure-event', self.move_event) self.connect('mykeypress', self.__on_key_press) self.mode = 0 self.vbox = None self.contentbox = gtk.VBox(False) # Valores de config. por defecto self.showed = True self.minimize = 'on' self.workspace = 'single' self.link_color = 'ff6633' self.home_interval = -1 self.replies_interval = -1 self.directs_interval = -1 self.me = None self.version = None self.home_timer = None self.replies_timer = None self.directs_timer = None self.notify = Notification() self.home = Home(self, self.workspace) self.profile = Profile(self) self.contenido = self.home self.updatebox = UpdateBox(self) self.replybox = ReplyBox(self) if self.extend: log.debug('Cargado modo GTK Extendido') self.browser = OAuthWindow(self) else: log.debug('Cargado modo GTK Simple') self.dock = Dock(self, self.workspace) self.__create_trayicon() def __create_trayicon(self): if gtk.check_version(2, 10, 0) is not None: self.log.debug("Disabled Tray Icon. It needs PyGTK >= 2.10.0") return self.tray = gtk.StatusIcon() self.tray.set_from_pixbuf(self.load_image('turpial_icon.png', True)) self.tray.set_tooltip('Turpial') self.tray.connect("activate", self.__on_trayicon_click) self.tray.connect("popup-menu", self.__show_tray_menu) def __on_trayicon_click(self, widget): if(self.showed is True): self.showed = False self.hide() else: self.showed = True self.show() #self.present() def __show_tray_menu(self, widget, button, activate_time): menu = gtk.Menu() tweet = gtk.MenuItem(_('Tweet')) exit = gtk.MenuItem(_('Exit')) if self.mode == 2: menu.append(tweet) menu.append(exit) exit.connect('activate', self.quit) tweet.connect('activate', self.__show_update_box_from_menu) menu.show_all() menu.popup(None, None, None, button, activate_time) def __show_update_box_from_menu(self, widget): self.show_update_box() def __close(self, widget, event=None): if self.minimize == 'on': self.showed = False self.hide() else: self.quit(widget) return True def __save_size(self): if self.mode < 2: return wide_value = "%i, %i" % (self.wide_win_size[0], self.wide_win_size[1]) single_value = "%i, %i" % (self.single_win_size[0], self.single_win_size[1]) pos_value = "%i, %i" % (self.win_pos[0], self.win_pos[1]) log.debug('Guardando tamaño de la ventana') log.debug('--Single: %s' % single_value) log.debug('--Wide: %s' % wide_value) log.debug('--Position: %s' % pos_value) self.save_config({'General': {'single-win-size': single_value, 'wide-win-size': wide_value, 'window-position': pos_value}}, update=False) def __toogle_remember(self, widget): if self.remember.get_active(): self.username.set_sensitive(False) self.password.set_sensitive(False) else: self.username.set_sensitive(True) self.password.set_sensitive(True) def load_image(self, path, pixbuf=False): img_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..', 'data', 'pixmaps', path)) pix = gtk.gdk.pixbuf_new_from_file(img_path) if pixbuf: return pix avatar = gtk.Image() avatar.set_from_pixbuf(pix) del pix return avatar def load_avatar(self, dir, path, image=False): img_path = os.path.join(dir, path) pix = gtk.gdk.pixbuf_new_from_file(img_path) if not image: return pix avatar = gtk.Image() avatar.set_from_pixbuf(pix) del pix return avatar def resize_avatar(self, pic): ext = pic[-3:].lower() fullname = os.path.join(self.imgdir, pic) orig = gtk.gdk.pixbuf_new_from_file(fullname) pw, ph = orig.get_width(), orig.get_height() if pw >= ph: ratio = float(ph) / pw fw = util.AVATAR_SIZE fh = int(fw * ratio) else: ratio = float(pw) / ph fh = util.AVATAR_SIZE fw = int(fh * ratio) dest = orig.scale_simple(fw, fh, gtk.gdk.INTERP_BILINEAR) dest.save(fullname, 'png') del orig del dest def request_conversation(self, twt_id, user): self.replybox.show(twt_id, user) BaseGui.request_conversation(self, twt_id, user) def get_user_avatar(self, user, pic_url): pix = self.request_user_avatar(user, pic_url) if pix: # Try to load user avatar from file. If fail (by corrupt data, etc) # then load default image try: return self.load_avatar(self.imgdir, pix) except: return self.load_image('unknown.png', pixbuf=True) else: return self.load_image('unknown.png', pixbuf=True) def quit(self, widget): self.__save_size() gtk.main_quit() self.destroy() self.tray = None self.request_signout() def main_loop(self): #gtk.gdk.threads_enter() gtk.main() #gtk.gdk.threads_leave() def show_login(self, global_config): self.mode = 1 if self.vbox is not None: self.remove(self.vbox) avatar = self.load_image('logo2.png') self.message = LoginLabel(self) lbl_user = gtk.Label() #lbl_user.set_justify(gtk.JUSTIFY_LEFT) lbl_user.set_use_markup(True) lbl_user.set_markup(u'<span size="small">%s</span>' % _('User and Password')) lbl_user.set_alignment(0, 0.5) self.username = gtk.Entry() self.password = gtk.Entry() self.password.set_visibility(False) self.remember = gtk.CheckButton(_('Remember my credentials')) self.btn_oauth = gtk.Button(_('Connect')) self.btn_settings = gtk.Button() self.btn_settings.set_relief(gtk.RELIEF_NONE) self.btn_settings.set_tooltip_text(_('Preferences')) self.btn_settings.set_image(self.load_image('settings-single.png')) settings_box = gtk.Alignment(xalign=1.0, yalign=0.5) settings_box.set_padding(70, 10, 40, 40) settings_box.add(self.btn_settings) self.waiting = CairoWaiting(self) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) hbox = gtk.HBox(False) hbox.pack_start(lbl_user, False, False, 2) hbox.pack_start(align, True, True, 2) table = gtk.Table(10, 1, False) table.attach(avatar, 0, 1, 0, 1, gtk.FILL, gtk.FILL, 10, 50) table.attach(self.message, 0, 1, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL, 20, 3) table.attach(hbox, 0, 1, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.username, 0, 1, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.password, 0, 1, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.btn_oauth, 0, 1, 7, 8, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(self.remember, 0, 1, 8, 9, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(settings_box, 0, 1, 9, 10, gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL, 0, 10) self.vbox = gtk.VBox(False, 5) self.vbox.pack_start(table, False, False, 2) self.add(self.vbox) self.show_all() self.btn_oauth.connect('clicked', self.oauth) self.password.connect('activate', self.oauth) self.remember.connect("toggled", self.__toogle_remember) self.btn_settings.connect('clicked', self.show_preferences, 'global') username = global_config.read('Login', 'username') password = global_config.read('Login', 'password') if username != '' and password != '': self.username.set_text(username) self.password.set_text(base64.b64decode(password)) self.remember.set_active(True) def signin(self, widget, username, password): self.message.deactivate() self.waiting.start() self.btn_oauth.set_sensitive(False) self.username.set_sensitive(False) self.password.set_sensitive(False) self.request_signin(username.get_text(), password.get_text()) def oauth(self, widget): self.message.deactivate() self.waiting.start() self.btn_oauth.set_sensitive(False) self.username.set_sensitive(False) self.password.set_sensitive(False) self.remember.set_sensitive(False) self.btn_settings.set_sensitive(False) self.request_oauth(self.username.get_text(), self.password.get_text(), self.remember.get_active()) def cancel_login(self, error): self.message.set_error(error) self.waiting.stop(error=True) self.btn_oauth.set_sensitive(True) self.remember.set_sensitive(True) self.btn_settings.set_sensitive(True) if not self.remember.get_active(): self.username.set_sensitive(True) self.password.set_sensitive(True) def show_main(self, config, global_cfg, p): log.debug('Cargando ventana principal') self.mode = 2 self.update_config(config, global_cfg, True) gtk.gdk.threads_enter() self.contentbox.add(self.contenido) self.statusbar = gtk.Statusbar() self.statusbar.push(0, _('Wait a few seconds while I load everything...')) if (self.vbox is not None): self.remove(self.vbox) self.vbox = gtk.VBox(False, 0) self.vbox.pack_start(self.contentbox, True, True, 0) self.vbox.pack_start(self.dock, False, False, 0) self.vbox.pack_start(self.statusbar, False, False, 0) self.profile.set_user_profile(p) self.me = p['screen_name'] title = 'Turpial - %s' % self.me self.set_title(title) self.tray.set_tooltip(title) if config.read('General', 'profile-color') == 'on': self.link_color = p['profile_link_color'] self.add(self.vbox) self.show_all() if (self.win_pos[0] > 0 and self.win_pos[1] > 0): self.move(self.win_pos[0], self.win_pos[1]) gtk.gdk.threads_leave() self.notify.login(p) gobject.timeout_add(6 * 60 * 1000, self.download_rates) def show_home(self, widget): self.contentbox.remove(self.contenido) self.contenido = self.home self.contentbox.add(self.contenido) def show_profile(self, widget): self.contentbox.remove(self.contenido) self.contenido = self.profile self.contentbox.add(self.contenido) def show_update_box(self, text='', id='', user=''): if self.updatebox.get_property('visible'): self.updatebox.present() return self.updatebox.show(text, id, user) def show_preferences(self, widget, mode='user'): prefs = Preferences(self, mode) def show_oauth_pin_request(self, url): if self.extend: gtk.gdk.threads_enter() self.browser.open(url) gtk.gdk.threads_leave() else: webbrowser.open(url) gtk.gdk.threads_enter() p = InputPin(self) response = p.run() if response == gtk.RESPONSE_ACCEPT: verifier = p.pin.get_text() if verifier == '': self.cancel_login(_('Must write a valid PIN')) else: self.request_auth_token(verifier) else: self.cancel_login(_('Login cancelled by user')) p.destroy() gtk.gdk.threads_leave() def start_updating_timeline(self): self.home.timeline.start_update() def start_updating_replies(self): self.home.replies.start_update() def start_updating_directs(self): self.home.direct.start_update() def start_search(self): self.profile.topics.topics.waiting.start() def update_timeline(self, tweets): log.debug(u'Actualizando el timeline') gtk.gdk.threads_enter() last = self.home.timeline.last count = self.home.timeline.update_tweets(tweets) if count > 0 and self.updating['home']: tweet = None i = 0 while 1: if tweets[i]['user']['screen_name'] == self.me: if not util.has_tweet(last, tweets[i]): tweet = tweets[i] break else: tweet = tweets[i] break i += 1 p = self.parse_tweet(tweet) icon = self.current_avatar_path(p['avatar']) text = util.escape_text(p['text']) text = "<b>@%s</b> %s" % (p['username'], text) self.notify.new_tweets(count, text, icon) gtk.gdk.threads_leave() self.updating['home'] = False def update_replies(self, tweets): log.debug(u'Actualizando las replies') gtk.gdk.threads_enter() count = self.home.replies.update_tweets(tweets) if count > 0 and self.updating['replies']: p = self.parse_tweet(tweets[0]) icon = self.current_avatar_path(p['avatar']) text = util.escape_text(p['text']) text = "<b>@%s</b> %s" % (p['username'], text) self.notify.new_replies(count, text, icon) gtk.gdk.threads_leave() self.updating['replies'] = False def update_directs(self, recv): log.debug(u'Actualizando mensajes directos') gtk.gdk.threads_enter() count = self.home.direct.update_tweets(recv) if count > 0 and self.updating['directs']: p = self.parse_tweet(recv[0]) icon = self.current_avatar_path(p['avatar']) text = util.escape_text(p['text']) text = "<b>@%s</b> %s" % (p['username'], text) self.notify.new_directs(count, text, icon) gtk.gdk.threads_leave() self.updating['directs'] = False def update_favorites(self, tweets, replies, favs): log.debug(u'Actualizando favoritos') gtk.gdk.threads_enter() self.home.timeline.update_tweets(tweets) self.home.replies.update_tweets(replies) self.profile.favorites.update_tweets(favs) gtk.gdk.threads_leave() def update_user_profile(self, profile): log.debug(u'Actualizando perfil del usuario') gtk.gdk.threads_enter() self.profile.set_user_profile(profile) gtk.gdk.threads_leave() def update_follow(self, user, follow): self.notify.following(user, follow) def update_rate_limits(self, val): if val is None or val == []: return gtk.gdk.threads_enter() self.statusbar.push(0, util.get_rates(val)) gtk.gdk.threads_leave() def update_search_topics(self, val): log.debug(u'Mostrando resultados de la búsqueda') gtk.gdk.threads_enter() if val is None: self.profile.topics.update_tweets(val) else: self.profile.topics.update_tweets(val['results']) gtk.gdk.threads_leave() def update_search_people(self, val): self.search.people.update_profiles(val) #self.show_search(self) #if self.workspace != 'wide': # self.contenido.wrapper.set_current_page(1) def update_trends(self, current, day, week): self.search.trending.update_trends(current, day, week) def update_friends(self, friends): pass def update_user_avatar(self, user, pic): self.home.timeline.update_user_pic(user, pic) self.home.replies.update_user_pic(user, pic) self.home.direct.update_user_pic(user, pic) self.profile.favorites.update_user_pic(user, pic) self.profile.user_form.update_user_pic(user, pic) self.profile.topics.update_user_pic(user, pic) def update_in_reply_to(self, tweet): gtk.gdk.threads_enter() self.replybox.update([tweet]) gtk.gdk.threads_leave() def update_conversation(self, tweets): gtk.gdk.threads_enter() self.replybox.update(tweets) gtk.gdk.threads_leave() def tweet_changed(self, timeline, replies, favs): log.debug(u'Tweet modificado') gtk.gdk.threads_enter() log.debug(u'--Actualizando el timeline') self.home.timeline.update_tweets(timeline) log.debug(u'--Actualizando las replies') self.home.replies.update_tweets(replies) log.debug(u'--Actualizando favoritos') self.profile.favorites.update_tweets(favs) gtk.gdk.threads_leave() def tweet_done(self, tweets): log.debug(u'Actualizando nuevo tweet') gtk.gdk.threads_enter() self.updatebox.release() if tweets: self.updatebox.done() gtk.gdk.threads_leave() self.update_timeline(tweets) def set_mode(self): cur_x, cur_y = self.get_position() cur_w, cur_h = self.get_size() if self.workspace == 'wide': size = self.wide_win_size self.resize(size[0], size[1]) self.set_default_size(size[0], size[1]) x = (size[0] - cur_w) / 2 self.move(cur_x - x, cur_y) else: size = self.single_win_size self.resize(size[0], size[1]) self.set_default_size(size[0], size[1]) x = (cur_w - size[0]) / 2 self.move(cur_x + x, cur_y) log.debug('Cambiando a modo %s (%s)' % (self.workspace, size)) self.dock.change_mode(self.workspace) self.home.change_mode(self.workspace) self.profile.change_mode(self.workspace) self.show_all() def update_config(self, config, global_cfg=None, thread=False): log.debug('Actualizando configuracion') self.workspace = config.read('General', 'workspace') self.minimize = config.read('General', 'minimize-on-close') home_interval = int(config.read('General', 'home-update-interval')) replies_interval = int(config.read('General', 'replies-update-interval')) directs_interval = int(config.read('General', 'directs-update-interval')) self.notify.update_config(config.read_section('Notifications')) if thread: self.version = global_cfg.read('App', 'version') self.imgdir = config.imgdir single_size = config.read('General', 'single-win-size').split(',') wide_size = config.read('General', 'wide-win-size').split(',') win_pos = config.read('General', 'window-position').split(',') self.single_win_size = (int(single_size[0]), int(single_size[1])) self.wide_win_size = (int(wide_size[0]), int(wide_size[1])) self.win_pos = (int(win_pos[0]), int(win_pos[1])) gtk.gdk.threads_enter() self.set_mode() if (self.home_interval != home_interval): if self.home_timer: gobject.source_remove(self.home_timer) self.home_interval = home_interval self.home_timer = gobject.timeout_add(self.home_interval * 60 * 1000, self.download_timeline) log.debug('--Creado timer de Timeline cada %i min' % self.home_interval) if (self.replies_interval != replies_interval): if self.replies_timer: gobject.source_remove(self.replies_timer) self.replies_interval = replies_interval self.replies_timer = gobject.timeout_add(self.replies_interval * 60 * 1000, self.download_replies) log.debug('--Creado timer de Replies cada %i min' % self.replies_interval) if (self.directs_interval != directs_interval): if self.directs_timer: gobject.source_remove(self.directs_timer) self.directs_interval = directs_interval self.directs_timer = gobject.timeout_add(self.directs_interval * 60 * 1000, self.download_directs) log.debug('--Creado timer de Directs cada %i min' % self.directs_interval) if thread: gtk.gdk.threads_leave() def size_request(self, widget, event, data=None): """Callback when the window changes its sizes. We use it to set the proper word-wrapping for the message column.""" if self.mode < 2: return w, h = self.get_size() if self.workspace == 'single': if (w, h) == self.single_win_size: return self.single_win_size = (w, h) else: if (w, h) == self.wide_win_size: return self.wide_win_size = (w, h) self.win_pos = self.get_position() self.contenido.update_wrap(w, self.workspace) return def move_event(self, widget, event): self.win_pos = self.get_position() def __on_key_press(self, widget, keycomb): if self.mode < 2: return if keycomb == 'ctrl+n': self.show_update_box()
def __init__(self, mainwin): gtk.VBox.__init__(self, False, 5) self.mainwin = mainwin avatar = self.mainwin.load_image('logo2.png') self.message = LoginLabel(self) us, pw, rem, auto = self.mainwin.request_remembered(0) lbl_user = gtk.Label() lbl_user.set_use_markup(True) lbl_user.set_markup(u'<span size="small">%s</span>' % _('User and Password')) lbl_user.set_alignment(0, 0.5) self.username = gtk.Entry() self.username.set_text(us) self.password = gtk.Entry() self.password.set_visibility(False) self.password.set_text(pw) self.remember = gtk.CheckButton(_('Remember my credentials')) self.autologin = gtk.CheckButton(_('Automatic login')) self.autologin.set_sensitive(False) self.btn_oauth = gtk.Button(_('Connect')) list = gtk.ListStore(gtk.gdk.Pixbuf, str, str) for p in PROTOCOLS: image = '%s.png' % p t_icon = self.mainwin.load_image(image, True) list.append([t_icon, p, p]) self.combo_protocol = gtk.ComboBox(list) icon_cell = gtk.CellRendererPixbuf() txt_cell = gtk.CellRendererText() self.combo_protocol.pack_start(icon_cell,False) self.combo_protocol.pack_start(txt_cell,False) self.combo_protocol.add_attribute(icon_cell,'pixbuf',0) self.combo_protocol.add_attribute(txt_cell,'markup',1) self.combo_protocol.set_active(0) self.btn_settings = gtk.Button() self.btn_settings.set_relief(gtk.RELIEF_NONE) self.btn_settings.set_tooltip_text(_('Preferences')) self.btn_settings.set_image(self.mainwin.load_image('dock-settings.png')) settings_box = gtk.Alignment(xalign=1.0, yalign=0.5) settings_box.add(self.btn_settings) self.waiting = CairoWaiting(self.mainwin) align = gtk.Alignment(xalign=1, yalign=0.5) align.add(self.waiting) hbox = gtk.HBox(False) hbox.pack_start(lbl_user, False, False, 2) hbox.pack_start(align, True, True, 2) table = gtk.Table(11, 1, False) table.attach(settings_box, 0, 1, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL, 0, 3) table.attach(avatar, 0, 1, 1, 2, gtk.FILL, gtk.FILL, 10, 50) table.attach(self.message, 0, 1, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL, 20, 3) table.attach(hbox, 0, 1, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.username, 0, 1, 4, 5, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.password, 0, 1, 6, 7, gtk.EXPAND | gtk.FILL, gtk.FILL, 50, 0) table.attach(self.combo_protocol, 0, 1, 8, 9, gtk.EXPAND, gtk.FILL, 0, 10) table.attach(self.btn_oauth, 0, 1, 9, 10, gtk.EXPAND, gtk.FILL, 0, 3) table.attach(self.remember, 0, 1, 10, 11, gtk.FILL, gtk.FILL, 60, 1) table.attach(self.autologin, 0, 1, 11, 12, gtk.FILL, gtk.FILL, 60, 1) self.pack_start(table, False, False, 2) self.btn_oauth.grab_focus() self.btn_oauth.connect('clicked', self.signin) self.password.connect('activate', self.signin) self.rhandler = self.remember.connect("toggled", self.__toogle_remember) self.btn_settings.connect('clicked', self.mainwin.show_preferences, 'global') self.combo_protocol.connect('changed', self.__change_protocol) self.autologin.connect('toggled', self.__remember) self.remember.set_active(rem) self.autologin.set_active(auto) if rem: self.btn_oauth.grab_focus() else: self.username.grab_focus() if auto: self.signin(None)