class SelectGame(tkSimpleDialog.Dialog, object): """Server settings window class.""" def __init__(self, *args, **kwargs): """Initiates SelectGame instance with additional attributes. :param args: positional arguments - positional arguments passed to parent __init__ method :param kwargs: keyword arguments - keyword arguments passed to parent __init__ method """ self.select_game, self.num_players, self.num_turns = None, None, None super(SelectGame, self).__init__(*args, **kwargs) def body(self, master): """Creates select game window. :param master: instance - master widget instance :return: Entry instance """ self.resizable(False, False) Label(master, text='Type in new game title or select existing one').grid(row=0, columnspan=2) Label(master, text='Select game:').grid(row=1, sticky='W') Label(master, text='Number of players:').grid(row=2, sticky='W') Label(master, text='Game duration:').grid(row=3, sticky='W') self.select_game = Combobox(master) self.select_game.bind('<Button-1>', self.refresh_games) self.select_game.grid(row=1, column=1, sticky='W') self.num_players = Entry(master) self.num_players.insert(END, self.parent.num_players if self.parent.num_players else '') self.num_players.grid(row=2, column=1, sticky='W') self.num_turns = Entry(master) self.num_turns.insert(END, self.parent.num_turns if self.parent.num_turns else '') self.num_turns.grid(row=3, column=1, sticky='W') return self.select_game def apply(self): """Assigns entered values to parent game and num_players attributes.""" self.parent.game = self.select_game.get() if self.select_game.get() != '' else None if self.parent.game not in self.parent.available_games: self.parent.num_players = int(self.num_players.get()) if self.num_players.get().isdigit() else None self.parent.num_turns = int(self.num_turns.get()) if self.num_turns.get().isdigit() else None def refresh_games(self, _): """Refreshes games list.""" self.select_game.configure(values=self.parent.available_games)
class SolinetteGUI(Tk): def __init__(self): # basics settings Tk.__init__(self) # constructor of parent graphic class self.title(u'Solinette: geolocalizar direcciones en Lima y Callo') self.iconbitmap('icone_Solinette.ico') self.resizable(width = False, height = False) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) # Frames self.FrPath = LabelFrame(self, name ='primero', text = u'1: las direcciones para geolocalizar', padx = 5, pady = 5) self.FrAttr = LabelFrame(self, name ='segundo', text = u'2: columnas indispensables', padx = 5, pady = 5) self.FrConn = LabelFrame(self, name ='tercero', text = u'3: parámetros de conexión a la base de datos', padx=5, pady=5) # Variables inutile = ['Esperando que se elige el archivo Excel'] self.typcols = [] self.host = StringVar() self.port = IntVar() self.dbnb = StringVar() self.usua = StringVar() self.mdpa = StringVar() self.ok = 0 self.dico_cols = OD() self.dico_vals = OD() self.dico_param = {} ## Frame 1 # target folder labtarg = Label(self.FrPath, text = u'Archivo Excel (.xls): ') self.target = Entry(self.FrPath, width = 35) self.browsetarg = Button(self.FrPath, text = 'Explorar', command = self.setpathtarg) # widgets placement labtarg.grid(row = 1, column = 1, columnspan = 1, sticky = N+S+W+E, padx = 2, pady = 2) self.target.grid(row = 1, column = 2, columnspan = 1, sticky = N+S+W+E, padx = 2, pady = 2) self.browsetarg.grid(row = 1, column = 3, columnspan = 1, sticky = N+S+W+E, padx = 2, pady = 2) ## Frame 2 # Drop-down lists of columns labdir = Label(self.FrAttr, text = u'Columna dirección: ') self.ddl_dir = Combobox(self.FrAttr, values = inutile) labdis = Label(self.FrAttr, text = u'Columna distrito: ') self.ddl_dis = Combobox(self.FrAttr, values = inutile) # nombre de la tabla en PostgreSQL labtabl = Label(self.FrAttr, text = u'Nombre de la tabla: ') self.tabl = Entry(self.FrAttr, width = 35) # widgets placement labdir.grid(row = 1, column = 1, sticky = N+S+W, padx = 2, pady = 2) self.ddl_dir.grid(row = 1, column = 2, sticky = N+S+W+E, padx = 2, pady = 2) labdis.grid(row = 2, column = 1, sticky = N+S+W, padx = 2, pady = 2) self.ddl_dis.grid(row = 2, column = 2, sticky = N+S+W+E, padx = 2, pady = 2) labtabl.grid(row = 3, column = 1, sticky = N+S+W, padx = 2, pady = 2) self.tabl.grid(row = 3, column = 2, sticky = N+S+W+E, padx = 2, pady = 2) ## Frame 3 # Etiquetas Label(self.FrConn, text = u'Host: ').grid(row = 1, column = 1, padx = 2, pady = 2, sticky = N+S+W) Label(self.FrConn, text = u'Puerto: ').grid(row = 2, column = 1, padx = 2, pady = 2, sticky = N+S+W) Label(self.FrConn, text = u'Base de datos: ').grid(row = 3, column = 1, padx = 2, pady = 2, sticky = N+S+W) Label(self.FrConn, text = u'Usuario: ').grid(row = 4, column = 1, padx = 2, pady = 2, sticky = N+S+W) Label(self.FrConn, text = u'Contraseña: ').grid(row = 5, column = 1, padx = 2, pady = 2, sticky = N+S+W) # Formulario self.H = Entry(self.FrConn, textvariable = self.host) self.P = Entry(self.FrConn, textvariable = self.port) self.D = Entry(self.FrConn, textvariable = self.dbnb) self.U = Entry(self.FrConn, textvariable = self.usua) self.M = Entry(self.FrConn, textvariable = self.mdpa, show='*') # pre relleno self.host.set('localhost') self.port.set('5432') self.usua.set('postgres') self.mdpa.set('') self.dbnb.set('solinette') # widgets placement self.H.grid(row = 1, column = 2, padx = 3, pady = 5, sticky = N+S+W+E) self.P.grid(row = 2, column = 2, padx = 3, pady = 5, sticky = N+S+W+E) self.D.grid(row = 3, column = 2, padx = 3, pady = 5, sticky = N+S+W+E) self.U.grid(row = 4, column = 2, padx = 3, pady = 5, sticky = N+S+W+E) self.M.grid(row = 5, column = 2, padx = 3, pady = 5, sticky = N+S+W+E) ## Global frame # Hola Label(self, text = '¡Hola! ' + env.get(u'USERNAME')).grid(row = 0, column = 0, columnspan = 2, sticky = W+E, padx = 2, pady = 5) # Imagen self.icone = PhotoImage(file = r'sources/logo_Solinette.GIF') Label(self, borderwidth = 2, relief = 'ridge', image = self.icone).grid(row = 1, rowspan = 4, column = 0, padx = 1, pady = 1, sticky = W) # Basic buttons self.val = Button(self, text = u'Probar la conexión', relief= 'raised', command = self.process, state = DISABLED) can = Button(self, text = 'Cancel (quit)', relief= 'groove', command = self.quit) # widgets placement self.FrPath.grid(row = 2, column = 1, sticky = N+S+W+E, padx = 2, pady = 2) self.val.grid(row = 5, column = 1, columnspan = 2, sticky = N+S+W+E, padx = 2, pady = 5) can.grid(row = 5, column = 0, sticky = N+S+W+E, padx = 2, pady = 5) def setpathtarg(self): """ ...browse and insert the path of target folder """ self.xls = askopenfilename(parent = self, title = u'Seleccionar el archivo Excel', filetypes = (("Archivos Excel (2003)", "*.xls"), ("All files", "*.*")), initialdir = '../sources') if path.splitext(self.xls)[1] == '.xls': hoy = '_' + strftime('%y%m%d', localtime()) self.target.insert(0, self.xls) self.licolumns() self.browsetarg.config(state=DISABLED) self.target.config(state=DISABLED) self.FrAttr.grid(row = 3, column = 1, sticky = N+S+W+E, padx = 2, pady = 2) self.FrConn.grid(row = 4, column = 1, sticky = N+S+W+E, padx = 2, pady = 2) self.tabl.insert(0, path.basename(self.xls).split('.')[0] + hoy) self.val.config(state = ACTIVE) # end of function return self.xls def licolumns(self): u""" litsing columns names and types from Excel file """ book = xlrd.open_workbook(self.target.get()) # lectura del archivo if book.nsheets > 1: print book.sheets() ish = 0 sheet = book.sheet_by_index(ish) # ouverture de la feuille 1 # names of columns (first row/line) cols = sheet.row_values(0) self.ddl_dir['values'] = cols self.ddl_dis['values'] = cols self.ddl_dir.current(1) self.ddl_dis.current(2) # types of columns self.typcols = list(sheet.row_types(1)) # add universal ID to list of columns self.dico_cols['SOL_IDU'] = 9 # loop on names and types of columns for i in range(len(cols)): self.dico_cols[cols[i]] = self.typcols[i] # End of function return book, self.typcols, self.dico_cols, self.ddl_dir, self.ddl_dis def check_campos(self): u""" Verifica que los campos del formulario son bien rellenos """ # conteo y mensaje de los errores err = 0 msj = u'Rellenar todos los campos' # checkeo de los campos vacios if self.host.get() == u'': self.H.configure(background = 'red') err = err +1 if self.port.get() == 0: self.P.configure(background = 'red') err = err +1 if self.dbnb.get() == u'': self.D.configure(background = 'red') err = err +1 if self.usua.get() == u'': self.U.configure(background = 'red') err = err +1 if self.mdpa.get() == u'': self.M.configure(background = 'red') err = err +1 if self.tabl.get() == u'': self.tabl.configure(background = 'red') err = err +1 if self.ddl_dir.get() == u'': self.ddl_dir.configure(background = 'red') err = err +1 if self.ddl_dis.get() == u'': self.ddl_dis.configure(background = 'red') err = err +1 # se colunas direcciones y distrito son diferentes if self.ddl_dir.get() == self.ddl_dis.get(): msj = msj + u'\nLas dos columnas no deben ser iguales' err = err +1 # Acción según si hay error(es) o no if err != 0: showerror(title = u'Error: campo(s) vacío(s)', message = msj) # End of function return err def testconnexion(self): u""" testing connection settings """ try: conn = pg.connect(host = self.host.get(), dbname = self.dbnb.get(), port = self.port.get(), user = self.usua.get(), password = self.mdpa.get()) curs = conn.cursor() # check PostgreSQL and PostGIS versions try: curs.execute('SELECT version()') ver = curs.fetchone() print ver except DatabaseError, e: showerror(title = u'Prueba de conexión ', message = 'Prueba de conexión fracasó. Mensaje de error:\n' + str(e)) return # check if destination table already exists query = "select table_name from information_schema.tables where 'sql_identifier' LIKE 'public'" #% (self.tabl.get()) curs.execute(query) li_tablas = curs.fetchall() print 'elle existe déjà connard : ', li_tablas # información al usuario self.val.config(text='¡D A L E!') showinfo(title = u'Prueba de conexión ', message = u'Prueba de conexión terminó con éxito') self.ok = 1 # clausura de la conexión conn.close() except pg.OperationalError, e: showerror(title = u'Prueba de conexión ', message = 'Prueba de conexión fracasó. Mensaje de error:\n' + str(e)) return
class MainFrame(Frame): def __init__(self,parent,stdoutq): Frame.__init__(self,parent) self.parent=parent self.width=700 self.height=400 self.title='Menotexport v1.0' self.stdoutq=stdoutq self.initUI() self.hasdb=False self.hasout=False self.hasaction=False self.exit=False self.path_frame=self.addPathFrame() self.action_frame=self.addActionFrame() self.message_frame=self.addMessageFrame() self.printStr() self.stateq=Queue.Queue() #self.workproc=Pool(1) def centerWindow(self): sw=self.parent.winfo_screenwidth() sh=self.parent.winfo_screenheight() x=(sw-self.width)/2 y=(sh-self.height)/2 self.parent.geometry('%dx%d+%d+%d' \ %(self.width,self.height,x,y)) def initUI(self): self.parent.title(self.title) self.style=Style() #Choose from default, clam, alt, classic self.style.theme_use('alt') self.pack(fill=tk.BOTH,expand=True) self.centerWindow() def printStr(self): while self.stdoutq.qsize() and self.exit==False: try: msg=self.stdoutq.get() self.text.update() self.text.insert(tk.END,'# '+msg) self.text.see(tk.END) except Queue.Empty: pass self.after(100,self.printStr) def checkReady(self): if self.isexport.get()==1 or self.ishighlight.get()==1\ or self.isnote.get()==1: self.hasaction=True else: self.hasaction=False if self.hasdb and self.hasout and self.hasaction: self.start_button.configure(state=tk.NORMAL) print('Menotexport Ready.') else: self.start_button.configure(state=tk.DISABLED) def addPathFrame(self): frame=Frame(self) frame.pack(fill=tk.X,expand=0,side=tk.TOP,padx=8,pady=5) frame.columnconfigure(1,weight=1) #------------------Database file------------------ label=tk.Label(frame,text='Mendeley Data file:',\ bg='#bbb') label.grid(row=0,column=0,\ sticky=tk.W,padx=8) self.db_entry=tk.Entry(frame) self.db_entry.grid(row=0,column=1,sticky=tk.W+tk.E,padx=8) self.db_button=tk.Button(frame,text='Open',command=self.openFile) self.db_button.grid(row=0,column=2,padx=8,sticky=tk.E) hint=''' Default location on Linux: ~/.local/share/data/Mendeley\ Ltd./Mendeley\ Desktop/[email protected] Default location on Windows: C:\Users\Your_name\AppData\Local\Mendeley Ltd\Mendeley Desktop\[email protected]''' hint_label=tk.Label(frame,text=hint,\ justify=tk.LEFT,anchor=tk.NW) hint_label.grid(row=1,column=0,columnspan=3,\ sticky=tk.W,padx=8) #--------------------Output dir-------------------- label2=tk.Label(frame,text='Output folder:',\ bg='#bbb') label2.grid(row=2,column=0,\ sticky=tk.W,padx=8) self.out_entry=tk.Entry(frame) self.out_entry.grid(row=2,column=1,sticky=tk.W+tk.E,padx=8) self.out_button=tk.Button(frame,text='Choose',command=self.openDir) self.out_button.grid(row=2,column=2,padx=8,sticky=tk.E) def openDir(self): self.out_entry.delete(0,tk.END) dirname=askdirectory() self.out_entry.insert(tk.END,dirname) if len(dirname)>0: print('Output folder: %s' %dirname) self.hasout=True self.checkReady() def openFile(self): self.db_entry.delete(0,tk.END) ftypes=[('sqlite files','*.sqlite'),('ALl files','*')] filename=askopenfilename(filetypes=ftypes) self.db_entry.insert(tk.END,filename) if len(filename)>0: print('Database file: %s' %filename) self.probeFolders() def probeFolders(self): dbfile=self.db_entry.get() try: db=sqlite3.connect(dbfile) query=\ '''SELECT Documents.title, DocumentFolders.folderid, Folders.name FROM Documents LEFT JOIN DocumentFolders ON Documents.id=DocumentFolders.documentId LEFT JOIN Folders ON Folders.id=DocumentFolders.folderid ''' ret=db.execute(query) data=ret.fetchall() df=pd.DataFrame(data=data,columns=['title',\ 'folerid','name']) fetchField=lambda x, f: x[f].unique().tolist() folders=fetchField(df,'name') folders.sort() folders.remove(None) self.menfolderlist=['All',]+folders self.foldersmenu['values']=tuple(self.menfolderlist) self.foldersmenu.current(0) db.close() self.hasdb=True self.checkReady() except Exception as e: print('Failed to recoganize the given database file.') print(e) def addActionFrame(self): frame=Frame(self,relief=tk.RAISED,borderwidth=1) frame.pack(fill=tk.X,side=tk.TOP,\ expand=0,padx=8,pady=5) label=tk.Label(frame,text='Actions:',bg='#bbb') label.grid(row=0,column=0,sticky=tk.W,padx=8) #---------------Action checkbuttons--------------- self.isexport=tk.IntVar() self.ishighlight=tk.IntVar() self.isnote=tk.IntVar() self.isseparate=tk.IntVar() self.check_export=tk.Checkbutton(frame,text='Export PDFs',\ variable=self.isexport,command=self.doExport) self.check_highlight=tk.Checkbutton(frame,\ text='Extract highlights',\ variable=self.ishighlight,command=self.doHighlight) self.check_note=tk.Checkbutton(frame,\ text='Extract notes',\ variable=self.isnote,command=self.doNote) self.check_separate=tk.Checkbutton(frame,\ text='Save separately',\ variable=self.isseparate,command=self.doSeparate,\ state=tk.DISABLED) frame.columnconfigure(0,weight=1) self.check_export.grid(row=0,column=1,padx=8,sticky=tk.W) self.check_highlight.grid(row=0,column=2,padx=8,sticky=tk.W) self.check_note.grid(row=0,column=3,padx=8,sticky=tk.W) self.check_separate.grid(row=0,column=4,padx=8,sticky=tk.W) #---------------------2nd row--------------------- subframe=Frame(frame) subframe.grid(row=1,column=0,columnspan=5,sticky=tk.W+tk.E,\ pady=5) #-------------------Folder options------------------- folderlabel=tk.Label(subframe,text='Mendeley folder:',\ bg='#bbb') folderlabel.pack(side=tk.LEFT, padx=8) self.menfolder=tk.StringVar() self.menfolderlist=['All',] self.foldersmenu=Combobox(subframe,textvariable=\ self.menfolder,values=self.menfolderlist,state='readonly') self.foldersmenu.current(0) self.foldersmenu.bind('<<ComboboxSelected>>',self.setfolder) self.foldersmenu.pack(side=tk.LEFT,padx=8) #-------------------Quit button------------------- quit_button=tk.Button(subframe,text='Quit',\ command=self.quit) quit_button.pack(side=tk.RIGHT,padx=8) #-------------------Stop button------------------- ''' self.stop_button=tk.Button(subframe,text='Stop',\ command=self.stop) self.stop_button.pack(side=tk.RIGHT,padx=8) ''' #-------------------Start button------------------- self.start_button=tk.Button(subframe,text='Start',\ command=self.start,state=tk.DISABLED) self.start_button.pack(side=tk.RIGHT,pady=8) #-------------------Help button------------------- self.help_button=tk.Button(subframe,text='Help',\ command=self.showHelp) self.help_button.pack(side=tk.RIGHT,padx=8) def setfolder(self,x): self.foldersmenu.selection_clear() self.menfolder=self.foldersmenu.get() self.foldersmenu.set(self.menfolder) if self.menfolder=='All': print('Work on all folders.') else: print('Select Mendeley folder: '+str(self.menfolder)) def doExport(self): if self.isexport.get()==1: print('Export annotated PDFs.') else: print('Dont export annotated PDFs.') self.checkReady() def doHighlight(self): if self.ishighlight.get()==1: print('Extract highlighted texts.') self.check_separate.configure(state=tk.NORMAL) else: print('Dont extract highlighted texts.') if self.isnote.get()==0: self.check_separate.configure(state=tk.DISABLED) self.checkReady() def doNote(self): if self.isnote.get()==1: print('Extract notes.') self.check_separate.configure(state=tk.NORMAL) else: print('Dont extract notes.') self.check_separate.state=tk.DISABLED if self.ishighlight.get()==0: self.check_separate.configure(state=tk.DISABLED) self.checkReady() def doSeparate(self): if self.isseparate.get()==1: print('Save annotations separately.') else: print('Save all annotations to single file.') def showHelp(self): helpstr=''' Menotexport v1.0\n\n - Export PDFs: Bulk export PDFs with annotations to <output folder>.\n - Extract highlights: Extract highlighted texts and output to a txt file in <output folder>.\n - Extract highlights: Extract notes and output to a txt file in <output folder>.\n - Save separately: If on, save each PDF's annotations to a separate txt.\n - See README.md for more info.\n ''' tkMessageBox.showinfo(title='Help', message=helpstr) print(self.menfolder.get()) def start(self): dbfile=self.db_entry.get() outdir=self.out_entry.get() action=[] if self.isexport.get()==1: action.append('e') if self.ishighlight.get()==1: action.append('m') if self.isnote.get()==1: action.append('n') if self.isseparate.get()==1: separate=True else: separate=False if 'e' in action or 'm' in action or 'n' in action: self.db_button.configure(state=tk.DISABLED) self.out_button.configure(state=tk.DISABLED) self.start_button.configure(state=tk.DISABLED) self.help_button.configure(state=tk.DISABLED) self.foldersmenu.configure(state=tk.DISABLED) self.check_export.configure(state=tk.DISABLED) self.check_highlight.configure(state=tk.DISABLED) self.check_note.configure(state=tk.DISABLED) self.check_separate.configure(state=tk.DISABLED) self.messagelabel.configure(text='Message (working...)') folder=None if self.menfolder=='All' else [self.menfolder,] args=[dbfile,outdir,action,folder,True,True,separate,True] self.workthread=WorkThread('work',False,self.stateq) self.workthread.deamon=True self.workthread.args=args self.workthread.start() self.reset() ''' self.workproc.apply_async(menotexport.main,args,\ callback=self.reset) self.workproc.join() ''' def reset(self): while self.stateq.qsize() and self.exit==False: try: msg=self.stateq.get() if msg=='done': self.db_button.configure(state=tk.NORMAL) self.out_button.configure(state=tk.NORMAL) self.start_button.configure(state=tk.NORMAL) self.help_button.configure(state=tk.NORMAL) self.foldersmenu.configure(state='readonly') self.check_export.configure(state=tk.NORMAL) self.check_highlight.configure(state=tk.NORMAL) self.check_note.configure(state=tk.NORMAL) self.check_separate.configure(state=tk.NORMAL) self.messagelabel.configure(text='Message') return except Queue.Empty: pass self.after(100,self.reset) def stop(self): #self.workthread.stop() pass def addMessageFrame(self): frame=Frame(self) frame.pack(fill=tk.BOTH,side=tk.TOP,\ expand=1,padx=8,pady=5) self.messagelabel=tk.Label(frame,text='Message',bg='#bbb') self.messagelabel.pack(side=tk.TOP,fill=tk.X) self.text=tk.Text(frame) self.text.pack(side=tk.TOP,fill=tk.BOTH,expand=1) self.text.height=10 scrollbar=tk.Scrollbar(self.text) scrollbar.pack(side=tk.RIGHT,fill=tk.Y) self.text.config(yscrollcommand=scrollbar.set) scrollbar.config(command=self.text.yview)
class MainFrame(Frame): def __init__(self,parent,stdoutq): Frame.__init__(self,parent) self.parent=parent self.width=750 self.height=450 self.title=ximaexport.__version__ self.stdoutq=stdoutq self.initUI() self.hasdb=False self.hasout=False self.exit=False self.path_frame=self.addPathFrame() self.action_frame=self.addActionFrame() self.message_frame=self.addMessageFrame() self.printStr() self.stateq=Queue.Queue() def centerWindow(self): sw=self.parent.winfo_screenwidth() sh=self.parent.winfo_screenheight() x=(sw-self.width)/2 y=(sh-self.height)/2 self.parent.geometry('%dx%d+%d+%d' \ %(self.width,self.height,x,y)) def initUI(self): self.parent.title(self.title) self.style=Style() #Choose from default, clam, alt, classic self.style.theme_use('alt') self.pack(fill=tk.BOTH,expand=True) self.centerWindow() def printStr(self): while self.stdoutq.qsize() and self.exit==False: try: msg=self.stdoutq.get() self.text.update() self.text.insert(tk.END,msg) self.text.see(tk.END) except Queue.Empty: pass self.after(100,self.printStr) def checkReady(self): if self.hasdb and self.hasout: self.start_button.configure(state=tk.NORMAL) #print('XimaExport Ready.') printch('XimaExport 就绪.') else: self.start_button.configure(state=tk.DISABLED) def addPathFrame(self): frame=Frame(self) frame.pack(fill=tk.X,expand=0,side=tk.TOP,padx=8,pady=5) frame.columnconfigure(1,weight=1) #------------------Database file------------------ label=tk.Label(frame,text=dgbk('ting.sqlite文件:'),\ bg='#bbb') label.grid(row=0,column=0,\ sticky=tk.W,padx=8) self.db_entry=tk.Entry(frame) self.db_entry.grid(row=0,column=1,sticky=tk.W+tk.E,padx=8) self.db_button=tk.Button(frame,text=dgbk('打开'),command=self.openFile) self.db_button.grid(row=0,column=2,padx=8,sticky=tk.E) #--------------------Output dir-------------------- label2=tk.Label(frame,text=dgbk('导出到文件夹:'),\ bg='#bbb') label2.grid(row=2,column=0,\ sticky=tk.W,padx=8) self.out_entry=tk.Entry(frame) self.out_entry.grid(row=2,column=1,sticky=tk.W+tk.E,padx=8) self.out_button=tk.Button(frame,text=dgbk('选择'),command=self.openDir) self.out_button.grid(row=2,column=2,padx=8,sticky=tk.E) def openDir(self): self.out_entry.delete(0,tk.END) dirname=askdirectory() self.out_entry.insert(tk.END,dirname) if len(dirname)>0: #print('Output folder: %s' %dirname) printch('输出到文件夹:') print(' '+dirname) self.hasout=True self.checkReady() def openFile(self): self.db_entry.delete(0,tk.END) ftypes=[('sqlite files','*.sqlite'),('ALL files','*')] filename=askopenfilename(filetypes=ftypes) self.db_entry.insert(tk.END,filename) if len(filename)>0: #print('Database file: %s' %filename) printch('数据文件:') print(' '+filename) self.probeAlbums() def probeAlbums(self): dbfile=self.db_entry.get() try: db=sqlite3.connect(dbfile) df=ximaexport.getData(db) self.albumlist=ximaexport.getAlbumList(df,None) #(id, name) self.albumnames=['All']+[ii[1] for ii in self.albumlist] #names to display self.albummenu['values']=tuple(self.albumnames) self.albummenu.current(0) db.close() self.hasdb=True self.checkReady() except Exception as e: #print('Failed to recoganize the given database file.') printch('无法识别sqlite数据文件.') print(e) def addActionFrame(self): frame=Frame(self,relief=tk.RAISED,borderwidth=1) frame.pack(fill=tk.X,side=tk.TOP,\ expand=0,padx=8,pady=5) #label=tk.Label(frame,text='Actions:',bg='#bbb') #label.grid(row=0,column=0,sticky=tk.W,padx=8) #---------------Action checkbuttons--------------- frame.columnconfigure(0,weight=1) #---------------------2nd row--------------------- subframe=Frame(frame) subframe.grid(row=1,column=0,columnspan=6,sticky=tk.W+tk.E,\ pady=5) #-------------------Album options------------------- albumlabel=tk.Label(subframe,text=dgbk('专辑:'),\ bg='#bbb') albumlabel.pack(side=tk.LEFT, padx=8) self.album=tk.StringVar() self.albumnames=['All',] self.albummenu=Combobox(subframe,textvariable=\ self.album,values=self.albumnames,state='readonly') self.albummenu.current(0) self.albummenu.bind('<<ComboboxSelected>>',self.setAlbum) self.albummenu.pack(side=tk.LEFT,padx=8) #-------------------Quit button------------------- quit_button=tk.Button(subframe,text=dgbk('退出'),\ command=self.quit) quit_button.pack(side=tk.RIGHT,padx=8) #-------------------Stop button------------------- ''' self.stop_button=tk.Button(subframe,text='Stop',\ command=self.stop) self.stop_button.pack(side=tk.RIGHT,padx=8) ''' #-------------------Start button------------------- self.start_button=tk.Button(subframe,text=dgbk('开始'),\ command=self.start,state=tk.DISABLED) self.start_button.pack(side=tk.RIGHT,pady=8) #-------------------Help button------------------- self.help_button=tk.Button(subframe,text=dgbk('帮助'),\ command=self.showHelp) self.help_button.pack(side=tk.RIGHT,padx=8) def setAlbum(self,x): import json self.albummenu.selection_clear() self.album=self.albummenu.get() self.albummenu.set(self.album) if self.album=='All': #print('Work on all albums.') printch('导出所有专辑.') else: #print('Select album: '+self.album) printch('导出所选专辑:') print(' '+self.album) def showHelp(self): helpstr=dgbk('''\n\n 导出喜马拉雅下载音频,并自动按专辑归档、重命名:\n 1. 找到手机/pad中的喜马拉雅数据文件夹:\n (1)苹果用户:链接电脑itunes,在app一栏中找到“喜马拉雅”,单击,右侧会出现“喜马拉雅”的数据文件。选择“iDoc”,并导出到电脑。\n (2)安卓用户:链接电脑后,拷贝出ting文件夹。\n 2. 运行ximaexport-gui.exe。\n 在 “ting.sqlite文件”一栏,选择步骤1中拷贝出的文件夹里的 ting.sqlite. 文件。\n 在 “导出到文件夹”一栏,选择音频存储位置。\n 在 “专辑”下拉菜单,选择要导出的专辑。若全部导出选择“All”。\n 点击“开始”开始处理。 ''') tkMessageBox.showinfo(title='Help', message=helpstr) #print(self.menfolder.get()) def start(self): dbfile=self.db_entry.get() outdir=self.out_entry.get() self.album=self.albummenu.get() self.out_button.configure(state=tk.DISABLED) self.start_button.configure(state=tk.DISABLED) self.help_button.configure(state=tk.DISABLED) self.albummenu.configure(state=tk.DISABLED) self.messagelabel.configure(text=dgbk('信息 (处理中...)')) album=None if self.album=='All' else self.album args=[dbfile,outdir,album,True] self.workthread=WorkThread('work',False,self.stateq) self.workthread.deamon=True self.workthread.args=args self.workthread.start() self.reset() def reset(self): while self.stateq.qsize() and self.exit==False: try: msg=self.stateq.get() if msg=='done': self.db_button.configure(state=tk.NORMAL) self.out_button.configure(state=tk.NORMAL) self.start_button.configure(state=tk.NORMAL) self.help_button.configure(state=tk.NORMAL) self.albummenu.configure(state='readonly') self.messagelabel.configure(text=dgbk('消息')) return except Queue.Empty: pass self.after(100,self.reset) def stop(self): #self.workthread.stop() pass def addMessageFrame(self): frame=Frame(self) frame.pack(fill=tk.BOTH,side=tk.TOP,\ expand=1,padx=8,pady=5) self.messagelabel=tk.Label(frame,text=dgbk('消息'),bg='#bbb') self.messagelabel.pack(side=tk.TOP,fill=tk.X) self.text=tk.Text(frame) self.text.pack(side=tk.TOP,fill=tk.BOTH,expand=1) self.text.height=10 scrollbar=tk.Scrollbar(self.text) scrollbar.pack(side=tk.RIGHT,fill=tk.Y) self.text.config(yscrollcommand=scrollbar.set) scrollbar.config(command=self.text.yview)
class Gui(Frame): """ Gui class for Graphical User Interface""" def __init__(self, parent): Frame.__init__(self, parent) self.searcher = Searcher() self.initUI() def initUI(self): self.pack(fill=BOTH, expand=True) Grid.columnconfigure(self, 0, weight=1) Label(self, text='Classroom Finder', font=('Arial', 20, 'bold'), bg='cyan', fg='white').grid(sticky=W + E, columnspan=3) # classroom finder header Label(self, text='Url:').grid(column=0, row=1, pady=10, padx=(50, 0)) self.urlentry = Entry(self, width=100) # url entry to get url self.urlentry.grid(column=1, row=1, padx=(0, 80)) self.color_label = Label( self, bg='red', width=10) # color label to make red,yellow,green self.color_label.grid(column=0, row=2, sticky=E, columnspan=2, padx=(120), pady=(0, 40)) self.fetchbtn = Button(self, text='Fetch', height=2, width=10, command=self.dynamic) # fetch button self.fetchbtn.grid(column=1, row=2, sticky=E, padx=(0, 30), pady=(10, 50)) Label(self, text='Filters', bg='cyan', fg='white', font=('Arial', 20, 'bold'), width=10).grid(column=0, row=3, padx=10) self.frame = Frame(self, borderwidth=3, relief=GROOVE) # frame to keep filters part self.frame.grid(column=0, row=4, columnspan=3, sticky=W + E + S + N, pady=10, padx=10) Label(self.frame, text='Where am I?').grid(sticky=W) self.where_combo = Combobox(self.frame, state='readonly') # where am i combobox self.where_combo.grid(column=1, row=0, pady=20) self.where_combo.bind( '<<ComboboxSelected>>', self.change_build) # to update room button wrt where combo Label(self.frame, text='Room').grid(sticky=W) self.room_combo = Combobox(self.frame, state='readonly') # rooms combobox self.room_combo.grid(column=1, row=1) Label(self.frame, text='Start').grid(sticky=W) self.start_combo = Combobox(self.frame, state='readonly', width=7) # start time combobox self.start_combo.grid(column=1, row=2, pady=20, sticky=W) Label(self.frame, text='End').grid(column=2, row=2, sticky=W) self.end_combo = Combobox(self.frame, state='readonly', width=7) # end time combobox self.end_combo.grid(column=3, row=2, sticky=W) Label(self.frame, text='Day').grid(sticky=W) self.day_combo = Combobox(self.frame, state='readonly') # days combobox self.day_combo.grid(column=1, row=3, pady=(0, 20)) self.search = Button(self.frame, text='Search', width=10, height=2, command=self.add_treeview) # seach button self.search.grid(padx=(0, 50), columnspan=2) Label(self.frame, text='Classroom results', bg='gray', fg='white').grid(sticky=N + E + W, column=4, row=0, rowspan=5, padx=(55, 0)) self.scroll = Scrollbar( self.frame, orient='vertical') # vertical scrollbar for treeview self.tree = Treeview(self.frame, columns=('', '', '', '', ''), selectmode='extended', show='headings') listofcolumn = [ 'Room', 'Traffic', 'Availability %', 'Closeness', 'Overall Score' ] # colums to treeview counter = 1 for column in listofcolumn: self.tree.column('#' + str(counter), width=90) # to resize columns self.tree.heading('#' + str(counter), text=column, anchor=CENTER) # to set headings counter += 1 self.scroll.config(command=self.tree.yview) self.tree.config(yscrollcommand=self.scroll.set) self.tree.grid(column=4, row=0, rowspan=5, padx=(40, 0), pady=(30, 0)) self.scroll.grid(column=5, row=0, rowspan=5, sticky=N + S, pady=(30, 0)) self.urlentry.insert( 0, 'https://www.sehir.edu.tr/en/announcements/2018-2019-bahar-donemi-ders-programi' ) def dynamic(self): self.color_label.configure( bg='yellow' ) # make color label yellow at the beginning of the process self.update_idletasks() self.searcher.fetch(self.urlentry.get( )) # to call fetch method in searcher class to start process self.color_label.configure(bg='green') room_num = [ room.room_num for room in self.searcher.buildings['ACAD BUILD 1'].classrooms ] self.where_combo.configure( values=[build for build in sorted(self.searcher.buildings)]) self.where_combo.current( 0) # to get values in combobox and set value 0 as a default self.room_combo.configure(values=[room for room in sorted(room_num)]) self.room_combo.current(0) self.start_combo.configure( values=["{}:00".format(time) for time in range(9, 20)]) self.start_combo.current( 0) # start and end combo both have the same interval from 9 to 19 self.end_combo.configure( values=["{}:00".format(time) for time in range(9, 20)]) self.end_combo.current(len(self.end_combo['values']) - 1) self.day_combo.configure( values=["Monday", 'Tuesday', 'Wednesday', 'Thursday', 'Friday']) self.day_combo.current(0) def change_build( self, event ): # when where am i combobox chance, room combobox also chance building = self.where_combo.get() room_num = [ room.room_num for room in self.searcher.buildings[building].classrooms ] self.room_combo.configure(values=[room for room in sorted(room_num)]) self.room_combo.current(0) def add_treeview(self): # to add scores in treeview self.tree.delete(*self.tree.get_children()) self.overall_scores = self.searcher.search( self.day_combo.get(), self.where_combo.get(), self.room_combo.get(), self.start_combo.get(), self.end_combo.get() ) # key operator for the sorted dict by values which overall score for item, score in sorted(self.overall_scores.items(), key=operator.itemgetter(1), reverse=True): if item.availability_score == 0: # to avoid from availability score 0 continue room = str(item.classroom.building_num) + str( item.classroom.room_num) self.tree.insert('', 'end', values=(room, item.traffic_score, item.availability_score, item.closeness_score, score))
class MainFrame(Frame): def __init__(self, parent, stdoutq): Frame.__init__(self, parent) self.parent = parent self.width = 850 self.height = 650 self.title = menotexport.__version__ self.stdoutq = stdoutq self.initUI() self.hasdb = False self.hasout = False self.hasaction = False self.exit = False self.path_frame = self.addPathFrame() self.action_frame = self.addActionFrame() self.message_frame = self.addMessageFrame() self.printStr() self.stateq = Queue.Queue() #self.workproc=Pool(1) def centerWindow(self): sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - self.width) / 2 y = (sh - self.height) / 2 self.parent.geometry('%dx%d+%d+%d' \ %(self.width,self.height,x,y)) def initUI(self): self.parent.title(self.title) self.style = Style() #Choose from default, clam, alt, classic self.style.theme_use('alt') self.pack(fill=tk.BOTH, expand=True) self.centerWindow() def printStr(self): while self.stdoutq.qsize() and self.exit == False: try: msg = self.stdoutq.get() self.text.update() self.text.insert(tk.END, msg) self.text.see(tk.END) except Queue.Empty: pass self.after(100, self.printStr) def checkReady(self): if self.isexport.get()==1 or self.ishighlight.get()==1\ or self.isnote.get()==1 or self.isbib.get()==1: self.hasaction = True else: self.hasaction = False if self.hasdb and self.hasout and self.hasaction: self.start_button.configure(state=tk.NORMAL) print('# <Menotexport>: Menotexport Ready.') else: self.start_button.configure(state=tk.DISABLED) def addPathFrame(self): frame = Frame(self) frame.pack(fill=tk.X, expand=0, side=tk.TOP, padx=8, pady=5) frame.columnconfigure(1, weight=1) #------------------Database file------------------ label=tk.Label(frame,text='Mendeley Data file:',\ bg='#bbb') label.grid(row=0,column=0,\ sticky=tk.W,padx=8) self.db_entry = tk.Entry(frame) self.db_entry.grid(row=0, column=1, sticky=tk.W + tk.E, padx=8) self.db_button = tk.Button(frame, text='Open', command=self.openFile) self.db_button.grid(row=0, column=2, padx=8, sticky=tk.E) hint = ''' Default location on Linux: ~/.local/share/data/Mendeley\ Ltd./Mendeley\ Desktop/[email protected] Default location on Windows: C:\Users\Your_name\AppData\Local\Mendeley Ltd\Mendeley Desktop\[email protected]''' hint_label=tk.Label(frame,text=hint,\ justify=tk.LEFT,anchor=tk.NW) hint_label.grid(row=1,column=0,columnspan=3,\ sticky=tk.W,padx=8) #--------------------Output dir-------------------- label2=tk.Label(frame,text='Output folder:',\ bg='#bbb') label2.grid(row=2,column=0,\ sticky=tk.W,padx=8) self.out_entry = tk.Entry(frame) self.out_entry.grid(row=2, column=1, sticky=tk.W + tk.E, padx=8) self.out_button = tk.Button(frame, text='Choose', command=self.openDir) self.out_button.grid(row=2, column=2, padx=8, sticky=tk.E) def openDir(self): self.out_entry.delete(0, tk.END) dirname = askdirectory() self.out_entry.insert(tk.END, dirname) if len(dirname) > 0: print('# <Menotexport>: Output folder: %s' % dirname) self.hasout = True self.checkReady() def openFile(self): self.db_entry.delete(0, tk.END) ftypes = [('sqlite files', '*.sqlite'), ('ALL files', '*')] initialdir = '~/.local/share/data/Mendeley Ltd./Mendeley Desktop' initialdir = os.path.expanduser(initialdir) if os.path.isdir(initialdir): filename = askopenfilename(filetypes=ftypes, initialdir=initialdir) else: filename = askopenfilename(filetypes=ftypes) self.db_entry.insert(tk.END, filename) if len(filename) > 0: print('# <Menotexport>: Database file: %s' % filename) self.probeFolders() def probeFolders(self): dbfile = self.db_entry.get() try: db = sqlite3.connect(dbfile) self.menfolderlist = menotexport.getFolderList(db, None) #(id, name) self.foldernames = ['All'] + [ii[1] for ii in self.menfolderlist ] #names to display self.foldersmenu['values'] = tuple(self.foldernames) self.foldersmenu.current(0) db.close() self.hasdb = True self.checkReady() except Exception as e: print( '# <Menotexport>: Failed to recoganize the given database file.' ) print(e) def addActionFrame(self): frame = Frame(self, relief=tk.RAISED, borderwidth=1) frame.pack(fill=tk.X,side=tk.TOP,\ expand=0,padx=8,pady=5) label = tk.Label(frame, text='Actions:', bg='#bbb') label.grid(row=0, column=0, sticky=tk.W, padx=8) #---------------Action checkbuttons--------------- self.isexport = tk.IntVar() self.ishighlight = tk.IntVar() self.isnote = tk.IntVar() self.isbib = tk.IntVar() self.isris = tk.IntVar() self.isseparate = tk.IntVar() self.iszotero = tk.IntVar() self.iscustomtemp = tk.IntVar() self.check_export=tk.Checkbutton(frame,text='Export PDFs',\ variable=self.isexport,command=self.doExport) self.check_highlight=tk.Checkbutton(frame,\ text='Extract highlights',\ variable=self.ishighlight,command=self.doHighlight) self.check_note=tk.Checkbutton(frame,\ text='Extract notes',\ variable=self.isnote,command=self.doNote) self.check_bib=tk.Checkbutton(frame,\ text='Export .bib',\ variable=self.isbib,command=self.doBib) self.check_ris=tk.Checkbutton(frame,\ text='Export .ris',\ variable=self.isris,command=self.doRis) self.check_separate=tk.Checkbutton(frame,\ text='Save separately',\ variable=self.isseparate,command=self.doSeparate,\ state=tk.DISABLED) self.check_iszotero=tk.Checkbutton(frame,\ text='For import to Zotero',\ variable=self.iszotero,command=self.doIszotero,\ state=tk.DISABLED) self.check_custom_template=tk.Checkbutton(frame,\ text='Use custom template (experimental)',\ variable=self.iscustomtemp,command=self.doCustomTemp,\ state=tk.DISABLED) frame.columnconfigure(0, weight=1) self.check_export.grid(row=1, column=1, padx=8, sticky=tk.W) self.check_highlight.grid(row=1, column=2, padx=8, sticky=tk.W) self.check_note.grid(row=1, column=3, padx=8, sticky=tk.W) self.check_bib.grid(row=2, column=1, padx=8, sticky=tk.W) self.check_ris.grid(row=2, column=2, padx=8, sticky=tk.W) self.check_separate.grid(row=2, column=3, padx=8, sticky=tk.W) self.check_iszotero.grid(row=3, column=1, padx=8, sticky=tk.W) self.check_custom_template.grid(row=3, column=2, padx=8, sticky=tk.W) #---------------------2nd row--------------------- subframe = Frame(frame) subframe.grid(row=4,column=0,columnspan=6,sticky=tk.W+tk.E,\ pady=5) #-------------------Folder options------------------- folderlabel=tk.Label(subframe,text='Mendeley folder:',\ bg='#bbb') folderlabel.pack(side=tk.LEFT, padx=8) self.menfolder = tk.StringVar() self.menfolderlist = [ 'All', ] self.foldersmenu=Combobox(subframe,textvariable=\ self.menfolder,values=self.menfolderlist,state='readonly') self.foldersmenu.current(0) self.foldersmenu.bind('<<ComboboxSelected>>', self.setfolder) self.foldersmenu.pack(side=tk.LEFT, padx=8) #-------------------Quit button------------------- quit_button=tk.Button(subframe,text='Quit',\ command=self.quit) quit_button.pack(side=tk.RIGHT, padx=8) #-------------------Stop button------------------- ''' self.stop_button=tk.Button(subframe,text='Stop',\ command=self.stop) self.stop_button.pack(side=tk.RIGHT,padx=8) ''' #-------------------Start button------------------- self.start_button=tk.Button(subframe,text='Start',\ command=self.start,state=tk.DISABLED) self.start_button.pack(side=tk.RIGHT, pady=8) #-------------------Help button------------------- self.help_button=tk.Button(subframe,text='Help',\ command=self.showHelp) self.help_button.pack(side=tk.RIGHT, padx=8) def setfolder(self, x): self.foldersmenu.selection_clear() self.menfolder = self.foldersmenu.get() self.foldersmenu.set(self.menfolder) if self.menfolder == 'All': print('# <Menotexport>: Work on all folders.') else: print('# <Menotexport>: Select Mendeley folder: ' + str(self.menfolder)) def doExport(self): if self.isexport.get() == 1: print('# <Menotexport>: Export annotated PDFs.') else: print('# <Menotexport>: Dont export annotated PDFs.') self.checkReady() def doHighlight(self): if self.ishighlight.get() == 1: print('# <Menotexport>: Extract highlighted texts.') self.check_separate.configure(state=tk.NORMAL) self.check_custom_template.configure(state=tk.NORMAL) else: print('# <Menotexport>: Dont extract highlighted texts.') if self.isnote.get() == 0: self.check_separate.configure(state=tk.DISABLED) self.check_custom_template.configure(state=tk.DISABLED) self.checkReady() def doNote(self): if self.isnote.get() == 1: print('# <Menotexport>: Extract notes.') self.check_separate.configure(state=tk.NORMAL) self.check_custom_template.configure(state=tk.NORMAL) else: print('# <Menotexport>: Dont extract notes.') self.check_separate.state = tk.DISABLED if self.ishighlight.get() == 0: self.check_separate.configure(state=tk.DISABLED) self.check_custom_template.configure(state=tk.DISABLED) self.checkReady() self.checkReady() def doBib(self): if self.isbib.get() == 1: print('# <Menotexport>: Export to .bib file.') self.check_iszotero.configure(state=tk.NORMAL) else: print('# <Menotexport>: Dont export .bib file.') if self.isris.get() == 0: self.check_iszotero.configure(state=tk.DISABLED) self.checkReady() def doRis(self): if self.isris.get() == 1: print('# <Menotexport>: Export to .ris file.') self.check_iszotero.configure(state=tk.NORMAL) else: print('# <Menotexport>: Dont export .ris file.') if self.isbib.get() == 0: self.check_iszotero.configure(state=tk.DISABLED) self.checkReady() def doSeparate(self): if self.isseparate.get() == 1: print('# <Menotexport>: Save annotations separately.') else: print('# <Menotexport>: Save all annotations to single file.') def doIszotero(self): if self.iszotero.get() == 1: print( '# <Menotexport>: Save .bib/.ris file in Zotero preferred format.' ) else: print('# <Menotexport>: Save .bib/.ris file to default format.') def doCustomTemp(self): if self.iscustomtemp.get() == 1: print( '# <Menotexport>: Use custom template for exported annotations.' ) else: print( '# <Menotexport>: Use default template for exported annotations.' ) def showHelp(self): helpstr = ''' %s\n\n - Export PDFs: Bulk export PDFs.\n - Extract highlights: Extract highlighted texts and output to txt files.\n - Extract notes: Extract notes and output to txt files.\n - Export .bib: Export meta-data and annotations to .bib files.\n - Export .ris: Export meta-data and annotations to .ris files.\n - For import to Zotero: Exported .bib and/or .ris files have suitable format to import to Zotero.\n - Save separately: If on, save each PDF's annotations to a separate txt.\n - Use custom annotation template: Use a custom template to format the exported annotations. See annotation_template.py for details. - See README.md for more info.\n ''' % self.title tkMessageBox.showinfo(title='Help', message=helpstr) #print(self.menfolder.get()) def start(self): dbfile = self.db_entry.get() outdir = self.out_entry.get() self.menfolder = self.foldersmenu.get() # get (folderid, folder) for folder for ii in self.menfolderlist: if ii[1] == self.menfolder: folder_sel = [ii[0], ii[1].split('/')[-1]] action = [] if self.isexport.get() == 1: action.append('p') if self.ishighlight.get() == 1: action.append('m') if self.isnote.get() == 1: action.append('n') if self.isbib.get() == 1: action.append('b') if self.isris.get() == 1: action.append('r') if self.isseparate.get() == 1: separate = True else: separate = False if self.iszotero.get() == 1: iszotero = True else: iszotero = False if self.iscustomtemp.get() == 1: action.append('t') if 'p' in action or 'm' in action or 'n' in action or 'b' in action or 'r' in action: self.db_button.configure(state=tk.DISABLED) self.out_button.configure(state=tk.DISABLED) self.start_button.configure(state=tk.DISABLED) self.help_button.configure(state=tk.DISABLED) self.foldersmenu.configure(state=tk.DISABLED) self.check_export.configure(state=tk.DISABLED) self.check_highlight.configure(state=tk.DISABLED) self.check_note.configure(state=tk.DISABLED) self.check_bib.configure(state=tk.DISABLED) self.check_ris.configure(state=tk.DISABLED) self.check_separate.configure(state=tk.DISABLED) self.check_iszotero.configure(state=tk.DISABLED) self.check_custom_template.configure(state=tk.DISABLED) self.messagelabel.configure(text='Message (working...)') folder = None if self.menfolder == 'All' else folder_sel args = [dbfile, outdir, action, folder, separate, iszotero, True] self.workthread = WorkThread('work', False, self.stateq) self.workthread.deamon = True self.workthread.args = args self.workthread.start() self.reset() ''' self.workproc.apply_async(menotexport.main,args,\ callback=self.reset) self.workproc.join() ''' def reset(self): while self.stateq.qsize() and self.exit == False: try: msg = self.stateq.get() if msg == 'done': self.db_button.configure(state=tk.NORMAL) self.out_button.configure(state=tk.NORMAL) self.start_button.configure(state=tk.NORMAL) self.help_button.configure(state=tk.NORMAL) self.foldersmenu.configure(state='readonly') self.check_export.configure(state=tk.NORMAL) self.check_highlight.configure(state=tk.NORMAL) self.check_note.configure(state=tk.NORMAL) self.check_bib.configure(state=tk.NORMAL) self.check_separate.configure(state=tk.NORMAL) self.check_iszotero.configure(state=tk.NORMAL) self.check_custom_template.configure(state=tk.NORMAL) self.messagelabel.configure(text='Message') return except Queue.Empty: pass self.after(100, self.reset) def stop(self): #self.workthread.stop() pass def addMessageFrame(self): frame = Frame(self) frame.pack(fill=tk.BOTH,side=tk.TOP,\ expand=1,padx=8,pady=5) self.messagelabel = tk.Label(frame, text='Message', bg='#bbb') self.messagelabel.pack(side=tk.TOP, fill=tk.X) self.text = tk.Text(frame) self.text.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.text.height = 10 scrollbar = tk.Scrollbar(self.text) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.text.config(yscrollcommand=scrollbar.set) scrollbar.config(command=self.text.yview)
class JobUI(Toplevel): # 编辑任务窗口 def __init__(self, parent_window, job, parent_name, job_name): self.edit_job = Toplevel() Log() self.log = logging.getLogger("Data_Collect_Log") self.parent = parent_window self.edit_job.protocol("WM_DELETE_WINDOW", self.job_cancel) self.job_file_ext = '.dat' self.job_script_ext = '.bat' self.txt_text_job = StringVar() self.txt_text_task = StringVar() self.txt_text_desc = StringVar() self.txt_text_server = StringVar() self.txt_text_user = StringVar() self.txt_text_pwd = StringVar() self.txt_text_tablespace = StringVar() self.txt_text_script = StringVar() self.job_conf_content = None # JOB配置内容 self.job_script_content = None # JOB脚本内容 self.edit_job.geometry('600x520') self.edit_job.title(u'任务编辑') self.edit_job.iconbitmap('ico.ico') self.edit_job.resizable(width=False, height=False) entry_opt = {'column': 2, 'ipadx': 30, 'sticky': W} # 文本框的字典GRID参数 top_frame = Frame(self.edit_job) top_frame.configure(borderwidth=2, bg='gray') Label(top_frame, text="JOB", bg='gray').grid(row=0, column=1, sticky=W) self.combobox_Job_name = Combobox(top_frame, width=18, textvariable=self.txt_text_job, state='readonly') self.combobox_Job_name.grid(row=0, **entry_opt) Label(top_frame, text=u"任务名称", bg='gray').grid(row=1, column=1, sticky=W) self.entry_text_name = Entry(top_frame, textvariable=self.txt_text_task) self.entry_text_name.grid(row=1, **entry_opt) tip = Label(top_frame) tip.configure(text=u"任务名称不能为空,表空间用户名密码等信息并没有实际意义。仅仅是为了方便在主界面查看代码是否匹配!") tip.configure(bg='gray', wraplength=290, justify='left', fg='red') tip.grid(row=2, column=2, sticky=E, rowspan=3) Label(top_frame, text=u"任务描述", bg='gray').grid(row=2, column=1, sticky=W) self.entry_text_desc = Entry(top_frame, textvariable=self.txt_text_desc) self.entry_text_desc.grid(row=2, **entry_opt) Label(top_frame, text=u"服务器地址", bg='gray').grid(row=3, column=1, sticky=W) self.entry_text_server = Entry(top_frame, textvariable=self.txt_text_server) self.entry_text_server.grid(row=3, **entry_opt) Label(top_frame, text=u"用户名", bg='gray').grid(row=4, column=1, sticky=W) self.entry_text_user = Entry(top_frame, textvariable=self.txt_text_user) self.entry_text_user.grid(row=4, **entry_opt) Label(top_frame, text=u"密码", bg='gray').grid(row=5, column=1, sticky=W) self.entry_text_pwd = Entry(top_frame, textvariable=self.txt_text_pwd) self.entry_text_pwd.grid(row=5, **entry_opt) Label(top_frame, text=u"表空间", bg='gray').grid(row=6, column=1, sticky=W) self.entry_text_tablespace = Entry( top_frame, textvariable=self.txt_text_tablespace) self.entry_text_tablespace.grid(row=6, **entry_opt) Label(top_frame, text=u"脚本", bg='gray').grid(row=7, column=1, sticky=W) self.entry_text_script = ScrolledText(top_frame, width=64, height=25) self.entry_text_script.grid(row=7, **entry_opt) top_frame.pack(side=TOP) bottom_frame = Frame(self.edit_job) bottom_frame.configure(height=30, borderwidth=2) bottom_frame.pack_propagate(0) button_ok = Button(bottom_frame, text=u"保 存", command=self.check_entry_is_empty) button_ok.pack(side=LEFT, padx=150, ipadx=10) button_cancel = Button(bottom_frame, text=u"取 消", command=self.job_cancel) button_cancel.pack( side=LEFT, ipadx=10, ) bottom_frame.pack(side=BOTTOM, fill=X) self.edit_job.update_idletasks() self.init_ui(job, parent_name, job_name) self.edit_job.deiconify() x, y = self.center(600, 520) self.edit_job.geometry('%dx%d+%d+%d' % (600, 520, x, y)) self.edit_job.deiconify() self.edit_job.focus_force() def init_ui(self, job, parent, job_name): u""" 根据传入的参数,决定窗口的初始状态 :param job: 0-新建菜单点击创建 1-JOB树右键新建JOB菜单 2-双击JOB 3--菜单打开JOB菜单调用 :param parent: 父节点 :param job_name: 节点名称_job_name :return: """ if job == 0: value_combobox = ManageJob.scan_all_job() tuple(value_combobox) self.combobox_Job_name['values'] = value_combobox self.parent.hide() elif job == 1: self.txt_text_job.set(job_name) self.combobox_Job_name.configure(state='disabled') self.parent.hide() elif job == 2: file_path = ManageJob.get_conf_path(parent, job_name) script_path = ManageJob.get_script_path(parent, job_name) try: self.job_conf_content = open(file_path).readlines() self.job_script_content = open(script_path).read() self.parent.hide() except Exception, e: self.log.error(parent + '_' + job_name + u'读取失败' + e.message.decode('gbk')) tkMessageBox.showinfo(title=u'警告', message=e.message) self.edit_job.destroy() self.set_text_value(parent) self.combobox_Job_name.configure(state='disabled') elif job == 3: parent = job_name[job_name.find('Job') + 4:job_name.find('/JobConf')] job_name = os.path.split(job_name)[1][:-4] file_path = ManageJob.get_conf_path(parent, job_name) script_path = ManageJob.get_script_path(parent, job_name) self.job_conf_content = open(file_path).readlines() self.job_script_content = open(script_path).read() self.set_text_value(parent) self.parent.hide()
class Example(Frame): counter = 0 def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def nuevoVoluntario(self, nombre, apellidos, dni, direccion, correo_electronico, localidad_id, estudio_id, parroquial_id, proyecto_id, telefono_1, telefono_2, genero, fecha_nacimiento,t,estado,id): global cnx cursor = cnx.cursor() if estado: query = ( "INSERT INTO caritas.voluntario (nombre, apellidos, dni, direccion, correo_electronico, localidad_id, estudio_id, parroquial_id, proyecto_id, telefono_1, telefono_2, genero, fecha_nacimiento) VALUES ('%s','%s','%s','%s','%s','%d','%d','%d','%d','%s','%s','%s','%s')" % ( nombre, apellidos, dni, direccion, correo_electronico, localidad_id, estudio_id, parroquial_id, proyecto_id, telefono_1, telefono_2, genero, fecha_nacimiento)) else: query = ( "UPDATE caritas.voluntario SET nombre = ('%s'), apellidos = ('%s'), dni = ('%s'), direccion = ('%s'), correo_electronico = ('%s'), localidad_id = ('%d'), estudio_id = ('%d'), parroquial_id = ('%d'),proyecto_id = ('%d'), telefono_1 = ('%s'), telefono_2 = ('%s'), genero = ('%s'), fecha_nacimiento = ('%s') WHERE id = ('%d')" % ( nombre, apellidos, dni, direccion, correo_electronico, localidad_id, estudio_id, parroquial_id,proyecto_id, telefono_1, telefono_2, genero, fecha_nacimiento,id)) cursor.execute(query) cnx.commit() cursor.close() t.destroy() def getEstudios(self): global cnx cursor = cnx.cursor(dictionary=True) query = ("SELECT * FROM estudio e") cursor.execute(query) valores = [] strings = [] for row in cursor: valores.append(row['id']) strings.append(row['nombre']) cursor.close() self.listadoEstudios = [strings, valores] def getParroquial(self): global cnx cursor = cnx.cursor(dictionary=True) query = ("SELECT * FROM parroquial e") cursor.execute(query) valores = [] strings = [] for row in cursor: valores.append(row['id']) strings.append(row['nombre']) cursor.close() self.listadoParroquial = [strings, valores] def getPais(self): global cnx cursor = cnx.cursor(dictionary=True) query = ("SELECT * FROM pais e") cursor.execute(query) valores = [] strings = [] for row in cursor: valores.append(row['id']) strings.append(row['nombre']) cursor.close() self.listadoPais = [strings, valores] def nuevoEstudio(self): t = Toplevel(self) t.wm_title("Estudio") Label(t, text="Nombre").grid(row=0, column=1) E2 = Entry(t) E2.grid(row=1, column=1) button1 = Button(t, text="Cancelar", command=lambda: t.destroy()) button2 = Button(t, text="Guardar", command=lambda: self.nuevaEntradaEstudios(E2.get(), t)) button3 = Button(t, text="Borrar", command=lambda: self.BorrarEstudios(E2.get(), t)) button3.config(state="disabled") button1.grid(row=2, column=0) button2.grid(row=2, column=1) button3.grid(row=2, column=2) def nuevoPais(self): t = Toplevel(self) t.wm_title("Pais") Label(t, text="Nombre").grid(row=0, column=1) E2 = Entry(t) E2.grid(row=1, column=1) button1 = Button(t, text="Cancelar", command=lambda: t.destroy()) button2 = Button(t, text="Guardar", command=lambda: self.nuevaEntradaPais(E2.get(), t)) button3 = Button(t, text="Borrar", command=lambda: self.BorrarPais(E2.get(), t)) button3.config(state="disabled") button1.grid(row=2, column=0) button2.grid(row=2, column=1) button3.grid(row=2, column=2) def nuevaParroquia(self): t = Toplevel(self) t.wm_title("Parroquial") Label(t, text="Nombre").grid(row=0, column=1) E2 = Entry(t) E2.grid(row=1, column=1) button1 = Button(t, text="Cancelar", command=lambda: t.destroy()) button2 = Button(t, text="Guardar", command=lambda: self.nuevaEntradaParroquia(E2.get(), t)) button3 = Button(t, text="Borrar", command=lambda: self.BorrarParroquial(E2.get(), t)) button3.config(state="disabled") button1.grid(row=2, column=0) button2.grid(row=2, column=1) button3.grid(row=2, column=2) def editarEstudio(self): t = Toplevel(self) t.wm_title("Estudio") Label(t, text="Nombre").grid(row=0, column=1) E2 = Entry(t) E2.insert(END, self.selectorEstudios.get()) E2.grid(row=1, column=1) nombreOld = self.selectorEstudios.get() button1 = Button(t, text="Cancelar", command=lambda: t.destroy()) button2 = Button(t, text="Guardar", command=lambda: self.actualizarEstudio(nombreOld, E2.get(), t)) button3 = Button(t, text="Borrar", command=lambda: self.BorrarEstudios(E2.get(), t)) button1.grid(row=2, column=0) button2.grid(row=2, column=1) button3.grid(row=2, column=2) def editarPais(self): t = Toplevel(self) t.wm_title("Pais") Label(t, text="Nombre").grid(row=0, column=1) E2 = Entry(t) E2.insert(END, self.selectorPais.get()) E2.grid(row=1, column=1) nombreOld = self.selectorPais.get() button1 = Button(t, text="Cancelar", command=lambda: t.destroy()) button2 = Button(t, text="Guardar", command=lambda: self.actualizarPais(nombreOld, E2.get(), t)) button3 = Button(t, text="Borrar", command=lambda: self.BorrarPais(E2.get(), t)) button1.grid(row=2, column=0) button2.grid(row=2, column=1) button3.grid(row=2, column=2) def editarParroquia(self): t = Toplevel(self) t.wm_title("Estudio") Label(t, text="Nombre").grid(row=0, column=1) E2 = Entry(t) E2.insert(END, self.selectorParroquial.get()) E2.grid(row=1, column=1) nombreOld = self.selectorParroquial.get() button1 = Button(t, text="Cancelar", command=lambda: t.destroy()) button2 = Button(t, text="Guardar", command=lambda: self.actualizarParroquia(nombreOld, E2.get(), t)) button3 = Button(t, text="Borrar", command=lambda: self.BorrarParroquial(E2.get(), t)) button1.grid(row=2, column=0) button2.grid(row=2, column=1) button3.grid(row=2, column=2) def actualizarPais(self, nombreOld, nombreN, t): global cnx cursor = cnx.cursor() query = ("UPDATE caritas.pais SET nombre= ('%s') WHERE nombre = ('%s')" % (nombreN, nombreOld)) cursor.execute(query) cnx.commit() cursor.close() self.getPais() self.selectorPais['values'] = self.listadoPais[0] t.destroy() def actualizarEstudio(self, nombreOld, nombreN, t): global cnx cursor = cnx.cursor() query = ("UPDATE caritas.estudio SET nombre= ('%s') WHERE nombre = ('%s')" % (nombreN, nombreOld)) cursor.execute(query) cnx.commit() cursor.close() self.getEstudios() self.selectorEstudios['values'] = self.listadoEstudios[0] t.destroy() def actualizarParroquia(self, nombreOld, nombreN, t): global cnx cursor = cnx.cursor() query = ("UPDATE caritas.parroquial SET nombre= ('%s') WHERE nombre = ('%s')" % (nombreN, nombreOld)) cursor.execute(query) cnx.commit() cursor.close() self.getParroquial() self.selectorParroquial['values'] = self.listadoParroquial[0] t.destroy() def BorrarEstudios(self, nombre, t): global cnx cursor = cnx.cursor() query = ("DELETE FROM caritas.estudio WHERE nombre = ('%s')" % nombre) cursor.execute(query) cnx.commit() cursor.close() self.getEstudios() self.selectorEstudios['values'] = self.listadoEstudios[0] t.destroy() def BorrarPais(self, nombre, t): global cnx cursor = cnx.cursor() query = ("DELETE FROM caritas.pais WHERE nombre = ('%s')" % nombre) cursor.execute(query) cnx.commit() cursor.close() self.getPais() self.selectorPais['values'] = self.listadoPais[0] t.destroy() def BorrarParroquial(self, nombre, t): global cnx cursor = cnx.cursor() query = ("DELETE FROM caritas.parroquial WHERE nombre = ('%s')" % nombre) cursor.execute(query) cnx.commit() cursor.close() self.getParroquial() self.selectorParroquial['values'] = self.listadoParroquial[0] t.destroy() def nuevaEntradaEstudios(self, nombre, t): global cnx cursor = cnx.cursor() query = ("INSERT INTO caritas.estudio (nombre) VALUE ('%s')" % nombre) cursor.execute(query) cnx.commit() cursor.close() self.getEstudios() self.selectorEstudios['values'] = self.listadoEstudios[0] t.destroy() def nuevaEntradaPais(self, nombre, t): global cnx cursor = cnx.cursor() query = ("INSERT INTO caritas.pais (nombre) VALUE ('%s')" % nombre) cursor.execute(query) cnx.commit() cursor.close() self.getPais() self.selectorPais['values'] = self.listadoPais[0] t.destroy() def nuevaEntradaParroquia(self, nombre, t): global cnx cursor = cnx.cursor() query = ("INSERT INTO caritas.parroquial (nombre) VALUE ('%s')" % nombre) cursor.execute(query) cnx.commit() cursor.close() self.getParroquial() self.selectorParroquial['values'] = self.listadoParroquial[0] t.destroy() def ventanaVoluntarios(self,row): id = -1 guardar = TRUE # Creamos una ventana nueva t = Toplevel(self) t.wm_title("Crear Voluntario") # Etiqueta y entrada de nombre Label(t, text="Nombre").grid(row=0) entradaNombre = Entry(t) entradaNombre.grid(row=0, column=1,sticky = "ew") # Etiqueta y entrada de apellidos Label(t, text="Apellidos").grid(row=1) entradaApellidos = Entry(t) entradaApellidos.grid(row=1, column=1,sticky = "ew") # Etiqueta y entrada de DNI Label(t, text="DNI").grid(row=2) entradaDNI = Entry(t) entradaDNI.grid(row=2, column=1,sticky = "ew") # Etiqueta y entrada de Dirreccion Label(t, text="Direccion").grid(row=3) entradaDireccion = Entry(t) entradaDireccion.grid(row=3, column=1) # Etiqueta y seleccion de Estudios Label(t, text="Estudios").grid(row=4) box_value = StringVar() self.getEstudios() self.selectorEstudios = Combobox(t, textvariable=box_value, state='readonly') self.selectorEstudios['values'] = self.listadoEstudios[0] self.selectorEstudios.configure(width=25) self.selectorEstudios.current(0) self.selectorEstudios.grid(row=4, column=1) botonEditarEstudios = Button(t, text="Editar", command=self.editarEstudio) botonNuevosEstudios = Button(t, text="Nuevo", command=self.nuevoEstudio) botonEditarEstudios.grid(row=4, column=2) botonNuevosEstudios.grid(row=4, column=3) # Etiqueta y seleccion de Genero Label(t, text="Genero").grid(row=5) seleccionGenero = Combobox(t, values=["Masculino (M)", "Femenino (F)"], state='readonly') seleccionGenero.grid(row=5, column=1) # Etiqueta y seleccion de Parroquial Label(t, text="Parroquial").grid(row=6) box_value = StringVar() self.getParroquial() self.selectorParroquial = Combobox(t, textvariable=box_value, state='readonly') self.selectorParroquial['values'] = self.listadoParroquial[0] self.selectorParroquial.configure(width=25) self.selectorParroquial.current(0) self.selectorParroquial.grid(row=6, column=1) botonEditarParroquial = Button(t, text="Editar", command=self.editarParroquia) botonNuevaParroqual = Button(t, text="Nuevo", command=self.nuevaParroquia) botonEditarParroquial.grid(row=6, column=2) botonNuevaParroqual.grid(row=6, column=3) # Etiqueta y seleccion de Correo Label(t, text="Correo").grid(row=0, column=4) entradaCorreo = Entry(t) entradaCorreo.grid(row=0, column=5) Label(t, text="Telefono 1").grid(row=1, column=4) entradaTelefono1 = Entry(t) entradaTelefono1.grid(row=1, column=5) Label(t, text="Telefono 2").grid(row=2, column=4) entradaTelefono2 = Entry(t) entradaTelefono2.grid(row=2, column=5) # Etiqueta y entrada de Fecha Label(t, text="Fecha").grid(row=3, column=4) entradaAno = Entry(t) entradaMes = Entry(t) entradaDia = Entry(t) entradaAno.grid(row=3, column=5) entradaMes.grid(row=3, column=6) entradaDia.grid(row=3, column=7) # Etiqueta y seleccion de Pais Label(t, text="Pais").grid(row=4, column=4) box_value = StringVar() self.getPais() self.selectorPais = Combobox(t, textvariable=box_value, state='readonly') self.selectorPais['values'] = self.listadoPais[0] self.selectorPais.configure(width=25) self.selectorPais.current(0) self.selectorPais.grid(row=4, column=5) botonEditarPais = Button(t, text="Editar", command=self.editarPais) botonNuevaPais = Button(t, text="Nuevo", command=self.nuevoPais) botonEditarPais.grid(row=4, column=6) botonNuevaPais.grid(row=4, column=7) #Rellenamos los cambos si estamos editando if row > -1: voluntario = self.table.model.getRecordAtRow(row) entradaNombre.insert(END,voluntario['nombre']) entradaApellidos.insert(END,voluntario['apellidos']) entradaCorreo.insert(END,voluntario['correo_electronico']) entradaTelefono1.insert(END,voluntario['telefono_1']) entradaTelefono2.insert(END,voluntario['telefono_2']) entradaDireccion.insert(END,voluntario['direccion']) entradaDNI.insert(END,voluntario['dni']) self.selectorEstudios.set(voluntario['estudio']) self.selectorParroquial.set(voluntario['parroquial']) guardar = FALSE id = voluntario['id'] button5 = Button(t, text="Guardar", command=lambda: self.nuevoVoluntario(entradaNombre.get(), entradaApellidos.get(),entradaDNI.get(),entradaDireccion.get(), entradaCorreo.get(),1,self.listadoEstudios[1][self.selectorEstudios.current()], self.listadoParroquial[1][self.selectorParroquial.current()], 1,entradaTelefono1.get(),entradaTelefono2.get(),"M","2001-01-01",t,guardar,id)) button6 = Button(t, text="Cancelar", command=t.destroy) button5.grid(row=7, column=4) button6.grid(row=7, column=5) def validarVoluntario(self, nombre, apellidos, dni, direccion, correo_electronico, localidad_id, estudio_id, parroquial_id, proyecto_id, telefono_1, telefono_2, genero, fecha_nacimiento,t,estado,id): guarda = True error = "" if len(nombre)<3 : error = error + "Nombre debe tener mas de 2 caracteres\n" guarda = False if len(apellidos)<3 : error = error + "Apellidos debe tener mas de 2 caracteres\n" guarda = False if len(dni)==9 and dni[8].isalpha() and dni[0-7].isdigit(): error = error + "Dni tiene el formato NNNNNNNNX donde N es un digito y X una letra \n" guarda = False if len(direccion)==0: error = error + "Introduzca una Dirección \n" guarda = False if len(correo_electronico)<5: error = error + "Introduzca una dirección de correo valida \n" guarda = False if len(telefono_1)<9: error = error + "Introduzca un numero valido \n" guarda = False if len(telefono_1)==0: telefono_1=0 if guarda:self.nuevoVoluntario(nombre, apellidos, dni, direccion, correo_electronico, localidad_id, estudio_id, parroquial_id, proyecto_id, telefono_1, telefono_2, genero, fecha_nacimiento,t,estado,id) # añadir el error else: print error def ventanaImprimir(self): t = Toplevel(self) t.wm_title("Imprimir") Label(t, text="Numero de Copias por etiqueta").pack() w = Spinbox(t, from_=1, to=10) w.pack() buttonImprimir = Button(t, text="Imprimir", command=lambda:self.imprimir(int(w.get()),t)) buttonImprimir.pack() def agregarListado(self,numero): voluntario = self.table.model.getRecordAtRow(numero) modelNuevo = TableModel() modelNuevo.addColumn("nombre") modelNuevo.addColumn("apellidos") modelNuevo.addColumn("dni") modelNuevo.addColumn("direccion") modelNuevo.addColumn("correo_electronico") modelNuevo.addColumn("estudio") modelNuevo.addColumn("parroquial") modelNuevo.addColumn("proyecto") modelNuevo.addColumn("genero") modelNuevo.addColumn("fecha_nacimiento") modelNuevo.addColumn("telefono_1") modelNuevo.addColumn("telefono_2") arrayListado = self.selectTable.getModel().data valores = {} i=1 for values in arrayListado: valores['row',i]=arrayListado['row',i] i+=1 valores['row',i]=voluntario modelNuevo.importDict(valores) self.selectTable.updateModel(modelNuevo) self.selectTable.redrawTable() def quitarListado(self,numero): voluntario = self.selectTable.model.getRecordAtRow(numero) modelNuevo = TableModel() modelNuevo.addColumn("nombre") modelNuevo.addColumn("apellidos") modelNuevo.addColumn("dni") modelNuevo.addColumn("direccion") modelNuevo.addColumn("correo_electronico") modelNuevo.addColumn("estudio") modelNuevo.addColumn("parroquial") modelNuevo.addColumn("proyecto") modelNuevo.addColumn("genero") modelNuevo.addColumn("fecha_nacimiento") modelNuevo.addColumn("telefono_1") modelNuevo.addColumn("telefono_2") print numero arrayListado = self.selectTable.getModel().data valores = {} i=1 for values in arrayListado: if numero+1 != i: valores['row',i]=arrayListado['row',i] i+=1 modelNuevo.importDict(valores) self.selectTable.updateModel(modelNuevo) self.selectTable.redrawTable() def imprimir(self,numero,label): pdf = fpdf.FPDF(format='letter') pdf.add_page() pdf.set_font("Arial", size=14) indice=1 columna=1 fila=0 p=0 for ficha in self.listadoSeleccionado: row = self.listadoSeleccionado['row',indice] for x in range(0, numero): if p==9: pdf.add_page() p=0 else: p+=1 texto = 'Nombre: %s\nApellidos: %s\nDireccion: %s\nTelefono: %s' %(row["nombre"],row["apellidos"],row["direccion"],row["telefono_1"]) pdf.multi_cell(65, 10,texto,align='C') pdf.set_xy(70*columna,60*fila +10) columna = columna + 1 if columna == 4: columna=1 fila=fila+1 pdf.set_xy(10,60*fila +10) indice = indice + 1 pdf.output("tutorial.pdf") label.destroy() def buscar(self,nombre,apellidos): modelCompleto = TableModel() modelNuevo = TableModel() modelNuevo.addColumn("nombre") modelNuevo.addColumn("apellidos") modelNuevo.addColumn("dni") modelNuevo.addColumn("direccion") modelNuevo.addColumn("correo_electronico") modelNuevo.addColumn("estudio") modelNuevo.addColumn("parroquial") modelNuevo.addColumn("proyecto") modelNuevo.addColumn("genero") modelNuevo.addColumn("fecha_nacimiento") modelNuevo.addColumn("telefono_1") modelNuevo.addColumn("telefono_2") self.listilla= queryAllVoluntarios() modelCompleto.importDict(self.listilla) searchterms = [('nombre', nombre, 'contains', 'AND'),('apellidos', apellidos, 'contains', 'AND')] result=modelCompleto.getDict(modelCompleto.columnNames, filters=searchterms) modelNuevo.importDict(result) self.listadoSeleccionado = result self.table.updateModel(modelNuevo) self.table.redrawTable() def eventoClic(self): print "Clicado" return def initUI(self): self.parent.title("Caritas") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) frameMenu = Frame(self) frameMenu.pack(fill="both", expand="0", side=RIGHT) labelBusqueda = LabelFrame(frameMenu, text="Busqueda") labelBusqueda.pack(fill="x",expand =1) labelVoluntarios = LabelFrame(frameMenu) labelVoluntarios.pack(fill="both",expand =0) frameTabla = Frame(self) frameTabla.pack(fill="both", expand="1", side=LEFT) labelTabla = LabelFrame(frameTabla) labelTabla.pack(fill="both", expand="1") labelBotonera = LabelFrame(frameTabla) labelTabla.pack(fill="both", expand="1") labelSelect = LabelFrame(frameTabla) labelSelect.pack(fill="both", expand="1") model = TableModel() modelSelect = TableModel() model.addColumn("nombre") model.addColumn("apellidos") model.addColumn("dni") model.addColumn("direccion") model.addColumn("correo_electronico") model.addColumn("estudio") model.addColumn("parroquial") model.addColumn("proyecto") model.addColumn("genero") model.addColumn("fecha_nacimiento") model.addColumn("telefono_1") model.addColumn("telefono_2") modelSelect.addColumn("nombre") modelSelect.addColumn("apellidos") modelSelect.addColumn("dni") modelSelect.addColumn("direccion") modelSelect.addColumn("correo_electronico") modelSelect.addColumn("estudio") modelSelect.addColumn("parroquial") modelSelect.addColumn("proyecto") modelSelect.addColumn("genero") modelSelect.addColumn("fecha_nacimiento") modelSelect.addColumn("telefono_1") modelSelect.addColumn("telefono_2") #Tabla Voluntarios self.listilla= queryAllVoluntarios() model.importDict(self.listilla) self.table = TableCanvas(labelTabla, model=model,editable=False) self.table.createTableFrame() self.table.handle_double_click(self.eventoClic) #Tabla Seleccionados self.selectTable = TableCanvas(labelSelect, model=modelSelect,editable=False) self.selectTable.createTableFrame() self.listadoSeleccionado = [] L1 = Label(labelBusqueda, text="Nombre") L1.pack() E1 = Entry(labelBusqueda) E1.pack() L2 = Label(labelBusqueda, text="Apellidos") L2.pack() E2 = Entry(labelBusqueda) E2.pack() botonArriba = Button(labelVoluntarios, text="Agregar al listado", command=lambda:self.agregarListado(self.table.getSelectedRow())) botonArriba.pack() botonAbajo = Button(labelVoluntarios, text="Quitar del listado", command=lambda:self.quitarListado(self.selectTable.getSelectedRow())) botonAbajo.pack() button = Button(labelBusqueda, text="Buscar", command=lambda: self.buscar(E1.get(),E2.get())) button.pack() button = Button(labelVoluntarios, text="Nuevo Voluntario", command=lambda:self.ventanaVoluntarios(-1)) button.pack() buttonEditar = Button(labelVoluntarios, text="Editar Voluntario", command=lambda:self.ventanaVoluntarios(self.table.getSelectedRow())) buttonEditar.pack() buttonImprimir = Button(labelVoluntarios, text="Imprimir", command=lambda:self.ventanaImprimir()) buttonImprimir.pack()
class IniGenGui(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.inigen = IniGen() self.initUIGlobals() def initUIGlobals(self): """ This is the first part of the window to be rendered. After these have been set by the user and 'Emit Globals' has been clicked, the given algorithm can then specify how to generate the second part of the window. All fields are disabled for user input after globals have been emitted. Information in Global Parameters: Algorithm - name of the algorithm to use File Name - name of the output file to be generated Min Time - Minimum Time for distillers to run Max Time - Maximum Time for distillers to run Set Enabled: - checkbox to specify if the distiller should be enabled True or False """ self.parent.title("Ini Generator") Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10') # initialize row counter. This is incremented after each element added to grid row = 0 # initialize column counter. This is incremented after a column has been filled self.column = 0 # Globals: entries for info common to all runs label_globals = Label(self, text="Globals") label_globals.grid(row=row, column=self.column) row += 1 label_alg = Label(self, text="Algorithm") label_alg.grid(row=row, column=self.column, sticky=E + W) row += 1 self.cbox_alg = Combobox(self, values=algorithms.keys(), state='readonly') self.cbox_alg.current(0) self.cbox_alg.grid(row=row, column=self.column, sticky=E + W + S + N) row += 1 label_filename = Label(self, text="Output File Name") label_filename.grid(row=row, column=self.column, sticky=E + W) row += 1 self.entry_filename = Entry(self) self.entry_filename.grid(row=row, column=self.column, sticky=W + E) row += 1 label_mintime = Label(self, text="Min Time") label_mintime.grid(row=row, column=self.column, sticky=E + W) row += 1 self.entry_mintime = Entry(self) self.entry_mintime.grid(row=row, column=self.column, sticky=W + E) row += 1 label_maxtime = Label(self, text="Max Time") label_maxtime.grid(row=row, column=self.column, sticky=W + E) row += 1 self.entry_maxtime = Entry(self) self.entry_maxtime.grid(row=row, column=self.column, sticky=W + E) row += 1 self.enabled = IntVar() self.check_enabled = Checkbutton(self, text="set enabled", variable=self.enabled) self.check_enabled.grid(row=row, column=self.column, sticky=W + E) row += 1 # Control: buttons used to emmiting text and generating file self.button_emit_globals = Button(self, text="Emit Globals", command=self.emit_globals) self.button_emit_globals.grid(row=row, column=self.column, sticky=W + E) row += 1 button_addrun = Button(self, text="Add Run", command=self.emit_run) button_addrun.grid(row=row, column=self.column, sticky=W + E) row += 1 button_generate = Button(self, text="Generate File", command=self.generate_file) button_generate.grid(row=row, column=self.column, sticky=W + E) row += 1 self.column += 1 self.pack() def initUIRuns(self): """ Second part of gui to be rendered. This contains all the fields needed to emit a single run within a distiller file. Multiple runs can be added by clicking 'Add Run' multiple times. Information in Run Parameters: Run Name - header name for run Dependencies - description and uuid fields for each dependency in the algorithm Params - parameter fields for each parameter in the algorithm """ self.entry_run_name = None self.entries_dep_description = [] self.entries_dep_uuid = [] self.entries_param = [] row = 0 label_runs = Label(self, text="Runs") label_runs.grid(row=row, column=self.column) row += 1 label_run_name = Label(self, text="Run Name") label_run_name.grid(row=row, column=self.column, sticky=W + E) row += 1 self.entry_run_name = Entry(self) self.entry_run_name.grid(row=row, column=self.column, sticky=W + E) row += 1 algorithm = self.cbox_alg.get() settings = algorithms[algorithm] for dep in settings['deps']: if row >= 21: self.column += 1 row = 1 label_dep_description = Label(self, text="{0} (description)".format(dep)) label_dep_description.grid(row=row, column=self.column, sticky=W + E) row += 1 entry_dep_description = Entry(self) entry_dep_description.grid(row=row, column=self.column, sticky=W + E) row += 1 label_dep_uuid = Label(self, text="{0} (uuid)".format(dep)) label_dep_uuid.grid(row=row, column=self.column, sticky=W + E) row += 1 entry_dep_uuid = Entry(self) entry_dep_uuid.grid(row=row, column=self.column, sticky=W + E) row += 1 self.entries_dep_description.append(entry_dep_description) self.entries_dep_uuid.append(entry_dep_uuid) for param in settings['params']: if row >= 21: self.column += 1 row = 1 label_param = Label(self, text=param) label_param.grid(row=row, column=self.column, sticky=W + E) row += 1 entry_param = Entry(self) entry_param.grid(row=row, column=self.column, sticky=W + E) row += 1 self.entries_param.append(entry_param) row = 0 self.column += 1 self.text_file = Text(self) self.text_file.grid(row=row, column=self.column, rowspan=31, sticky=W + E + N + S, padx=5, pady=5) self.column += 1 scrollbar = Scrollbar(self, command=self.text_file.yview) self.text_file.config(yscrollcommand=scrollbar.set) scrollbar.grid(row=row, column=self.column, rowspan=31, sticky=N + S) self.pack() def emit_globals(self): self.algorithm = algorithms[self.cbox_alg.get()] path = self.algorithm['path'] if self.enabled.get(): enabled = 'True' else: enabled = 'False' lines = self.inigen.emit_global(path, enabled) self.mintime = self.entry_mintime.get() self.maxtime = self.entry_maxtime.get() self.cbox_alg.configure(state='disabled') self.entry_filename.configure(state='disabled') self.entry_mintime.configure(state='disabled') self.entry_maxtime.configure(state='disabled') self.check_enabled.configure(state='disabled') self.button_emit_globals.configure(state='disabled') self.initUIRuns() self.update_text(lines) def emit_run(self): label = self.entry_run_name.get() chunking = 'parallel' #hardcoded for now mintime = self.mintime maxtime = self.maxtime lines = self.inigen.emit_run_header(label, chunking, mintime, maxtime) self.update_text(lines) deps = [] for i in range(len(self.entries_dep_description)): deps.append([ self.entries_dep_description[i].get(), self.algorithm['deps'][i], self.entries_dep_uuid[i].get() ]) params = [] for i in range(len(self.entries_param)): params.append( [self.algorithm['params'][i], self.entries_param[i].get()]) outputs = self.algorithm['outputs'] lines = self.inigen.emit_run_body(deps, params, outputs) self.update_text(lines) def generate_file(self): self.inigen.generate_file(self.entry_filename.get()) self.quit() def update_text(self, lines): self.text_file.configure(state='normal') string = "\n".join(lines) self.text_file.insert(END, string) self.text_file.configure(state='disabled')
class MainFrame(Frame): def __init__(self,parent,stdoutq): Frame.__init__(self,parent) self.parent=parent self.width=850 self.height=650 self.title=menotexport.__version__ self.stdoutq=stdoutq self.initUI() self.hasdb=False self.hasout=False self.hasaction=False self.exit=False self.path_frame=self.addPathFrame() self.action_frame=self.addActionFrame() self.message_frame=self.addMessageFrame() self.printStr() self.stateq=Queue.Queue() #self.workproc=Pool(1) def centerWindow(self): sw=self.parent.winfo_screenwidth() sh=self.parent.winfo_screenheight() x=(sw-self.width)/2 y=(sh-self.height)/2 self.parent.geometry('%dx%d+%d+%d' \ %(self.width,self.height,x,y)) def initUI(self): self.parent.title(self.title) self.style=Style() #Choose from default, clam, alt, classic self.style.theme_use('alt') self.pack(fill=tk.BOTH,expand=True) self.centerWindow() def printStr(self): while self.stdoutq.qsize() and self.exit==False: try: msg=self.stdoutq.get() self.text.update() self.text.insert(tk.END,msg) self.text.see(tk.END) except Queue.Empty: pass self.after(100,self.printStr) def checkReady(self): if self.isexport.get()==1 or self.ishighlight.get()==1\ or self.isnote.get()==1 or self.isbib.get()==1: self.hasaction=True else: self.hasaction=False if self.hasdb and self.hasout and self.hasaction: self.start_button.configure(state=tk.NORMAL) print('# <Menotexport>: Menotexport Ready.') else: self.start_button.configure(state=tk.DISABLED) def addPathFrame(self): frame=Frame(self) frame.pack(fill=tk.X,expand=0,side=tk.TOP,padx=8,pady=5) frame.columnconfigure(1,weight=1) #------------------Database file------------------ label=tk.Label(frame,text='Mendeley Data file:',\ bg='#bbb') label.grid(row=0,column=0,\ sticky=tk.W,padx=8) self.db_entry=tk.Entry(frame) self.db_entry.grid(row=0,column=1,sticky=tk.W+tk.E,padx=8) self.db_button=tk.Button(frame,text='Open',command=self.openFile) self.db_button.grid(row=0,column=2,padx=8,sticky=tk.E) hint=''' Default location on Linux: ~/.local/share/data/Mendeley\ Ltd./Mendeley\ Desktop/[email protected] Default location on Windows: C:\Users\Your_name\AppData\Local\Mendeley Ltd\Mendeley Desktop\[email protected]''' hint_label=tk.Label(frame,text=hint,\ justify=tk.LEFT,anchor=tk.NW) hint_label.grid(row=1,column=0,columnspan=3,\ sticky=tk.W,padx=8) #--------------------Output dir-------------------- label2=tk.Label(frame,text='Output folder:',\ bg='#bbb') label2.grid(row=2,column=0,\ sticky=tk.W,padx=8) self.out_entry=tk.Entry(frame) self.out_entry.grid(row=2,column=1,sticky=tk.W+tk.E,padx=8) self.out_button=tk.Button(frame,text='Choose',command=self.openDir) self.out_button.grid(row=2,column=2,padx=8,sticky=tk.E) def openDir(self): self.out_entry.delete(0,tk.END) dirname=askdirectory() self.out_entry.insert(tk.END,dirname) if len(dirname)>0: print('# <Menotexport>: Output folder: %s' %dirname) self.hasout=True self.checkReady() def openFile(self): self.db_entry.delete(0,tk.END) ftypes=[('sqlite files','*.sqlite'),('ALL files','*')] initialdir='~/.local/share/data/Mendeley Ltd./Mendeley Desktop' initialdir=os.path.expanduser(initialdir) if os.path.isdir(initialdir): filename=askopenfilename(filetypes=ftypes,initialdir=initialdir) else: filename=askopenfilename(filetypes=ftypes) self.db_entry.insert(tk.END,filename) if len(filename)>0: print('# <Menotexport>: Database file: %s' %filename) self.probeFolders() def probeFolders(self): dbfile=self.db_entry.get() try: db=sqlite3.connect(dbfile) self.menfolderlist=menotexport.getFolderList(db,None) #(id, name) self.foldernames=['All']+[ii[1] for ii in self.menfolderlist] #names to display self.foldersmenu['values']=tuple(self.foldernames) self.foldersmenu.current(0) db.close() self.hasdb=True self.checkReady() except Exception as e: print('# <Menotexport>: Failed to recoganize the given database file.') print(e) def addActionFrame(self): frame=Frame(self,relief=tk.RAISED,borderwidth=1) frame.pack(fill=tk.X,side=tk.TOP,\ expand=0,padx=8,pady=5) label=tk.Label(frame,text='Actions:',bg='#bbb') label.grid(row=0,column=0,sticky=tk.W,padx=8) #---------------Action checkbuttons--------------- self.isexport=tk.IntVar() self.ishighlight=tk.IntVar() self.isnote=tk.IntVar() self.isbib=tk.IntVar() self.isris=tk.IntVar() self.isseparate=tk.IntVar() self.iszotero=tk.IntVar() self.iscustomtemp=tk.IntVar() self.check_export=tk.Checkbutton(frame,text='Export PDFs',\ variable=self.isexport,command=self.doExport) self.check_highlight=tk.Checkbutton(frame,\ text='Extract highlights',\ variable=self.ishighlight,command=self.doHighlight) self.check_note=tk.Checkbutton(frame,\ text='Extract notes',\ variable=self.isnote,command=self.doNote) self.check_bib=tk.Checkbutton(frame,\ text='Export .bib',\ variable=self.isbib,command=self.doBib) self.check_ris=tk.Checkbutton(frame,\ text='Export .ris',\ variable=self.isris,command=self.doRis) self.check_separate=tk.Checkbutton(frame,\ text='Save separately',\ variable=self.isseparate,command=self.doSeparate,\ state=tk.DISABLED) self.check_iszotero=tk.Checkbutton(frame,\ text='For import to Zotero',\ variable=self.iszotero,command=self.doIszotero,\ state=tk.DISABLED) self.check_custom_template=tk.Checkbutton(frame,\ text='Use custom template (experimental)',\ variable=self.iscustomtemp,command=self.doCustomTemp,\ state=tk.DISABLED) frame.columnconfigure(0,weight=1) self.check_export.grid(row=1,column=1,padx=8,sticky=tk.W) self.check_highlight.grid(row=1,column=2,padx=8,sticky=tk.W) self.check_note.grid(row=1,column=3,padx=8,sticky=tk.W) self.check_bib.grid(row=2,column=1,padx=8,sticky=tk.W) self.check_ris.grid(row=2,column=2,padx=8,sticky=tk.W) self.check_separate.grid(row=2,column=3,padx=8,sticky=tk.W) self.check_iszotero.grid(row=3,column=1,padx=8,sticky=tk.W) self.check_custom_template.grid(row=3,column=2,padx=8,sticky=tk.W) #---------------------2nd row--------------------- subframe=Frame(frame) subframe.grid(row=4,column=0,columnspan=6,sticky=tk.W+tk.E,\ pady=5) #-------------------Folder options------------------- folderlabel=tk.Label(subframe,text='Mendeley folder:',\ bg='#bbb') folderlabel.pack(side=tk.LEFT, padx=8) self.menfolder=tk.StringVar() self.menfolderlist=['All',] self.foldersmenu=Combobox(subframe,textvariable=\ self.menfolder,values=self.menfolderlist,state='readonly') self.foldersmenu.current(0) self.foldersmenu.bind('<<ComboboxSelected>>',self.setfolder) self.foldersmenu.pack(side=tk.LEFT,padx=8) #-------------------Quit button------------------- quit_button=tk.Button(subframe,text='Quit',\ command=self.quit) quit_button.pack(side=tk.RIGHT,padx=8) #-------------------Stop button------------------- ''' self.stop_button=tk.Button(subframe,text='Stop',\ command=self.stop) self.stop_button.pack(side=tk.RIGHT,padx=8) ''' #-------------------Start button------------------- self.start_button=tk.Button(subframe,text='Start',\ command=self.start,state=tk.DISABLED) self.start_button.pack(side=tk.RIGHT,pady=8) #-------------------Help button------------------- self.help_button=tk.Button(subframe,text='Help',\ command=self.showHelp) self.help_button.pack(side=tk.RIGHT,padx=8) def setfolder(self,x): self.foldersmenu.selection_clear() self.menfolder=self.foldersmenu.get() self.foldersmenu.set(self.menfolder) if self.menfolder=='All': print('# <Menotexport>: Work on all folders.') else: print('# <Menotexport>: Select Mendeley folder: '+str(self.menfolder)) def doExport(self): if self.isexport.get()==1: print('# <Menotexport>: Export annotated PDFs.') else: print('# <Menotexport>: Dont export annotated PDFs.') self.checkReady() def doHighlight(self): if self.ishighlight.get()==1: print('# <Menotexport>: Extract highlighted texts.') self.check_separate.configure(state=tk.NORMAL) self.check_custom_template.configure(state=tk.NORMAL) else: print('# <Menotexport>: Dont extract highlighted texts.') if self.isnote.get()==0: self.check_separate.configure(state=tk.DISABLED) self.check_custom_template.configure(state=tk.DISABLED) self.checkReady() def doNote(self): if self.isnote.get()==1: print('# <Menotexport>: Extract notes.') self.check_separate.configure(state=tk.NORMAL) self.check_custom_template.configure(state=tk.NORMAL) else: print('# <Menotexport>: Dont extract notes.') self.check_separate.state=tk.DISABLED if self.ishighlight.get()==0: self.check_separate.configure(state=tk.DISABLED) self.check_custom_template.configure(state=tk.DISABLED) self.checkReady() self.checkReady() def doBib(self): if self.isbib.get()==1: print('# <Menotexport>: Export to .bib file.') self.check_iszotero.configure(state=tk.NORMAL) else: print('# <Menotexport>: Dont export .bib file.') if self.isris.get()==0: self.check_iszotero.configure(state=tk.DISABLED) self.checkReady() def doRis(self): if self.isris.get()==1: print('# <Menotexport>: Export to .ris file.') self.check_iszotero.configure(state=tk.NORMAL) else: print('# <Menotexport>: Dont export .ris file.') if self.isbib.get()==0: self.check_iszotero.configure(state=tk.DISABLED) self.checkReady() def doSeparate(self): if self.isseparate.get()==1: print('# <Menotexport>: Save annotations separately.') else: print('# <Menotexport>: Save all annotations to single file.') def doIszotero(self): if self.iszotero.get()==1: print('# <Menotexport>: Save .bib/.ris file in Zotero preferred format.') else: print('# <Menotexport>: Save .bib/.ris file to default format.') def doCustomTemp(self): if self.iscustomtemp.get()==1: print('# <Menotexport>: Use custom template for exported annotations.') else: print('# <Menotexport>: Use default template for exported annotations.') def showHelp(self): helpstr=''' %s\n\n - Export PDFs: Bulk export PDFs.\n - Extract highlights: Extract highlighted texts and output to txt files.\n - Extract notes: Extract notes and output to txt files.\n - Export .bib: Export meta-data and annotations to .bib files.\n - Export .ris: Export meta-data and annotations to .ris files.\n - For import to Zotero: Exported .bib and/or .ris files have suitable format to import to Zotero.\n - Save separately: If on, save each PDF's annotations to a separate txt.\n - Use custom annotation template: Use a custom template to format the exported annotations. See annotation_template.py for details. - See README.md for more info.\n ''' %self.title tkMessageBox.showinfo(title='Help', message=helpstr) #print(self.menfolder.get()) def start(self): dbfile=self.db_entry.get() outdir=self.out_entry.get() self.menfolder=self.foldersmenu.get() # get (folderid, folder) for folder for ii in self.menfolderlist: if ii[1]==self.menfolder: folder_sel=[ii[0],ii[1].split('/')[-1]] action=[] if self.isexport.get()==1: action.append('p') if self.ishighlight.get()==1: action.append('m') if self.isnote.get()==1: action.append('n') if self.isbib.get()==1: action.append('b') if self.isris.get()==1: action.append('r') if self.isseparate.get()==1: separate=True else: separate=False if self.iszotero.get()==1: iszotero=True else: iszotero=False if self.iscustomtemp.get()==1: action.append('t') if 'p' in action or 'm' in action or 'n' in action or 'b' in action or 'r' in action: self.db_button.configure(state=tk.DISABLED) self.out_button.configure(state=tk.DISABLED) self.start_button.configure(state=tk.DISABLED) self.help_button.configure(state=tk.DISABLED) self.foldersmenu.configure(state=tk.DISABLED) self.check_export.configure(state=tk.DISABLED) self.check_highlight.configure(state=tk.DISABLED) self.check_note.configure(state=tk.DISABLED) self.check_bib.configure(state=tk.DISABLED) self.check_ris.configure(state=tk.DISABLED) self.check_separate.configure(state=tk.DISABLED) self.check_iszotero.configure(state=tk.DISABLED) self.check_custom_template.configure(state=tk.DISABLED) self.messagelabel.configure(text='Message (working...)') folder=None if self.menfolder=='All' else folder_sel args=[dbfile,outdir,action,folder,separate,iszotero,True] self.workthread=WorkThread('work',False,self.stateq) self.workthread.deamon=True self.workthread.args=args self.workthread.start() self.reset() ''' self.workproc.apply_async(menotexport.main,args,\ callback=self.reset) self.workproc.join() ''' def reset(self): while self.stateq.qsize() and self.exit==False: try: msg=self.stateq.get() if msg=='done': self.db_button.configure(state=tk.NORMAL) self.out_button.configure(state=tk.NORMAL) self.start_button.configure(state=tk.NORMAL) self.help_button.configure(state=tk.NORMAL) self.foldersmenu.configure(state='readonly') self.check_export.configure(state=tk.NORMAL) self.check_highlight.configure(state=tk.NORMAL) self.check_note.configure(state=tk.NORMAL) self.check_bib.configure(state=tk.NORMAL) self.check_separate.configure(state=tk.NORMAL) self.check_iszotero.configure(state=tk.NORMAL) self.check_custom_template.configure(state=tk.NORMAL) self.messagelabel.configure(text='Message') return except Queue.Empty: pass self.after(100,self.reset) def stop(self): #self.workthread.stop() pass def addMessageFrame(self): frame=Frame(self) frame.pack(fill=tk.BOTH,side=tk.TOP,\ expand=1,padx=8,pady=5) self.messagelabel=tk.Label(frame,text='Message',bg='#bbb') self.messagelabel.pack(side=tk.TOP,fill=tk.X) self.text=tk.Text(frame) self.text.pack(side=tk.TOP,fill=tk.BOTH,expand=1) self.text.height=10 scrollbar=tk.Scrollbar(self.text) scrollbar.pack(side=tk.RIGHT,fill=tk.Y) self.text.config(yscrollcommand=scrollbar.set) scrollbar.config(command=self.text.yview)
class MainFrame(Frame): def __init__(self, parent, stdoutq): Frame.__init__(self, parent) self.parent = parent self.width = 750 self.height = 450 self.title = ximaexport.__version__ self.stdoutq = stdoutq self.initUI() self.hasdb = False self.hasout = False self.exit = False self.path_frame = self.addPathFrame() self.action_frame = self.addActionFrame() self.message_frame = self.addMessageFrame() self.printStr() self.stateq = Queue.Queue() def centerWindow(self): sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - self.width) / 2 y = (sh - self.height) / 2 self.parent.geometry('%dx%d+%d+%d' \ %(self.width,self.height,x,y)) def initUI(self): self.parent.title(self.title) self.style = Style() #Choose from default, clam, alt, classic self.style.theme_use('alt') self.pack(fill=tk.BOTH, expand=True) self.centerWindow() def printStr(self): while self.stdoutq.qsize() and self.exit == False: try: msg = self.stdoutq.get() self.text.update() self.text.insert(tk.END, msg) self.text.see(tk.END) except Queue.Empty: pass self.after(100, self.printStr) def checkReady(self): if self.hasdb and self.hasout: self.start_button.configure(state=tk.NORMAL) #print('XimaExport Ready.') printch('XimaExport 就绪.') else: self.start_button.configure(state=tk.DISABLED) def addPathFrame(self): frame = Frame(self) frame.pack(fill=tk.X, expand=0, side=tk.TOP, padx=8, pady=5) frame.columnconfigure(1, weight=1) #------------------Database file------------------ label=tk.Label(frame,text=dgbk('ting.sqlite文件:'),\ bg='#bbb') label.grid(row=0,column=0,\ sticky=tk.W,padx=8) self.db_entry = tk.Entry(frame) self.db_entry.grid(row=0, column=1, sticky=tk.W + tk.E, padx=8) self.db_button = tk.Button(frame, text=dgbk('打开'), command=self.openFile) self.db_button.grid(row=0, column=2, padx=8, sticky=tk.E) #--------------------Output dir-------------------- label2=tk.Label(frame,text=dgbk('导出到文件夹:'),\ bg='#bbb') label2.grid(row=2,column=0,\ sticky=tk.W,padx=8) self.out_entry = tk.Entry(frame) self.out_entry.grid(row=2, column=1, sticky=tk.W + tk.E, padx=8) self.out_button = tk.Button(frame, text=dgbk('选择'), command=self.openDir) self.out_button.grid(row=2, column=2, padx=8, sticky=tk.E) def openDir(self): self.out_entry.delete(0, tk.END) dirname = askdirectory() self.out_entry.insert(tk.END, dirname) if len(dirname) > 0: #print('Output folder: %s' %dirname) printch('输出到文件夹:') print(' ' + dirname) self.hasout = True self.checkReady() def openFile(self): self.db_entry.delete(0, tk.END) ftypes = [('sqlite files', '*.sqlite'), ('ALL files', '*')] filename = askopenfilename(filetypes=ftypes) self.db_entry.insert(tk.END, filename) if len(filename) > 0: #print('Database file: %s' %filename) printch('数据文件:') print(' ' + filename) self.probeAlbums() def probeAlbums(self): dbfile = self.db_entry.get() try: db = sqlite3.connect(dbfile) df = ximaexport.getData(db) self.albumlist = ximaexport.getAlbumList(df, None) #(id, name) self.albumnames = ['All'] + [ii[1] for ii in self.albumlist ] #names to display self.albummenu['values'] = tuple(self.albumnames) self.albummenu.current(0) db.close() self.hasdb = True self.checkReady() except Exception as e: #print('Failed to recoganize the given database file.') printch('无法识别sqlite数据文件.') print(e) def addActionFrame(self): frame = Frame(self, relief=tk.RAISED, borderwidth=1) frame.pack(fill=tk.X,side=tk.TOP,\ expand=0,padx=8,pady=5) #label=tk.Label(frame,text='Actions:',bg='#bbb') #label.grid(row=0,column=0,sticky=tk.W,padx=8) #---------------Action checkbuttons--------------- frame.columnconfigure(0, weight=1) #---------------------2nd row--------------------- subframe = Frame(frame) subframe.grid(row=1,column=0,columnspan=6,sticky=tk.W+tk.E,\ pady=5) #-------------------Album options------------------- albumlabel=tk.Label(subframe,text=dgbk('专辑:'),\ bg='#bbb') albumlabel.pack(side=tk.LEFT, padx=8) self.album = tk.StringVar() self.albumnames = [ 'All', ] self.albummenu=Combobox(subframe,textvariable=\ self.album,values=self.albumnames,state='readonly') self.albummenu.current(0) self.albummenu.bind('<<ComboboxSelected>>', self.setAlbum) self.albummenu.pack(side=tk.LEFT, padx=8) #-------------------Quit button------------------- quit_button=tk.Button(subframe,text=dgbk('退出'),\ command=self.quit) quit_button.pack(side=tk.RIGHT, padx=8) #-------------------Stop button------------------- ''' self.stop_button=tk.Button(subframe,text='Stop',\ command=self.stop) self.stop_button.pack(side=tk.RIGHT,padx=8) ''' #-------------------Start button------------------- self.start_button=tk.Button(subframe,text=dgbk('开始'),\ command=self.start,state=tk.DISABLED) self.start_button.pack(side=tk.RIGHT, pady=8) #-------------------Help button------------------- self.help_button=tk.Button(subframe,text=dgbk('帮助'),\ command=self.showHelp) self.help_button.pack(side=tk.RIGHT, padx=8) def setAlbum(self, x): import json self.albummenu.selection_clear() self.album = self.albummenu.get() self.albummenu.set(self.album) if self.album == 'All': #print('Work on all albums.') printch('导出所有专辑.') else: #print('Select album: '+self.album) printch('导出所选专辑:') print(' ' + self.album) def showHelp(self): helpstr = dgbk('''\n\n 导出喜马拉雅下载音频,并自动按专辑归档、重命名:\n 1. 找到手机/pad中的喜马拉雅数据文件夹:\n (1)苹果用户:链接电脑itunes,在app一栏中找到“喜马拉雅”,单击,右侧会出现“喜马拉雅”的数据文件。选择“iDoc”,并导出到电脑。\n (2)安卓用户:链接电脑后,拷贝出ting文件夹。\n 2. 运行ximaexport-gui.exe。\n 在 “ting.sqlite文件”一栏,选择步骤1中拷贝出的文件夹里的 ting.sqlite. 文件。\n 在 “导出到文件夹”一栏,选择音频存储位置。\n 在 “专辑”下拉菜单,选择要导出的专辑。若全部导出选择“All”。\n 点击“开始”开始处理。 ''') tkMessageBox.showinfo(title='Help', message=helpstr) #print(self.menfolder.get()) def start(self): dbfile = self.db_entry.get() outdir = self.out_entry.get() self.album = self.albummenu.get() self.out_button.configure(state=tk.DISABLED) self.start_button.configure(state=tk.DISABLED) self.help_button.configure(state=tk.DISABLED) self.albummenu.configure(state=tk.DISABLED) self.messagelabel.configure(text=dgbk('信息 (处理中...)')) album = None if self.album == 'All' else self.album args = [dbfile, outdir, album, True] self.workthread = WorkThread('work', False, self.stateq) self.workthread.deamon = True self.workthread.args = args self.workthread.start() self.reset() def reset(self): while self.stateq.qsize() and self.exit == False: try: msg = self.stateq.get() if msg == 'done': self.db_button.configure(state=tk.NORMAL) self.out_button.configure(state=tk.NORMAL) self.start_button.configure(state=tk.NORMAL) self.help_button.configure(state=tk.NORMAL) self.albummenu.configure(state='readonly') self.messagelabel.configure(text=dgbk('消息')) return except Queue.Empty: pass self.after(100, self.reset) def stop(self): #self.workthread.stop() pass def addMessageFrame(self): frame = Frame(self) frame.pack(fill=tk.BOTH,side=tk.TOP,\ expand=1,padx=8,pady=5) self.messagelabel = tk.Label(frame, text=dgbk('消息'), bg='#bbb') self.messagelabel.pack(side=tk.TOP, fill=tk.X) self.text = tk.Text(frame) self.text.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.text.height = 10 scrollbar = tk.Scrollbar(self.text) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.text.config(yscrollcommand=scrollbar.set) scrollbar.config(command=self.text.yview)
class IniGenGui(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.inigen = IniGen() self.initUIGlobals() def initUIGlobals(self): """ This is the first part of the window to be rendered. After these have been set by the user and 'Emit Globals' has been clicked, the given algorithm can then specify how to generate the second part of the window. All fields are disabled for user input after globals have been emitted. Information in Global Parameters: Algorithm - name of the algorithm to use File Name - name of the output file to be generated Min Time - Minimum Time for distillers to run Max Time - Maximum Time for distillers to run Set Enabled: - checkbox to specify if the distiller should be enabled True or False """ self.parent.title("Ini Generator") Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10') # initialize row counter. This is incremented after each element added to grid row = 0 # initialize column counter. This is incremented after a column has been filled self.column = 0 # Globals: entries for info common to all runs label_globals = Label(self, text="Globals") label_globals.grid(row=row, column=self.column) row += 1 label_alg = Label(self, text="Algorithm") label_alg.grid(row=row, column=self.column, sticky=E+W) row += 1 self.cbox_alg = Combobox(self, values=algorithms.keys(), state='readonly') self.cbox_alg.current(0) self.cbox_alg.grid(row=row, column=self.column, sticky=E+W+S+N) row += 1 label_filename = Label(self, text="Output File Name") label_filename.grid(row=row, column=self.column, sticky=E+W) row += 1 self.entry_filename = Entry(self) self.entry_filename.grid(row=row, column=self.column, sticky=W+E) row += 1 label_mintime = Label(self, text="Min Time") label_mintime.grid(row=row, column=self.column, sticky=E+W) row += 1 self.entry_mintime = Entry(self) self.entry_mintime.grid(row=row, column=self.column, sticky=W+E) row += 1 label_maxtime = Label(self, text="Max Time") label_maxtime.grid(row=row, column=self.column, sticky=W+E) row += 1 self.entry_maxtime = Entry(self) self.entry_maxtime.grid(row=row, column=self.column, sticky=W+E) row += 1 self.enabled = IntVar() self.check_enabled = Checkbutton(self, text="set enabled", variable=self.enabled) self.check_enabled.grid(row=row, column=self.column, sticky=W+E) row += 1 # Control: buttons used to emmiting text and generating file self.button_emit_globals = Button(self, text="Emit Globals", command=self.emit_globals) self.button_emit_globals.grid(row=row, column=self.column, sticky=W+E) row += 1 button_addrun = Button(self, text="Add Run", command=self.emit_run) button_addrun.grid(row=row, column=self.column, sticky=W+E) row += 1 button_generate = Button(self, text="Generate File", command=self.generate_file) button_generate.grid(row=row, column=self.column, sticky=W+E) row += 1 self.column += 1 self.pack() def initUIRuns(self): """ Second part of gui to be rendered. This contains all the fields needed to emit a single run within a distiller file. Multiple runs can be added by clicking 'Add Run' multiple times. Information in Run Parameters: Run Name - header name for run Dependencies - description and uuid fields for each dependency in the algorithm Params - parameter fields for each parameter in the algorithm """ self.entry_run_name = None self.entries_dep_description = [] self.entries_dep_uuid = [] self.entries_param = [] row = 0 label_runs = Label(self, text="Runs") label_runs.grid(row=row, column=self.column) row += 1 label_run_name = Label(self, text="Run Name") label_run_name.grid(row=row, column=self.column, sticky=W+E) row += 1 self.entry_run_name = Entry(self) self.entry_run_name.grid(row=row, column=self.column, sticky=W+E) row += 1 algorithm = self.cbox_alg.get() settings = algorithms[algorithm] for dep in settings['deps']: if row >= 21: self.column += 1 row = 1 label_dep_description = Label(self, text="{0} (description)".format(dep)) label_dep_description.grid(row=row, column=self.column, sticky=W+E) row += 1 entry_dep_description = Entry(self) entry_dep_description.grid(row=row, column=self.column, sticky=W+E) row += 1 label_dep_uuid = Label(self, text="{0} (uuid)".format(dep)) label_dep_uuid.grid(row=row, column=self.column, sticky=W+E) row += 1 entry_dep_uuid = Entry(self) entry_dep_uuid.grid(row=row, column=self.column, sticky=W+E) row += 1 self.entries_dep_description.append(entry_dep_description) self.entries_dep_uuid.append(entry_dep_uuid) for param in settings['params']: if row >= 21: self.column += 1 row = 1 label_param = Label(self, text=param) label_param.grid(row=row, column=self.column, sticky=W+E) row += 1 entry_param = Entry(self) entry_param.grid(row=row, column=self.column, sticky=W+E) row += 1 self.entries_param.append(entry_param) row = 0 self.column += 1 self.text_file = Text(self) self.text_file.grid(row=row, column=self.column, rowspan=31, sticky=W+E+N+S, padx=5, pady=5) self.column += 1 scrollbar = Scrollbar(self, command=self.text_file.yview) self.text_file.config(yscrollcommand=scrollbar.set) scrollbar.grid(row=row, column=self.column, rowspan=31, sticky=N+S) self.pack() def emit_globals(self): self.algorithm = algorithms[self.cbox_alg.get()] path = self.algorithm['path'] if self.enabled.get(): enabled = 'True' else: enabled = 'False' lines = self.inigen.emit_global(path, enabled) self.mintime = self.entry_mintime.get() self.maxtime = self.entry_maxtime.get() self.cbox_alg.configure(state='disabled') self.entry_filename.configure(state='disabled') self.entry_mintime.configure(state='disabled') self.entry_maxtime.configure(state='disabled') self.check_enabled.configure(state='disabled') self.button_emit_globals.configure(state='disabled') self.initUIRuns() self.update_text(lines) def emit_run(self): label = self.entry_run_name.get() chunking = 'parallel' #hardcoded for now mintime = self.mintime maxtime = self.maxtime lines = self.inigen.emit_run_header(label, chunking, mintime, maxtime) self.update_text(lines) deps = [] for i in range(len(self.entries_dep_description)): deps.append([self.entries_dep_description[i].get(), self.algorithm['deps'][i], self.entries_dep_uuid[i].get()]) params = [] for i in range(len(self.entries_param)): params.append([self.algorithm['params'][i], self.entries_param[i].get()]) outputs = self.algorithm['outputs'] lines = self.inigen.emit_run_body(deps, params, outputs) self.update_text(lines) def generate_file(self): self.inigen.generate_file(self.entry_filename.get()) self.quit() def update_text(self, lines): self.text_file.configure(state='normal') string = "\n".join(lines) self.text_file.insert(END, string) self.text_file.configure(state='disabled')