def entry_clicked(obj, item=None): win = StandardWindow("entry", "Entry", autodel=True) bx = Box(win, size_hint_weight=EXPAND_BOTH) win.resize_object_add(bx) bx.show() en = Entry(win, line_wrap=False, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) en.entry_set("This is an entry widget in this window that<br>" "uses markup <b>like this</> for styling and<br>" "formatting <em>like this</>, as well as<br>" "<a href=X><link>links in the text</></a>, so enter text<br>" "in here to edit it. By the way, links are<br>" "called <a href=anc-02>Anchors</a> so you will need<br>" "to refer to them this way.") en.callback_anchor_clicked_add(my_entry_anchor_test, en) bx.pack_end(en) en.show() bx2 = Box(win, horizontal=True, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) bt = Button(win, text="Clear", size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) bt.callback_clicked_add(my_entry_bt_1, en) bx2.pack_end(bt) bt.show() bt = Button(win, text="Print", size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) bt.callback_clicked_add(my_entry_bt_2, en) bx2.pack_end(bt) bt.show() bt = Button(win, text="Selection", size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) bt.callback_clicked_add(my_entry_bt_3, en) bx2.pack_end(bt) bt.show() bt = Button(win, text="Insert", size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) bt.callback_clicked_add(my_entry_bt_4, en) bx2.pack_end(bt) bt.show() bx.pack_end(bx2) bx2.show() en.focus_set(True) win.show()
class Interface(object): def __init__( self ): self.mainWindow = StandardWindow("epad", "Untitled - ePad", size=(600, 400)) self.mainWindow.callback_delete_request_add(self.closeChecks) self.mainWindow.elm_event_callback_add(self.eventsCb) icon = Icon(self.mainWindow) icon.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND) icon.size_hint_align_set(EVAS_HINT_FILL, EVAS_HINT_FILL) icon.standard_set('accessories-text-editor') # assumes image icon is in local dir, may need to change later icon.show() self.mainWindow.icon_object_set(icon.object_get()) self.mainBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainBox.show() self.mainTb = Toolbar(self.mainWindow, homogeneous=False, size_hint_weight=(0.0, 0.0), size_hint_align=(EVAS_HINT_FILL, 0.0)) self.mainTb.menu_parent = self.mainWindow self.mainTb.item_append("document-new", "New", self.newPress) self.mainTb.item_append("document-open", "Open", self.openPress) self.mainTb.item_append("document-save", "Save", self.savePress) self.mainTb.item_append("document-save-as", "Save As", self.saveAsPress) # -- Edit Dropdown Menu -- tb_it = self.mainTb.item_append("edit", "Edit") tb_it.menu = True menu = tb_it.menu menu.item_add(None, "Copy", "edit-copy", self.copyPress) menu.item_add(None, "Paste", "edit-paste", self.pastePress) menu.item_add(None, "Cut", "edit-cut", self.cutPress) menu.item_separator_add() menu.item_add(None, "Select All", "edit-select-all", self.selectAllPress) # ----------------------- # self.mainTb.item_append("settings", "Options", self.optionsPress) self.mainTb.item_append("dialog-information", "About", self.aboutPress) self.mainEn = Entry(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainEn.callback_changed_user_add(self.textEdited) self.mainEn.scrollable_set(True) # creates scrollbars rather than enlarge window self.mainEn.line_wrap_set(False) # does not allow line wrap (can be changed by user) self.mainEn.autosave_set(False) # set to false to reduce disk I/O self.mainEn.elm_event_callback_add(self.eventsCb) self.mainEn.markup_filter_append(self.textFilter) self.mainEn.show() self.mainTb.show() self.mainBox.pack_end(self.mainTb) self.mainBox.pack_end(self.mainEn) #Build our file selector for saving/loading files self.fileBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileBox.show() self.fileLabel = Label(self.mainWindow, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) self.fileLabel.text = "" self.fileLabel.show() self.fileSelector = Fileselector(self.mainWindow, is_save=False, expandable=False, folder_only=False, path=os.getenv("HOME"), size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileSelector.callback_done_add(self.fileSelected) #self.fileSelector.callback_selected_add(fs_cb_selected, win) #self.fileSelector.callback_directory_open_add(fs_cb_directory_open, win) self.fileSelector.show() self.fileBox.pack_end(self.fileLabel) self.fileBox.pack_end(self.fileSelector) # the flip object has the file selector on one side and the GUI on the other self.flip = Flip(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.flip.part_content_set("front", self.mainBox) self.flip.part_content_set("back", self.fileBox) self.mainWindow.resize_object_add(self.flip) self.flip.show() self.isSaved = True self.isNewFile = False self.confirmPopup = None def newPress( self, obj, it ): self.newFile() it.selected_set(False) def openPress( self, obj, it ): self.openFile() it.selected_set(False) def savePress( self, obj, it ): self.saveFile() it.selected_set(False) def saveAsPress( self, obj, it ): self.saveAs() it.selected_set(False) def optionsPress( self, obj, it ): it.selected_set(False) def copyPress( self, obj, it ): self.mainEn.selection_copy() it.selected_set(False) def pastePress( self, obj, it ): self.mainEn.selection_paste() it.selected_set(False) def cutPress( self, obj, it ): self.mainEn.selection_cut() it.selected_set(False) def selectAllPress( self, obj, it ): self.mainEn.select_all() it.selected_set(False) def textEdited( self, obj ): ourFile = self.mainEn.file_get()[0] if ourFile and not self.isNewFile: self.mainWindow.title_set("*%s - ePad"%self.mainEn.file_get()[0].split("/")[len(self.mainEn.file_get()[0].split("/"))-1]) else: self.mainWindow.title_set("*Untitlted - ePad") self.isSaved = False def fileSelected( self, fs, file_selected, onStartup=False ): if not onStartup: self.flip.go(ELM_FLIP_INTERACTION_ROTATE) print(file_selected) IsSave = fs.is_save_get() if file_selected: if IsSave: newfile = open(file_selected,'w') # creates new file tmp_text = self.mainEn.entry_get() newfile.write(tmp_text) newfile.close() self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) self.mainEn.entry_set(tmp_text) self.mainEn.file_save() self.mainWindow.title_set("%s - ePad" % file_selected.split("/")[len(file_selected.split("/"))-1]) self.isSaved = True self.isNewFile = False else: try: self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) except RuntimeError: print("Empty file: {0}".format(file_selected)) self.mainWindow.title_set("%s - ePad" % file_selected.split("/")[len(file_selected.split("/"))-1]) def aboutPress( self, obj, it ): #About popup self.popupAbout = Popup(self.mainWindow, size_hint_weight=EXPAND_BOTH) self.popupAbout.text = "ePad - A simple text editor written in python and elementary<br><br> " \ "By: Jeff Hoogland" bt = Button(self.mainWindow, text="Done") bt.callback_clicked_add(self.aboutClose) self.popupAbout.part_content_set("button1", bt) self.popupAbout.show() it.selected_set(False) def aboutClose( self, bt ): self.popupAbout.delete() def newFile( self , obj=None, ignoreSave=False ): if self.isSaved == True or ignoreSave == True: trans = Transit() trans.object_add(self.mainEn) trans.auto_reverse = True trans.effect_wipe_add( ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE, ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT) trans.duration = 0.5 trans.go() time.sleep(0.5) self.mainWindow.title_set("Untitlted - ePad") self.mainEn.delete() self.mainEn = Entry(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainEn.callback_changed_user_add(self.textEdited) self.mainEn.scrollable_set(True) # creates scrollbars rather than enlarge window self.mainEn.line_wrap_set(False) # does not allow line wrap (can be changed by user) self.mainEn.autosave_set(False) # set to false to reduce disk I/O self.mainEn.elm_event_callback_add(self.eventsCb) self.mainEn.markup_filter_append(self.textFilter) self.mainEn.show() self.mainBox.pack_end(self.mainEn) self.isNewFile = True elif self.confirmPopup == None: self.confirmSave(self.newFile) def openFile( self, obj=None, ignoreSave=False ): if self.isSaved == True or ignoreSave == True: self.fileSelector.is_save_set(False) self.fileLabel.text = "<b>Select a text file to open:</b>" self.flip.go(ELM_FLIP_ROTATE_YZ_CENTER_AXIS) elif self.confirmPopup == None: self.confirmSave(self.openFile) def confirmSave( self, ourCallback=None ): self.confirmPopup = Popup(self.mainWindow, size_hint_weight=EXPAND_BOTH) self.confirmPopup.part_text_set("title,text","File Unsaved") if self.mainEn.file_get()[0]: self.confirmPopup.text = "Save changes to '%s'?" % self.mainEn.file_get()[0].split("/")[len(self.mainEn.file_get()[0].split("/"))-1] else: self.confirmPopup.text = "Save changes to 'Untitlted'?" # Close without saving button no_btt = Button(self.mainWindow) no_btt.text = "No" no_btt.callback_clicked_add(self.closePopup, self.confirmPopup) if ourCallback is not None: no_btt.callback_clicked_add(ourCallback, True) no_btt.show() # cancel close request cancel_btt = Button(self.mainWindow) cancel_btt.text = "Cancel" cancel_btt.callback_clicked_add(self.closePopup, self.confirmPopup) cancel_btt.show() # Save the file and then close button sav_btt = Button(self.mainWindow) sav_btt.text = "Yes" sav_btt.callback_clicked_add(self.saveFile) sav_btt.callback_clicked_add(self.closePopup, self.confirmPopup) sav_btt.show() # add buttons to popup self.confirmPopup.part_content_set("button1", no_btt) self.confirmPopup.part_content_set("button2", cancel_btt) self.confirmPopup.part_content_set("button3", sav_btt) self.confirmPopup.show() def saveAs( self ): self.fileSelector.is_save_set(True) self.fileLabel.text = "<b>Save new file to where:</b>" self.flip.go(ELM_FLIP_ROTATE_XZ_CENTER_AXIS) def saveFile( self, obj=False ): if self.mainEn.file_get()[0] == None or self.isNewFile: self.saveAs() else: self.mainEn.file_save() self.mainWindow.title_set("%s - ePad"%self.mainEn.file_get()[0].split("/")[len(self.mainEn.file_get()[0].split("/"))-1]) self.isSaved = True def closeChecks( self, obj ): print(self.isSaved) if self.isSaved == False and self.confirmPopup == None: self.confirmSave(self.closeApp) else: self.closeApp() def closePopup( self, bt, confirmPopup ): self.confirmPopup.delete() self.confirmPopup = None def closeApp( self, obj=False, trash=False ): elementary.exit() def eventsCb( self, obj, src, event_type, event ): #print event_type #print event.key #print "Control Key Status: %s" %event.modifier_is_set("Control") #print "Shift Key Status: %s" %event.modifier_is_set("Shift") #print event.modifier_is_set("Alt") if event.modifier_is_set("Control"): if event.key.lower() == "n": self.newFile() elif event.key.lower() == "s" and event.modifier_is_set("Shift"): self.saveAs() elif event.key.lower() == "s": self.saveFile() elif event.key.lower() == "o": self.openFile() def textFilter( self, obj, theText, data ): #print theText #Block ctrl+hot keys if theText == "" or theText == "" or theText == "": return None else: return theText def launch( self, startingFile=False ): if startingFile: self.fileSelected(self.fileSelector, startingFile, True) self.mainWindow.show()
class Interface(object): def __init__(self): self.mainWindow = StandardWindow("epad", "Untitled - ePad", size=(600, 400)) self.mainWindow.callback_delete_request_add(self.closeChecks) self.mainWindow.elm_event_callback_add(self.eventsCb) icon = Icon(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) icon.standard_set('accessories-text-editor') icon.show() self.mainWindow.icon_object_set(icon.object_get()) self.mainBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainBox.show() self.mainTb = ePadToolbar(self, self.mainWindow) self.mainTb.show() self.mainBox.pack_end(self.mainTb) # Initialize Text entry box print("Word wrap Initialized: {0}".format(self.wordwrap)) self.entryInit() # Add label to show current cursor position if SHOW_POS: self.line_label = Label(self.mainWindow, size_hint_weight=EXPAND_HORIZ, size_hint_align=ALIGN_RIGHT) self.curChanged(self.mainEn, self.line_label) self.line_label.show() self.mainBox.pack_end(self.line_label) self.mainEn.callback_cursor_changed_add(self.curChanged, self.line_label) # Build our file selector for saving/loading files self.fileBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileBox.show() self.fileLabel = Label(self.mainWindow, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH, text="") self.fileLabel.show() self.fileSelector = Fileselector(self.mainWindow, is_save=False, expandable=False, folder_only=False, path=os.getenv("HOME"), size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileSelector.callback_done_add(self.fileSelected) self.fileSelector.show() self.fileBox.pack_end(self.fileLabel) self.fileBox.pack_end(self.fileSelector) # Flip object has the file selector on one side # and the GUI on the other self.flip = Flip(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.flip.part_content_set("front", self.mainBox) self.flip.part_content_set("back", self.fileBox) self.mainWindow.resize_object_add(self.flip) self.flip.show() self.isSaved = True self.isNewFile = False self.confirmPopup = None def entryInit(self): self.mainEn = Entry(self.mainWindow, scrollable=True, line_wrap=self.wordwrap, autosave=False, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainEn.callback_changed_user_add(self.textEdited) self.mainEn.elm_event_callback_add(self.eventsCb) # self.mainEn.markup_filter_append(self.textFilter) self.mainEn.show() self.mainBox.pack_end(self.mainEn) def curChanged(self, entry, label): # get linear index into current text index = entry.cursor_pos_get() # Replace <br /> tag with single char # to simplify (line, col) calculation tmp_text = entry.entry_get().replace("<br/>", "\n") line = tmp_text[:index].count("\n") + 1 col = len(tmp_text[:index].split("\n")[-1]) + 1 # Update label text with line, col label.text = "Ln {0} Col {1} ".format(line, col) def textEdited(self, obj): current_file = self.mainEn.file[0] current_file = \ os.path.basename(current_file) if \ current_file and not self.isNewFile else \ "Untitled" self.mainWindow.title = "*%s - ePad" % (current_file) self.isSaved = False def fileSelected(self, fs, file_selected, onStartup=False): if not onStartup: self.flip.go(ELM_FLIP_INTERACTION_ROTATE) print(file_selected) IsSave = fs.is_save_get() if file_selected: if IsSave: newfile = open(file_selected, 'w') tmp_text = self.mainEn.entry_get() newfile.write(tmp_text) newfile.close() self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) self.mainEn.entry_set(tmp_text) self.mainEn.file_save() self.mainWindow.title_set("%s - ePad" % os.path.basename(file_selected)) self.isSaved = True self.isNewFile = False else: try: self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) except RuntimeError: print("Empty file: {0}".format(file_selected)) self.mainWindow.title_set("%s - ePad" % os.path.basename(file_selected)) def newFile(self, obj=None, ignoreSave=False): if self.isSaved is True or ignoreSave is True: trans = Transit() trans.object_add(self.mainEn) trans.auto_reverse = True trans.effect_wipe_add(ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE, ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT) trans.duration = 0.5 trans.go() time.sleep(0.5) self.mainWindow.title_set("Untitled - ePad") self.mainEn.delete() self.entryInit() self.isNewFile = True elif self.confirmPopup is None: self.confirmSave(self.newFile) def openFile(self, obj=None, ignoreSave=False): if self.isSaved is True or ignoreSave is True: self.fileSelector.is_save_set(False) self.fileLabel.text = "<b>Select a text file to open:</b>" self.flip.go(ELM_FLIP_ROTATE_YZ_CENTER_AXIS) elif self.confirmPopup is None: self.confirmSave(self.openFile) def confirmSave(self, ourCallback=None): self.confirmPopup = Popup(self.mainWindow, size_hint_weight=EXPAND_BOTH) self.confirmPopup.part_text_set("title,text", "File Unsaved") current_file = self.mainEn.file[0] current_file = \ os.path.basename(current_file) if current_file else "Untitled" self.confirmPopup.text = "Save changes to '%s'?" % (current_file) # Close without saving button no_btt = Button(self.mainWindow) no_btt.text = "No" no_btt.callback_clicked_add(self.closePopup, self.confirmPopup) if ourCallback is not None: no_btt.callback_clicked_add(ourCallback, True) no_btt.show() # cancel close request cancel_btt = Button(self.mainWindow) cancel_btt.text = "Cancel" cancel_btt.callback_clicked_add(self.closePopup, self.confirmPopup) cancel_btt.show() # Save the file and then close button sav_btt = Button(self.mainWindow) sav_btt.text = "Yes" sav_btt.callback_clicked_add(self.saveFile) sav_btt.callback_clicked_add(self.closePopup, self.confirmPopup) sav_btt.show() # add buttons to popup self.confirmPopup.part_content_set("button1", no_btt) self.confirmPopup.part_content_set("button2", cancel_btt) self.confirmPopup.part_content_set("button3", sav_btt) self.confirmPopup.show() def saveAs(self): self.fileSelector.is_save_set(True) self.fileLabel.text = "<b>Save new file to where:</b>" self.flip.go(ELM_FLIP_ROTATE_XZ_CENTER_AXIS) def saveFile(self, obj=False): if self.mainEn.file_get()[0] is None or self.isNewFile: self.saveAs() else: self.mainEn.file_save() self.mainWindow.title_set("%s - ePad" % os.path.basename(self.mainEn.file[0])) self.isSaved = True def closeChecks(self, obj): print(self.isSaved) if self.isSaved is False and self.confirmPopup is None: self.confirmSave(self.closeApp) else: self.closeApp() def closePopup(self, bt, confirmPopup): self.confirmPopup.delete() self.confirmPopup = None def closeApp(self, obj=False, trash=False): elementary.exit() def eventsCb(self, obj, src, event_type, event): if event.modifier_is_set("Control"): if event.key.lower() == "n": self.newFile() elif event.key.lower() == "s" and event.modifier_is_set("Shift"): self.saveAs() elif event.key.lower() == "s": self.saveFile() elif event.key.lower() == "o": self.openFile() # Legacy hack no longer needed # there was an issue in elementary entry where it would # accept those character controls # def textFilter( self, obj, theText, data ): # # Block ctrl+hot keys used in eventsCb # # # # Ctrl O Ctrl N Ctrl S # ctrl_block = [chr(14), chr(15), chr(19)] # if theText in ctrl_block: # return None # else: # return theText def launch(self, startingFile=False): if startingFile: self.fileSelected(self.fileSelector, startingFile, True) self.mainWindow.show()
class Interface(object): def __init__(self): self.mainWindow = StandardWindow("epad", "Untitled - ePad", size=(600, 400)) self.mainWindow.callback_delete_request_add(self.closeChecks) self.mainWindow.elm_event_callback_add(self.eventsCb) icon = Icon(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) icon.standard_set('accessories-text-editor') icon.show() self.mainWindow.icon_object_set(icon.object_get()) self.mainBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainBox.show() self.mainTb = ePadToolbar(self, self.mainWindow) self.mainTb.show() self.mainBox.pack_end(self.mainTb) # Initialize Text entry box print("Word wrap Initialized: {0}".format(self.wordwrap)) self.entryInit() # Add label to show current cursor position if SHOW_POS: self.line_label = Label(self.mainWindow, size_hint_weight=EXPAND_HORIZ, size_hint_align=ALIGN_RIGHT) self.curChanged(self.mainEn, self.line_label) self.line_label.show() self.mainBox.pack_end(self.line_label) self.mainEn.callback_cursor_changed_add(self.curChanged, self.line_label) # Build our file selector for saving/loading files self.fileBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileBox.show() self.fileLabel = Label(self.mainWindow, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH, text="") self.fileLabel.show() self.fileSelector = Fileselector(self.mainWindow, is_save=False, expandable=False, folder_only=False, path=os.getenv("HOME"), size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileSelector.callback_done_add(self.fileSelected) self.fileSelector.show() self.fileBox.pack_end(self.fileLabel) self.fileBox.pack_end(self.fileSelector) # Flip object has the file selector on one side # and the GUI on the other self.flip = Flip(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.flip.part_content_set("front", self.mainBox) self.flip.part_content_set("back", self.fileBox) self.mainWindow.resize_object_add(self.flip) self.flip.show() self.isSaved = True self.isNewFile = False self.confirmPopup = None def entryInit(self): self.mainEn = Entry(self.mainWindow, scrollable=True, line_wrap=self.wordwrap, autosave=False, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainEn.callback_changed_user_add(self.textEdited) self.mainEn.elm_event_callback_add(self.eventsCb) # self.mainEn.markup_filter_append(self.textFilter) self.mainEn.show() self.mainBox.pack_end(self.mainEn) def curChanged(self, entry, label): # get linear index into current text index = entry.cursor_pos_get() # Replace <br /> tag with single char # to simplify (line, col) calculation tmp_text = entry.entry_get().replace("<br/>", "\n") line = tmp_text[:index].count("\n") + 1 col = len(tmp_text[:index].split("\n")[-1]) + 1 # Update label text with line, col label.text = "Ln {0} Col {1} ".format(line, col) def textEdited(self, obj): current_file = self.mainEn.file[0] current_file = \ os.path.basename(current_file) if \ current_file and not self.isNewFile else \ "Untitled" self.mainWindow.title = "*%s - ePad" % (current_file) self.isSaved = False def fileSelected(self, fs, file_selected, onStartup=False): if not onStartup: self.flip.go(ELM_FLIP_INTERACTION_ROTATE) print(file_selected) IsSave = fs.is_save_get() if file_selected: if IsSave: newfile = open(file_selected, 'w') tmp_text = self.mainEn.entry_get() newfile.write(tmp_text) newfile.close() self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) self.mainEn.entry_set(tmp_text) self.mainEn.file_save() self.mainWindow.title_set("%s - ePad" % os.path.basename(file_selected)) self.isSaved = True self.isNewFile = False else: try: self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) except RuntimeError: print("Empty file: {0}".format(file_selected)) self.mainWindow.title_set("%s - ePad" % os.path.basename(file_selected)) def newFile(self, obj=None, ignoreSave=False): if self.isSaved is True or ignoreSave is True: trans = Transit() trans.object_add(self.mainEn) trans.auto_reverse = True trans.effect_wipe_add( ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE, ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT) trans.duration = 0.5 trans.go() time.sleep(0.5) self.mainWindow.title_set("Untitled - ePad") self.mainEn.delete() self.entryInit() self.isNewFile = True elif self.confirmPopup is None: self.confirmSave(self.newFile) def openFile(self, obj=None, ignoreSave=False): if self.isSaved is True or ignoreSave is True: self.fileSelector.is_save_set(False) self.fileLabel.text = "<b>Select a text file to open:</b>" self.flip.go(ELM_FLIP_ROTATE_YZ_CENTER_AXIS) elif self.confirmPopup is None: self.confirmSave(self.openFile) def confirmSave(self, ourCallback=None): self.confirmPopup = Popup(self.mainWindow, size_hint_weight=EXPAND_BOTH) self.confirmPopup.part_text_set("title,text", "File Unsaved") current_file = self.mainEn.file[0] current_file = \ os.path.basename(current_file) if current_file else "Untitled" self.confirmPopup.text = "Save changes to '%s'?" % (current_file) # Close without saving button no_btt = Button(self.mainWindow) no_btt.text = "No" no_btt.callback_clicked_add(self.closePopup, self.confirmPopup) if ourCallback is not None: no_btt.callback_clicked_add(ourCallback, True) no_btt.show() # cancel close request cancel_btt = Button(self.mainWindow) cancel_btt.text = "Cancel" cancel_btt.callback_clicked_add(self.closePopup, self.confirmPopup) cancel_btt.show() # Save the file and then close button sav_btt = Button(self.mainWindow) sav_btt.text = "Yes" sav_btt.callback_clicked_add(self.saveFile) sav_btt.callback_clicked_add(self.closePopup, self.confirmPopup) sav_btt.show() # add buttons to popup self.confirmPopup.part_content_set("button1", no_btt) self.confirmPopup.part_content_set("button2", cancel_btt) self.confirmPopup.part_content_set("button3", sav_btt) self.confirmPopup.show() def saveAs(self): self.fileSelector.is_save_set(True) self.fileLabel.text = "<b>Save new file to where:</b>" self.flip.go(ELM_FLIP_ROTATE_XZ_CENTER_AXIS) def saveFile(self, obj=False): if self.mainEn.file_get()[0] is None or self.isNewFile: self.saveAs() else: self.mainEn.file_save() self.mainWindow.title_set("%s - ePad" % os.path.basename(self.mainEn.file[0])) self.isSaved = True def closeChecks(self, obj): print(self.isSaved) if self.isSaved is False and self.confirmPopup is None: self.confirmSave(self.closeApp) else: self.closeApp() def closePopup(self, bt, confirmPopup): self.confirmPopup.delete() self.confirmPopup = None def closeApp(self, obj=False, trash=False): elementary.exit() def eventsCb(self, obj, src, event_type, event): if event.modifier_is_set("Control"): if event.key.lower() == "n": self.newFile() elif event.key.lower() == "s" and event.modifier_is_set("Shift"): self.saveAs() elif event.key.lower() == "s": self.saveFile() elif event.key.lower() == "o": self.openFile() # Legacy hack no longer needed # there was an issue in elementary entry where it would # accept those character controls # def textFilter( self, obj, theText, data ): # # Block ctrl+hot keys used in eventsCb # # # # Ctrl O Ctrl N Ctrl S # ctrl_block = [chr(14), chr(15), chr(19)] # if theText in ctrl_block: # return None # else: # return theText def launch(self, startingFile=False): if startingFile: self.fileSelected(self.fileSelector, startingFile, True) self.mainWindow.show()
class FontSelector(Box): def __init__(self, parent_widget, *args, **kwargs): Box.__init__(self, parent_widget, *args, **kwargs) self.cancelCallback = None self.actionCallback = None self.__first_run = True self.use_theme = False self.override_theme_font_size = True self.override_font_size = 14 self.theme_data = None self.default_font = 'Sans' self.default_font_style = 'Regular' self.default_font_size = 14 self.selected_font = self.default_font self.selected_font_style = self.default_font_style self.selected_font_size = self.default_font_size self.font_style_str = self.get_text_style(self.selected_font, self.selected_font_style, self.selected_font_size) self.preview_text = 'abcdefghijk ABCDEFGHIJK' # Font size min and max self.fs_min = 8 self.fs_max = 72 lb = Label(self, text="<br><hilight><i>Select Font</i></hilight>", size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) lb.show() self.pack_end(lb) sp = Separator(self, horizontal=True, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) sp.show() self.pack_end(sp) # A horizontal box to hold our font list and font styles fontBox = Box(self, horizontal=True, homogeneous=True, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) fontBox.show() self.pack_end(fontBox) # A vertical box to hold label and list of font families vBoxFL = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) vBoxFL.show() fontBox.pack_end(vBoxFL) # A vertical box to hold label and list of font styles vBoxFS = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) vBoxFS.show() fontBox.pack_end(vBoxFS) # Generate our needed font data #now =time.time() fonts = [] fonts_raw = self.evas.font_available_list() # populate with default font families # see elm_font_available_hash_add Function in EFL f_families = ['Sans', 'Serif', 'Monospace'] f_styles = ['Regular', 'Italic', 'Bold', 'Bold Italic'] fonts_raw += [i + ':style=' + s for i in f_families for s in f_styles] self.fonts_hash = {} for font in fonts_raw: a = font_properties_get(font) # if font name contains a '-' a.name will replace with '\\-' # This needs removed to properly display the name fn = a.name.replace('\\', '') fonts.append(fn) if fn in self.fonts_hash: self.fonts_hash.setdefault(fn, []).append(a.styles[0]) else: self.fonts_hash[fn] = [a.styles[0]] # Deal with some problematic special cases for a, s in self.fonts_hash.items(): #print(a,s) if s: if len(s) == 1: s[0] = s[0].rstrip() if s[0] == u'regular': s[0] = u'Regular' if s[0] == u'Medium Italic': self.fonts_hash.setdefault(a, []).append(u'Bold Italic') elif s[0] == u'Italic': if a != u'Romande ADF Script Std': self.fonts_hash.setdefault(a, []).append(u'Regular') self.fonts_hash.setdefault(a, []).append(u'Bold') self.fonts_hash.setdefault(a, []).append(u'Bold Italic') else: self.fonts_hash.setdefault(a, []).append(u'Italic') self.fonts_hash.setdefault(a, []).append(u'Bold') self.fonts_hash.setdefault(a, []).append(u'Bold Italic') elif len(s) == 2: if any(u'Oblique' in w for w in s): if a not in { u'Baskervald ADF Std Heavy', u'Latin Modern Roman Demi' }: self.fonts_hash.setdefault(a, []).append(u'Bold') self.fonts_hash.setdefault( a, []).append(u'Bold Oblique') elif any(u'Italic' in w for w in s): self.fonts_hash.setdefault(a, []).append(u'Bold') self.fonts_hash.setdefault(a, []).append(u'Bold Italic') else: self.fonts_hash.setdefault(a, []).append(u'Italic') self.fonts_hash.setdefault(a, []).append(u'Bold Italic') elif len(s) == 3 and set(s) == { u'Bold', u'Oblique', u'Medium' }: # case GWMonospace self.fonts_hash.setdefault(a, []).append(u'Bold Oblique') elif len(s) == 3 and set(s) == { u'Italic', u'Regular', u'Bold' }: # Case Eden Mills self.fonts_hash.setdefault(a, []).append(u'Bold Italic') elif len(s) < 4: print("may need fixed Font style for %s: %s" % (a, s)) #print(self.fonts_hash) # for some strange reason many fonts are displayed multiple times. The following lines remove # all duplicates and then sort them alphabetically. # FIXME: Is this still true fonts = list(set(fonts)) fonts.sort(cmp=locale.strcoll) # Elm List for holding font options self.font_list = List(self, size_hint_align=FILL_BOTH, size_hint_weight=EXPAND_BOTH, mode=ELM_LIST_LIMIT) #self.font_list.callback_selected_add(self.__font_demo_name_set) for font in fonts: self.font_list.item_append(font.replace('\\', '')) if font == self.selected_font: font_it = self.font_list.last_item_get() #print (time.time()- now) self.font_list.go() self.font_list.show() font_family_label = Label(self) font_family_label.text = "<br><b>Font:</b>" font_family_label.show() vBoxFL.pack_end(font_family_label) vBoxFL.pack_end(self.font_list) # Elm List for hold font styles self.font_style = List(self, size_hint_align=FILL_BOTH, size_hint_weight=EXPAND_BOTH, mode=ELM_LIST_LIMIT) #self.font_style.callback_selected_add(self.__font_demo_style_set) self.__reset_font_style_list(font_it.text_get()) self.font_style.go() self.font_style.show() font_style_label = Label(self) font_style_label.text = "<br><b>Style:</b>" font_style_label.show() vBoxFS.pack_end(font_style_label) vBoxFS.pack_end(self.font_style) # A table to hold font size Spinner and set theme default Check tb = Table(self, homogeneous=True, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) self.pack_end(tb) tb.show() # spinner to choose the font size self.font_sizer = Spinner(self) self.font_sizer.min_max_set(self.fs_min, self.fs_max) self.font_sizer.value_set(self.selected_font_size) #self.font_sizer.callback_changed_add(self.__font_demo_size_set) self.font_sizer.show() # Label for Spinner font_sizer_label = Label(self) font_sizer_label.text = "Font Size: " font_sizer_label.show() size_box = Box(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) size_box.horizontal_set(True) size_box.pack_end(font_sizer_label) size_box.pack_end(self.font_sizer) size_box.show() tb.pack(size_box, 33, 0, 34, 34) self.use_theme_ck = Check(self, text="Theme Default ", size_hint_weight=EXPAND_HORIZ, size_hint_align=(1, 0.5)) self.use_theme_ck.callback_changed_add(self.__use_theme_checked) self.use_theme_ck.show() tb.pack(self.use_theme_ck, 67, 0, 33, 34) # Entry to hold sample text self.font_demo = Entry(self, single_line=True, editable=False, context_menu_disabled=True, text=self.preview_text, scrollable=True, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) self.font_demo.show() demo_box = Frame(self, size_hint_align=FILL_BOTH, text="Preview:", content=self.font_demo) demo_box.show() # Fixme: move this shit font_it.selected_set(True) font_it.show() # Ensure focus is on Font List self.font_list.focus_set(True) self.pack_end(demo_box) # cancel and OK buttons ok_button = Button(self) ok_button.text = "OK" ok_button.callback_pressed_add(self.__ok_button_pressed) ok_button.show() cancel_button = Button(self) cancel_button.text = "Cancel" cancel_button.callback_pressed_add(self.__cancel_button_pressed) cancel_button.show() # box for buttons button_box = Box(self) button_box.horizontal_set(True) button_box.show() button_box.pack_end(cancel_button) button_box.pack_end(ok_button) self.pack_end(button_box) def callback_activated_add(self, cb): self.actionCallback = cb def callback_cancel_add(self, cb): self.cancelCallback = cb def set_preview_text(self, text): self.preview_text = text self.font_demo.entry_set(text) def __cancel_button_pressed(self, btn): self.use_theme = self.show.use_theme_init #print("cancel", self.use_theme) self.selected_font = self.default_font self.selected_font_style = self.default_font_style self.selected_font_size = self.default_font_size self.font_style_str = self.get_text_style(self.selected_font, self.selected_font_style, self.selected_font_size) if self.cancelCallback: self.cancelCallback(self) def __ok_button_pressed(self, btn): # Set selections # if use_theme is set any of these could be potentially unset try: self.selected_font = self.font_list.selected_item_get().text_get() self.selected_font_style = self.font_style.selected_item_get( ).text_get() self.selected_font_size = self.font_sizer.value_get() self.font_style_str = self.get_text_style(self.selected_font, self.selected_font_style, self.selected_font_size) except AttributeError: self.selected_font = self.default_font if self.default_font_style in self.fonts_hash[self.selected_font]: self.selected_font_style = self.default_font_style else: #print("OK attribute error", self.selected_font, self.default_font_style) self.selected_font_style = self.fonts_hash.items[ self.selected_font][0] self.selected_font_size = self.default_font_size self.font_style_str = self.get_text_style(self.selected_font, self.selected_font_style, self.selected_font_size) self.use_theme = self.use_theme_ck.state_get() if self.actionCallback: self.actionCallback(self) def __use_theme_checked(self, ck): self.use_theme = ck.state_get() #print ( '__use_theme_checked') if self.use_theme: if not self.theme_data: self._set_theme_data() self.set_font(*self.theme_data) while self.font_demo.text_style_user_peek(): self.font_demo.text_style_user_pop() if self.theme_data[1] == None: try: self.font_style.selected_item_get().selected = False except AttributeError: pass if self.override_theme_font_size: self.font_demo.text_style_user_push( "DEFAULT='font_size={0}'".format(self.override_font_size)) self.font_sizer.value_set(self.override_font_size) # Ensure these are unchanged ck.state = self.use_theme = True else: # ensure style is selected self.selected_font = self.default_font self.selected_font_style = self.default_font_style self.selected_font_size = self.default_font_size self.font_style_str = self.get_text_style(self.selected_font, self.selected_font_style, self.selected_font_size) self.set_font(self.default_font, self.default_font_style, self.default_font_size) # Ensure these are unchanged ck.state = self.use_theme = False def _set_theme_data(self): tb_style = self.font_demo.textblock.style_get() font = tb_style.split('text_class=entry_text')[1].split( 'font=')[1].split("'em=")[0] # font may or may not have style associated with it if ':style=' in font: font, style = font.split(':style=') else: style = None # If font name or styyle has spaces in it # textblock.style_get() inserts '\' before space # then the python string split function adds another space # To set the style with a font name that has spaces spaces need to be removed font = font.replace('\\ ', ' ') if style: style = style.replace('\\ ', ' ') size = tb_style.split('text_class=entry_text')[1].split( 'font_size=')[1].split(' ')[0] self.theme_data = [font, style, float(size)] def set_font(self, font, style=None, size=None): found_font = found_style = False #print(self.set_font.__name__, font, style, size, self.use_theme) for font_it in self.font_list.items: if '\\' in font: # Special characters in font names cause problems # need to remove the escape characters before comparison font = font.replace('\\', '') if font == font_it.text: found = True self.selected_font = font_it.text font_it.selected = True font_it.show() break if size and self.fs_min <= size <= self.fs_max: self.selected_font_size = size self.font_sizer.value_set(size) if found_font: self.__reset_font_style_list(font) if style in self.fonts_hash[font_it.text]: for style_it in self.font_style.items: if style == style_it.text: self.selected_font_style = style_it.text style_it.selected = True style_it.show() found_style = True break if not found_style: self.__font_style_set(self.selected_font) # Ensure focus is on Font List self.font_list.focus_set(True) def __font_demo_name_set(self, f_list, font): if self.use_theme: self.use_theme = self.use_theme_ck.state = False self.__reset_font_style_list(font.text_get()) self.__font_style_set(font.text_get()) # Ensure focus is on Font List self.font_list.focus_set(True) def __font_demo_style_set(self, s_list, style): if self.use_theme: self.use_theme = self.use_theme_ck.state = False self.__font_style_set(self.font_list.selected_item_get().text_get()) def __font_demo_size_set(self, sizer): if self.use_theme: self.use_theme = self.use_theme_ck.state = False self.__font_style_set(self.font_list.selected_item_get().text_get()) def __font_style_set(self, font_name): #print (" __font_style_set", font_name) while self.font_demo.text_style_user_peek(): self.font_demo.text_style_user_pop() if self.font_style.selected_item_get(): font_style = self.font_style.selected_item_get().text_get() else: font_style = self.font_style.first_item_get().text_get() font_size = self.font_sizer.value_get() style = self.get_text_style(font_name, font_style, font_size) self.font_demo.text_style_user_push(style) self.font_style_str = style def __reset_font_style_list(self, font_name): self.font_style.clear() self.__normalize_font_style_list(font_name) for style in self.fonts_hash[font_name]: self.font_style.item_append(style) if font_name == self.default_font and style == self.selected_font_style: self.font_style.last_item_get().selected_set(True) if font_name != self.default_font: self.font_style.first_item_get().selected_set(True) #print(self.font_style.first_item_get()) #self.font_style.first_item_get().selected_set(True) self.font_style.first_item_get().show() def get_text_style(self, font_name, font_style_str, font_size): if "'" in font_name: # Special characters in font name issue font_name = font_name.replace("'", "\\'") if font_style_str: style = "DEFAULT='font_size={0} font={1}:style={2}'".format( font_size, font_name.replace(' ', '\ '), font_style_str.replace(' ', '\ ')) else: style = "DEFAULT='font_size={0} font={1}'".format( font_size, font_name.replace(' ', '\ ')) return style def __normalize_font_style_list(self, font_name): styles_list = self.fonts_hash[font_name] if 'Regular' in styles_list and styles_list[0] != 'Regular': styles_list.remove('Regular') styles_list.insert(0, 'Regular') def show(self): #print("SHOW Selected ", self.use_theme, self.selected_font, self.selected_font_style) #print("SHOW default ", self.use_theme, self.default_font, self.default_font_style) if self.__first_run: # only set the callbacks once # needed when called from another window repeatedly #print("__first_run__") self.font_list.callback_selected_add(self.__font_demo_name_set) self.font_style.callback_selected_add(self.__font_demo_style_set) self.font_sizer.callback_changed_add(self.__font_demo_size_set) self.__first_run = False self.show.__func__.use_theme_init = self.use_theme self.use_theme_ck.state = self.use_theme if self.use_theme: self.__use_theme_checked(self.use_theme_ck) #print("selected", self.font_list.selected_item_get().text_get()) if not self.use_theme: self.set_font(self.selected_font, self.selected_font_style, self.selected_font_size) super(FontSelector, self).show()
class Interface(object): def __init__(self): self.mainWindow = StandardWindow("epad", "Untitled - ePad", size=(600, 400)) self.mainWindow.callback_delete_request_add(self.closeChecks) self.mainWindow.elm_event_callback_add(self.eventsCb) icon = Icon(self.mainWindow) icon.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND) icon.size_hint_align_set(EVAS_HINT_FILL, EVAS_HINT_FILL) icon.standard_set( 'accessories-text-editor' ) # assumes image icon is in local dir, may need to change later icon.show() self.mainWindow.icon_object_set(icon.object_get()) self.mainBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainBox.show() self.mainTb = Toolbar(self.mainWindow, homogeneous=False, size_hint_weight=(0.0, 0.0), size_hint_align=(EVAS_HINT_FILL, 0.0)) self.mainTb.menu_parent = self.mainWindow self.mainTb.item_append("document-new", "New", self.newPress) self.mainTb.item_append("document-open", "Open", self.openPress) self.mainTb.item_append("document-save", "Save", self.savePress) self.mainTb.item_append("document-save-as", "Save As", self.saveAsPress) # -- Edit Dropdown Menu -- tb_it = self.mainTb.item_append("edit", "Edit") tb_it.menu = True menu = tb_it.menu menu.item_add(None, "Copy", "edit-copy", self.copyPress) menu.item_add(None, "Paste", "edit-paste", self.pastePress) menu.item_add(None, "Cut", "edit-cut", self.cutPress) menu.item_separator_add() menu.item_add(None, "Select All", "edit-select-all", self.selectAllPress) # ----------------------- # self.mainTb.item_append("settings", "Options", self.optionsPress) self.mainTb.item_append("dialog-information", "About", self.aboutPress) self.mainEn = Entry(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainEn.callback_changed_user_add(self.textEdited) self.mainEn.scrollable_set( True) # creates scrollbars rather than enlarge window self.mainEn.line_wrap_set( False) # does not allow line wrap (can be changed by user) self.mainEn.autosave_set(False) # set to false to reduce disk I/O self.mainEn.elm_event_callback_add(self.eventsCb) self.mainEn.markup_filter_append(self.textFilter) self.mainEn.show() self.mainTb.show() self.mainBox.pack_end(self.mainTb) self.mainBox.pack_end(self.mainEn) #Build our file selector for saving/loading files self.fileBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileBox.show() self.fileLabel = Label(self.mainWindow, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) self.fileLabel.text = "" self.fileLabel.show() self.fileSelector = Fileselector(self.mainWindow, is_save=False, expandable=False, folder_only=False, path=os.getenv("HOME"), size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileSelector.callback_done_add(self.fileSelected) #self.fileSelector.callback_selected_add(fs_cb_selected, win) #self.fileSelector.callback_directory_open_add(fs_cb_directory_open, win) self.fileSelector.show() self.fileBox.pack_end(self.fileLabel) self.fileBox.pack_end(self.fileSelector) # the flip object has the file selector on one side and the GUI on the other self.flip = Flip(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.flip.part_content_set("front", self.mainBox) self.flip.part_content_set("back", self.fileBox) self.mainWindow.resize_object_add(self.flip) self.flip.show() self.isSaved = True self.isNewFile = False self.confirmPopup = None def newPress(self, obj, it): self.newFile() it.selected_set(False) def openPress(self, obj, it): self.openFile() it.selected_set(False) def savePress(self, obj, it): self.saveFile() it.selected_set(False) def saveAsPress(self, obj, it): self.saveAs() it.selected_set(False) def optionsPress(self, obj, it): it.selected_set(False) def copyPress(self, obj, it): self.mainEn.selection_copy() it.selected_set(False) def pastePress(self, obj, it): self.mainEn.selection_paste() it.selected_set(False) def cutPress(self, obj, it): self.mainEn.selection_cut() it.selected_set(False) def selectAllPress(self, obj, it): self.mainEn.select_all() it.selected_set(False) def textEdited(self, obj): ourFile = self.mainEn.file_get()[0] if ourFile and not self.isNewFile: self.mainWindow.title_set( "*%s - ePad" % self.mainEn.file_get()[0].split("/")[ len(self.mainEn.file_get()[0].split("/")) - 1]) else: self.mainWindow.title_set("*Untitlted - ePad") self.isSaved = False def fileSelected(self, fs, file_selected, onStartup=False): if not onStartup: self.flip.go(ELM_FLIP_INTERACTION_ROTATE) print(file_selected) IsSave = fs.is_save_get() if file_selected: if IsSave: newfile = open(file_selected, 'w') # creates new file tmp_text = self.mainEn.entry_get() newfile.write(tmp_text) newfile.close() self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) self.mainEn.entry_set(tmp_text) self.mainEn.file_save() self.mainWindow.title_set( "%s - ePad" % file_selected.split("/")[len(file_selected.split("/")) - 1]) self.isSaved = True self.isNewFile = False else: try: self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) except RuntimeError: print("Empty file: {0}".format(file_selected)) self.mainWindow.title_set( "%s - ePad" % file_selected.split("/")[len(file_selected.split("/")) - 1]) def aboutPress(self, obj, it): #About popup self.popupAbout = Popup(self.mainWindow, size_hint_weight=EXPAND_BOTH) self.popupAbout.text = "ePad - A simple text editor written in python and elementary<br><br> " \ "By: Jeff Hoogland" bt = Button(self.mainWindow, text="Done") bt.callback_clicked_add(self.aboutClose) self.popupAbout.part_content_set("button1", bt) self.popupAbout.show() it.selected_set(False) def aboutClose(self, bt): self.popupAbout.delete() def newFile(self, obj=None, ignoreSave=False): if self.isSaved == True or ignoreSave == True: trans = Transit() trans.object_add(self.mainEn) trans.auto_reverse = True trans.effect_wipe_add(ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE, ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT) trans.duration = 0.5 trans.go() time.sleep(0.5) self.mainWindow.title_set("Untitlted - ePad") self.mainEn.delete() self.mainEn = Entry(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainEn.callback_changed_user_add(self.textEdited) self.mainEn.scrollable_set( True) # creates scrollbars rather than enlarge window self.mainEn.line_wrap_set( False) # does not allow line wrap (can be changed by user) self.mainEn.autosave_set(False) # set to false to reduce disk I/O self.mainEn.elm_event_callback_add(self.eventsCb) self.mainEn.markup_filter_append(self.textFilter) self.mainEn.show() self.mainBox.pack_end(self.mainEn) self.isNewFile = True elif self.confirmPopup == None: self.confirmSave(self.newFile) def openFile(self, obj=None, ignoreSave=False): if self.isSaved == True or ignoreSave == True: self.fileSelector.is_save_set(False) self.fileLabel.text = "<b>Select a text file to open:</b>" self.flip.go(ELM_FLIP_ROTATE_YZ_CENTER_AXIS) elif self.confirmPopup == None: self.confirmSave(self.openFile) def confirmSave(self, ourCallback=None): self.confirmPopup = Popup(self.mainWindow, size_hint_weight=EXPAND_BOTH) self.confirmPopup.part_text_set("title,text", "File Unsaved") if self.mainEn.file_get()[0]: self.confirmPopup.text = "Save changes to '%s'?" % self.mainEn.file_get( )[0].split("/")[len(self.mainEn.file_get()[0].split("/")) - 1] else: self.confirmPopup.text = "Save changes to 'Untitlted'?" # Close without saving button no_btt = Button(self.mainWindow) no_btt.text = "No" no_btt.callback_clicked_add(self.closePopup, self.confirmPopup) if ourCallback is not None: no_btt.callback_clicked_add(ourCallback, True) no_btt.show() # cancel close request cancel_btt = Button(self.mainWindow) cancel_btt.text = "Cancel" cancel_btt.callback_clicked_add(self.closePopup, self.confirmPopup) cancel_btt.show() # Save the file and then close button sav_btt = Button(self.mainWindow) sav_btt.text = "Yes" sav_btt.callback_clicked_add(self.saveFile) sav_btt.callback_clicked_add(self.closePopup, self.confirmPopup) sav_btt.show() # add buttons to popup self.confirmPopup.part_content_set("button1", no_btt) self.confirmPopup.part_content_set("button2", cancel_btt) self.confirmPopup.part_content_set("button3", sav_btt) self.confirmPopup.show() def saveAs(self): self.fileSelector.is_save_set(True) self.fileLabel.text = "<b>Save new file to where:</b>" self.flip.go(ELM_FLIP_ROTATE_XZ_CENTER_AXIS) def saveFile(self, obj=False): if self.mainEn.file_get()[0] == None or self.isNewFile: self.saveAs() else: self.mainEn.file_save() self.mainWindow.title_set( "%s - ePad" % self.mainEn.file_get()[0].split("/")[ len(self.mainEn.file_get()[0].split("/")) - 1]) self.isSaved = True def closeChecks(self, obj): print(self.isSaved) if self.isSaved == False and self.confirmPopup == None: self.confirmSave(self.closeApp) else: self.closeApp() def closePopup(self, bt, confirmPopup): self.confirmPopup.delete() self.confirmPopup = None def closeApp(self, obj=False, trash=False): elementary.exit() def eventsCb(self, obj, src, event_type, event): #print event_type #print event.key #print "Control Key Status: %s" %event.modifier_is_set("Control") #print "Shift Key Status: %s" %event.modifier_is_set("Shift") #print event.modifier_is_set("Alt") if event.modifier_is_set("Control"): if event.key.lower() == "n": self.newFile() elif event.key.lower() == "s" and event.modifier_is_set("Shift"): self.saveAs() elif event.key.lower() == "s": self.saveFile() elif event.key.lower() == "o": self.openFile() def textFilter(self, obj, theText, data): #print theText #Block ctrl+hot keys if theText == "" or theText == "" or theText == "": return None else: return theText def launch(self, startingFile=False): if startingFile: self.fileSelected(self.fileSelector, startingFile, True) self.mainWindow.show()
class Interface(object): def __init__(self): self.mainWindow = StandardWindow("epad", "Untitled - ePad", size=(600, 400)) self.mainWindow.callback_delete_request_add(self.closeChecks) self.mainWindow.elm_event_callback_add(self.eventsCb) icon = Icon(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) icon.standard_set('accessories-text-editor') icon.show() self.mainWindow.icon_object_set(icon.object_get()) self.mainBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainBox.show() self.newInstance = NEW_INSTANCE self.mainTb = ePadToolbar(self, self.mainWindow) self.mainTb.focus_allow = False self.mainTb.show() self.mainBox.pack_end(self.mainTb) # Root User Notification if os.geteuid() == 0: printErr("Caution: Root User") if NOTIFY_ROOT: notifyBox = Box(self.mainWindow, horizontal=True) notifyBox.show() notify = Notify(self.mainWindow, size_hint_weight=EXPAND_BOTH, align=(ELM_NOTIFY_ALIGN_FILL, 0.0), content=notifyBox) notifyLabel = Label(self.mainWindow) notifyLabel.text = "<b><i>Root User</i></b>" notifyBox.pack_end(notifyLabel) notifyLabel.show() self.mainBox.pack_end(notifyBox) self.about = aboutWin(self, self.mainWindow) self.about.hide() # Initialize Text entry box and line label # FIXME: self.wordwrap initialized by ePadToolbar print("Word wrap Initialized: {0}".format(self.wordwrap)) self.entryInit() # Build our file selector for saving/loading files self.fileBox = Box(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileBox.show() self.fileLabel = Label(self.mainWindow, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH, text="") self.fileLabel.show() self.lastDir = os.getenv("HOME") self.fileSelector = Fileselector(self.mainWindow, is_save=False, expandable=False, folder_only=False, hidden_visible=SHOW_HIDDEN, path=self.lastDir, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.fileSelector.callback_done_add(self.fileSelected) self.fileSelector.callback_activated_add(self.fileSelected) self.fileSelector.callback_directory_open_add(self.updateLastDir) self.fileSelector.path_set(os.getcwd()) self.fileSelector.show() self.fileBox.pack_end(self.fileLabel) self.fileBox.pack_end(self.fileSelector) # Flip object has the file selector on one side # and the GUI on the other self.flip = Flip(self.mainWindow, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.flip.part_content_set("front", self.mainBox) self.flip.part_content_set("back", self.fileBox) self.mainWindow.resize_object_add(self.flip) self.flip.show() self.isSaved = True self.isNewFile = False self.confirmPopup = None self.fileExistsFlag = False def entryInit(self): self.mainEn = Entry(self.mainWindow, scrollable=True, line_wrap=self.wordwrap, autosave=False, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainEn.callback_changed_user_add(self.textEdited) self.mainEn.elm_event_callback_add(self.eventsCb) self.mainEn.callback_clicked_add(resetCloseMenuCount) # delete line lable if it exist so we can create and add new one # Later need to rethink logic here try: self.line_label.delete() except AttributeError: pass # Add label to show current cursor position if SHOW_POS: self.line_label = Label(self.mainWindow, size_hint_weight=EXPAND_HORIZ, size_hint_align=ALIGN_RIGHT) self.mainEn.callback_cursor_changed_add(self.curChanged, self.line_label) self.curChanged(self.mainEn, self.line_label) self.line_label.show() self.mainBox.pack_end(self.line_label) # self.mainEn.markup_filter_append(self.textFilter) self.mainEn.show() self.mainEn.focus_set(True) try: self.mainBox.pack_before(self.mainEn, self.line_label) except AttributeError: # line_label has not been initialized on first run # Should have better logic on all this self.mainBox.pack_end(self.mainEn) def curChanged(self, entry, label): # get linear index into current text index = entry.cursor_pos_get() # Replace <br /> tag with single char # to simplify (line, col) calculation tmp_text = markup_to_utf8(entry.entry_get()) line = tmp_text[:index].count("\n") + 1 col = len(tmp_text[:index].split("\n")[-1]) + 1 # Update label text with line, col label.text = "Ln {0} Col {1} ".format(line, col) def textEdited(self, obj): current_file = self.mainEn.file[0] current_file = \ os.path.basename(current_file) if \ current_file and not self.isNewFile else \ "Untitled" self.mainWindow.title = "*%s - ePad" % (current_file) self.isSaved = False def newFile(self, obj=None, ignoreSave=False): if self.newInstance: # sh does not properly handle space between -d and path command = "epad -d'{0}'".format(self.lastDir) print("Launching new instance: {0}".format(command)) ecore.Exe(command, ecore.ECORE_EXE_PIPE_READ | ecore.ECORE_EXE_PIPE_ERROR | ecore.ECORE_EXE_PIPE_WRITE) return if self.isSaved is True or ignoreSave is True: trans = Transit() trans.object_add(self.mainEn) trans.auto_reverse = True trans.effect_wipe_add( ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE, ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT) trans.duration = 0.5 trans.go() time.sleep(0.5) self.mainWindow.title_set("Untitled - ePad") self.mainEn.delete() self.entryInit() self.isNewFile = True elif self.confirmPopup is None: self.confirmSave(self.newFile) self.mainEn.focus_set(True) def openFile(self, obj=None, ignoreSave=False): if self.isSaved is True or ignoreSave is True: self.fileSelector.is_save_set(False) self.fileLabel.text = "<b>Select a text file to open:</b>" self.flip.go(ELM_FLIP_ROTATE_YZ_CENTER_AXIS) elif self.confirmPopup is None: self.confirmSave(self.openFile) def confirmSave(self, ourCallback=None): self.confirmPopup = Popup(self.mainWindow, size_hint_weight=EXPAND_BOTH) self.confirmPopup.part_text_set("title,text", "File Unsaved") current_file = self.mainEn.file[0] current_file = \ os.path.basename(current_file) if current_file else "Untitled" self.confirmPopup.text = "Save changes to '%s'?" % (current_file) # Close without saving button no_btt = Button(self.mainWindow) no_btt.text = "No" no_btt.callback_clicked_add(self.closePopup, self.confirmPopup) if ourCallback is not None: no_btt.callback_clicked_add(ourCallback, True) no_btt.show() # cancel close request cancel_btt = Button(self.mainWindow) cancel_btt.text = "Cancel" cancel_btt.callback_clicked_add(self.closePopup, self.confirmPopup) cancel_btt.show() # Save the file and then close button sav_btt = Button(self.mainWindow) sav_btt.text = "Yes" sav_btt.callback_clicked_add(self.saveFile) sav_btt.callback_clicked_add(self.closePopup, self.confirmPopup) sav_btt.show() # add buttons to popup self.confirmPopup.part_content_set("button1", no_btt) self.confirmPopup.part_content_set("button2", cancel_btt) self.confirmPopup.part_content_set("button3", sav_btt) self.confirmPopup.show() def saveAs(self): self.fileSelector.is_save_set(True) self.fileLabel.text = "<b>Save new file to where:</b>" self.flip.go(ELM_FLIP_ROTATE_XZ_CENTER_AXIS) def saveFile(self, obj=False): if self.mainEn.file_get()[0] is None or self.isNewFile: self.saveAs() else: file_selected = self.mainEn.file_get()[0] # Detect save errors as entry.file_save currently returns no errors # even in the case where the file fails to save :( try: newfile = open(file_selected, 'w') except IOError as err: if err.errno == errno.EACCES: errorMsg = ("Permision denied: <b>'%s'</b>." "<br><br>Operation failed !!!" % (file_selected)) errorPopup(self.mainWindow, errorMsg) else: errorMsg = ("ERROR: %s: '%s'" "<br><br>Operation failed !!!" % (err.strerror, file_selected)) errorPopup(self.mainWindow, errorMsg) return newfile.close() # if entry is empty and the file does not exists then # entry.file_save will destroy the file created about by the # open statement above for some odd reason ... if not self.mainEn.is_empty: self.mainEn.file_save() self.mainWindow.title_set("%s - ePad" % os.path.basename(self.mainEn.file[0])) self.isSaved = True def doSelected(self, obj): # Something I should avoid but here I prefer a polymorphic function if isinstance(obj, Button): file_selected = self.fileSelector.selected_get() else: file_selected = obj IsSave = self.fileSelector.is_save_get() if file_selected: if IsSave: try: newfile = open(file_selected, 'w') except IOError as err: print("ERROR: {0}: '{1}'".format(err.strerror, file_selected)) if err.errno == errno.EACCES: errorMsg = ("Permision denied: <b>'%s'</b>." "<br><br>Operation failed !!!</br>" % (file_selected)) errorPopup(self.mainWindow, errorMsg) else: errorMsg = ("ERROR: %s: '%s'" "<br><br>Operation failed !!!</br>" % (err.strerror, file_selected)) errorPopup(self.mainWindow, errorMsg) return tmp_text = self.mainEn.entry_get() # FIXME: Why save twice? newfile.write(tmp_text) newfile.close() # Suppress error message when empty file is saved try: self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) except RuntimeError: print("Empty file saved:{0}".format(file_selected)) self.mainEn.entry_set(tmp_text) # if empty file entry.file_save destroys file :( if len(tmp_text): self.mainEn.file_save() self.mainWindow.title_set("%s - ePad" % os.path.basename(file_selected)) self.isSaved = True self.isNewFile = False else: if os.path.isdir(file_selected): print("ERROR: {0}: is a directory. " "Could not set file.".format(file_selected)) current_file = os.path.basename(file_selected) errorMsg = ("<b>'%s'</b> is a folder." "<br><br>Operation failed !!!</br>" % (current_file)) errorPopup(self.mainWindow, errorMsg) return # Test to see if file can be opened to catch permission errors # as entry.file_set function does not differentiate # different possible errors. try: with open(file_selected) as f: tmp_text = f.readline() except IOError as err: if err.errno == errno.ENOENT: print("Creating New file '{0}'".format(file_selected)) # self.fileSelector.current_name_set(file_selected) self.isSaved = False elif err.errno == errno.EACCES: print("ERROR: {0}: '{1}'".format(err.strerror, file_selected)) errorMsg = ("Permision denied: <b>'%s'</b>." "<br><br>Operation failed !!!</br>" % (file_selected)) errorPopup(self.mainWindow, errorMsg) return else: print("ERROR: {0}: '{1}'".format(err.strerror, file_selected)) errorMsg = ("ERROR: %s: '%s'" "<br><br>Operation failed !!!</br>" % (err.strerror, file_selected)) errorPopup(self.mainWindow, errorMsg) return try: self.mainEn.file_set(file_selected, ELM_TEXT_FORMAT_PLAIN_UTF8) except RuntimeError as msg: # Entry.file_set fails on empty files print("Empty file: {0}".format(file_selected)) self.mainWindow.title_set("%s - ePad" % os.path.basename(file_selected)) self.mainEn.focus_set(True) def fileExists(self, filePath): self.confirmPopup = Popup(self.mainWindow, size_hint_weight=EXPAND_BOTH) # Add a table to hold dialog image and text to Popup tb = Table(self.confirmPopup, size_hint_weight=EXPAND_BOTH) self.confirmPopup.part_content_set("default", tb) tb.show() # Add dialog-error Image to table need_ethumb() icon = Icon(self.confirmPopup, thumb='True') icon.standard_set('dialog-question') # Using gksudo or sudo fails to load Image here # unless options specify using preserving their existing environment. # may also fail to load other icons but does not raise an exception # in that situation. # Works fine using eSudo as a gksudo alternative, # other alternatives not tested try: dialogImage = Image(self.confirmPopup, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH, file=icon.file_get()) tb.pack(dialogImage, 0, 0, 1, 1) dialogImage.show() except RuntimeError: # An error message is displayed for this same error # when aboutWin is initialized so no need to redisplay. pass # Add dialog text to table dialogLabel = Label(self.confirmPopup, line_wrap=ELM_WRAP_WORD, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_BOTH) current_file = os.path.basename(filePath) dialogLabel.text = "'%s' already exists. Overwrite?<br><br>" \ % (current_file) tb.pack(dialogLabel, 1, 0, 1, 1) dialogLabel.show() # Close without saving button no_btt = Button(self.mainWindow) no_btt.text = "No" no_btt.callback_clicked_add(self.closePopup, self.confirmPopup) no_btt.show() # Save the file and then close button sav_btt = Button(self.mainWindow) sav_btt.text = "Yes" sav_btt.callback_clicked_add(self.doSelected) sav_btt.callback_clicked_add(self.closePopup, self.confirmPopup) sav_btt.show() # add buttons to popup self.confirmPopup.part_content_set("button1", no_btt) self.confirmPopup.part_content_set("button3", sav_btt) self.confirmPopup.show() def fileSelected(self, fs, file_selected, onStartup=False): if not onStartup: self.flip.go(ELM_FLIP_INTERACTION_ROTATE) # Markup can end up in file names because file_selector name_entry # is an elementary entry. So lets sanitize file_selected. file_selected = markup_to_utf8(file_selected) if file_selected: print("File Selected: {0}".format(file_selected)) self.lastDir = os.path.dirname(file_selected) fs.path_set(self.lastDir) # This fails if file_selected does not exist yet try: fs.selected = file_selected except RuntimeError: # FIXME: would be nice if I could set fileSelector name entry pass IsSave = fs.is_save_get() if file_selected: if IsSave: if os.path.isdir(file_selected): current_file = os.path.basename(file_selected) errorMsg = ("<b>'%s'</b> is a folder." "<br><br>Operation failed !!!" % (current_file)) errorPopup(self.mainWindow, errorMsg) return elif os.path.exists(file_selected): self.fileExistsFlag = True self.fileExists(file_selected) return self.doSelected(file_selected) def updateLastDir(self, fs, path): self.lastDir = path def closeChecks(self, obj): print("File is Saved: ", self.isSaved) if not self.flip.front_visible_get(): self.flip.go(ELM_FLIP_ROTATE_XZ_CENTER_AXIS) elif self.isSaved is False and self.confirmPopup is None: self.confirmSave(self.closeApp) else: self.closeApp() def closePopup(self, bt, confirmPopup): self.confirmPopup.delete() self.confirmPopup = None def showAbout(self): self.about.launch() def closeApp(self, obj=False, trash=False): elementary.exit() def eventsCb(self, obj, src, event_type, event): if event.modifier_is_set("Control"): if event.key.lower() == "n": self.newFile() elif event.key.lower() == "s" and event.modifier_is_set("Shift"): self.saveAs() elif event.key.lower() == "s": self.saveFile() elif event.key.lower() == "o": self.openFile() elif event.key.lower() == "h": if not self.flip.front_visible_get(): toggleHidden(self.fileSelector) elif event.key.lower() == "q": closeCtrlChecks(self) # Legacy hack no longer needed # there was an issue in elementary entry where it would # accept those character controls # def textFilter( self, obj, theText, data ): # # Block ctrl+hot keys used in eventsCb # # # # Ctrl O Ctrl N Ctrl S # ctrl_block = [chr(14), chr(15), chr(19)] # if theText in ctrl_block: # return None # else: # return theText def launch(self, start=[]): if start and start[0] and os.path.dirname(start[0]) == '': start[0] = os.getcwd() + '/' + start[0] if start and start[0]: if os.path.isdir(os.path.dirname(start[0])): self.fileSelected(self.fileSelector, start[0], True) else: print("Error: {0} is an Invalid Path".format(start)) errorMsg = ("<b>'%s'</b> is an Invalid path." "<br><br>Open failed !!!" % (start)) errorPopup(self.mainWindow, errorMsg) if start and start[1]: if os.path.isdir(start[1]): print("Initializing file selection path: {0}".format(start[1])) self.fileSelector.path_set(start[1]) self.lastDir = start[1] else: print("Error: {0} is an Invalid Path".format(start[1])) self.mainWindow.show()