Ejemplo n.º 1
0
 def launch_thread(self, on_complete, userData=None):        
     self.evtStop    = Event()
     self.taskQueue  = Queue()
     self.condition  = Condition(RLock())
     self.thimpra2   = None    
     self.thimpra    = ImpraThread(self.evtStop, self.taskQueue, self.condition, self.conf, 'impra-1')
     self.signalsDef = (('completed'    , on_complete),
                       ('interrupted'   , self.on_interrupted),
                       ('progress'      , self.on_progress),
                       ('fileadded'     , self.on_common_ending_action),
                       ('fileget'       , self.on_common_ending_action),
                       ('fileinfos'     , self.on_common_ending_action),
                       ('fileremoved'   , self.on_common_ending_action),
                       ('fileedited'    , self.on_common_ending_action),
                       ('fileaddretry'  , self.on_common_ending_action),
                       ('indexrefreshed', self.on_index_refresh),                          
                       ('hasaddretry'   , self.on_has_add_retry),
                       ('needconfig'    , self.on_need_config))
     self.thimpra.connect_signals(self.signalsDef, userData)
     self.thimpra.start()
Ejemplo n.º 2
0
class AppGui(Gui):

    start           = False
    poslog          = 0

    TASK_RUN        = False
    BAD_CONF        = False
    PENDING_ID      = 0

    @Log(Const.LOG_BUILD)
    def __init__(self, wname='window1'):
        """"""            
        super().__init__(wname)


    @Log(Const.LOG_UI)
    def on_start(self):
        """"""
        Sys.g.GUI_PRINT_STDOUT = False
        Sys.g.GUI              = True
        init(conf.PRG_NAME, False, Sys.getpid(), True, Const.LOG_ALL)
        self.conf        = ImpraConf(KiniFile('impra2.ini'))
        self.populate_profiles()
        self.populate_config()
        self.taskLabel     = ImpraThread.TASK_LABEL
        self.taskStock     = ImpraThread.TASK_STOCK
        self.progressbar   = self.get('progressbar1')
        self.textview      = self.get('textview1')
        try :
            self.textview.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 1.0))
            self.textview.modify_font(Pango.font_description_from_string ('DejaVu Sans Mono Book 11' if Sys.isUnix() else 'Lucida Conosle 11'))
        except :
            pass
        self.textbuffer    = self.textview.get_buffer()
        self.tags          = self.buildTxtTags(self.textbuffer)
        self.initWidgetByThread('impra-1', self.textview, self.textbuffer, self.progressbar, self.tags)
        self.initWidgetByThread('MainThread', self.textview, self.textbuffer, self.progressbar, self.tags)
        self.tree          = self.get('treeview1')
        self.tree.connect('row-activated', self.on_row_select)
        self.tree.get_selection().connect('changed', self.on_tree_selection_changed)
        self.launch_thread(self.on_ended)
        
        self.searchCatg    = self.get('comboboxtext1')
        self.searchUser    = self.get('comboboxtext4')
        self.searchAccount = self.get('comboboxtext5')
        self.filterIds     = None
        self.index         = None
        self.taskList      = {}
        self.threads_work  = [False, False]


    def on_ended(self, thread=None, ref=None):
        """""" 
        print('ended')

    
    def on_delete_event(self, data=None, data2=None):
        """"""
        print('on_delete_event')
        self.thimpra.stop()
        if self.thimpra2 is not None :
            self.thimpra2.stop()



    # ~~ INDEX ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Log(Const.LOG_UI)
    def on_tree_selection_changed(self, selection):
        """"""
        model, treeiter = selection.get_selected()
        hasSel = treeiter != None
        if hasSel :
            """"""
        self.unselect_actions(hasSel, True)
    

    @Log(Const.LOG_UI)
    def unselect_actions(self, sensible=False, exceptAdd=False):
        """"""
        self.get('button5').set_sensitive(sensible)
        self.get('button6').set_sensitive(sensible)
        if not exceptAdd : self.get('button12').set_sensitive(sensible)
        self.get('button7').set_sensitive(sensible)

    
    @Log(Const.LOG_UI)
    def build_treeview_column(self):
        """"""
        if self.tree.get_column(0)==None :            
            self.get('label5').set_label(' '+self.conf.get('user', 'imap',defaultValue=''))
            self.get('label7').set_label(' '+self.conf.get('uid', 'index',defaultValue=''))
            self.get('label9').set_label(' '+self.conf.get('box', 'imap',defaultValue=''))
            self.get('label10').set_label(' '+self.conf.get('date', 'index',defaultValue=''))
            #~ self.update_progress(10, 10)
            #~ self.progressbar.set_fraction(10/100.0)
            css      = [('#900000', 'white'), (None, '#82C59A'), (None, '#D4D4D4'), (None, '#D290C5'), (None, '#D87475'), (None, '#C58473'), (None, '#A7A2A2'), (None, '#EAD049'), (None, '#81AFDD')]
            for i, s in enumerate(ImpraIndex.COLS[:-1]):
                r  = Gtk.CellRendererText()
                
                #~ r.set_property('family', 'mono')
                r.set_property('size-set', True)
                r.set_property('size-points', 11)
                if css[i][0] is not None :
                    r.set_property('cell-background', css[i][0])
                if css[i][1] is not None :    
                    r.set_property('foreground', css[i][1])
                if i==0:
                    r.set_property('weight', 800)
                if i==1 or i==0 or i==3:
                    r.set_property('family', 'DejaVu Sans Mono')
                    #~ r.set_property('size-points', 10)
                if i==2:
                    r.set_property('width', 350)
                if i==6:
                    r.set_property('width', 90)
                if i==7:
                    r.set_property('width', 120)
                    """"""
                cl = Gtk.TreeViewColumn(s, r, text=i)
                cl.set_attributes(r, text=i, cell_background=ImpraIndex.ACCOUNT+1+(1 if i==0 else 0)) 
                cl.set_sort_column_id(i)
                cl.set_resizable(True)
                cl.connect('clicked', self.on_column_click)
                self.tree.append_column(cl)


    @Log(Const.LOG_UI)
    def populate_index(self):
        """"""
        self.BLOCK_REPOPULATE = False
        if self.index is None or self.index != self.thimpra.impst.idxu.index :
            self.index = self.thimpra.impst.idxu.index
        data     = sorted([(self.index.dic.get(k),k) for i, k in enumerate(self.index.dic) if not k.startswith(self.index.SEP_KEY_INTERN)], reverse=False, key=lambda lst:lst[0][self.index.UID])
        store    = self.get('treestore1')
        store.clear()
        drow     = None
        i        = 0
        tsize    = 0
        psize    = 0
        accounts = self.thimpra.impst.idxu.getAccountList()
        allCatg, allUsers, allAccounts, tmp = [], [], [ accounts[a] for a in accounts], ''
        for row, key in data :
            
            tsize += row[self.index.SIZE]
            if self.filterIds==None or row[self.index.UID] in self.filterIds:
            
                drow = list(row[:-1])
                psize += row[self.index.SIZE]

                if drow[self.index.CATG] not in allCatg :
                    allCatg.append(drow[self.index.CATG])
                tmp = self.index.getUser(drow[self.index.USER])                
                if tmp not in allUsers :
                    allUsers.append(tmp)
                drow[self.index.PARTS]     = ('%s' % drow[self.index.PARTS]).rjust(2,' ')
                drow[self.index.UID]       = ('%s' % drow[self.index.UID]).rjust(4,' ')
                drow[self.index.HASH]      = '%s' % drow[self.index.HASH][0:6]+'…'
                drow[self.index.SIZE]      = Sys.readableBytes(row[self.index.SIZE]).rjust(11,' ')+'  '
                drow[self.index.USER]      = self.index.getUser(drow[self.index.USER])
                drow[self.index.ACCOUNT]   = self.index.acclist[drow[self.index.ACCOUNT]]
                drow.append('#222222' if i%2!=0 else '#1C1C1C')
                drow.append('#640000' if i%2!=0 else '#900000')
                store.append(None, drow)
                i += 1
                self.progressbar.set_fraction(10+i*90/len(data)/100.0)
            
        # repopulate only if not search
        if self.filterIds==None :
            #~ Sys.pwlog([(' Populating search filters...', Const.CLZ_0, True)])
            self.populate_search_filters(allCatg, allUsers, allAccounts)
        
        self.get('checkbutton1').set_sensitive(True)
        
        self.get('label12').set_label(' '+(Sys.readableBytes(psize)+' / ' if psize != tsize else '')+Sys.readableBytes(tsize))
        
        self.get('button9').set_sensitive(True)
        self.get('button12').set_sensitive(True)
        return False


    # ~~ force redrawing odd/even tree rows ~~~~~~~
    
    @Log(Const.LOG_UI)
    def on_column_click(self, treeviewcolumn, user_param1=None):
        """"""
        for i, row in enumerate(self.tree.get_model()):
            row[self.index.ACCOUNT+1] = '#222222' if i%2!=0 else '#1C1C1C'
            row[self.index.ACCOUNT+2] = '#640000' if i%2!=0 else '#900000'


    @Log(Const.LOG_UI)
    def populate_search_filters(self, catgs=(), users=(), accounts=()):
        """"""        
        lst = ((Gtk.ListStore(str), sorted(catgs)   , '-- All categories --', self.searchCatg),
               (Gtk.ListStore(str), sorted(users)   , '-- All users --'     , self.searchUser),
               (Gtk.ListStore(str), sorted(accounts), '-- All accounts --'  , self.searchAccount))
        for data in lst :
            data[0].append([data[2]])
            for item in data[1]:
                data[0].append([item])
            data[3].set_model(data[0])
            data[3].set_active(0)

    
    # ~~ SEARCH ACTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    def on_search(self, btn, data=None):
        """"""
        self.get('entry16').set_sensitive(btn.get_active())
        self.get('comboboxtext1').set_sensitive(btn.get_active())
        self.get('comboboxtext4').set_sensitive(btn.get_active())
        self.get('comboboxtext5').set_sensitive(btn.get_active())
        self.get('button8').set_sensitive(btn.get_active())
        if not btn.get_active() :
            self.filterIds = None
            if not self.BLOCK_REPOPULATE :
                self.populate_index()


    def get_search_filter(self, comboName):
        """"""
        value = ''
        citer = self.get(comboName).get_active_iter()     
        if citer != None:
            model =  self.get(comboName).get_model()
            if model[citer][0] != model[model.get_iter_first()][0] :
                value = model[citer][0]
        return value

    
    def on_launch_search(self, btn, data=None):
        """"""
        self.on_search(self.get('checkbutton1'))
        slabel = self.get('entry16').get_text()
        scatg  = self.get_search_filter('comboboxtext1')
        suser  = self.get_search_filter('comboboxtext4')
        sacc   = self.get_search_filter('comboboxtext5')
        
        matchIdsAcc  = None
        matchIdsCatg = None
        matchIdsUser = None
        matchIdsCrit = None
        matchIds     = self.index.getByPattern(slabel)
        
        if sacc != '' :
            matchIdsAcc = []
            for k in self.index.acclist.keys():
                if self.index.acclist[k] == sacc :    
                    print('key : '+str(k)+' - sacc : '+str(sacc))
                    matchIdsAcc = self.index.getByAccount(k)
                    break        
            matchIds     = self.index.getIntersection(matchIds,matchIdsAcc)
            
        if   scatg != '' : matchIdsCatg = self.index.getByCategory(scatg)
        if   suser != '' : matchIdsUser = self.index.getByUser(suser)        
        if   scatg != '' : matchIdsCrit = self.index.getIntersection(matchIdsCatg,matchIdsUser) if suser != '' else matchIdsCatg           
        elif suser != '' : matchIdsCrit = matchIdsUser
        else             : matchIdsCrit = matchIds

        if matchIdsCrit is not None :
            self.filterIds = self.index.getIntersection(matchIds,matchIdsCrit)        
        
        self.populate_index()

        
    
    # ~~ ADD ACTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    @Log(Const.LOG_UI)
    def on_add_file(self, btn, data=None):
        """"""
        self.get('dialog1').show()


    @Log(Const.LOG_UI)
    def on_add_file_set(self, fc, data=None):
        """"""
        fname, ext = Sys.getFileExt( fc.get_filename())
        catg = self.index.getAutoCatg(ext)
        if (self.get('entry2').get_text() == '' or self.get('checkbutton2').get_active()) and catg!='none' :
            self.get('entry2').set_text(catg)


    @Log(Const.LOG_UI)
    def add_file(self, btn, data=None):
        """"""
        fileName = self.get('filechooserbutton1').get_filename()
        label    = self.get('entry1').get_text()
        category = self.get('entry2').get_text()
        btn.set_sensitive(False)
        self.on_cancel_add(btn)
        self.launch_action(ImpraThread.TASK_ADD, (fileName, label, category))


    @Log(Const.LOG_UI)
    def on_cancel_add(self, btn, data=None):
        """"""
        self.get('dialog1').hide()
        self.get('filechooserbutton1').set_filename('')
        self.get('entry1').set_text('')
        self.get('entry2').set_text('')
        btn.set_sensitive(True)

    
    # ~~ EDIT ACTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    # double-clic row
    @Log(Const.LOG_UI)
    def on_row_select(self, treeview, path, view_column, data=None):
        """"""
        store    = self.get('treestore1')
        treeiter = store.get_iter(path)
        self.editUid      = store.get_value(treeiter, self.index.UID)
        self.editKey      = self.index.getById(self.editUid)
        self.editLabel    = store.get_value(treeiter, self.index.LABEL)
        self.editCategory = store.get_value(treeiter, self.index.CATG)
        self.on_edit_file()


    @Log(Const.LOG_UI)
    def on_edit_file(self):
        """"""        
        self.get('label39').set_text(' Editing `'+self.editLabel+'` ('+str(self.editUid)+')')
        self.get('entry17').set_text(self.editLabel)
        self.get('entry18').set_text(self.editCategory)
        self.get('dialog2').show()

    
    @Log(Const.LOG_UI)
    def on_edit(self, btn, data=None):
        """"""
        label    = self.get('entry17').get_text()
        category = self.get('entry18').get_text()
        btn.set_sensitive(False)
        self.on_cancel_edit(btn)
        if label != self.editLabel or category != self.editCategory :
            self.launch_action(ImpraThread.TASK_EDIT, (self.editKey, label, category))


    @Log(Const.LOG_UI)
    def on_cancel_edit(self, btn, data=None):
        """"""
        self.get('dialog2').hide()
        self.get('entry17').set_text('')
        self.get('entry18').set_text('')
        btn.set_sensitive(True)


    def get_selected_uid(self):
        """"""
        model, treeiter = self.tree.get_selection().get_selected()
        return int(model[treeiter][0])
    
    # ~~ INFOS ACTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Log(Const.LOG_UI)
    def on_file_infos(self, btn, data=None):
        """"""        
        self.launch_action(ImpraThread.TASK_INFOS, self.get_selected_uid())

    
    # ~~ GET ACTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Log(Const.LOG_UI)
    def on_file_download(self, btn, data=None):
        """"""
        self.launch_action(ImpraThread.TASK_GET, self.get_selected_uid())


    # ~~ REMOVE ACTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Log(Const.LOG_UI)
    def on_file_delete(self, btn, data=None):
        """"""
        self.launch_action(ImpraThread.TASK_REMOVE, self.get_selected_uid())


    # ~~ REFRESH ACTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Log(Const.LOG_UI)
    def on_refresh(self, btn, data=None):
        """"""
        self.BLOCK_REPOPULATE = True
        self.get('treestore1').clear()
        if btn is not None :
            Sys.cli_emit_progress(0)
            self.get('checkbutton1').set_sensitive(False)
            self.get('checkbutton1').set_active(False)
            self.unselect_actions()
            self.get('button9').set_sensitive(False)
            self.launch_action(ImpraThread.TASK_REFRESH, [])
        else :
            self.populate_index()


    def on_remove_pending(self, btn, keyPending, execute=False, keepRetry=True):
        """"""
        print('on_remove_pending')
        if keyPending in self.taskList :
            action, params, keep = self.taskList[keyPending]
            print('keyPending : '+str(keyPending))
            print('execute : '+str(execute))
            print('keepRetry : '+str(keepRetry))
            print('action : '+str(action))
            print('params : '+str(params))
            print('keep : '+str(keep))
            if keep and keepRetry :
                pass
            else :
                self.taskList.pop(keyPending)
                self.get('box19').remove(btn)
                if len(self.taskList)==0:
                    self.get('paned1').set_position(5000)
                if execute :
                    self.launch_action(action, params)


    def populate_pending_task(self, action, params, execute=False):
        """"""
        print('populate_pending_task')
        self.get('paned1').set_position(1030)
        keyPending = 'pending-'+str(self.PENDING_ID)
        keep       = action==ImpraThread.TASK_ADD_RETRY
        self.taskList[keyPending] = (action, params, keep)
        w     = Gtk.Button(label='Pending task '+self.taskLabel[action], image=Gtk.Image(stock=self.taskStock[action]))
        w.set_tooltip_text('click to '+('execute' if keep else 'remove')+' task '+self.taskLabel[action]+('' if keep else ' ('+str(params)+')'))
        w.set_property('halign', Gtk.Align.START)
        w.connect('clicked', self.on_remove_pending, keyPending, execute, not keep)
        w.set_name(keyPending)        
        self.get('box19').pack_start(w, False, False, 1)
        w.show()
        #~ self.get('box19').show()


    def launch_action(self, action, params):
        """"""
        if not self.threads_work[0] :
            self.threads_work[0] = True            
            self.taskQueue.put_nowait((action, params, self.PENDING_ID))
            
        else:
            self.populate_pending_task(action, params)
            
        self.PENDING_ID += 1
            
            #~ self.do_pending_task()
            
            
            #~ self.threads_work[1] = True
            #~ print('task thread 2')
            #~ self.taskQueue.put_nowait((action, params))
            #~ if self.thimpra2 is None :
                #~ self.thimpra2  = ImpraThread(self.evtStop, self.taskQueue, self.condition, self.conf, 'impra-2')            
                #~ self.thimpra2.connect_signals(self.signalsDef, None)
                #~ self.thimpra2.start()

            #~ keyPending = 'pending-'+str(self.PENDING_ID)
            #~ ltask = ['wait','add','get','refresh','remove','infos','edit','exit']
            #~ self.taskList[keyPending] = (action, params)
            #~ w     = Gtk.Button(label='remove pending task '+ltask[action]+' ['+str(params)+']', image=Gtk.Image(stock=Gtk.STOCK_REMOVE))
            #~ w.connect('clicked', self.on_remove_pending, keyPending)
            #~ self.get('box19').pack_start(w, True, True, 5)
            #~ self.PENDING_ID += 1

        
    def do_pending_task(self):
        """"""
        print('do_pending_task')
        wlist = self.get('box19').get_children()
        if len(wlist)>0 :
            keyPending = wlist[0].get_name()
            self.on_remove_pending(wlist[0], keyPending, True)            

    




    # ~~ ACTIONS CALLBACK ~~~~~~~~~~~~~~~~~~~~~~~~~
    
    def on_has_add_retry(self, thread, usrData):
        """"""
        print('on_has_add_retry')
        self.populate_pending_task(ImpraThread.TASK_ADD_RETRY, None, True)        
        self.PENDING_ID += 1
    
    
    def on_common_ending_action(self, thread=None, done=None, key=None, usrData=None):
        """"""
        if thread.name == 'impra-1' :
            self.threads_work[0] = False
            self.do_pending_task()
        self.on_progress(thread)

    
    def on_need_config(self, thread=None, usrData=None):
        """"""
        self.BAD_CONF = True
        if thread.name == 'impra-1' :
            self.threads_work[0] = False
            self.do_pending_task()
        self.get('notebook1').set_current_page(1)
        self.get('label42').set_text('Something is wrong in your configuration')


    def on_index_refresh(self, thread=None, ref=None, updated=None, usrData=None):
        """"""
        self.on_common_ending_action(thread)
        if self.tree.get_column(0) == None :
            self.build_treeview_column()
        self.on_refresh(None)
        

    # ~~ IMPRA THREAD ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Log(Const.LOG_UI)
    def launch_thread(self, on_complete, userData=None):        
        self.evtStop    = Event()
        self.taskQueue  = Queue()
        self.condition  = Condition(RLock())
        self.thimpra2   = None    
        self.thimpra    = ImpraThread(self.evtStop, self.taskQueue, self.condition, self.conf, 'impra-1')
        self.signalsDef = (('completed'    , on_complete),
                          ('interrupted'   , self.on_interrupted),
                          ('progress'      , self.on_progress),
                          ('fileadded'     , self.on_common_ending_action),
                          ('fileget'       , self.on_common_ending_action),
                          ('fileinfos'     , self.on_common_ending_action),
                          ('fileremoved'   , self.on_common_ending_action),
                          ('fileedited'    , self.on_common_ending_action),
                          ('fileaddretry'  , self.on_common_ending_action),
                          ('indexrefreshed', self.on_index_refresh),                          
                          ('hasaddretry'   , self.on_has_add_retry),
                          ('needconfig'    , self.on_need_config))
        self.thimpra.connect_signals(self.signalsDef, userData)
        self.thimpra.start()


    # ~~ CONFIG PAGE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    def populate_profiles(self):
        """"""
        l = Gtk.ListStore(str)
        l.append(['current profile'])
        sections = sorted(self.conf.ini.getSections())
        if len(sections) > 0:
            ap  = self.conf.ini.get('profile')
            sep = ''
            for p in sections:
                if p != ap and p != '':
                    l.append([p])
        self.get('comboboxtext3').set_model(l)
        self.get('comboboxtext3').set_active(0)


    def on_profile_change(self, combo, data=None):
        """"""
        citer = combo.get_active_iter()     
        if citer != None:
            model   = combo.get_model()
            profile = model[citer][0]
            if profile == 'current profile' :
                profile = None
            self.populate_config(profile)

    
    def on_gen_new_key(self, btn, data=None):
        """"""
        kg = KeyGen(int(self.get('spinbutton1').get_value()))
        self.get('entry14').set_text(kg.key)
        self.get('entry15').set_text(kg.mark)
        # 18


    def on_delete_profile(self, btn, data=None):
        """"""
        p = self.get('entry3').get_text()
        if p != self.conf.profile :
            self.conf.remProfile(p)
        else :
            """"""
            print('is current')
        model = self.get('comboboxtext3').get_model()
        citer = self.get('comboboxtext3').get_active_iter()
        del(model[citer])
        self.get('comboboxtext3').set_active(0)
        # 17


    def on_edit_new_profile(self, btn, data=None):
        """"""
        self.populate_config('new')
        self.get('spinbutton1').set_sensitive(True)
        self.get('spinbutton2').set_sensitive(True)
        self.get('button18').set_sensitive(True)


    def on_hide_pwd(self, btn, data=None):
        """"""
        self.get('entry12').set_visibility(not btn.get_active())
        self.get('entry13').set_visibility(not btn.get_active())


    @Log(Const.LOG_UI)
    def populate_config(self, p=None):
        """"""
        self.get('button18').set_sensitive(False)
        profile = self.conf.profile if p is None else p
        self.get('label41').set_label('')
        self.get('label42').set_label('')
        self.get('label2').set_label('')
        self.get('entry3').set_text(profile)
        
        self.get('entry4').set_text(self.conf.get('name', 'infos', profile,''))
        self.get('entry5').set_text(self.conf.get('host', 'imap', profile,''))
        self.get('entry6').set_text(self.conf.get('port', 'imap', profile,''))
        self.get('entry7').set_text(self.conf.get('user', 'imap', profile,''))
        self.get('entry13').set_text(self.conf.get('pass', 'imap', profile,''))

        m = self.getMultiAccount()

        l = Gtk.ListStore(str)
        l.append(['*new'])
        for a in m:l.append([a])
        self.get('comboboxtext2').set_model(l)
        self.get('comboboxtext2').set_active(0)

        self.get('entry8').set_text('')
        self.get('entry9').set_text('')
        self.get('entry10').set_text('')
        self.get('entry11').set_text('')
        self.get('entry12').set_text('')

        key = self.conf.get('key', 'keys', profile,'')
        hasKey = key != ''
        self.get('entry14').set_text(key)
        self.get('entry14').set_sensitive(False)
        self.get('entry15').set_text(self.conf.get('mark', 'keys', profile,''))
        self.get('entry15').set_sensitive(False)
        self.get('spinbutton1').set_value(len(key))
        self.get('spinbutton1').set_sensitive(p is not None or self.BAD_CONF)
        self.get('spinbutton2').set_value(128)
        self.get('spinbutton2').set_sensitive(p is not None or self.BAD_CONF)
        self.get('button18').set_sensitive(p is not None or self.BAD_CONF)
        self.get('button17').set_sensitive(p is not None or self.BAD_CONF)
        
    
    def getMultiAccount(self):
        """"""
        if self.conf.ini.has('multi' , self.conf.profile+'.imap'):
            m = self.conf.ini.get('multi', self.conf.profile+'.imap')
        else : m = None
        if m is None : m = []
        else : m = m.split(',')
        m = [x for x in m if x]
        return sorted(m)
        
        
    def on_add_multiaccount(self, btn, data=None):
        """"""
        profile = self.get('entry8').get_text()
        if profile != '' :
            m = self.getMultiAccount()
            if profile is not None and profile is not '' :
                canAdd = self.on_test_account(None)
                if canAdd :
                    if profile not in m :
                        m.append(profile)
                    
                    self.conf.ini.set('multi', ','.join(m), self.conf.profile+'.imap')        
                    self.conf.ini.set('host' , self.get('entry9').get_text()   , profile+'.imap')
                    self.conf.ini.set('user' , self.get('entry11').get_text()  , profile+'.imap')
                    self.conf.ini.set('pass' , self.get('entry12').get_text()  , profile+'.imap')
                    self.conf.ini.set('port' , self.get('entry10').get_text()  , profile+'.imap')            
                    self.conf.ini.save()
                    self.conf.ini.print(profile)
                    self.get('entry9').set_text('')
                    self.get('entry10').set_text('')
                    self.get('entry11').set_text('')
                    self.get('entry12').set_text('')
                    self.populate_config()
                
                else :
                    self.get('label2').set_label('can\'t add : '+self.get('label2').get_label())
        else :
            self.get('label2').show()
            self.get('label2').set_label('need an account name')


    def test_imap(self, names):
        """"""
        self.get(names[4]).set_label('testing...')        
        conf = ImapConfig(self.get(names[0]).get_text(), self.get(names[1]).get_text(), self.get(names[2]).get_text(), self.get(names[3]).get_text())
        done = False
        if not ((conf.host != '' and conf.host is not None) and (conf.user != '' and conf.user is not None) and (conf.port != '' and conf.port is not None) and (conf.pwd != '' and conf.pwd is not None)):
            msg = 'nodata'
        else :
            print('test_imap')
            try :
                msg  = ''     
                ih   = ImapHelper(conf, 'INBOX', True)
                done = True
            except Exception as e:
                msg = e.__name__                
                print(e)

        self.get(names[4]).set_label('test ok' if done else 'test failed ! ['+msg+']')
        self.get(names[4]).show()
        return done


    def on_test_main_imap(self, btn, data=None):
        """"""
        return self.test_imap(('entry5', 'entry7', 'entry13', 'entry6', 'label41'))


    def on_test_account(self, btn, data=None):
        """"""
        return self.test_imap(('entry9', 'entry11', 'entry12', 'entry10', 'label2'))        
        
    
    def on_multiaccount_change(self, combo, data=None):
        """"""
        citer = combo.get_active_iter()
        self.get('button15').set_sensitive(True)    
        if citer != None:
            model   = combo.get_model()
            account = model[citer][0]
            self.get('entry8').set_text('')
            self.get('label2').set_label('')
            if account == '*new' :
                self.get('button2').set_label('add account')
                self.get('button4').set_sensitive(False)
            if account is not None and account is not '' and account != '*new':
                self.get('button2').set_label('edit account')
                self.get('button4').set_sensitive(True)
                self.get('entry8').set_text(account)
                self.get('entry9').set_text(self.conf.get('host', 'imap', account,''))
                self.get('entry10').set_text(self.conf.get('port', 'imap', account,''))
                self.get('entry11').set_text(self.conf.get('user', 'imap', account,''))
                self.get('entry12').set_text(self.conf.get('pass', 'imap', account,''))
        
    
    def on_remove_multiaccount(self, btn, data=None):
        """"""
        m = self.getMultiAccount()
        profile = self.get('entry8').get_text()        
        citer = self.get('comboboxtext2').get_active_iter()
        if citer != None:
            model =self.get('comboboxtext2').get_model()
            account = model[citer][0]
        
        #~ if profile != account
        if account in m :
            m.remove(account)
            self.conf.remProfile(account)
            self.conf.ini.set('multi', ','.join(m), self.conf.profile+'.imap') 
        self.populate_config()
        
        
    def on_save_profile(self, btn, data=None):
        """"""
        profile = self.get('entry3').get_text()
        if profile != '' :
            usr = self.get('entry4').get_text()
            if usr != '' :
                canSave = self.on_test_main_imap(None)
                if canSave :
                    if not(self.get('entry14').get_text() != '' and self.get('entry15').get_text()!= '') :
                        self.on_gen_new_key(None)

                    self.get('spinbutton1').set_sensitive(False)
                    self.get('spinbutton2').set_sensitive(False)

                    self.conf.ini.set('name', usr                           , profile+'.infos')
                    
                    self.conf.ini.set('key' , self.get('entry14').get_text(), profile+'.keys')
                    self.conf.ini.set('mark', self.get('entry15').get_text(), profile+'.keys')
                    self.conf.ini.set('salt', '-¤-ImpraStorage-¤-'          , profile+'.keys')

                    self.conf.ini.set('host', self.get('entry5').get_text() , profile+'.imap')
                    self.conf.ini.set('user', self.get('entry7').get_text() , profile+'.imap')
                    self.conf.ini.set('pass', self.get('entry13').get_text(), profile+'.imap')
                    self.conf.ini.set('port', self.get('entry6').get_text() , profile+'.imap')
                    self.conf.ini.set('box' , '__impra2__'                  , profile+'.imap')

                    self.conf.ini.set('profile', profile, 'main')
                    self.conf.ini.print(profile)
                    self.conf.ini.print('main')

                    self.conf.ini.save()
                    if self.BAD_CONF :
                        self.BAD_CONF = False
                    self.on_delete_event()    
                    self.launch_thread(self.on_ended)
                else :
                    self.get('label42').set_label('can\'t save : '+self.get('label41').get_label())
            
            else :
                self.get('label42').set_label('user name is empty')
            
        else :
            self.get('label42').set_label('profile name is empty')