#!/usr/bin/env python2 import signal signal.signal(signal.SIGINT, signal.SIG_DFL) import os, sys os.environ['GTK_THEME'] = 'light' from gi.repository import GObject, Gst, Gtk, Gdk, GtkSource GObject.threads_init() Gdk.threads_init() import command, validate, dialog class SourceView(Gtk.Window): def __init__(self, filename=None): super(SourceView, self).__init__() self.filename = 'unsaved' self.connect("destroy", self.quit) self.set_default_size(1024, 768) self.set_border_width(10) self.set_title('Homeostasis editor') tabs = Gtk.Notebook() self.tabs = tabs vbox = Gtk.VBox() # contains tabs and buttons self.source_buffer = GtkSource.Buffer() lang_manager = GtkSource.LanguageManager() self.source_buffer.set_language(lang_manager.get_language('xml')) self.source_buffer.set_modified(False) self.source_view = GtkSource.View.new_with_buffer(self.source_buffer) self.source_view.set_show_line_numbers(True) self.source_view.set_tab_width(4) self.source_view.set_wrap_mode(Gtk.WrapMode.WORD) self.scrolled = Gtk.ScrolledWindow() self.scrolled.add(self.source_view) #vbox.pack_start(self.scrolled, True, True, 5) self.command = command.Command() #vbox.pack_start(self.command, False, True, 5) hbox = Gtk.HBox() new_button = Gtk.Button('New') new_button.connect('clicked', self.new) hbox.pack_start(new_button, False, False, 5) load_button = Gtk.Button('Load') load_button.connect('clicked', lambda *args: self.show_filechooser("load")) hbox.pack_start(load_button, False, False, 5) validate_button = Gtk.Button('Validate') validate_button.connect('clicked', self.validate) hbox.pack_start(validate_button, False, False, 5) compile_button = Gtk.Button('Compile') compile_button.connect('clicked', self.compile) hbox.pack_start(compile_button, False, False, 5) save_button = Gtk.Button('Save') save_button.connect('clicked', self.save) hbox.pack_start(save_button, False, False, 5) saveas_button = Gtk.Button('Save as') saveas_button.connect('clicked', lambda *args: self.show_filechooser("saveas")) hbox.pack_start(saveas_button, False, False, 5) vbox.pack_start(tabs, True, True, 5) vbox.pack_start(hbox, False, True, 5) tabs.append_page(self.scrolled, Gtk.Label(self.filename)) tabs.append_page(self.command, Gtk.Label('Compilation result')) tabs.set_show_border(False) if filename != None: self.set_filename(filename) self.load() self.add(vbox) self.show_all() self.command.add_text('READY') def new(self, *args): if not self.source_buffer.get_modified() or dialog.confirm('Discard changes to "%s"?' % self.filename): self.source_buffer.set_text("""<homeostasis version="25-11-2014"> <liste_section sequences="1" ordre="variable" repetition="oui" action="exclusive"> <section id="2" action="example1"> <sequence ordre="strict" repetition="non" action="" lang="esp"> <keyword action="example2" lang="eng"> hello </keyword> </sequence> </section> </liste_section> </homeostasis>""") self.set_filename('unsaved') def set_filename(self, filename): self.filename = filename self.tabs.set_tab_label(self.scrolled, Gtk.Label(os.path.basename(filename))) def show_filechooser(self, dialog_type="load"): if dialog_type == "load": chooser = Gtk.FileChooserDialog("Please choose a file to load", self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) else: chooser = Gtk.FileChooserDialog("Please set a file to save", self, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK)) filter_text = Gtk.FileFilter() filter_text.set_name("XML files") filter_text.add_mime_type("text/xml") chooser.add_filter(filter_text) chooser.set_current_folder('%s/data' % (os.path.dirname(__file__) or '.')) response = chooser.run() if response == -5: self.filename = chooser.get_filename() print self.filename self.set_filename(self.filename) chooser.destroy() if dialog_type == "load": return self.load() else: self.source_buffer.set_modified(True) # force to save return self.save() chooser.destroy() def load(self, *args): if not self.source_buffer.get_modified() or dialog.confirm('Discard changes to "%s"?' % self.filename): try: with open(self.filename) as fp: self.source_buffer.set_text(fp.read()) self.source_buffer.set_modified(False) except Exception as e: print e self.command.add_text('FAILED to load "%s"' % self.filename) return False return True return False def save(self, *args): if not self.source_buffer.get_modified(): # no need to save return True if os.path.exists(self.filename) and not dialog.confirm('Overwrite "%s"?' % self.filename): return False if self.filename == 'unsaved': return self.show_filechooser("save") else: self.command.clear() try: with open(self.filename, 'w') as fp: bounds = self.source_buffer.get_bounds() fp.write(self.source_buffer.get_text(bounds[0], bounds[1], True)) self.source_buffer.set_modified(False) except Exception as e: print e self.command.add_text('FAILED to save as "%s"' % self.filename) return False return True def validate(self, *args): #self.command.clear() if self.save(): self.command.add_text('VALIDATE...') self.tabs.set_current_page(1) result, message = validate.validate_xml(self.filename) self.command.add_text(message) if result: self.command.add_text('SUCCESS') else: self.command.add_text('FAILED') return result def compile(self, *args): #self.command.clear() self.tabs.set_current_page(1) if self.save(): if self.validate(): self.command.add_text('COMPILE...') self.command.run('./asr/tools/compile.sh "%s"' % self.filename) def quit(self, window): #if not self.source_buffer.get_modified() or dialog.confirm('Discard changes to "%s"?' % self.filename): Gtk.main_quit() # return True #return False if __name__ == '__main__': if len(sys.argv) > 1: app = SourceView(sys.argv[1]) else: app = SourceView() Gtk.main()