10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"Dialog to specify or edit the parameters for a user configured help source."
20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport os
40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport sys
50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom Tkinter import *
70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport tkMessageBox
80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport tkFileDialog
90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass GetHelpSourceDialog(Toplevel):
110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, parent, title, menuItem='', filePath=''):
120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        """Get menu entry and url/ local file location for Additional Help
130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        User selects a name for the Help resource and provides a web url
150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        or a local file as its source.  The user can enter a url or browse
160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for the file.
170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        """
190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        Toplevel.__init__(self, parent)
200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.configure(borderwidth=5)
210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.resizable(height=FALSE, width=FALSE)
220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.title(title)
230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.transient(parent)
240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.grab_set()
250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.protocol("WM_DELETE_WINDOW", self.Cancel)
260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.parent = parent
270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.result = None
280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.CreateWidgets()
290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.menu.set(menuItem)
300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.path.set(filePath)
310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.withdraw() #hide while setting geometry
320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #needs to be done here so that the winfo_reqwidth is valid
330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.update_idletasks()
340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #centre dialog over parent:
350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.geometry("+%d+%d" %
360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                      ((parent.winfo_rootx() + ((parent.winfo_width()/2)
370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                                -(self.winfo_reqwidth()/2)),
380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        parent.winfo_rooty() + ((parent.winfo_height()/2)
390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                                -(self.winfo_reqheight()/2)))))
400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.deiconify() #geometry set, unhide
410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.bind('<Return>', self.Ok)
420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.wait_window()
430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def CreateWidgets(self):
450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.menu = StringVar(self)
460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.path = StringVar(self)
470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.fontSize = StringVar(self)
480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.frameMain = Frame(self, borderwidth=2, relief=GROOVE)
490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH)
500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        labelMenu = Label(self.frameMain, anchor=W, justify=LEFT,
510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          text='Menu Item:')
520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.entryMenu = Entry(self.frameMain, textvariable=self.menu,
530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                               width=30)
540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.entryMenu.focus_set()
550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        labelPath = Label(self.frameMain, anchor=W, justify=LEFT,
560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          text='Help File Path: Enter URL or browse for file')
570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.entryPath = Entry(self.frameMain, textvariable=self.path,
580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                               width=40)
590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.entryMenu.focus_set()
600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        labelMenu.pack(anchor=W, padx=5, pady=3)
610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.entryMenu.pack(anchor=W, padx=5, pady=3)
620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        labelPath.pack(anchor=W, padx=5, pady=3)
630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.entryPath.pack(anchor=W, padx=5, pady=3)
640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        browseButton = Button(self.frameMain, text='Browse', width=8,
650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              command=self.browseFile)
660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        browseButton.pack(pady=3)
670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        frameButtons = Frame(self)
680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        frameButtons.pack(side=BOTTOM, fill=X)
690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.buttonOk = Button(frameButtons, text='OK',
700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                               width=8, default=ACTIVE,  command=self.Ok)
710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.buttonOk.grid(row=0, column=0, padx=5,pady=5)
720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.buttonCancel = Button(frameButtons, text='Cancel',
730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                   width=8, command=self.Cancel)
740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.buttonCancel.grid(row=0, column=1, padx=5, pady=5)
750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def browseFile(self):
770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        filetypes = [
780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            ("HTML Files", "*.htm *.html", "TEXT"),
790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            ("PDF Files", "*.pdf", "TEXT"),
800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            ("Windows Help Files", "*.chm"),
810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            ("Text Files", "*.txt", "TEXT"),
820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            ("All Files", "*")]
830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        path = self.path.get()
840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if path:
850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dir, base = os.path.split(path)
860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            base = None
880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if sys.platform[:3] == 'win':
890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                dir = os.path.join(os.path.dirname(sys.executable), 'Doc')
900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if not os.path.isdir(dir):
910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    dir = os.getcwd()
920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                dir = os.getcwd()
940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        opendialog = tkFileDialog.Open(parent=self, filetypes=filetypes)
950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        file = opendialog.show(initialdir=dir, initialfile=base)
960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if file:
970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.path.set(file)
980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def MenuOk(self):
1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        "Simple validity check for a sensible menu item name"
1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        menuOk = True
1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        menu = self.menu.get()
1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        menu.strip()
1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not menu:
1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            tkMessageBox.showerror(title='Menu Item Error',
1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                   message='No menu item specified',
1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                   parent=self)
1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.entryMenu.focus_set()
1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            menuOk = False
1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif len(menu) > 30:
1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            tkMessageBox.showerror(title='Menu Item Error',
1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                   message='Menu item too long:'
1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                           '\nLimit 30 characters.',
1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                   parent=self)
1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.entryMenu.focus_set()
1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            menuOk = False
1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return menuOk
1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def PathOk(self):
1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        "Simple validity check for menu file path"
1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        pathOk = True
1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        path = self.path.get()
1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        path.strip()
1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not path: #no path specified
1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            tkMessageBox.showerror(title='File Path Error',
1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                   message='No help file path specified.',
1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                   parent=self)
1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.entryPath.focus_set()
1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            pathOk = False
1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        elif path.startswith(('www.', 'http')):
1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            pass
1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if path[:5] == 'file:':
1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                path = path[5:]
1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if not os.path.exists(path):
1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                tkMessageBox.showerror(title='File Path Error',
1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                       message='Help file path does not exist.',
1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                       parent=self)
1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.entryPath.focus_set()
1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                pathOk = False
1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return pathOk
1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def Ok(self, event=None):
1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.MenuOk() and self.PathOk():
1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.result = (self.menu.get().strip(),
1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           self.path.get().strip())
1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if sys.platform == 'darwin':
1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                path = self.result[1]
1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if path.startswith(('www', 'file:', 'http:')):
1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    pass
1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                else:
1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # Mac Safari insists on using the URI form for local files
1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.result = list(self.result)
1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.result[1] = "file://" + path
1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.destroy()
1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def Cancel(self, event=None):
1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.result = None
1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.destroy()
1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == '__main__':
1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    #test the dialog
1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    root = Tk()
1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def run():
1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        keySeq = ''
1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dlg = GetHelpSourceDialog(root, 'Get Help Source')
1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        print dlg.result
1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    Button(root,text='Dialog', command=run).pack()
1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    root.mainloop()
170