fork download
  1. #!/usr/bin/env python
  2.  
  3. from Tkinter import *
  4.  
  5. from tkSimpleDialog import askstring
  6.  
  7. from tkFileDialog import asksaveasfilename
  8.  
  9. from tkFileDialog import askopenfilename
  10.  
  11. from tkMessageBox import askokcancel
  12.  
  13. import Tkinter as tk
  14.  
  15. import ttk
  16.  
  17. import threading
  18.  
  19. from ScrolledText import ScrolledText
  20.  
  21. Window = Tk()
  22. Window.title("TekstEDIT")
  23. index = ["True"]
  24.  
  25.  
  26. class fontGUI:
  27. def __init__(self, parent_win, text):
  28. self.parent_win = parent_win
  29. self.text = text
  30.  
  31. self.font_win = Toplevel(self.parent_win)
  32. self.font_win.title("Font options")
  33.  
  34. self.frame = ttk.Frame(self.font_win, padding=(12,12,12,12))
  35. ttk.Style().configure("Tframe", background="beige")
  36.  
  37. self.fontsize_options = []
  38. for i in range(4, 74, 2):
  39. self.fontsize_options.append(str(i))
  40.  
  41. self.fontstyle_options = ["Arial", "Comic Sans", "Courier New", "Helvetica", "Times New Roman"]
  42.  
  43. self.fontsize_var = StringVar()
  44. self.fontstyle_var = StringVar()
  45.  
  46. self.fontsize_optbox = apply(OptionMenu, (self.frame, self.fontsize_var) + tuple(self.fontsize_options))
  47. self.fontstyle_optbox = apply(OptionMenu, (self.frame, self.fontstyle_var) + tuple(self.fontstyle_options))
  48.  
  49. self.fontsize_var.set("12")
  50. self.fontstyle_var.set("Arial")
  51.  
  52. self.fontsize_label = ttk.Label(self.frame, text="Font Size")
  53. self.fontstyle_label = ttk.Label(self.frame, text="Font Style")
  54.  
  55. self.accept_butt = ttk.Button(self.frame, text="Accept", command=self.accept)
  56. self.cancel_butt = ttk.Button(self.frame, text="Cancel", command=lambda: self.font_win.destroy())
  57.  
  58. self.frame.grid(column=0, row=0, columnspan=3, rowspan=5)
  59. self.fontsize_label.grid(column=0, row=0, sticky=(N,W,E,S))
  60. self.fontsize_optbox.grid(column=0, row=1, sticky=(N,W,E,S))
  61. self.fontstyle_label.grid(column=0, row=2, columnspan=2, sticky=(N,W,E,S))
  62. self.fontstyle_optbox.grid(column=0, row=3, columnspan=2, sticky=(N,W,E,S))
  63. self.accept_butt.grid(column=1, row=4, padx=4, pady=6, sticky=(N,W,E,S))
  64. self.cancel_butt.grid(column=2, row=4, pady=6, sticky=(N,W,E,S))
  65.  
  66. self.font_win.columnconfigure("all", weight=1)
  67. self.font_win.rowconfigure("all", weight=1)
  68. self.frame.columnconfigure("all", weight=1)
  69. self.frame.rowconfigure("all", weight=1)
  70.  
  71. def accept(self):
  72. fontsize = self.fontsize_var.get()
  73. fontstyle = self.fontstyle_var.get()
  74. self.text.config(font=(fontstyle, int(fontsize)))
  75. self.font_win.destroy()
  76.  
  77. #Sets up window for find. findNext does all the actual work
  78. class findGUI:
  79. def __init__(self, parent_win, text):
  80. self.parent_win = parent_win
  81. self.text = text
  82.  
  83. self.find_win = Toplevel(self.parent_win)
  84. self.index = "1.0"
  85.  
  86. self.find_win.title("Find")
  87. self.frame = ttk.Frame(self.find_win, padding=(12,12,12,12))
  88. ttk.Style().configure("Tframe", background="beige")
  89.  
  90. self.search_label = ttk.Label(self.frame, text="Find:")
  91. self.search_entry = ttk.Entry(self.frame)
  92.  
  93. self.next_but = ttk.Button(self.frame, text="Next", command=lambda: self.findNext(self.search_entry.get()))
  94. self.cancel_but = ttk.Button(self.frame, text="Cancel", command=lambda: self.find_win.destroy())
  95.  
  96. self.frame.grid(column=0, row=0, columnspan=3, rowspan=2)
  97. self.search_label.grid(column=1, row=0, sticky=(N,W,E,S))
  98. self.search_entry.grid(column=0, row=1, columnspan=3, pady=4, sticky=(N,W,E,S))
  99. self.next_but.grid(column=2, row=2, sticky=(N,W,E,S))
  100. self.cancel_but.grid(column=3,row=2, sticky=(N,W,E,S))
  101.  
  102. self.find_win.columnconfigure("all", weight=1)
  103. self.find_win.rowconfigure("all", weight=1)
  104. self.frame.columnconfigure("all", weight=1)
  105. self.frame.rowconfigure("all", weight=1)
  106.  
  107. #Each click of next should call findNext which will highlight
  108. #and cycle through found instances of text
  109. def findNext(self, text):
  110. txt_index = self.text.search(text, self.index, "end")
  111. if txt_index:
  112. txt_end = txt_index + "+%dc"%len(text)
  113. self.text.tag_remove("sel", "1.0", "end")
  114. self.text.tag_add("sel", txt_index, txt_end)
  115. self.text.mark_set("insert", txt_end)
  116. self.text.see("insert")
  117. self.index = txt_end
  118. if self.text.compare(self.index, ">=", "end-1c"):
  119. self.index = "1.0"
  120.  
  121. class newWindowThread(threading.Thread):
  122. def __init__(self, choosen=""):
  123. threading.Thread.__init__(self)
  124. self.choosen = choosen
  125.  
  126. def run(self):
  127. if self.choosen == "":
  128. root = Tk()
  129. newEditor = SimpleEditor(root)
  130. root.mainloop()
  131. else:
  132. root = Tk()
  133. newEditor = SimpleEditor(root, self.choosen)
  134. root.mainloop()
  135.  
  136. class TextLineNumbers(tk.Canvas):
  137. def __init__(self, *args, **kwargs):
  138. tk.Canvas.__init__(self, *args, **kwargs)
  139. self.textwidget = None
  140.  
  141. def attach(self, text_widget):
  142. self.textwidget = text_widget
  143.  
  144. def redraw(self, *args):
  145. '''redraw line numbers'''
  146. self.delete("all")
  147.  
  148. i = self.textwidget.index("@0,0")
  149. while True :
  150. dline= self.textwidget.dlineinfo(i)
  151. if dline is None: break
  152. y = dline[1]
  153. linenum = str(i).split(".")[0]
  154. self.create_text(2,y,anchor="nw", text=linenum)
  155. i = self.textwidget.index("%s+1line" % i)
  156.  
  157. class CustomText(tk.Text):
  158. def __init__(self, *args, **kwargs):
  159. tk.Text.__init__(self, *args, **kwargs)
  160.  
  161. self.tk.eval('''
  162. proc widget_proxy {widget widget_command args} {
  163.  
  164. # call the real tk widget command with the real args
  165. set result [uplevel [linsert $args 0 $widget_command]]
  166.  
  167. # generate the event for certain types of commands
  168. if {([lindex $args 0] in {insert replace delete}) ||
  169. ([lrange $args 0 2] == {mark set insert}) ||
  170. ([lrange $args 0 1] == {xview moveto}) ||
  171. ([lrange $args 0 1] == {xview scroll}) ||
  172. ([lrange $args 0 1] == {yview moveto}) ||
  173. ([lrange $args 0 1] == {yview scroll})} {
  174.  
  175. event generate $widget <<Change>> -when tail
  176. }
  177.  
  178. # return the result from the real widget command
  179. return $result
  180. }
  181. ''')
  182. self.tk.eval('''
  183. rename {widget} _{widget}
  184. interp alias {{}} ::{widget} {{}} widget_proxy {widget} _{widget}
  185. '''.format(widget=str(self)))
  186.  
  187. class ScrolledText(Frame):
  188.  
  189. def __init__(self, parent=None, text='', file=None, background='black'):
  190.  
  191. Frame.__init__(self, parent)
  192.  
  193. self.pack(expand=True, fill=BOTH)
  194.  
  195. self.makewidgets()
  196.  
  197. self.settext(text, file)
  198.  
  199. def makewidgets(self):
  200.  
  201. sbar = Scrollbar(self)
  202.  
  203. text = Text(self, relief=SUNKEN)
  204.  
  205. sbar.config(command=text.yview)
  206.  
  207. sbar.config(command=text.xview)
  208.  
  209. text.config(yscrollcommand=sbar.set)
  210.  
  211. text.config(xscrollcommand=sbar.set)
  212.  
  213. self.text = text
  214.  
  215. def settext(self, text='', file=None):
  216.  
  217. if file:
  218.  
  219. text = open(file, 'r').read()
  220.  
  221. self.text.delete('1.0', END)
  222.  
  223. self.text.insert('1.0', text)
  224.  
  225. self.text.mark_set(INSERT, '1.0')
  226.  
  227. self.text.focus()
  228.  
  229. def gettext(self):
  230.  
  231. return self.text.get('1.0', END+'-1c')
  232.  
  233.  
  234. class Example(tk.Frame):
  235. def __init__(self, parent,file=None,*args, **kwargs):
  236. self.choosen = None
  237. self.parent = parent
  238. self.parent.option_add("*tearOff", False)
  239. self.parent.protocol("WM_DELETE_WINDOW", self.onQuit)
  240. tk.Frame.__init__(self, *args, **kwargs)
  241. self.text = CustomText(self)
  242. self.vsb = tk.Scrollbar(orient="vertical", command=self.text.yview)
  243. self.hsb = tk.Scrollbar(orient="horizontal", command=self.text.xview)
  244. self.text.configure(yscrollcommand=self.vsb.set)
  245. self.text.configure(xscrollcommand=self.hsb.set)
  246. self.text.tag_configure("bigfont", font=("Helvetica", "24", "bold"))
  247. self.linenumbers = TextLineNumbers(self, width=30)
  248. self.linenumbers.attach(self.text)
  249. self.bindings()
  250.  
  251. self.vsb.pack(side="right", fill="y")
  252. self.hsb.pack(side="bottom", fill="y")
  253. self.linenumbers.pack(side="left", fill="y")
  254. self.text.pack(side="right", fill="both", expand=True)
  255.  
  256. self.text.bind("<<Change>>", self._on_change)
  257. self.text.bind("<Configure>", self._on_change)
  258.  
  259. frm=Frame(parent)
  260.  
  261. frm.pack(fill=X)
  262.  
  263. Button(frm, text='Find', command=self.onFind).pack(side=LEFT)
  264.  
  265. Button(frm, text='Night-Mode', command=self.onNightMode).pack(side=LEFT)
  266.  
  267. menubar=Menu(Window)
  268.  
  269. wFile = Menu(menubar, tearoff=0,relief="raised")
  270. wFile.add_command(label="New", accelerator="Ctrl+N", command=self.onNew)
  271. wFile.add_command(label="New Window", accelerator="Ctrl+Shift+N", command=self.onNewWindow)
  272. wFile.add_command(label="Open...", accelerator="Ctrl+O", command=self.onOpen)
  273. wFile.add_command(label="Save", accelerator="Ctrl+S", command=self.onSave)
  274. wFile.add_command(label="Save As...", accelerator="Ctrl+Shift+S", command=self.onSaveAs)
  275. wFile.add_separator()
  276. wFile.add_command(label="Quit", accelerator="Ctrl+Q", command=self.onQuit)
  277.  
  278. menubar.add_cascade(label="File", menu=wFile)
  279.  
  280. wEdit = Menu(menubar, tearoff=0)
  281. wEdit.add_command(label="Cut", accelerator="Ctrl+X", command=self.onCut)
  282. wEdit.add_command(label="Copy",accelerator="Ctrl+C", command=self.onCopy)
  283. wEdit.add_command(label="Paste", accelerator="Ctrl+V",command=self.onPaste)
  284.  
  285. menubar.add_cascade(label="Edit", menu=wEdit)
  286.  
  287. wFormat = Menu(menubar, tearoff=0,relief="raised")
  288. wFormat.add_command(label="Font", accelerator="Control+F", command=self.setFont)
  289.  
  290. menubar.add_cascade(label="Format", menu=wFormat)
  291.  
  292.  
  293. Window.config(menu=menubar)
  294.  
  295. # label showing filename
  296. self.choosen_label_var = StringVar()
  297. self.choosen_label = Label(Window,
  298. textvariable=self.choosen_label_var, anchor=W,
  299. justify=LEFT)
  300. self.choosen_label_var.set("")
  301. self.choosen_label.pack()
  302.  
  303. def setFont(self):
  304. fG = fontGUI(self.parent, self.text)
  305.  
  306. def bindings(self):
  307. Window.focus_set()
  308. Window.bind_all("<Control-C>", self.onCopy)
  309. Window.bind_all("<Control-X>", self.onCut)
  310. Window.bind_all("<Control-V>", self.onPaste)
  311. Window.bind_all("<Control-N>", self.onNew)
  312. Window.bind_all("<Control-F>", self.setFont)
  313.  
  314. def onNew(self):
  315. self.choosen = None
  316. self.choosen_label_var.set("")
  317. self.text.delete(1.0, END)
  318.  
  319. def onNewWindow(self):
  320. t=newWindowThread()
  321. t.start()
  322.  
  323. def onSave(self):
  324. if not self.choosen:
  325. self.onSaveAs()
  326. else:
  327. file = open(self.choosen, 'w')
  328. textoutput=self.text.get(0.0, END)
  329. file.write(textoutput)
  330. file.close()
  331.  
  332. def onSaveAs(self):
  333. self.choosen = asksaveasfilename(initialfile='Untitled.txt',defaultextension=".txt",filetypes=[("All Files","*.*"),("Text Documents","*.txt")])
  334. if self.choosen:
  335. file = open(self.choosen, 'w')
  336. textoutput = self.text.get(0.0, END)
  337. file.write(textoutput)
  338. file.close()
  339. self.choosen_label_var.set(self.choosen)
  340.  
  341. def onOpen(self):
  342.  
  343. self.choosen = askopenfilename()
  344. if self.choosen:
  345. self.choosen_label_var.set(self.choosen)
  346. self.text.delete("1.0",END)
  347. self.text.insert(END, open(self.choosen).read())
  348.  
  349. def onCut(self):
  350.  
  351. text = self.text.get(SEL_FIRST, SEL_LAST)
  352.  
  353. self.text.delete(SEL_FIRST, SEL_LAST)
  354.  
  355. self.clipboard_clear()
  356.  
  357. self.clipboard_append(text)
  358.  
  359. def onCopy(self):
  360.  
  361. text = self.text.get(SEL_FIRST, SEL_LAST)
  362.  
  363. self.clipboard_clear()
  364.  
  365. self.clipboard_append(text)
  366.  
  367.  
  368. def onPaste(self):
  369.  
  370. try:
  371.  
  372. text = self.selection_get(selection='CLIPBOARD')
  373.  
  374. self.text.insert(INSERT, text)
  375.  
  376. except TclError:
  377.  
  378. pass
  379.  
  380. def onFind(self):
  381. fG = findGUI(self.parent, self.text)
  382.  
  383. def onNightMode(self):
  384. if index[0]:
  385. self.text.config(font=('courier', 12, 'normal'), background='black', fg='white', insertbackground='white')
  386.  
  387. else:
  388. self.text.config(font=('courier', 12, 'normal'), background='white', fg='black', insertbackground='black')
  389. index[0] = not index[0]
  390.  
  391. def onQuit(self):
  392.  
  393. ans = askokcancel('Verify exit', "Really quit?")
  394.  
  395. if ans:
  396. Frame.quit(self)
  397. Window.destroy()
  398.  
  399.  
  400. def _on_change(self, event):
  401. self.linenumbers.redraw()
  402.  
  403.  
  404. class SimpleEditor(ScrolledText):
  405.  
  406. def __init__(self, parent=None, file=None):
  407.  
  408. Example(Window).pack(side="left", fill="both", expand=True)
  409.  
  410. ScrolledText.__init__(self, parent, file=None)
  411.  
  412. self.text.config(font=('courier', 12, 'normal'))
  413.  
  414. if __name__ == '__main__':
  415.  
  416. try:
  417.  
  418. SimpleEditor(file=sys.argv[1]).mainloop()
  419.  
  420. except IndexError:
  421.  
  422. SimpleEditor().mainloop()
  423.  
  424.  
Runtime error #stdin #stdout #stderr 0.09s 25712KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Traceback (most recent call last):
  File "prog.py", line 21, in <module>
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1712, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable