~jconti/ubuntu/precise/emesene/fix-956422

« back to all changes in this revision

Viewing changes to dialog.py

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2010-04-14 01:33:51 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20100414013351-r2icbt5gs4ai71j8
Tags: 1.6.1-0ubuntu1
* New upstream release (LP: #562646).
* Fix missing-debian-source-format lintian warning.
* Refresh 20_dont_build_own_libmimic.patch patch.
* Bump Standards-Version to 3.8.4.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
import Avatar
26
26
import urllib
27
27
import Theme
 
28
import thread
 
29
import time
 
30
 
 
31
import gc
28
32
 
29
33
import abstract.stock as stock
30
34
 
407
411
 
408
412
    def _on_hide(window):
409
413
        global _avatar_chooser
 
414
        
 
415
        if _avatar_chooser:
 
416
            _avatar_chooser.stop_and_clear()
 
417
            del _avatar_chooser
 
418
                
410
419
        _avatar_chooser = None
411
420
 
412
421
    if not _avatar_chooser:
570
579
        self.later = gtk.Button()
571
580
        self.later.add(gtk.Label(_('Remind me later')))
572
581
        self.later.connect('clicked', self.cb_cancel)
573
 
        self.profile = gtk.Button()
574
 
        self.profile.add(gtk.Label(_('View profile')))
575
 
        self.profile.connect('clicked', self.cb_profile)
576
582
        self.addbutton = gtk.Button(stock=gtk.STOCK_ADD)
577
583
        self.addbutton.connect('clicked', self.cb_add)
578
584
        self.bReject = gtk.Button()
579
585
        self.bReject.add(gtk.Label(_('Reject')))
580
586
        self.bReject.connect('clicked', self.cb_rej)
 
587
        self.profile = gtk.Button()
 
588
        self.profile.add(gtk.Label(_('View profile')))
 
589
        self.profile.connect('clicked', self.cb_profile)
 
590
        self.showDetails = False
 
591
        self.bDetails = gtk.Button()
 
592
        self.bDetails.add(gtk.Label(_('Details')))
 
593
        self.bDetails.connect('clicked', self.cb_show_details)
 
594
        self.bHideDetails = gtk.Button()
 
595
        self.bHideDetails.add(gtk.Label(_('Hide details')))
 
596
        self.bHideDetails.connect('clicked', self.cb_hide_details)
581
597
 
582
598
        ## packing
583
599
        self.add(self.vbox)
592
608
 
593
609
        self.hboxbuttons.pack_start(self.bReject, False, False)
594
610
        self.hboxbuttons.pack_start(self.later, False, False)
595
 
        self.hboxbuttons.pack_start(self.profile, False, False)
596
 
        self.hboxbuttons.pack_start(self.buttonbox)
597
 
        self.buttonbox.pack_start(self.addbutton)
 
611
        self.hboxbuttons.pack_start(self.addbutton, False, False)
 
612
        self.hboxbuttons.pack_end(self.buttonbox)
 
613
        self.buttonbox.pack_start(self.bDetails)
 
614
 
 
615
    def cb_show_details(self, button):
 
616
        #the widget that appears when the user clicks "details"
 
617
        self.detailsSection = gtk.HBox(spacing=5)
 
618
        genericAvatar = gtk.image_new_from_pixbuf(self.controller.theme.getImage('login'))
 
619
        genericAvatar.set_size_request(96, 96)
 
620
        labelAlias = gtk.Label(_("Alias"))
 
621
        labelAlias_align = gtk.Alignment(0.0, 0.5)
 
622
        labelAlias_align.add(labelAlias)
 
623
        self.entryAlias = gtk.Entry()
 
624
 
 
625
        group_label = gtk.Label(_("Group"))
 
626
        groupsList = gtk.ListStore(gobject.TYPE_STRING)
 
627
        self.groupComboEntry = gtk.ComboBoxEntry(groupsList, 0)
 
628
        groupCompletion = gtk.EntryCompletion()
 
629
        groupCompletion.set_model(groupsList)
 
630
        self.groupComboEntry.get_children()[0].set_completion(groupCompletion)
 
631
        groupCompletion.set_text_column(0)
 
632
        group_label_align = gtk.Alignment(0.0, 0.5)
 
633
        group_label_align.add(group_label)
 
634
 
 
635
        #fill groups combo box
 
636
        for i in self.controller.groups.groups.keys():
 
637
            groupsList.append([i])
 
638
 
 
639
        labelsVBox = gtk.VBox()
 
640
        labelsVBox.pack_start(labelAlias_align)
 
641
        labelsVBox.pack_start(group_label_align)
 
642
 
 
643
        entriesVBox = gtk.VBox()
 
644
        entriesVBox.pack_start(self.entryAlias)
 
645
        entriesVBox.pack_start(self.groupComboEntry)
 
646
 
 
647
        attributesHBox = gtk.HBox()
 
648
        attributesHBox.pack_start(labelsVBox)
 
649
        attributesHBox.pack_start(entriesVBox, True, True)
 
650
 
 
651
        profileHBox = gtk.HButtonBox()
 
652
        profileHBox.set_layout(gtk.BUTTONBOX_END)
 
653
        profileHBox.pack_start(self.profile)
 
654
 
 
655
        rightSideVBox = gtk.VBox()
 
656
        rightSideVBox.pack_start(attributesHBox)
 
657
        rightSideVBox.pack_start(profileHBox)
 
658
 
 
659
        self.detailsSection.pack_start(genericAvatar)
 
660
        self.detailsSection.pack_start(rightSideVBox, True, True)
 
661
 
 
662
        self.vbox.pack_end(self.detailsSection)
 
663
        self.detailsSection.show_all()
 
664
 
 
665
        self.buttonbox.remove(self.bDetails)
 
666
        self.buttonbox.pack_start(self.bHideDetails)
 
667
        self.profile.show_all()
 
668
        self.bHideDetails.show_all()
 
669
        self.showDetails = True
 
670
 
 
671
    def cb_hide_details(self, button):
 
672
        self.profile.get_parent().remove(self.profile)
 
673
        self.vbox.remove(self.detailsSection)
 
674
        self.detailsSection.destroy()
 
675
        self.buttonbox.remove(self.bHideDetails)
 
676
        self.buttonbox.pack_start(self.bDetails)
 
677
        self.bDetails.show_all()
 
678
        self.showDetails = False
598
679
 
599
680
    def _buildpages(self):
600
681
        '''Builds hboxpages, that is a bit complex to include in __init__'''
601
682
        hboxpages = gtk.HBox()
602
683
 
603
 
        arrowleft = Widgets.TinyArrow(gtk.ARROW_LEFT)
 
684
        arrowleft = gtk.Arrow(gtk.ARROW_LEFT,gtk.SHADOW_NONE)
 
685
        arrowleft.set_size_request(-1,15)
604
686
        self.buttonleft = gtk.Button()
605
687
        self.buttonleft.set_relief(gtk.RELIEF_NONE)
606
688
        self.buttonleft.add(arrowleft)
607
689
        self.buttonleft.connect('clicked', self.switchmail, -1)
608
690
 
609
 
        arrowright = Widgets.TinyArrow(gtk.ARROW_RIGHT)
 
691
        arrowright = gtk.Arrow(gtk.ARROW_RIGHT,gtk.SHADOW_NONE)
 
692
        arrowright.set_size_request(-1,15)
610
693
        self.buttonright = gtk.Button()
611
694
        self.buttonright.set_relief(gtk.RELIEF_NONE)
612
695
        self.buttonright.add(arrowright)
654
737
        self.currentpage.set_markup('<b>(%s/%s)</b>' % \
655
738
            (self.pointer + 1, len(self.mails)))
656
739
 
 
740
        if self.showDetails:
 
741
            self.entryAlias.set_text("")
 
742
            self.groupComboEntry.child.set_text("")
 
743
 
657
744
    def switchmail(self, button, order):
658
745
        '''Moves the mail pointer +1 or -1'''
659
746
        if (self.pointer + order) >= 0:
689
776
    def cb_add(self, button):
690
777
        '''Callback when the add button is clicked'''
691
778
        mail, nick = self.mails[self.pointer]
692
 
        self.controller.contacts.add(mail, '')
 
779
        group = ''
 
780
        alias = ''
 
781
        if self.showDetails:
 
782
            group = self.groupComboEntry.get_children()[0].get_text()
 
783
            if group and not group in self.controller.groups.groups.keys():
 
784
                    self.controller.groups.add(group)
 
785
            alias = self.entryAlias.get_text()
 
786
 
 
787
        self.controller.contacts.add(mail, group, *(self.delayedAlias, mail, alias))
 
788
#        self.controller.contacts.add(mail, group)
693
789
        self.cb_cancel(None)
694
 
        
 
790
 
 
791
    def delayedAlias(self, account, alias):
 
792
        self.controller.contacts.set_alias(account, alias)
 
793
        return False
 
794
 
695
795
    def cb_rej(self, button):
696
796
        mail, nick = self.mails[self.pointer]
697
797
        self.controller.contacts.remove_from_pending_list(mail)
721
821
        self.nickLabel=gtk.Label(_('Nick:'))
722
822
        self.nickLabel.set_alignment(0.0,0.5)
723
823
        self.nickEntry=gtk.Entry()
724
 
        self.nickEntry.set_text(nick)
 
824
        self.nickEntry.set_text(self.nick)
725
825
        self.psmLabel=gtk.Label(_('Personal Message:'))
726
826
        self.psmLabel.set_alignment(0.0,0.5)
727
827
        self.psmEntry=gtk.Entry()
728
 
        self.psmEntry.set_text(psm)
 
828
        self.psmEntry.set_text(self.psm)
729
829
        self.vbox = gtk.VBox()
730
830
        self.vbox.add(self.nickLabel)
731
831
        self.vbox.add(self.nickEntry)
768
868
        self.nickEntry.connect('activate', self.on_accept)
769
869
        self.psmEntry.connect('activate', self.on_accept)
770
870
        self.controller.connect('avatar-changed', self.updateAvatar)
 
871
        self.controller.msn.connect('self-personal-message-changed', self.update_pm_entry)
 
872
        self.controller.msn.connect('self-nick-changed', self.update_nick_entry)
771
873
 
772
874
        #add everything to the window and show it
773
875
        self.add(self.vbox2)
784
886
            pixbuf = gtk.gdk.pixbuf_new_from_file(avatarPath)
785
887
            self.currentAvatar.set_from_pixbuf(pixbuf)
786
888
 
 
889
    def update_nick_entry(self, msnp, oldNick, newNick):
 
890
        self.nickEntry.set_text(newNick)
 
891
 
 
892
    def update_pm_entry(self, msnp, user, pm):
 
893
        self.psmEntry.set_text(pm)
 
894
 
787
895
    #this method show the avatar chooser dialog and saves the new avatar if any
788
896
    #this method does not change the actual avatar, just the dialog's avatar
789
897
    def choose_picture(self, widget, event):
819
927
        self.destroy()
820
928
        self.response_cb(stock.CLOSE, '', '', '')
821
929
 
 
930
# Class that holds the iconview from the avatar chooser dialog
 
931
class IconView(gtk.HBox):
 
932
    def __init__(self, label, path_list, avatar_chooser):
 
933
        gtk.HBox.__init__(self)
 
934
        self.set_spacing(4)
 
935
        self.chooser = avatar_chooser
 
936
        self.model = gtk.ListStore(gtk.gdk.Pixbuf, str)   
 
937
        self.iconview = gtk.IconView(self.model)
 
938
        self.iconview.enable_model_drag_dest([('text/uri-list', 0, 0)], gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_COPY)
 
939
        self.iconview.connect("drag-data-received", self._drag_data_received)
 
940
        self.iconview.set_pixbuf_column(0)
 
941
        self.iconview.connect("item-activated", self._on_icon_activated)
 
942
        self.iconview.connect("button_press_event", self.pop_up)
 
943
 
 
944
        self.label = gtk.Label(label)
 
945
        
 
946
        self.scroll = gtk.ScrolledWindow()
 
947
        self.scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
948
        self.scroll.set_shadow_type(gtk.SHADOW_IN)
 
949
        self.scroll.add(self.iconview)
 
950
        self.pack_start(self.scroll, True, True)
 
951
 
 
952
        self.STOP = False
 
953
        # Start a new thread to fill the iconview with images from path_list
 
954
        thread.start_new_thread(self.fill, (path_list,))
 
955
 
 
956
    def stop_and_clear(self):
 
957
        self.STOP = True
 
958
        self.model.clear()
 
959
 
 
960
    def fill(self, path_list):
 
961
        '''fill the IconView with avatars from the list of pictures'''
 
962
        for search_path in path_list:
 
963
            if os.path.exists(search_path):
 
964
                for path in os.listdir(search_path):
 
965
                    name = os.path.splitext(path)[0]
 
966
                    if self.STOP:
 
967
                        return False
 
968
                    if not name.endswith('_thumb') and not path.endswith('tmp') \
 
969
                       and not path.endswith('xml') and not path.endswith('db'):
 
970
                        gtk.gdk.threads_enter()
 
971
                        self.add_picture(os.path.join(search_path, path))
 
972
                        # make update the iconview
 
973
                        self.iconview.queue_draw()
 
974
                        gtk.gdk.threads_leave()        
 
975
                        
 
976
                        # give some time to the main thread (for GUI updates)
 
977
                        time.sleep(0.001)
 
978
        # Force Garbage Collector to tidy objects
 
979
        # see http://faq.pygtk.org/index.py?req=show&file=faq08.004.htp
 
980
        gc.collect()
 
981
    
 
982
    def pop_up(self, iconview, event):
 
983
        if event.button == 3 and self.label.get_text() != _('System pictures'):
 
984
            path = self.iconview.get_path_at_pos(event.x, event.y)
 
985
            if path != None:
 
986
                self.iconview.select_path(path)
 
987
                remove_menu = gtk.Menu()
 
988
                remove_item = gtk.ImageMenuItem(_('Delete'))
 
989
                remove_item.set_image(gtk.image_new_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU))
 
990
                remove_item.connect('activate', self.chooser._on_remove)
 
991
                remove_menu.append(remove_item)
 
992
                remove_menu.popup(None, None, None, event.button, event.time)
 
993
                remove_menu.show_all()
 
994
 
 
995
    def _drag_data_received(self, treeview, context, x, y, selection, info, timestamp):
 
996
        '''method called on an image dragged to the view'''
 
997
        urls = selection.data.split('\n')
 
998
        for url in urls:
 
999
            path = url.replace('file://', '')
 
1000
            path = path.replace('\r', '')
 
1001
 
 
1002
            # the '\x00' value makes an error
 
1003
            path = path.replace(chr(0), '')
 
1004
 
 
1005
            # this seems to be an error on ntpath but we take care :S
 
1006
            try:
 
1007
                if os.path.exists(path):
 
1008
                    self.add_picture(path)
 
1009
            except TypeError, e:
 
1010
                error(_("Could not add picture:\n %s") % (str(e),))
 
1011
 
 
1012
    def add_picture(self, path):
 
1013
        '''Adds an avatar into the IconView'''
 
1014
        try:
 
1015
            if os.path.exists(path) and os.access(path, os.R_OK)\
 
1016
                    and not self.is_in_view(path):
 
1017
                try:
 
1018
                    pixbuf = gtk.gdk.pixbuf_new_from_file(path)
 
1019
                except:
 
1020
                    try:
 
1021
                        os.remove(path)
 
1022
                    except:
 
1023
                        pass
 
1024
                    return
 
1025
 
 
1026
                # On nt images are 128x128 (48x48 on xp)
 
1027
                # On kde, images are 64x64
 
1028
                if (self.label.get_text() == _('System pictures') or \
 
1029
                 self.label.get_text() == _('Contact pictures')) and \
 
1030
                 (pixbuf.get_width() != 96 or pixbuf.get_height() != 96):
 
1031
                    pixbuf = pixbuf.scale_simple(96, 96, gtk.gdk.INTERP_BILINEAR)
 
1032
 
 
1033
                if self.model != None and not self.STOP:
 
1034
                    self.model.append([pixbuf, path])
 
1035
                    # Esplicitely delete gtkpixbuf
 
1036
                    # see http://faq.pygtk.org/index.py?req=show&file=faq08.004.htp
 
1037
                    del pixbuf
 
1038
            else:
 
1039
                print path, 'not readable'
 
1040
        except gobject.GError:
 
1041
            print "image at %s could not be loaded" % path
 
1042
 
 
1043
    def is_in_view(self, filename):
 
1044
        '''return True if filename already on the iconview'''
 
1045
        if os.name != 'nt' and not self.STOP:
 
1046
            for (pixbuf, path) in self.model:
 
1047
                if os.path.samefile(filename, path):
 
1048
                    return True
 
1049
        return False
 
1050
 
 
1051
    def _on_icon_activated(self, *args):
 
1052
        '''method called when a picture is double clicked'''
 
1053
        self.chooser._on_accept(None)
 
1054
    
 
1055
    def get_selected_items(self):
 
1056
        return self.iconview.get_selected_items()
822
1057
 
823
1058
class AvatarChooser(gtk.Window):
824
1059
    '''A dialog to choose an avatar'''
836
1071
        self.cache_path = cache_path
837
1072
 
838
1073
        self.set_title(_("Avatar chooser"))
839
 
        self.set_default_size(602, 400)
 
1074
        self.set_default_size(640, 400)
840
1075
        self.set_border_width(4)
841
1076
        self.set_position(gtk.WIN_POS_CENTER)
842
1077
        self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
843
1078
 
844
 
        self.model = gtk.ListStore(gtk.gdk.Pixbuf, str)
845
 
 
846
 
        self.view = gtk.IconView(self.model)
847
 
        self.view.enable_model_drag_dest([('text/uri-list', 0, 0)], gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_COPY)
848
 
        self.view.connect("drag-data-received", self._drag_data_received)
849
 
 
850
 
        self.view.set_pixbuf_column(0)
851
 
        self.view.connect("item-activated", self._on_icon_activated)
852
 
 
853
 
        scroll = gtk.ScrolledWindow()
854
 
        scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
855
 
        scroll.set_shadow_type(gtk.SHADOW_IN)
856
 
        scroll.add(self.view)
 
1079
        faces_paths = []
 
1080
        if os.name == 'nt':
 
1081
            appDataFolder = os.path.split(os.environ['APPDATA'])[1]
 
1082
            faces_path = os.path.join(os.environ['ALLUSERSPROFILE'], appDataFolder, \
 
1083
                         "Microsoft", "User Account Pictures", "Default Pictures")
 
1084
            #little hack to fix problems with encoding
 
1085
            unicodepath=u"%s" % faces_path
 
1086
            faces_paths = [unicodepath]
 
1087
        else:
 
1088
            faces_paths = ['/usr/share/kde/apps/faces',\
 
1089
                           '/usr/share/kde4/apps/kdm/pics/users', \
 
1090
                           '/usr/share/pixmaps/faces']
 
1091
 
 
1092
        self.iconViews = []
 
1093
        self.iconViews.append( IconView(_('Used'), [cache_path], self) )
 
1094
        self.iconViews.append( IconView(_('System pictures'), faces_paths, self) )
 
1095
        self.iconViews.append( IconView(_('Contact pictures'),[self.controller.config.getCachePath()], self) )
857
1096
 
858
1097
        vbox = gtk.VBox(spacing=4)
859
1098
        side_vbox = gtk.VBox(spacing=4)
868
1107
        vbbox.set_layout(gtk.BUTTONBOX_START)
869
1108
 
870
1109
        b_clear = gtk.Button(_("No picture"))
871
 
        b_add = gtk.Button(stock=gtk.STOCK_ADD)
872
 
        b_remove = gtk.Button(stock=gtk.STOCK_REMOVE)
873
 
        b_remove_all = gtk.Button(_("Remove all"))
 
1110
        self.b_add = gtk.Button(stock=gtk.STOCK_ADD)
 
1111
        self.b_remove = gtk.Button(stock=gtk.STOCK_REMOVE)
 
1112
        self.b_remove_all = gtk.Button(_("Remove all"))
874
1113
        b_accept = gtk.Button(stock=gtk.STOCK_OK)
875
1114
        b_cancel = gtk.Button(stock=gtk.STOCK_CANCEL)
 
1115
        b_accept.set_sensitive(False)
876
1116
 
877
1117
        b_clear.connect('clicked', self._on_clear)
878
 
        b_add.connect('clicked', self._on_add)
879
 
        b_remove.connect('clicked', self._on_remove)
880
 
        b_remove_all.connect('clicked', self._on_remove_all)
 
1118
        self.b_add.connect('clicked', self._on_add)
 
1119
        self.b_remove.connect('clicked', self._on_remove)
 
1120
        self.b_remove_all.connect('clicked', self._on_remove_all)
881
1121
        b_accept.connect('clicked', self._on_accept)
882
1122
        b_cancel.connect('clicked', self._on_cancel)
883
1123
        self.connect('delete-event', self._on_close)
892
1132
        hbbox.pack_start(b_cancel, False)
893
1133
        hbbox.pack_start(b_accept, False)
894
1134
 
895
 
        vbbox.pack_start(b_add, False)
896
 
        vbbox.pack_start(b_remove, False)
897
 
        vbbox.pack_start(b_remove_all, False)
 
1135
        vbbox.pack_start(self.b_add, False)
 
1136
        vbbox.pack_start(self.b_remove, False)
 
1137
        vbbox.pack_start(self.b_remove_all, False)
898
1138
 
899
1139
        side_vbox.pack_start(frame_current, False)
900
1140
        side_vbox.pack_start(vbbox)
901
1141
 
902
 
        hbox.pack_start(scroll, True, True)
 
1142
        self.notebook = gtk.Notebook()
 
1143
        self.notebook.set_show_tabs(True)
 
1144
        
 
1145
        for view in self.iconViews:
 
1146
            self.notebook.append_page(view, view.label)
 
1147
            view.iconview.connect("selection-changed",\
 
1148
                                self.onSelectionChanged, b_accept)
 
1149
        self.notebook.connect("switch-page", self._on_tab_changed, b_accept)
 
1150
 
 
1151
        #close dialog at logout
 
1152
        self.controller.msn.connect('user-disconnected', self._on_close)
 
1153
        self.controller.msn.connect('connection-problem', self._on_close)
 
1154
        self.controller.msn.connect('connection-closed', self._on_close)
 
1155
        self.controller.msn.connect('disconnected', self._on_close)
 
1156
        self.controller.mainWindow.menu.disconnectItem.connect(\
 
1157
                                    'button-release-event', self._on_close)
 
1158
        if self.controller.trayIcon != None and \
 
1159
           self.controller.trayDisconnect != None:
 
1160
            self.controller.trayDisconnect.connect('activate', self._on_close)
 
1161
 
 
1162
        hbox.pack_start(self.notebook, True, True)
903
1163
        hbox.pack_start(side_vbox, False, False)
904
1164
 
905
1165
        vbox.pack_start(hbox, True, True)
908
1168
        vbox.show_all()
909
1169
        self.add(vbox)
910
1170
 
911
 
        self.fill()
912
1171
        self.set_current_picture(picture_path)
913
1172
 
 
1173
    def onSelectionChanged(self, iconView, accept_button):
 
1174
        selected = iconView.get_selected_items()
 
1175
        if len(selected) == 0:
 
1176
            accept_button.set_sensitive(False)
 
1177
        else:
 
1178
            accept_button.set_sensitive(True)
 
1179
        
 
1180
    def stop_and_clear(self):
 
1181
        for view in self.iconViews:
 
1182
            view.stop_and_clear()
 
1183
        # Force Garbage Collector to tidy objects
 
1184
        # see http://faq.pygtk.org/index.py?req=show&file=faq08.004.htp
 
1185
        gc.collect()
 
1186
 
 
1187
    def _on_tab_changed(self, notebook, page, page_num, b_accept):
 
1188
        view = self.iconViews[page_num]
 
1189
        if view.label.get_text() == _('System pictures'):
 
1190
            self.b_add.set_sensitive(False)
 
1191
            self.b_remove.set_sensitive(False)
 
1192
            self.b_remove_all.set_sensitive(False)
 
1193
        elif view.label.get_text() == _('Contact pictures'):
 
1194
            self.b_add.set_sensitive(False)
 
1195
            self.b_remove.set_sensitive(True)
 
1196
            self.b_remove_all.set_sensitive(True)
 
1197
        else:
 
1198
            self.b_add.set_sensitive(True)
 
1199
            self.b_remove.set_sensitive(True)
 
1200
            self.b_remove_all.set_sensitive(True)
 
1201
        self.onSelectionChanged(view.iconview, b_accept)
 
1202
 
914
1203
    def set_current_picture(self, path):
915
1204
        '''set the current picture on the frame'''
916
1205
        if os.path.exists(path):
922
1211
        iter = self.get_selected_iter()
923
1212
 
924
1213
        if iter:
925
 
            return self.model[iter]
 
1214
            view = self.iconViews[self.notebook.get_current_page()]
 
1215
            return view.model[iter]
926
1216
 
927
1217
        return None
928
1218
 
929
1219
    def get_selected_iter(self):
930
1220
        '''return the selected iter or None'''
931
 
        if len(self.view.get_selected_items()) > 0:
932
 
            item = self.view.get_selected_items()[0]
933
 
            return self.model.get_iter(item)
 
1221
        view = self.iconViews[self.notebook.get_current_page()]
 
1222
        if len(view.get_selected_items()) > 0:
 
1223
            item = view.get_selected_items()[0]
 
1224
            return view.model.get_iter(item)
934
1225
 
935
1226
        return None
936
1227
 
937
1228
    def get_iter_from_filename(self, path):
938
1229
        '''return the iter of a filename or None'''
939
 
        for row in self.model:
 
1230
        view = self.iconViews[self.notebook.get_current_page()]
 
1231
        for row in view.model:
940
1232
            (pixbuf, filename) = row
941
1233
 
942
1234
            if self.samefile(filename, path):
955
1247
           os.path.samefile(path1, path2)) or \
956
1248
           (path1.lower() == path2.lower()))
957
1249
 
958
 
    def fill(self):
959
 
        '''fill the IconView with avatars from the list of pictures'''
960
 
 
961
 
        for path in os.listdir(self.cache_path):
962
 
            if not os.path.splitext(path)[0].endswith('_thumb'):
963
 
                self.add_picture(os.path.join(self.cache_path, path))
964
 
 
965
 
    def is_in_view(self, filename):
966
 
        '''return True if filename already on the iconview'''
967
 
 
968
 
        if os.name == 'nt':
969
 
            # nt doesn't include os.path.samefile
970
 
            return False
971
 
 
972
 
        for (pixbuf, path) in self.model:
973
 
            if os.path.samefile(filename, path):
974
 
                return True
975
 
 
976
 
        return False
977
 
 
978
 
 
979
 
    def add_picture(self, path):
980
 
        '''Adds an avatar into the IconView'''
981
 
        try:
982
 
            if os.path.exists(path) and os.access(path, os.R_OK)\
983
 
                    and not self.is_in_view(path):
984
 
                pixbuf = gtk.gdk.pixbuf_new_from_file(path)
985
 
 
986
 
                self.model.append([pixbuf, path])
987
 
            else:
988
 
                print path, 'not readable'
989
 
        except gobject.GError:
990
 
            print 'image at %s could not be loaded'
991
 
            print gobject.GError
992
 
 
993
1250
    def remove(self, path):
994
1251
        '''remove the avatar in path'''
995
 
        del self.model[self.get_iter_from_filename(path)]
 
1252
        view = self.iconViews[self.notebook.get_current_page()]
 
1253
        del view.model[self.get_iter_from_filename(path)]
996
1254
        try:
997
1255
            os.remove(path)
 
1256
        except Exception, e:
 
1257
            print "could not remove", path
 
1258
            
 
1259
        try:
998
1260
            parts = os.path.splitext(path)
999
1261
            os.remove(parts[0] + "_thumb" + parts[1])
1000
1262
        except Exception, e:
1001
 
            print "could not remove", path
 
1263
            pass
1002
1264
 
1003
1265
    def remove_selected(self):
1004
1266
        '''Removes avatar from a TreeIter'''
1010
1272
 
1011
1273
    def remove_all(self):
1012
1274
        '''remove all the items on the view'''
1013
 
        for (pixbuf, path) in self.model:
 
1275
        view = self.iconViews[self.notebook.get_current_page()]
 
1276
        for (pixbuf, path) in view.model:
1014
1277
            self.remove(path)
1015
1278
 
1016
 
        self.model.clear()
1017
 
 
1018
 
    def _drag_data_received(self, treeview, context, x, y, selection, info,
1019
 
                             timestamp):
1020
 
        '''method called on an image dragged to the view'''
1021
 
        urls = selection.data.split('\n')
1022
 
        for url in urls:
1023
 
            path = url.replace('file://', '')
1024
 
            path = path.replace('\r', '')
1025
 
 
1026
 
            # the '\x00' value makes an error
1027
 
            path = path.replace(chr(0), '')
1028
 
 
1029
 
            # this seems to be an error on ntpath but we take care :S
1030
 
            try:
1031
 
                if os.path.exists(path):
1032
 
                    self.add_picture(path)
1033
 
            except TypeError, e:
1034
 
                error(_("Could not add picture:\n %s") % (str(e),))
1035
 
 
1036
 
    def _on_icon_activated(self, *args):
1037
 
        '''method called when a picture is double clicked'''
1038
 
        self._on_accept(None)
 
1279
        view.model.clear()
1039
1280
 
1040
1281
    def _on_add(self, button):
1041
1282
        '''called when the user select the add button'''
1042
1283
        def _on_image_selected(response, path):
1043
1284
            '''method called when an image is selected'''
1044
 
            if response == stock.ACCEPT:
 
1285
            if response == gtk.RESPONSE_ACCEPT:
1045
1286
                try:
1046
1287
                    av = Avatar.Avatar(self.controller, path, self.cache_path, resizeDialog=True)
1047
1288
                    filename = av.getImagePath()
1048
 
                    self.add_picture(av.getImagePath())
 
1289
                    view = self.iconViews[self.notebook.get_current_page()] 
 
1290
                    view.add_picture(av.getImagePath())
1049
1291
                except Exception, e:
1050
1292
                    error(str(e))
1051
1293
 
1052
 
        ImageChooser(paths.HOME_DIR, _on_image_selected).show()
 
1294
        ImageChooser(paths.HOME_DIR, _on_image_selected).run()
1053
1295
 
1054
1296
    def _on_remove(self, event):
1055
1297
        '''Removes the selected avatar'''
1088
1330
        self.hide()
1089
1331
        self.response_cb(stock.CLEAR, '')
1090
1332
 
1091
 
    def _on_close(self, window, event):
 
1333
    def _on_close(self, *args):
1092
1334
        '''called when the user click on close'''
1093
1335
        self.hide()
1094
1336
        self.response_cb(stock.CLOSE, '')
1098
1340
        if event.keyval == gtk.keysyms.Delete:
1099
1341
            self.remove_selected()
1100
1342
 
1101
 
class ImageChooser(gtk.Window):
 
1343
class ImageChooser(gtk.FileChooserDialog):
1102
1344
    '''a class to select images'''
1103
1345
 
1104
1346
    def __init__(self, path, response_cb):
1105
1347
        '''class constructor, path is the directory where the
1106
1348
        dialog opens'''
1107
 
        gtk.Window.__init__(self)
 
1349
        gtk.FileChooserDialog.__init__(self, _("Image Chooser"), \
 
1350
                    parent=None, action=gtk.FILE_CHOOSER_ACTION_OPEN)
1108
1351
 
1109
1352
        self.response_cb = response_cb
1110
1353
 
1111
 
        self.set_title(_("Image Chooser"))
1112
1354
        self.set_default_size(600, 400)
1113
1355
        self.set_border_width(4)
1114
1356
        self.set_position(gtk.WIN_POS_CENTER)
1115
 
        self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
1116
 
 
1117
 
        self.vbox = gtk.VBox(spacing=4)
1118
 
 
1119
 
        self.file_chooser = gtk.FileChooserWidget()
1120
 
        self.file_chooser.set_current_folder(path)
 
1357
 
 
1358
        self.vbox.set_spacing(4)
 
1359
 
 
1360
        self.set_current_folder(path)
1121
1361
 
1122
1362
        hbbox = gtk.HButtonBox()
1123
1363
        hbbox.set_spacing(4)
1129
1369
        b_accept.connect('clicked', self._on_accept)
1130
1370
        b_cancel.connect('clicked', self._on_cancel)
1131
1371
        self.connect('delete-event', self._on_close)
1132
 
        self.file_chooser.connect("file-activated",self._on_accept)
 
1372
        self.connect("file-activated",self._on_accept)
1133
1373
 
1134
1374
        hbbox.pack_start(b_cancel, False)
1135
1375
        hbbox.pack_start(b_accept, False)
1136
1376
 
1137
 
        vbox = gtk.VBox()
1138
 
        self.vbox.pack_start(self.file_chooser, True, True)
 
1377
        self.vbox.pack_end(hbbox, False)
1139
1378
 
1140
 
        vbox.add(self.vbox)
1141
 
        vbox.pack_start(hbbox, False)
1142
 
        self.add(vbox)
1143
 
        vbox.show_all()
 
1379
        self.show_all()
1144
1380
 
1145
1381
        self._add_filters()
1146
1382
        self._add_preview()
1179
1415
            filters.append(filter)
1180
1416
 
1181
1417
 
1182
 
        self.file_chooser.add_filter(all_files)
1183
 
        self.file_chooser.add_filter(all_images)
1184
 
        self.file_chooser.set_filter(all_images)
 
1418
        self.add_filter(all_files)
 
1419
        self.add_filter(all_images)
 
1420
        self.set_filter(all_images)
1185
1421
 
1186
1422
        for filter in filters:
1187
 
            self.file_chooser.add_filter(filter)
 
1423
            self.add_filter(filter)
1188
1424
 
1189
1425
    def _add_preview(self):
1190
1426
        '''
1195
1431
        self.image.set_size_request(128, 128)
1196
1432
        self.image.show()
1197
1433
 
1198
 
        self.file_chooser.set_preview_widget(self.image)
1199
 
        self.file_chooser.set_preview_widget_active(True)
 
1434
        self.set_preview_widget(self.image)
 
1435
        self.set_preview_widget_active(True)
1200
1436
 
1201
 
        self.file_chooser.connect('update-preview', self._on_update_preview)
 
1437
        self.connect('selection-changed', self._on_update_preview)
1202
1438
 
1203
1439
    def _on_accept(self, button):
1204
1440
        '''method called when the user clicks the button'''
1205
1441
        filename = get_filename(self)
1206
1442
        if os.path.isfile(filename):
1207
1443
            self.hide()
1208
 
            self.response_cb(stock.ACCEPT, filename)
 
1444
            self.response_cb(gtk.RESPONSE_ACCEPT, filename)
1209
1445
        else:
1210
1446
            error(_("No picture selected"))
1211
1447
 
1212
1448
    def _on_cancel(self, button):
1213
1449
        '''method called when the user clicks the button'''
1214
1450
        self.hide()
1215
 
        self.response_cb(stock.CANCEL, get_filename(self))
 
1451
        self.response_cb(gtk.RESPONSE_CANCEL, get_filename(self))
1216
1452
 
1217
1453
    def _on_close(self, window, event):
1218
1454
        '''called when the user click on close'''
1219
1455
        self.hide()
1220
 
        self.response_cb(stock.CLOSE, get_filename(self))
 
1456
        self.response_cb(gtk.RESPONSE_CLOSE, get_filename(self))
1221
1457
 
1222
1458
    def _on_update_preview(self, filechooser):
1223
1459
        '''
1256
1492
        self.response_cb = response_cb
1257
1493
 
1258
1494
        label = gtk.Label(_("Shortcut"))
1259
 
        self.shortcut = gtk.Entry()
 
1495
        self.shortcut = gtk.Entry(7)
1260
1496
        self.combo = gtk.combo_box_new_text()
1261
1497
 
1262
 
        tooltip_t = _("You can add an emoticon also by entering the url of a png/gif image.")
 
1498
        tooltip_t = _("You can add an emoticon also by entering the url an image (url must start with www. or http:// and finish with a file extension of the supported files).")
1263
1499
 
1264
1500
        labelurl = gtk.Label(_("Or enter an image url"))
1265
1501
        labelurl.set_tooltip_text(tooltip_t)
1300
1536
        size = self.combo.get_model().get_value(self.combo.get_active_iter(), 0)
1301
1537
 
1302
1538
        URL = self.url.get_text()
1303
 
        if URL[:4] == 'www.':
1304
 
                    URL = 'http://'+URL
1305
 
        ENDEXT = URL.endswith('.gif') or URL.endswith('.png')
 
1539
        if URL.startswith('www.'):
 
1540
            URL = 'http://'+URL
 
1541
 
 
1542
        ENDEXT = False
 
1543
        for format in gtk.gdk.pixbuf_get_formats():
 
1544
            for ext in format['extensions']:
 
1545
                ENDEXT = ENDEXT or URL.endswith('.'+ext)
 
1546
 
1306
1547
        if URL.startswith('http://') and ENDEXT == True:
1307
1548
            if not shortcut:
1308
1549
                error(_("Empty shortcut"))
1345
1586
 
1346
1587
def get_filename(self):
1347
1588
    '''Shortcut to get a properly-encoded filename from a file chooser'''
1348
 
    filename = self.file_chooser.get_filename()
 
1589
    filename = self.get_filename()
1349
1590
    if filename and gtk.gtk_version >= (2, 10, 0):
1350
1591
        return gobject.filename_display_name(filename)
1351
1592
    else:
1353
1594
 
1354
1595
def get_preview_filename(self):
1355
1596
    '''Shortcut to get a properly-encoded preview filename'''
1356
 
    filename = self.file_chooser.get_preview_filename()
 
1597
    filename = self.get_filename()
1357
1598
    if filename and gtk.gtk_version >= (2, 10, 0):
1358
1599
        return gobject.filename_display_name(filename)
1359
1600
    else: