Beispiel #1
0
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)
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #4
0
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)
Beispiel #5
0
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)